comparison 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
comparison
equal deleted inserted replaced
404:9ab878fb9fa2 405:f81478065901
1 /* 1 /*
2 * Json.cpp -- jansson C++11 wrapper 2 * Json.cpp -- C++14 JSON manipulation using jansson parser
3 * 3 *
4 * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr> 4 * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
5 * 5 *
6 * Permission to use, copy, modify, and/or distribute this software for any 6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
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 <stdexcept> 19 #include "Json.h"
20 20
21 #include "Json.h" 21 #include <jansson.h>
22 22
23 namespace json { 23 namespace json {
24 24
25 /* -------------------------------------------------------- 25 namespace {
26 * Object 26
27 * -------------------------------------------------------- */ 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 }
28 133
29 Object Value::toObject() const noexcept 134 Object Value::toObject() const noexcept
30 { 135 {
31 json_incref(m_handle.get()); 136 if (m_type != Type::Object) {
137 return Object{};
138 }
32 139
33 return Object(m_handle.get()); 140 return Object(*this);
34 } 141 }
35 142
36 Array Value::toArray() const noexcept 143 Array Value::toArray() const noexcept
37 { 144 {
38 json_incref(m_handle.get()); 145 if (m_type != Type::Array) {
146 return Array{};
147 }
39 148
40 return Array(m_handle.get()); 149 return Array(*this);
41 } 150 }
42 151
43 /* -------------------------------------------------------- 152 Document::Document(Buffer buffer)
44 * Array
45 * -------------------------------------------------------- */
46
47 Value Array::at(int index) const
48 { 153 {
49 auto value = json_array_get(m_handle.get(), index); 154 m_value = convert(json_loads, buffer.text.c_str(), 0);
50
51 if (value == nullptr)
52 throw Error("index out of bounds");
53
54 json_incref(value);
55
56 return Value{value};
57 } 155 }
58 156
59 Value Array::operator[](int index) const noexcept 157 Document::Document(File file)
60 { 158 {
61 auto value = json_array_get(m_handle.get(), index); 159 m_value = convert(json_load_file, file.path.c_str(), 0);
62
63 if (value == nullptr)
64 return Value();
65
66 json_incref(value);
67
68 return Value(value);
69 }
70
71 Array::Ref Array::operator[](int index) noexcept
72 {
73 auto value = json_array_get(m_handle.get(), index);
74
75 if (value == nullptr)
76 value = json_null();
77 else
78 json_incref(value);
79
80 return Ref(value, *this, index);
81 }
82
83 /* --------------------------------------------------------
84 * Object
85 * -------------------------------------------------------- */
86
87 Object::Ref Object::operator[](const std::string &name)
88 {
89 if (typeOf() != Type::Object)
90 return Ref(Value(), *this, name);
91
92 auto value = json_object_get(m_handle.get(), name.c_str());
93
94 json_incref(value);
95
96 return Ref(value, *this, name);
97 }
98
99 Value Object::operator[](const std::string &name) const
100 {
101 if (typeOf() != Type::Object)
102 return Value();
103
104 auto value = json_object_get(m_handle.get(), name.c_str());
105
106 if (value == nullptr)
107 return Value();
108
109 json_incref(value);
110
111 return Value(value);
112 }
113
114 /* --------------------------------------------------------
115 * Document
116 * -------------------------------------------------------- */
117
118 Value Document::read(std::string content, int flags) const
119 {
120 json_error_t error;
121 json_t *json = json_loads(content.c_str(), flags, &error);
122
123 if (json == nullptr)
124 throw Error(error);
125
126 return Value(json);
127 }
128
129 Value Document::read(std::ifstream &stream, int flags) const
130 {
131 if (!stream.is_open())
132 throw Error("File not opened");
133
134 stream.seekg(0, stream.end);
135 auto length = stream.tellg();
136 stream.seekg(0, stream.beg);
137
138 std::string buffer;
139 buffer.resize(length, ' ');
140
141 stream.read(&buffer[0], length);
142 stream.close();
143
144 return read(std::move(buffer), flags);
145 }
146
147 Document::Document(std::ifstream &stream, int flags)
148 {
149 m_value = read(stream, flags);
150 }
151
152 Document::Document(std::ifstream &&stream, int flags)
153 {
154 m_value = read(stream, flags);
155 }
156
157 Document::Document(std::string content, int flags)
158 {
159 m_value = read(std::move(content), flags);
160 } 160 }
161 161
162 } // !json 162 } // !json