-
Notifications
You must be signed in to change notification settings - Fork 0
/
json_builder.h
157 lines (109 loc) · 3.51 KB
/
json_builder.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#pragma once
#include <vector>
#include <stdexcept>
#include <string>
#include <string_view>
#include <variant>
#include "json.h"
namespace json {
class Builder {
class BaseContext;
class DictValueContext;
class DictItemContext;
class ArrayItemContext;
public:
DictValueContext Key(std::string key);
BaseContext Value(json::Value value);
DictItemContext StartDict();
ArrayItemContext StartArray();
BaseContext EndDict();
BaseContext EndArray();
json::Node Build();
private:
json::Node root_;
std::vector<json::Node*> nodes_stack_;
bool is_key_ = false;
class BaseContext {
public:
explicit BaseContext(Builder& builder) : builder_(builder) {
}
DictValueContext Key(std::string key) {
return builder_.Key(std::move(key));
}
BaseContext Value(json::Value value) {
return builder_.Value(std::move(value));
}
DictItemContext StartDict() {
return builder_.StartDict();
}
ArrayItemContext StartArray() {
return builder_.StartArray();
}
BaseContext EndDict() {
return builder_.EndDict();
}
BaseContext EndArray() {
return builder_.EndArray();
}
json::Node Build() {
return builder_.Build();
}
Builder& GetBuilder() const {
return builder_;
}
private:
Builder& builder_;
};
class DictItemContext final : public BaseContext {
public:
DictItemContext(BaseContext context) : BaseContext(context.GetBuilder()) {
}
BaseContext Value(json::Value) = delete;
DictItemContext StartDict() = delete;
ArrayItemContext StartArray() = delete;
BaseContext EndArray() = delete;
json::Node Build() = delete;
};
class DictValueContext final : public BaseContext {
public:
DictValueContext(BaseContext context) : BaseContext(context.GetBuilder()) {
}
DictValueContext Key(std::string) = delete;
BaseContext EndDict() = delete;
BaseContext EndArray() = delete;
json::Node Build() = delete;
DictItemContext Value(json::Value value) {
return BaseContext::Value(std::move(value));
}
};
class ArrayItemContext final : public BaseContext {
public:
ArrayItemContext(BaseContext context) : BaseContext(context.GetBuilder()) {
}
DictValueContext Key(std::string) = delete;
BaseContext EndDict() = delete;
json::Node Build() = delete;
ArrayItemContext Value(json::Value value) {
return BaseContext::Value(std::move(value));
}
};
bool IsSingleValueRoot();
bool NotAKeyValue();
template<typename T>
void StartContainer();
};
template<typename T>
void Builder::StartContainer() {
if (root_.IsNull() && nodes_stack_.empty()) {
json::Node* cont_ptr = reinterpret_cast<json::Node*> (&root_.GetValue().emplace<T>());
nodes_stack_.push_back(cont_ptr);
} else if ((!nodes_stack_.empty() && nodes_stack_.back()->IsNull()) && is_key_) {
is_key_ = false;
nodes_stack_.back()->GetValue() = T{};
} else if (!nodes_stack_.empty() && nodes_stack_.back()->IsArray()) {
json::Node* cont_ptr = static_cast<json::Node*> (&std::get<json::Array>(
nodes_stack_.back()->GetValue()).emplace_back(T{}));
nodes_stack_.push_back(cont_ptr);
}
}
} // namespace json