Mercurial > code
annotate C++/modules/Json/Json.cpp @ 405:f81478065901
Json:
- Complete rewrite,
- Convert jansson tree to own C++ tree,
- Conversion from Value to Object/Array makes copies
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 05 Oct 2015 17:04:40 +0200 |
parents | 9ab878fb9fa2 |
children | d485d36a8de1 |
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 } | |
38 if (json_is_number(v)) { | |
39 return Value{json_number_value(v)}; | |
40 } | |
41 if (json_is_boolean(v)) { | |
42 return Value{json_boolean_value(v)}; | |
43 } | |
44 if (json_is_object(v)) { | |
45 Object object; | |
46 | |
47 readObject(object, v); | |
48 | |
49 return object; | |
50 } | |
51 if (json_is_array(v)) { | |
52 Array array; | |
53 | |
54 readArray(array, v); | |
55 | |
56 return array; | |
57 } | |
58 | |
59 return Value{}; | |
60 } | |
61 | |
62 void readObject(Value &parent, json_t *object) | |
63 { | |
64 const char *key; | |
65 json_t *value; | |
66 | |
67 json_object_foreach(object, key, value) { | |
68 static_cast<Object &>(parent).insert(key, readValue(value)); | |
69 } | |
70 } | |
71 | |
72 void readArray(Value &parent, json_t *array) | |
73 { | |
74 size_t index; | |
75 json_t *value; | |
76 | |
77 json_array_foreach(array, index, value) { | |
78 static_cast<Array &>(parent).append(readValue(value)); | |
79 } | |
80 } | |
81 | |
82 template <typename Func, typename... Args> | |
83 Value convert(Func fn, Args&&... args) | |
84 { | |
85 json_error_t error; | |
86 json_t *json = fn(std::forward<Args>(args)..., &error); | |
87 | |
88 if (json == nullptr) { | |
89 throw Error{error.text, error.source, error.line, error.column, error.position}; | |
90 } | |
91 | |
92 Value value; | |
93 | |
94 if (json_is_object(json)) { | |
95 value = Object{}; | |
96 readObject(value, json); | |
97 } else { | |
98 value = Array{}; | |
99 readArray(value, json); | |
100 } | |
101 | |
102 json_decref(json); | |
103 | |
104 return value; | |
105 } | |
106 | |
107 } // !namespace | |
108 | |
109 bool Value::toBool() const noexcept | |
110 { | |
111 if (m_type != Type::Boolean) | |
112 return false; | |
113 | |
114 return m_boolean; | |
115 } | |
116 | |
117 double Value::toNumber() const noexcept | |
118 { | |
119 if (m_type != Type::Number) | |
120 return 0; | |
121 | |
122 return m_number; | |
123 } | |
124 | |
125 std::string Value::toString() const noexcept | |
126 { | |
127 if (m_type != Type::String) { | |
128 return ""; | |
129 } | |
130 | |
131 return m_string; | |
132 } | |
244
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
133 |
404
9ab878fb9fa2
Json: bring classes into json namespace
David Demelier <markand@malikania.fr>
parents:
403
diff
changeset
|
134 Object Value::toObject() const noexcept |
244
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
135 { |
405 | 136 if (m_type != Type::Object) { |
137 return Object{}; | |
138 } | |
311 | 139 |
405 | 140 return Object(*this); |
311 | 141 } |
142 | |
404
9ab878fb9fa2
Json: bring classes into json namespace
David Demelier <markand@malikania.fr>
parents:
403
diff
changeset
|
143 Array Value::toArray() const noexcept |
311 | 144 { |
405 | 145 if (m_type != Type::Array) { |
146 return Array{}; | |
147 } | |
314 | 148 |
405 | 149 return Array(*this); |
311 | 150 } |
151 | |
405 | 152 Document::Document(Buffer buffer) |
311 | 153 { |
405 | 154 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
|
155 } |
777bc3cb665a
Add Json, a jansson wrapper
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
156 |
405 | 157 Document::Document(File file) |
314 | 158 { |
405 | 159 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
|
160 } |
9ab878fb9fa2
Json: bring classes into json namespace
David Demelier <markand@malikania.fr>
parents:
403
diff
changeset
|
161 |
9ab878fb9fa2
Json: bring classes into json namespace
David Demelier <markand@malikania.fr>
parents:
403
diff
changeset
|
162 } // !json |