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 }