Mercurial > code
annotate C++/modules/Json/Json.cpp @ 445:f5e62f6c1475
Json: add escape free function
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 26 Oct 2015 19:29:34 +0100 |
parents | d485d36a8de1 |
children | 902b034df6e3 |
rev | line source |
---|---|
244
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
1 /* |
405 | 2 * Json.cpp -- C++14 JSON manipulation using jansson parser |
244
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
3 * |
403 | 4 * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr> |
244
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
5 * |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
6 * Permission to use, copy, modify, and/or distribute this software for any |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
7 * purpose with or without fee is hereby granted, provided that the above |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
8 * copyright notice and this permission notice appear in all copies. |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
9 * |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
17 */ |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
18 |
405 | 19 #include "Json.h" |
314 | 20 |
405 | 21 #include <jansson.h> |
244
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
22 |
404
9ab878fb9fa2
Json: bring classes into json namespace
David Demelier <markand@malikania.fr>
parents:
403
diff
changeset
|
23 namespace json { |
9ab878fb9fa2
Json: bring classes into json namespace
David Demelier <markand@malikania.fr>
parents:
403
diff
changeset
|
24 |
405 | 25 namespace { |
26 | |
27 void readObject(Value &parent, json_t *object); | |
28 void readArray(Value &parent, json_t *array); | |
29 | |
30 Value readValue(json_t *v) | |
31 { | |
32 if (json_is_null(v)) { | |
33 return Value{nullptr}; | |
34 } | |
35 if (json_is_string(v)) { | |
36 return Value{json_string_value(v)}; | |
37 } | |
406 | 38 if (json_is_real(v)) { |
405 | 39 return Value{json_number_value(v)}; |
40 } | |
406 | 41 if (json_is_integer(v)) { |
42 return Value{static_cast<int>(json_integer_value(v))}; | |
43 } | |
405 | 44 if (json_is_boolean(v)) { |
45 return Value{json_boolean_value(v)}; | |
46 } | |
47 if (json_is_object(v)) { | |
48 Object object; | |
49 | |
50 readObject(object, v); | |
51 | |
52 return object; | |
53 } | |
54 if (json_is_array(v)) { | |
55 Array array; | |
56 | |
57 readArray(array, v); | |
58 | |
59 return array; | |
60 } | |
61 | |
62 return Value{}; | |
63 } | |
64 | |
65 void readObject(Value &parent, json_t *object) | |
66 { | |
67 const char *key; | |
68 json_t *value; | |
69 | |
70 json_object_foreach(object, key, value) { | |
71 static_cast<Object &>(parent).insert(key, readValue(value)); | |
72 } | |
73 } | |
74 | |
75 void readArray(Value &parent, json_t *array) | |
76 { | |
77 size_t index; | |
78 json_t *value; | |
79 | |
80 json_array_foreach(array, index, value) { | |
81 static_cast<Array &>(parent).append(readValue(value)); | |
82 } | |
83 } | |
84 | |
85 template <typename Func, typename... Args> | |
86 Value convert(Func fn, Args&&... args) | |
87 { | |
88 json_error_t error; | |
89 json_t *json = fn(std::forward<Args>(args)..., &error); | |
90 | |
91 if (json == nullptr) { | |
92 throw Error{error.text, error.source, error.line, error.column, error.position}; | |
93 } | |
94 | |
95 Value value; | |
96 | |
97 if (json_is_object(json)) { | |
98 value = Object{}; | |
99 readObject(value, json); | |
100 } else { | |
101 value = Array{}; | |
102 readArray(value, json); | |
103 } | |
104 | |
105 json_decref(json); | |
106 | |
107 return value; | |
108 } | |
109 | |
110 } // !namespace | |
111 | |
112 bool Value::toBool() const noexcept | |
113 { | |
406 | 114 if (m_type != Type::Boolean) { |
405 | 115 return false; |
406 | 116 } |
405 | 117 |
118 return m_boolean; | |
119 } | |
120 | |
406 | 121 double Value::toReal() const noexcept |
405 | 122 { |
406 | 123 if (m_type != Type::Real) { |
405 | 124 return 0; |
406 | 125 } |
405 | 126 |
127 return m_number; | |
128 } | |
129 | |
406 | 130 int Value::toInt() const noexcept |
131 { | |
132 if (m_type != Type::Int) { | |
133 return 0; | |
134 } | |
135 | |
136 return m_integer; | |
137 } | |
138 | |
405 | 139 std::string Value::toString() const noexcept |
140 { | |
141 if (m_type != Type::String) { | |
142 return ""; | |
143 } | |
144 | |
145 return m_string; | |
146 } | |
244
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
147 |
404
9ab878fb9fa2
Json: bring classes into json namespace
David Demelier <markand@malikania.fr>
parents:
403
diff
changeset
|
148 Object Value::toObject() const noexcept |
244
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
149 { |
405 | 150 if (m_type != Type::Object) { |
151 return Object{}; | |
152 } | |
311 | 153 |
405 | 154 return Object(*this); |
311 | 155 } |
156 | |
404
9ab878fb9fa2
Json: bring classes into json namespace
David Demelier <markand@malikania.fr>
parents:
403
diff
changeset
|
157 Array Value::toArray() const noexcept |
311 | 158 { |
405 | 159 if (m_type != Type::Array) { |
160 return Array{}; | |
161 } | |
314 | 162 |
405 | 163 return Array(*this); |
311 | 164 } |
165 | |
405 | 166 Document::Document(Buffer buffer) |
311 | 167 { |
405 | 168 m_value = convert(json_loads, buffer.text.c_str(), 0); |
244
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
169 } |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
170 |
405 | 171 Document::Document(File file) |
314 | 172 { |
405 | 173 m_value = convert(json_load_file, file.path.c_str(), 0); |
404
9ab878fb9fa2
Json: bring classes into json namespace
David Demelier <markand@malikania.fr>
parents:
403
diff
changeset
|
174 } |
9ab878fb9fa2
Json: bring classes into json namespace
David Demelier <markand@malikania.fr>
parents:
403
diff
changeset
|
175 |
445
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
176 std::string escape(std::string value) noexcept |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
177 { |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
178 for (auto it = value.begin(); it != value.end(); ++it) { |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
179 switch (*it) { |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
180 case '\\': |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
181 case '/': |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
182 case '"': |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
183 it = value.insert(it, '\\'); |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
184 it++; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
185 break; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
186 case '\b': |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
187 value.replace(it, it + 1, "\\b"); |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
188 it += 1; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
189 break; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
190 case '\f': |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
191 value.replace(it, it + 1, "\\f"); |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
192 it += 1; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
193 break; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
194 case '\n': |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
195 value.replace(it, it + 1, "\\n"); |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
196 it += 1; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
197 break; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
198 case '\r': |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
199 value.replace(it, it + 1, "\\r"); |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
200 it += 1; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
201 break; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
202 case '\t': |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
203 value.replace(it, it + 1, "\\t"); |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
204 it += 1; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
205 break; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
206 default: |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
207 break; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
208 } |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
209 } |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
210 |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
211 return value; |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
212 } |
f5e62f6c1475
Json: add escape free function
David Demelier <markand@malikania.fr>
parents:
406
diff
changeset
|
213 |
406 | 214 } // !json |