Mercurial > code
comparison C++/Json.cpp @ 311:ed3cc10761e4
Json:
* Split Json class into several classes
* Add unit tests
* Json is considered usable
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 13 Feb 2015 13:42:21 +0100 |
parents | 777bc3cb665a |
children | ea1a73a7d468 |
comparison
equal
deleted
inserted
replaced
310:46e2211fed58 | 311:ed3cc10761e4 |
---|---|
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 */ | 17 */ |
18 | 18 |
19 #include "Json.h" | 19 #include "Json.h" |
20 | 20 |
21 Json Json::fromString(const std::string &data, int flags) | 21 /* -------------------------------------------------------- |
22 { | 22 * JsonValue implementation |
23 return from(json_loads, data.c_str(), flags); | 23 * -------------------------------------------------------- */ |
24 } | 24 |
25 | 25 JsonValue::JsonValue(const JsonValue &value) |
26 Json Json::fromFile(const std::string &path, int flags) | 26 : m_handle(json_deep_copy(value.m_handle.get()), json_decref) |
27 { | 27 { |
28 return from(json_load_file, path.c_str(), flags); | 28 } |
29 } | 29 |
30 | 30 JsonValue &JsonValue::operator=(const JsonValue &value) |
31 Json::Json() | 31 { |
32 : m_handle(json_object(), json_decref) | 32 m_handle = Handle(json_deep_copy(value.m_handle.get()), json_decref); |
33 { | 33 } |
34 } | 34 |
35 | 35 JsonValue::JsonValue(json_t *json) |
36 Json::Json(bool value) | 36 : m_handle(json, json_decref) |
37 { | |
38 } | |
39 | |
40 JsonValue::JsonValue() | |
41 : m_handle(json_null(), json_decref) | |
42 { | |
43 } | |
44 | |
45 JsonValue::JsonValue(bool value) | |
37 : m_handle(json_boolean(value), json_decref) | 46 : m_handle(json_boolean(value), json_decref) |
38 { | 47 { |
39 } | 48 } |
40 | 49 |
41 Json::Json(int value) | 50 JsonValue::JsonValue(int value) |
42 : m_handle(json_integer(value), json_decref) | 51 : m_handle(json_integer(value), json_decref) |
43 { | 52 { |
44 } | 53 } |
45 | 54 |
46 Json::Json(double value) | 55 JsonValue::JsonValue(double value) |
47 : m_handle(json_real(value), json_decref) | 56 : m_handle(json_real(value), json_decref) |
48 { | 57 { |
49 } | 58 } |
50 | 59 |
51 Json::Json(const std::string &value) | 60 JsonValue::JsonValue(std::string value) |
52 : m_handle(json_string(value.c_str()), json_decref) | 61 : m_handle(json_string(value.c_str()), json_decref) |
53 { | 62 { |
54 } | 63 } |
55 | 64 |
56 Json::Json(const Json &json) | 65 JsonValue::JsonValue(const char *value) |
57 : m_handle(json_deep_copy(json.m_handle.get()), json_decref) | 66 : m_handle(json_string(value), json_decref) |
58 , m_list(json.m_list) | 67 { |
59 , m_map(json.m_map) | 68 } |
60 { | 69 |
61 } | 70 JsonType JsonValue::typeOf() const |
62 | 71 { |
63 Json::Json(Json &&value) | 72 return static_cast<JsonType>(json_typeof(m_handle.get())); |
64 : m_handle(value.m_handle.release(), json_decref) | 73 } |
65 , m_list(std::move(value.m_list)) | 74 |
66 , m_map(std::move(value.m_map)) | 75 bool JsonValue::isObject() const |
67 { | |
68 } | |
69 | |
70 Json::Json(std::initializer_list<Json> list) | |
71 : m_handle(json_array(), json_decref) | |
72 { | |
73 m_list.reserve(list.size()); | |
74 | |
75 for (const auto &v : list) { | |
76 m_list.push_back(v); | |
77 json_array_append(m_handle.get(), m_list.back().m_handle.get()); | |
78 } | |
79 } | |
80 | |
81 Json &Json::operator=(const Json &json) | |
82 { | |
83 m_handle = Handle(json.m_handle.get(), json_decref); | |
84 m_list = json.m_list; | |
85 m_map = json.m_map; | |
86 | |
87 return *this; | |
88 } | |
89 | |
90 Json &Json::operator=(Json &&value) | |
91 { | |
92 m_handle = Handle(value.m_handle.release(), json_decref); | |
93 m_list = std::move(value.m_list); | |
94 m_map = std::move(value.m_map); | |
95 | |
96 return *this; | |
97 } | |
98 | |
99 int Json::typeOf() const | |
100 { | |
101 return json_typeof(m_handle.get()); | |
102 } | |
103 | |
104 bool Json::isObject() const | |
105 { | 76 { |
106 return json_is_object(m_handle.get()) != 0; | 77 return json_is_object(m_handle.get()) != 0; |
107 } | 78 } |
108 | 79 |
109 bool Json::isArray() const | 80 bool JsonValue::isArray() const |
110 { | 81 { |
111 return json_is_array(m_handle.get()) != 0; | 82 return json_is_array(m_handle.get()) != 0; |
112 } | 83 } |
113 | 84 |
114 bool Json::isString() const | 85 bool JsonValue::isString() const |
115 { | 86 { |
116 return json_is_string(m_handle.get()) != 0; | 87 return json_is_string(m_handle.get()) != 0; |
117 } | 88 } |
118 | 89 |
119 bool Json::isReal() const | 90 bool JsonValue::isReal() const |
120 { | 91 { |
121 return json_is_real(m_handle.get()) != 0; | 92 return json_is_real(m_handle.get()) != 0; |
122 } | 93 } |
123 | 94 |
124 bool Json::isTrue() const | 95 bool JsonValue::isTrue() const |
125 { | 96 { |
126 return json_is_true(m_handle.get()) != 0; | 97 return json_is_true(m_handle.get()) != 0; |
127 } | 98 } |
128 | 99 |
129 bool Json::isFalse() const | 100 bool JsonValue::isFalse() const |
130 { | 101 { |
131 return json_is_true(m_handle.get()) != 0; | 102 return json_is_false(m_handle.get()) != 0; |
132 } | 103 } |
133 | 104 |
134 bool Json::isNull() const | 105 bool JsonValue::isNull() const |
135 { | 106 { |
136 return json_is_null(m_handle.get()) != 0; | 107 return json_is_null(m_handle.get()) != 0; |
137 } | 108 } |
138 | 109 |
139 bool Json::isNumber() const | 110 bool JsonValue::isNumber() const |
140 { | 111 { |
141 return json_is_number(m_handle.get()) != 0; | 112 return json_is_number(m_handle.get()) != 0; |
142 } | 113 } |
143 | 114 |
144 bool Json::isInteger() const | 115 bool JsonValue::isInteger() const |
145 { | 116 { |
146 return json_is_integer(m_handle.get()) != 0; | 117 return json_is_integer(m_handle.get()) != 0; |
147 } | 118 } |
148 | 119 |
149 bool Json::isBoolean() const | 120 bool JsonValue::isBoolean() const |
150 { | 121 { |
151 return json_is_boolean(m_handle.get()) != 0; | 122 return json_is_boolean(m_handle.get()) != 0; |
152 } | 123 } |
153 | 124 |
154 unsigned Json::size() const noexcept | 125 std::string JsonValue::toString() const |
155 { | |
156 return m_list.size(); | |
157 } | |
158 | |
159 void Json::append(const Json &value) | |
160 { | |
161 m_list.push_back(value); | |
162 json_array_append(m_handle.get(), m_list.back().m_handle.get()); | |
163 } | |
164 | |
165 void Json::append(Json &&value) | |
166 { | |
167 m_list.push_back(std::move(value)); | |
168 json_array_append(m_handle.get(), m_list.back().m_handle.get()); | |
169 } | |
170 | |
171 void Json::insert(const Json &value, int index) | |
172 { | |
173 m_list.insert(m_list.begin() + index, value); | |
174 json_array_insert(m_handle.get(), index, m_list[index].m_handle.get()); | |
175 } | |
176 | |
177 void Json::insert(Json &&value, int index) | |
178 { | |
179 m_list.insert(m_list.begin() + index, std::move(value)); | |
180 json_array_insert(m_handle.get(), index, m_list[index].m_handle.get()); | |
181 } | |
182 | |
183 void Json::set(const Json &value, const std::string &name) | |
184 { | |
185 m_map[name] = value; | |
186 json_object_set(m_handle.get(), name.c_str(), m_map[name].m_handle.get()); | |
187 } | |
188 | |
189 void Json::set(Json &&value, const std::string &name) | |
190 { | |
191 m_map[name] = std::move(value); | |
192 json_object_set(m_handle.get(), name.c_str(), m_map[name].m_handle.get()); | |
193 } | |
194 | |
195 std::string Json::toString() const | |
196 { | 126 { |
197 auto value = json_string_value(m_handle.get()); | 127 auto value = json_string_value(m_handle.get()); |
198 | 128 |
199 return (value == nullptr) ? "" : value; | 129 return (value == nullptr) ? "" : value; |
200 } | 130 } |
201 | 131 |
202 int Json::toInteger() const noexcept | 132 int JsonValue::toInteger() const noexcept |
203 { | 133 { |
204 return json_integer_value(m_handle.get()); | 134 return json_integer_value(m_handle.get()); |
205 } | 135 } |
206 | 136 |
207 double Json::toReal() const noexcept | 137 double JsonValue::toReal() const noexcept |
208 { | 138 { |
209 return json_real_value(m_handle.get()); | 139 return json_real_value(m_handle.get()); |
210 } | 140 } |
211 | 141 |
212 std::string Json::dump(int flags) | 142 JsonObject JsonValue::toObject() const |
213 { | 143 { |
214 auto v = json_dumps(m_handle.get(), flags); | 144 json_incref(m_handle.get()); |
215 | 145 |
216 if (v == nullptr) | 146 return JsonObject(m_handle.get()); |
217 throw std::runtime_error("failed to dump"); | 147 } |
218 | 148 |
219 return std::string(v); | 149 JsonArray JsonValue::toArray() const |
220 } | 150 { |
221 | 151 json_incref(m_handle.get()); |
222 void Json::dump(const std::string &path, int flags) | 152 |
223 { | 153 return JsonArray(m_handle.get()); |
224 if (json_dump_file(m_handle.get(), path.c_str(), flags) < 0) | 154 } |
225 throw std::runtime_error("failed to dump"); | 155 |
226 } | 156 /* -------------------------------------------------------- |
227 | 157 * JsonArray |
228 Json &Json::operator[](int index) | 158 * -------------------------------------------------------- */ |
229 { | 159 |
230 if (!isArray()) | 160 JsonArray::JsonArray() |
231 throw std::invalid_argument("not an array"); | 161 : JsonValue(json_array()) |
232 | 162 { |
233 if (index >= m_list.size()) | 163 } |
234 throw std::out_of_range("invalid index"); | 164 |
235 | 165 unsigned JsonArray::size() const noexcept |
236 return m_list[index]; | 166 { |
237 } | 167 return json_array_size(m_handle.get()); |
238 | 168 } |
239 const Json &Json::operator[](int index) const | 169 |
240 { | 170 void JsonArray::push(const JsonValue &value) |
241 if (!isArray()) | 171 { |
242 throw std::invalid_argument("not an array"); | 172 json_array_insert(m_handle.get(), 0, value.m_handle.get()); |
243 | 173 } |
244 if (index >= m_list.size()) | 174 |
245 throw std::out_of_range("invalid index"); | 175 void JsonArray::append(const JsonValue &value) |
246 | 176 { |
247 return m_list[index]; | 177 json_array_append(m_handle.get(), value.m_handle.get()); |
248 } | 178 } |
249 | 179 |
250 Json &Json::operator[](const std::string &name) | 180 void JsonArray::insert(const JsonValue &value, int index) |
251 { | 181 { |
252 if (!isObject()) | 182 json_array_insert(m_handle.get(), index, value.m_handle.get()); |
253 throw std::invalid_argument("not an object"); | 183 } |
254 | 184 |
255 if (m_map.count(name) == 0) | 185 JsonValue JsonArray::operator[](int index) const |
256 throw std::out_of_range("invalid key"); | 186 { |
257 | 187 if (typeOf() != JsonType::Array) |
258 return m_map[name]; | 188 throw JsonError("not an array"); |
259 } | 189 |
260 | 190 auto value = json_array_get(m_handle.get(), index); |
261 const Json &Json::operator[](const std::string &name) const | 191 |
262 { | 192 if (value == nullptr) |
263 if (!isObject()) | 193 throw JsonError("index out of bounds"); |
264 throw std::invalid_argument("not an object"); | 194 |
265 | 195 json_incref(value); |
266 if (m_map.count(name) == 0) | 196 |
267 throw std::out_of_range("invalid key"); | 197 return JsonValue(value); |
268 | 198 } |
269 return m_map.at(name); | 199 |
270 } | 200 /* -------------------------------------------------------- |
271 | 201 * JsonObject |
272 bool operator==(const Json &j1, const Json &j2) | 202 * -------------------------------------------------------- */ |
273 { | 203 |
274 return json_equal(j1.m_handle.get(), j2.m_handle.get()) != 0; | 204 JsonObject::JsonObject() |
275 } | 205 : JsonValue(json_object()) |
206 { | |
207 } | |
208 | |
209 JsonValue JsonObject::operator[](const std::string &name) const | |
210 { | |
211 if (typeOf() != JsonType::Object) | |
212 throw JsonError("not an object"); | |
213 | |
214 auto value = json_object_get(m_handle.get(), name.c_str()); | |
215 | |
216 if (value == nullptr) | |
217 throw JsonError("key " + name + +" not found"); | |
218 | |
219 json_incref(value); | |
220 | |
221 return JsonValue(value); | |
222 } | |
223 | |
224 void JsonObject::set(const std::string &key, const JsonValue &value) | |
225 { | |
226 json_object_set(m_handle.get(), key.c_str(), value.m_handle.get()); | |
227 } | |
228 | |
229 /* -------------------------------------------------------- | |
230 * JsonReaderFile | |
231 * -------------------------------------------------------- */ | |
232 | |
233 JsonReaderFile::JsonReaderFile(std::string path) | |
234 : m_path(std::move(path)) | |
235 { | |
236 } | |
237 | |
238 JsonValue JsonReaderFile::read() | |
239 { | |
240 json_error_t error; | |
241 json_t *handle = json_load_file(m_path.c_str(), 0, &error); | |
242 | |
243 if (handle == nullptr) | |
244 throw JsonError{error}; | |
245 | |
246 return JsonValue(handle); | |
247 } | |
248 | |
249 /* -------------------------------------------------------- | |
250 * JsonWriterFile | |
251 * -------------------------------------------------------- */ | |
252 | |
253 JsonWriterFile::JsonWriterFile(std::string path) | |
254 : m_path(std::move(path)) | |
255 { | |
256 } | |
257 | |
258 void JsonWriterFile::write(const JsonValue &value) | |
259 { | |
260 if (json_dump_file(value, m_path.c_str(), 0) < 0) | |
261 throw JsonError("Failed to write file: " + m_path); | |
262 } |