User | Revision | Line number | New contents of line |
samux |
0:0cf0e27feaad
|
1
|
/**
|
samux |
0:0cf0e27feaad
|
2
|
* @author Samuel Mokrani
|
samux |
0:0cf0e27feaad
|
3
|
*
|
samux |
0:0cf0e27feaad
|
4
|
* @section LICENSE
|
samux |
0:0cf0e27feaad
|
5
|
*
|
samux |
0:0cf0e27feaad
|
6
|
* Copyright (c) 2011 mbed
|
samux |
0:0cf0e27feaad
|
7
|
*
|
samux |
0:0cf0e27feaad
|
8
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
samux |
0:0cf0e27feaad
|
9
|
* of this software and associated documentation files (the "Software"), to deal
|
samux |
0:0cf0e27feaad
|
10
|
* in the Software without restriction, including without limitation the rights
|
samux |
0:0cf0e27feaad
|
11
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
samux |
0:0cf0e27feaad
|
12
|
* copies of the Software, and to permit persons to whom the Software is
|
samux |
0:0cf0e27feaad
|
13
|
* furnished to do so, subject to the following conditions:
|
samux |
0:0cf0e27feaad
|
14
|
*
|
samux |
0:0cf0e27feaad
|
15
|
* The above copyright notice and this permission notice shall be included in
|
samux |
0:0cf0e27feaad
|
16
|
* all copies or substantial portions of the Software.
|
samux |
0:0cf0e27feaad
|
17
|
*
|
samux |
0:0cf0e27feaad
|
18
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
samux |
0:0cf0e27feaad
|
19
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
samux |
0:0cf0e27feaad
|
20
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
samux |
0:0cf0e27feaad
|
21
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
samux |
0:0cf0e27feaad
|
22
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
samux |
0:0cf0e27feaad
|
23
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
samux |
0:0cf0e27feaad
|
24
|
* THE SOFTWARE.
|
samux |
0:0cf0e27feaad
|
25
|
*
|
samux |
0:0cf0e27feaad
|
26
|
* @section DESCRIPTION
|
samux |
0:0cf0e27feaad
|
27
|
* Types Abstraction. JSON serializer and parser. (inspired by picojson). Is used by MbedJSONRpc.
|
samux |
0:0cf0e27feaad
|
28
|
*
|
samux |
0:0cf0e27feaad
|
29
|
*/
|
samux |
0:0cf0e27feaad
|
30
|
|
samux |
0:0cf0e27feaad
|
31
|
#ifndef _Mbed_RPC_VALUE_H_
|
samux |
0:0cf0e27feaad
|
32
|
#define _Mbed_RPC_VALUE_H_
|
samux |
0:0cf0e27feaad
|
33
|
|
samux |
0:0cf0e27feaad
|
34
|
#define NB_TOKEN 20
|
samux |
0:0cf0e27feaad
|
35
|
/*!< Number maximum of MbedJSONValue in an array or an object */
|
samux |
0:0cf0e27feaad
|
36
|
|
samux |
0:0cf0e27feaad
|
37
|
#include <string>
|
samux |
0:0cf0e27feaad
|
38
|
#include <stdio.h>
|
samux |
0:0cf0e27feaad
|
39
|
#include <stdlib.h>
|
samux |
0:0cf0e27feaad
|
40
|
#include <string.h>
|
samux |
0:0cf0e27feaad
|
41
|
|
samux |
0:0cf0e27feaad
|
42
|
/** MbedJSONValue class
|
samux |
0:0cf0e27feaad
|
43
|
*
|
samux |
0:0cf0e27feaad
|
44
|
* Example:
|
samux |
0:0cf0e27feaad
|
45
|
* - creation of an MbedJSONValue of type TypeObject containing two others MbedJSONValue:
|
samux |
0:0cf0e27feaad
|
46
|
* -one array of one string and one integer identified by "my_array"
|
samux |
0:0cf0e27feaad
|
47
|
* -a boolean identified by "my_boolean"
|
samux |
0:0cf0e27feaad
|
48
|
* - serialization in JSON format of this object
|
samux |
0:0cf0e27feaad
|
49
|
* @code
|
samux |
0:0cf0e27feaad
|
50
|
* MbedJSONValue demo;
|
samux |
0:0cf0e27feaad
|
51
|
* std::string s;
|
samux |
0:0cf0e27feaad
|
52
|
*
|
samux |
0:0cf0e27feaad
|
53
|
* //fill the object
|
samux |
0:0cf0e27feaad
|
54
|
* demo["my_array"][0] = "demo_string";
|
samux |
0:0cf0e27feaad
|
55
|
* demo["my_array"][1] = 10;
|
samux |
0:0cf0e27feaad
|
56
|
* demo["my_boolean"] = true;
|
samux |
0:0cf0e27feaad
|
57
|
*
|
samux |
0:0cf0e27feaad
|
58
|
* //serialize it into a JSON string
|
samux |
0:0cf0e27feaad
|
59
|
* s = demo.serialize();
|
samux |
0:0cf0e27feaad
|
60
|
*
|
samux |
0:0cf0e27feaad
|
61
|
*
|
samux |
0:0cf0e27feaad
|
62
|
* @endcode
|
samux |
0:0cf0e27feaad
|
63
|
*
|
samux |
0:0cf0e27feaad
|
64
|
* Example:
|
samux |
0:0cf0e27feaad
|
65
|
* - creation of an MbedJSONValue from a JSON string
|
samux |
0:0cf0e27feaad
|
66
|
* - extraction of different values from this existing MbedJSONValue
|
samux |
0:0cf0e27feaad
|
67
|
* @code
|
samux |
0:0cf0e27feaad
|
68
|
*
|
samux |
0:0cf0e27feaad
|
69
|
* MbedJSONValue demo;
|
samux |
0:0cf0e27feaad
|
70
|
*
|
samux |
0:0cf0e27feaad
|
71
|
* const char * json = "{\"my_array\": [\"demo_string\", 10], \"my_boolean\": true}";
|
samux |
0:0cf0e27feaad
|
72
|
*
|
samux |
0:0cf0e27feaad
|
73
|
* //parse the previous string and fill the object demo
|
samux |
0:0cf0e27feaad
|
74
|
* parse(demo, json);
|
samux |
0:0cf0e27feaad
|
75
|
*
|
samux |
0:0cf0e27feaad
|
76
|
* std::string my_str;
|
samux |
0:0cf0e27feaad
|
77
|
* int my_int;
|
samux |
0:0cf0e27feaad
|
78
|
* bool my_bool;
|
samux |
0:0cf0e27feaad
|
79
|
*
|
samux |
0:0cf0e27feaad
|
80
|
* my_str = demo["my_array"][0];
|
samux |
0:0cf0e27feaad
|
81
|
* my_int = demo["my_array"][1];
|
samux |
0:0cf0e27feaad
|
82
|
* my_bool = demo["my_boolean"];
|
samux |
0:0cf0e27feaad
|
83
|
*
|
samux |
0:0cf0e27feaad
|
84
|
* @endcode
|
samux |
0:0cf0e27feaad
|
85
|
*/
|
samux |
0:0cf0e27feaad
|
86
|
class MbedJSONValue {
|
samux |
0:0cf0e27feaad
|
87
|
public:
|
samux |
0:0cf0e27feaad
|
88
|
|
samux |
0:0cf0e27feaad
|
89
|
/**
|
samux |
0:0cf0e27feaad
|
90
|
* \enum Type
|
samux |
0:0cf0e27feaad
|
91
|
* \brief All types which can be used
|
samux |
0:0cf0e27feaad
|
92
|
*/
|
samux |
0:0cf0e27feaad
|
93
|
enum Type {
|
samux |
0:0cf0e27feaad
|
94
|
TypeNull, /*!< Null type */
|
samux |
0:0cf0e27feaad
|
95
|
TypeBoolean, /*!< Boolean */
|
samux |
0:0cf0e27feaad
|
96
|
TypeInt, /*!< Integer */
|
samux |
0:0cf0e27feaad
|
97
|
TypeDouble, /*!< Double */
|
samux |
0:0cf0e27feaad
|
98
|
TypeString, /*!< String */
|
samux |
0:0cf0e27feaad
|
99
|
TypeArray, /*!< Array of Type */
|
samux |
0:0cf0e27feaad
|
100
|
TypeObject /*!< Object */
|
samux |
0:0cf0e27feaad
|
101
|
};
|
samux |
0:0cf0e27feaad
|
102
|
|
samux |
0:0cf0e27feaad
|
103
|
/**
|
samux |
0:0cf0e27feaad
|
104
|
* MbedJSONValue constructor of type TypeNull
|
samux |
0:0cf0e27feaad
|
105
|
*/
|
samux |
0:0cf0e27feaad
|
106
|
MbedJSONValue() : _type(TypeNull), index_array(0), index_token(0) {}
|
samux |
0:0cf0e27feaad
|
107
|
|
samux |
0:0cf0e27feaad
|
108
|
/**
|
samux |
0:0cf0e27feaad
|
109
|
* MbedJSONValue constructor of type TypeBoolean
|
samux |
0:0cf0e27feaad
|
110
|
*
|
samux |
0:0cf0e27feaad
|
111
|
* @param value the object created will be initialized with this boolean
|
samux |
0:0cf0e27feaad
|
112
|
*/
|
samux |
0:0cf0e27feaad
|
113
|
MbedJSONValue(bool value) : _type(TypeBoolean), index_array(0), index_token(0) {
|
samux |
0:0cf0e27feaad
|
114
|
_value.asBool = value;
|
samux |
0:0cf0e27feaad
|
115
|
}
|
samux |
0:0cf0e27feaad
|
116
|
|
samux |
0:0cf0e27feaad
|
117
|
/**
|
samux |
0:0cf0e27feaad
|
118
|
* MbedJSONValue constructor of type TypeInt
|
samux |
0:0cf0e27feaad
|
119
|
*
|
samux |
0:0cf0e27feaad
|
120
|
* @param value the object created will be initialized with this integer
|
samux |
0:0cf0e27feaad
|
121
|
*/
|
samux |
0:0cf0e27feaad
|
122
|
MbedJSONValue(int value) : _type(TypeInt), index_array(0), index_token(0) {
|
samux |
0:0cf0e27feaad
|
123
|
_value.asInt = value;
|
samux |
0:0cf0e27feaad
|
124
|
}
|
samux |
0:0cf0e27feaad
|
125
|
|
samux |
0:0cf0e27feaad
|
126
|
/**
|
samux |
0:0cf0e27feaad
|
127
|
* MbedJSONValue constructor of type TypeDouble
|
samux |
0:0cf0e27feaad
|
128
|
*
|
samux |
0:0cf0e27feaad
|
129
|
* @param value the object created will be initialized with this double
|
samux |
0:0cf0e27feaad
|
130
|
*/
|
samux |
0:0cf0e27feaad
|
131
|
MbedJSONValue(double value) : _type(TypeDouble), index_array(0), index_token(0) {
|
samux |
0:0cf0e27feaad
|
132
|
_value.asDouble = value;
|
samux |
0:0cf0e27feaad
|
133
|
}
|
samux |
0:0cf0e27feaad
|
134
|
|
samux |
0:0cf0e27feaad
|
135
|
/**
|
samux |
0:0cf0e27feaad
|
136
|
* MbedJSONValue constructor of type TypeString
|
samux |
0:0cf0e27feaad
|
137
|
*
|
samux |
0:0cf0e27feaad
|
138
|
* @param value the object created will be initialized with this string
|
samux |
0:0cf0e27feaad
|
139
|
*/
|
samux |
0:0cf0e27feaad
|
140
|
MbedJSONValue(std::string const& value) : _type(TypeString), index_array(0), index_token(0) {
|
samux |
0:0cf0e27feaad
|
141
|
_value.asString = new std::string(value);
|
samux |
0:0cf0e27feaad
|
142
|
}
|
samux |
0:0cf0e27feaad
|
143
|
|
samux |
0:0cf0e27feaad
|
144
|
/**
|
samux |
0:0cf0e27feaad
|
145
|
* MbedJSONValue constructor of type TypeString
|
samux |
0:0cf0e27feaad
|
146
|
*
|
samux |
0:0cf0e27feaad
|
147
|
* @param value the object created will be initialized with this string
|
samux |
0:0cf0e27feaad
|
148
|
*/
|
samux |
0:0cf0e27feaad
|
149
|
MbedJSONValue(const char* value) : _type(TypeString), index_array(0), index_token(0) {
|
samux |
0:0cf0e27feaad
|
150
|
_value.asString = new std::string(value);
|
samux |
0:0cf0e27feaad
|
151
|
}
|
samux |
0:0cf0e27feaad
|
152
|
|
samux |
0:0cf0e27feaad
|
153
|
/**
|
samux |
0:0cf0e27feaad
|
154
|
* Copy constructor
|
samux |
0:0cf0e27feaad
|
155
|
*
|
samux |
0:0cf0e27feaad
|
156
|
* @param rhs object which will be copied
|
samux |
0:0cf0e27feaad
|
157
|
*/
|
samux |
0:0cf0e27feaad
|
158
|
MbedJSONValue(MbedJSONValue const& rhs) : _type(TypeNull) { *this = rhs; }
|
samux |
0:0cf0e27feaad
|
159
|
|
samux |
0:0cf0e27feaad
|
160
|
/**
|
samux |
0:0cf0e27feaad
|
161
|
* Destructor
|
samux |
0:0cf0e27feaad
|
162
|
*/
|
samux |
0:0cf0e27feaad
|
163
|
~MbedJSONValue() { clean(); }
|
samux |
0:0cf0e27feaad
|
164
|
|
samux |
0:0cf0e27feaad
|
165
|
/**
|
samux |
0:0cf0e27feaad
|
166
|
* = Operator overloading for an MbedJSONValue from an MbedJSONValue
|
samux |
0:0cf0e27feaad
|
167
|
*
|
samux |
0:0cf0e27feaad
|
168
|
* @param rhs object
|
samux |
0:0cf0e27feaad
|
169
|
* @return a reference on the MbedJSONValue affected
|
samux |
0:0cf0e27feaad
|
170
|
*/
|
samux |
0:0cf0e27feaad
|
171
|
MbedJSONValue& operator=(MbedJSONValue const & rhs);
|
samux |
0:0cf0e27feaad
|
172
|
|
samux |
0:0cf0e27feaad
|
173
|
/**
|
samux |
0:0cf0e27feaad
|
174
|
* = Operator overloading for an MbedJSONValue from an int
|
samux |
0:0cf0e27feaad
|
175
|
*
|
samux |
0:0cf0e27feaad
|
176
|
* @param rhs integer
|
samux |
0:0cf0e27feaad
|
177
|
* @return a reference on the MbedJSONValue affected
|
samux |
0:0cf0e27feaad
|
178
|
*/
|
samux |
0:0cf0e27feaad
|
179
|
MbedJSONValue& operator=(int const& rhs) { return operator=(MbedJSONValue(rhs)); }
|
samux |
0:0cf0e27feaad
|
180
|
|
samux |
0:0cf0e27feaad
|
181
|
/**
|
samux |
0:0cf0e27feaad
|
182
|
* = Operator overloading for an MbedJSONValue from a double
|
samux |
0:0cf0e27feaad
|
183
|
*
|
samux |
0:0cf0e27feaad
|
184
|
* @param rhs double
|
samux |
0:0cf0e27feaad
|
185
|
* @return a reference on the MbedJSONValue affected
|
samux |
0:0cf0e27feaad
|
186
|
*/
|
samux |
0:0cf0e27feaad
|
187
|
MbedJSONValue& operator=(double const& rhs) { return operator=(MbedJSONValue(rhs)); }
|
samux |
0:0cf0e27feaad
|
188
|
|
samux |
0:0cf0e27feaad
|
189
|
/**
|
samux |
0:0cf0e27feaad
|
190
|
* = Operator overloading for an MbedJSONValue from a string
|
samux |
0:0cf0e27feaad
|
191
|
*
|
samux |
0:0cf0e27feaad
|
192
|
* @param rhs string
|
samux |
0:0cf0e27feaad
|
193
|
* @return a reference on the MbedJSONValue affected
|
samux |
0:0cf0e27feaad
|
194
|
*/
|
samux |
0:0cf0e27feaad
|
195
|
MbedJSONValue& operator=(const char* rhs) { return operator=(MbedJSONValue(std::string(rhs))); }
|
samux |
0:0cf0e27feaad
|
196
|
|
samux |
0:0cf0e27feaad
|
197
|
|
samux |
0:0cf0e27feaad
|
198
|
/**
|
samux |
0:0cf0e27feaad
|
199
|
* [] Operator overloading for an MbedJSONValue.
|
samux |
0:0cf0e27feaad
|
200
|
* Each TypeObject object can contain an array of NB_TOKEN MbedJSONValue.
|
samux |
0:0cf0e27feaad
|
201
|
* This operator is useful to create an array or to retrieve an MbedJSONValue of an existing array.
|
samux |
0:0cf0e27feaad
|
202
|
*
|
samux |
0:0cf0e27feaad
|
203
|
* @param i index of the array
|
samux |
0:0cf0e27feaad
|
204
|
* @return a reference on the MbedJSONValue created or retrieved
|
samux |
0:0cf0e27feaad
|
205
|
*/
|
samux |
0:0cf0e27feaad
|
206
|
MbedJSONValue& operator[](int i);
|
samux |
0:0cf0e27feaad
|
207
|
|
samux |
0:0cf0e27feaad
|
208
|
/**
|
samux |
0:0cf0e27feaad
|
209
|
* [] Operator overloading for an MbedJSONValue.
|
samux |
0:0cf0e27feaad
|
210
|
* Each TypeObject MbedJSONValue can contain NB_TOKEN MbedJSONValue IDENTIFIED BY A NAME
|
samux |
0:0cf0e27feaad
|
211
|
* This operator is useful to create a TypeObject MbedJSONValue or to retrieve an MbedJSONValue of an existing TypeObject.
|
samux |
0:0cf0e27feaad
|
212
|
*
|
samux |
0:0cf0e27feaad
|
213
|
*
|
samux |
0:0cf0e27feaad
|
214
|
* @param str identifier of the sub MbedJSONValue
|
samux |
0:0cf0e27feaad
|
215
|
* @return a reference on the MbedJSONValue created or retrieved
|
samux |
0:0cf0e27feaad
|
216
|
*/
|
samux |
0:0cf0e27feaad
|
217
|
MbedJSONValue& operator[](std::string str);
|
samux |
0:0cf0e27feaad
|
218
|
|
samux |
0:0cf0e27feaad
|
219
|
/**
|
samux |
0:0cf0e27feaad
|
220
|
* Retrieve the value of an MbedJSONValue object.
|
samux |
0:0cf0e27feaad
|
221
|
*
|
samux |
0:0cf0e27feaad
|
222
|
* Let's suppose that we have an MbedJSONValue of type TypeString.
|
samux |
0:0cf0e27feaad
|
223
|
* To retrieve this string, you have to do:
|
samux |
0:0cf0e27feaad
|
224
|
* my_obj.get<std::string>();
|
samux |
0:0cf0e27feaad
|
225
|
*
|
samux |
0:0cf0e27feaad
|
226
|
* @return A contant reference on the value of the object
|
samux |
0:0cf0e27feaad
|
227
|
*/
|
samux |
0:0cf0e27feaad
|
228
|
template <typename T> const T& get() const;
|
samux |
0:0cf0e27feaad
|
229
|
|
samux |
0:0cf0e27feaad
|
230
|
/**
|
samux |
0:0cf0e27feaad
|
231
|
* Retrieve the value of an MbedJSONValue object.
|
samux |
0:0cf0e27feaad
|
232
|
*
|
samux |
0:0cf0e27feaad
|
233
|
* Let's suppose that we have an MbedJSONValue of type TypeInt.
|
samux |
0:0cf0e27feaad
|
234
|
* To retrieve this integer, you have to do:
|
samux |
0:0cf0e27feaad
|
235
|
* my_obj.get<int>();
|
samux |
0:0cf0e27feaad
|
236
|
*
|
samux |
0:0cf0e27feaad
|
237
|
* @return A reference on the value of the object
|
samux |
0:0cf0e27feaad
|
238
|
*/
|
samux |
0:0cf0e27feaad
|
239
|
template <typename T> T& get();
|
samux |
0:0cf0e27feaad
|
240
|
|
samux |
0:0cf0e27feaad
|
241
|
|
samux |
0:0cf0e27feaad
|
242
|
/**
|
samux |
0:0cf0e27feaad
|
243
|
* Return the type of the MbedJSONValue object
|
samux |
0:0cf0e27feaad
|
244
|
*
|
samux |
0:0cf0e27feaad
|
245
|
* @return type of the MbedJSONValue object
|
samux |
0:0cf0e27feaad
|
246
|
*/
|
samux |
0:0cf0e27feaad
|
247
|
Type const &getType() const {
|
samux |
0:0cf0e27feaad
|
248
|
return _type;
|
samux |
0:0cf0e27feaad
|
249
|
}
|
samux |
0:0cf0e27feaad
|
250
|
|
samux |
0:0cf0e27feaad
|
251
|
/**
|
samux |
0:0cf0e27feaad
|
252
|
* Return the size of an MbedJSONValue object (works for TypeString, TypeArray or TypeObject)
|
samux |
0:0cf0e27feaad
|
253
|
*
|
samux |
0:0cf0e27feaad
|
254
|
* @return size
|
samux |
0:0cf0e27feaad
|
255
|
*/
|
samux |
0:0cf0e27feaad
|
256
|
int size() const;
|
samux |
0:0cf0e27feaad
|
257
|
|
samux |
0:0cf0e27feaad
|
258
|
/**
|
samux |
0:0cf0e27feaad
|
259
|
* Check for the existence in a TypeObject object of member identified by name
|
samux |
0:0cf0e27feaad
|
260
|
*
|
samux |
0:0cf0e27feaad
|
261
|
* @param name Identifier
|
samux |
0:0cf0e27feaad
|
262
|
* @return true if the object is of type TypeObject AND contains a member named "name", false otherwise
|
samux |
0:0cf0e27feaad
|
263
|
*/
|
samux |
0:0cf0e27feaad
|
264
|
bool hasMember(char * name);
|
samux |
0:0cf0e27feaad
|
265
|
|
samux |
0:0cf0e27feaad
|
266
|
/**
|
samux |
0:0cf0e27feaad
|
267
|
* Convert an MbedJSONValue in a JSON frame
|
samux |
0:0cf0e27feaad
|
268
|
*
|
samux |
0:0cf0e27feaad
|
269
|
* @return JSON string
|
samux |
0:0cf0e27feaad
|
270
|
*/
|
samux |
0:0cf0e27feaad
|
271
|
std::string serialize();
|
samux |
0:0cf0e27feaad
|
272
|
|
samux |
0:0cf0e27feaad
|
273
|
protected:
|
samux |
0:0cf0e27feaad
|
274
|
|
samux |
0:0cf0e27feaad
|
275
|
// object type
|
samux |
0:0cf0e27feaad
|
276
|
Type _type;
|
samux |
0:0cf0e27feaad
|
277
|
|
samux |
0:0cf0e27feaad
|
278
|
//indexes of TypeObject and TypeArray
|
samux |
0:0cf0e27feaad
|
279
|
int index_array;
|
samux |
0:0cf0e27feaad
|
280
|
int index_token;
|
samux |
0:0cf0e27feaad
|
281
|
|
samux |
0:0cf0e27feaad
|
282
|
//an object can contain NB_TOKEN tokens. Each token have a name
|
samux |
0:0cf0e27feaad
|
283
|
MbedJSONValue * token[NB_TOKEN];
|
samux |
0:0cf0e27feaad
|
284
|
std::string * token_name[NB_TOKEN];
|
samux |
0:0cf0e27feaad
|
285
|
|
samux |
0:0cf0e27feaad
|
286
|
//an object can contain an array of NB_TOKEN elements
|
samux |
0:0cf0e27feaad
|
287
|
MbedJSONValue * array[NB_TOKEN];
|
samux |
0:0cf0e27feaad
|
288
|
|
samux |
0:0cf0e27feaad
|
289
|
// Clean up
|
samux |
0:0cf0e27feaad
|
290
|
void clean();
|
samux |
0:0cf0e27feaad
|
291
|
|
samux |
0:0cf0e27feaad
|
292
|
union {
|
samux |
0:0cf0e27feaad
|
293
|
bool asBool;
|
samux |
0:0cf0e27feaad
|
294
|
int asInt;
|
samux |
0:0cf0e27feaad
|
295
|
double asDouble;
|
samux |
0:0cf0e27feaad
|
296
|
std::string* asString;
|
samux |
0:0cf0e27feaad
|
297
|
} _value;
|
samux |
0:0cf0e27feaad
|
298
|
|
samux |
0:0cf0e27feaad
|
299
|
|
samux |
0:0cf0e27feaad
|
300
|
MbedJSONValue& operator[](int i) const { return *(array[i]); }
|
samux |
0:0cf0e27feaad
|
301
|
MbedJSONValue& operator[](std::string k) const;
|
samux |
0:0cf0e27feaad
|
302
|
|
samux |
0:0cf0e27feaad
|
303
|
std::string to_str();
|
samux |
0:0cf0e27feaad
|
304
|
void serialize(std::back_insert_iterator<std::string> os);
|
samux |
0:0cf0e27feaad
|
305
|
|
samux |
0:0cf0e27feaad
|
306
|
};
|
samux |
0:0cf0e27feaad
|
307
|
|
samux |
0:0cf0e27feaad
|
308
|
|
samux |
0:0cf0e27feaad
|
309
|
#define GET(ctype, var) \
|
samux |
0:0cf0e27feaad
|
310
|
template <> inline const ctype& MbedJSONValue::get<ctype>() const { \
|
samux |
0:0cf0e27feaad
|
311
|
return var; \
|
samux |
0:0cf0e27feaad
|
312
|
} \
|
samux |
0:0cf0e27feaad
|
313
|
template <> inline ctype& MbedJSONValue::get<ctype>() { \
|
samux |
0:0cf0e27feaad
|
314
|
return var; \
|
samux |
0:0cf0e27feaad
|
315
|
}
|
samux |
0:0cf0e27feaad
|
316
|
GET(bool, _value.asBool)
|
samux |
0:0cf0e27feaad
|
317
|
GET(double, _value.asDouble)
|
samux |
0:0cf0e27feaad
|
318
|
GET(int, _value.asInt)
|
samux |
0:0cf0e27feaad
|
319
|
GET(std::string, *_value.asString)
|
samux |
0:0cf0e27feaad
|
320
|
#undef GET
|
samux |
0:0cf0e27feaad
|
321
|
|
samux |
0:0cf0e27feaad
|
322
|
|
samux |
0:0cf0e27feaad
|
323
|
//Input class for JSON parser
|
samux |
0:0cf0e27feaad
|
324
|
class input {
|
samux |
0:0cf0e27feaad
|
325
|
protected:
|
samux |
0:0cf0e27feaad
|
326
|
const char * cur_;
|
samux |
0:0cf0e27feaad
|
327
|
const char * end_;
|
samux |
0:0cf0e27feaad
|
328
|
int last_ch_;
|
samux |
0:0cf0e27feaad
|
329
|
bool ungot_;
|
samux |
0:0cf0e27feaad
|
330
|
int line_;
|
samux |
0:0cf0e27feaad
|
331
|
public:
|
samux |
0:0cf0e27feaad
|
332
|
input(const char * first, const char * last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {};
|
samux |
0:0cf0e27feaad
|
333
|
|
samux |
0:0cf0e27feaad
|
334
|
int getc() {
|
samux |
0:0cf0e27feaad
|
335
|
if (ungot_) {
|
samux |
0:0cf0e27feaad
|
336
|
ungot_ = false;
|
samux |
0:0cf0e27feaad
|
337
|
return last_ch_;
|
samux |
0:0cf0e27feaad
|
338
|
}
|
samux |
0:0cf0e27feaad
|
339
|
if (cur_ == end_) {
|
samux |
0:0cf0e27feaad
|
340
|
last_ch_ = -1;
|
samux |
0:0cf0e27feaad
|
341
|
return -1;
|
samux |
0:0cf0e27feaad
|
342
|
}
|
samux |
0:0cf0e27feaad
|
343
|
if (last_ch_ == '\n') {
|
samux |
0:0cf0e27feaad
|
344
|
line_++;
|
samux |
0:0cf0e27feaad
|
345
|
}
|
samux |
0:0cf0e27feaad
|
346
|
last_ch_ = *cur_++ & 0xff;
|
samux |
0:0cf0e27feaad
|
347
|
return last_ch_;
|
samux |
0:0cf0e27feaad
|
348
|
}
|
samux |
0:0cf0e27feaad
|
349
|
|
samux |
0:0cf0e27feaad
|
350
|
void ungetc() {
|
samux |
0:0cf0e27feaad
|
351
|
if (last_ch_ != -1) {
|
samux |
0:0cf0e27feaad
|
352
|
ungot_ = true;
|
samux |
0:0cf0e27feaad
|
353
|
}
|
samux |
0:0cf0e27feaad
|
354
|
}
|
samux |
0:0cf0e27feaad
|
355
|
|
samux |
0:0cf0e27feaad
|
356
|
const char * cur() const {
|
samux |
0:0cf0e27feaad
|
357
|
return cur_;
|
samux |
0:0cf0e27feaad
|
358
|
}
|
samux |
0:0cf0e27feaad
|
359
|
int line() const {
|
samux |
0:0cf0e27feaad
|
360
|
return line_;
|
samux |
0:0cf0e27feaad
|
361
|
}
|
samux |
0:0cf0e27feaad
|
362
|
void skip_ws() {
|
samux |
0:0cf0e27feaad
|
363
|
while (1) {
|
samux |
0:0cf0e27feaad
|
364
|
int ch = getc();
|
samux |
0:0cf0e27feaad
|
365
|
if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
|
samux |
0:0cf0e27feaad
|
366
|
ungetc();
|
samux |
0:0cf0e27feaad
|
367
|
break;
|
samux |
0:0cf0e27feaad
|
368
|
}
|
samux |
0:0cf0e27feaad
|
369
|
}
|
samux |
0:0cf0e27feaad
|
370
|
}
|
samux |
0:0cf0e27feaad
|
371
|
int expect(int expect) {
|
samux |
0:0cf0e27feaad
|
372
|
skip_ws();
|
samux |
0:0cf0e27feaad
|
373
|
if (getc() != expect) {
|
samux |
0:0cf0e27feaad
|
374
|
ungetc();
|
samux |
0:0cf0e27feaad
|
375
|
return false;
|
samux |
0:0cf0e27feaad
|
376
|
}
|
samux |
0:0cf0e27feaad
|
377
|
return true;
|
samux |
0:0cf0e27feaad
|
378
|
}
|
samux |
0:0cf0e27feaad
|
379
|
bool match(const std::string& pattern) {
|
samux |
0:0cf0e27feaad
|
380
|
for (std::string::const_iterator pi(pattern.begin());
|
samux |
0:0cf0e27feaad
|
381
|
pi != pattern.end();
|
samux |
0:0cf0e27feaad
|
382
|
++pi) {
|
samux |
0:0cf0e27feaad
|
383
|
if (getc() != *pi) {
|
samux |
0:0cf0e27feaad
|
384
|
ungetc();
|
samux |
0:0cf0e27feaad
|
385
|
return false;
|
samux |
0:0cf0e27feaad
|
386
|
}
|
samux |
0:0cf0e27feaad
|
387
|
}
|
samux |
0:0cf0e27feaad
|
388
|
return true;
|
samux |
0:0cf0e27feaad
|
389
|
}
|
samux |
0:0cf0e27feaad
|
390
|
};
|
samux |
0:0cf0e27feaad
|
391
|
|
samux |
0:0cf0e27feaad
|
392
|
|
samux |
0:0cf0e27feaad
|
393
|
|
samux |
0:0cf0e27feaad
|
394
|
inline const char * parse(MbedJSONValue& out, const char * first, const char * last, std::string* err);
|
samux |
0:0cf0e27feaad
|
395
|
|
samux |
0:0cf0e27feaad
|
396
|
/**
|
samux |
0:0cf0e27feaad
|
397
|
* JSON string parser and creation of an MbedJSONValue
|
samux |
0:0cf0e27feaad
|
398
|
*
|
samux |
0:0cf0e27feaad
|
399
|
* @param out reference of an MbedJSONValue which will be filled according to the JSON string
|
samux |
0:0cf0e27feaad
|
400
|
* @param str JSON string
|
samux |
0:0cf0e27feaad
|
401
|
* @return A non empty string if there is a parsing error
|
samux |
0:0cf0e27feaad
|
402
|
*
|
samux |
0:0cf0e27feaad
|
403
|
*/
|
samux |
0:0cf0e27feaad
|
404
|
|
samux |
0:0cf0e27feaad
|
405
|
inline std::string parse(MbedJSONValue& out, const char * str);
|
samux |
0:0cf0e27feaad
|
406
|
inline bool _parse(MbedJSONValue& out, input& in);
|
samux |
0:0cf0e27feaad
|
407
|
inline bool _parse_number(MbedJSONValue& out, input& in);
|
samux |
0:0cf0e27feaad
|
408
|
inline bool _parse_string(MbedJSONValue& out, input& in);
|
samux |
0:0cf0e27feaad
|
409
|
inline bool _parse_array(MbedJSONValue& out, input& in);
|
samux |
0:0cf0e27feaad
|
410
|
inline bool _parse_object(MbedJSONValue& out, input& in);
|
samux |
0:0cf0e27feaad
|
411
|
|
samux |
0:0cf0e27feaad
|
412
|
|
samux |
0:0cf0e27feaad
|
413
|
inline bool _parse_string(MbedJSONValue& out, input& in) {
|
samux |
0:0cf0e27feaad
|
414
|
#ifdef DEBUG
|
samux |
0:0cf0e27feaad
|
415
|
printf("string detected\r\n");
|
samux |
0:0cf0e27feaad
|
416
|
#endif
|
samux |
0:0cf0e27feaad
|
417
|
out = MbedJSONValue(std::string(""));
|
samux |
0:0cf0e27feaad
|
418
|
std::string& s = out.get<std::string>();
|
samux |
0:0cf0e27feaad
|
419
|
while (1) {
|
samux |
0:0cf0e27feaad
|
420
|
int ch = in.getc();
|
samux |
0:0cf0e27feaad
|
421
|
if (ch < ' ') {
|
samux |
0:0cf0e27feaad
|
422
|
in.ungetc();
|
samux |
0:0cf0e27feaad
|
423
|
return false;
|
samux |
0:0cf0e27feaad
|
424
|
} else if (ch == '"') {
|
samux |
0:0cf0e27feaad
|
425
|
return true;
|
samux |
0:0cf0e27feaad
|
426
|
} else if (ch == '\\') {
|
samux |
0:0cf0e27feaad
|
427
|
if ((ch = in.getc()) == -1) {
|
samux |
0:0cf0e27feaad
|
428
|
return false;
|
samux |
0:0cf0e27feaad
|
429
|
}
|
samux |
0:0cf0e27feaad
|
430
|
switch (ch) {
|
samux |
0:0cf0e27feaad
|
431
|
#define MAP(sym, val) case sym: s.push_back(val); break
|
samux |
0:0cf0e27feaad
|
432
|
MAP('"', '\"');
|
samux |
0:0cf0e27feaad
|
433
|
MAP('\\', '\\');
|
samux |
0:0cf0e27feaad
|
434
|
MAP('/', '/');
|
samux |
0:0cf0e27feaad
|
435
|
MAP('b', '\b');
|
samux |
0:0cf0e27feaad
|
436
|
MAP('f', '\f');
|
samux |
0:0cf0e27feaad
|
437
|
MAP('n', '\n');
|
samux |
0:0cf0e27feaad
|
438
|
MAP('r', '\r');
|
samux |
0:0cf0e27feaad
|
439
|
MAP('t', '\t');
|
samux |
0:0cf0e27feaad
|
440
|
#undef MAP
|
samux |
0:0cf0e27feaad
|
441
|
default:
|
samux |
0:0cf0e27feaad
|
442
|
return false;
|
samux |
0:0cf0e27feaad
|
443
|
}
|
samux |
0:0cf0e27feaad
|
444
|
} else {
|
samux |
0:0cf0e27feaad
|
445
|
s.push_back(ch);
|
samux |
0:0cf0e27feaad
|
446
|
}
|
samux |
0:0cf0e27feaad
|
447
|
}
|
samux |
0:0cf0e27feaad
|
448
|
}
|
samux |
0:0cf0e27feaad
|
449
|
|
samux |
0:0cf0e27feaad
|
450
|
inline bool _parse_array(MbedJSONValue& out, input& in) {
|
samux |
0:0cf0e27feaad
|
451
|
#ifdef DEBUG
|
samux |
0:0cf0e27feaad
|
452
|
printf("array detected\r\n");
|
samux |
0:0cf0e27feaad
|
453
|
#endif
|
samux |
0:0cf0e27feaad
|
454
|
int i = 0;
|
samux |
0:0cf0e27feaad
|
455
|
if (in.expect(']')) {
|
samux |
0:0cf0e27feaad
|
456
|
return true;
|
samux |
0:0cf0e27feaad
|
457
|
}
|
samux |
0:0cf0e27feaad
|
458
|
do {
|
samux |
0:0cf0e27feaad
|
459
|
if (! _parse(out[i], in)) {
|
samux |
0:0cf0e27feaad
|
460
|
return false;
|
samux |
0:0cf0e27feaad
|
461
|
}
|
samux |
0:0cf0e27feaad
|
462
|
i++;
|
samux |
0:0cf0e27feaad
|
463
|
} while (in.expect(','));
|
samux |
0:0cf0e27feaad
|
464
|
return in.expect(']');
|
samux |
0:0cf0e27feaad
|
465
|
}
|
samux |
0:0cf0e27feaad
|
466
|
|
samux |
0:0cf0e27feaad
|
467
|
inline bool _parse_object(MbedJSONValue& out, input& in) {
|
samux |
0:0cf0e27feaad
|
468
|
#ifdef DEBUG
|
samux |
0:0cf0e27feaad
|
469
|
printf("object detected\r\n");
|
samux |
0:0cf0e27feaad
|
470
|
#endif
|
samux |
0:0cf0e27feaad
|
471
|
if (in.expect('}')) {
|
samux |
0:0cf0e27feaad
|
472
|
return true;
|
samux |
0:0cf0e27feaad
|
473
|
}
|
samux |
0:0cf0e27feaad
|
474
|
do {
|
samux |
0:0cf0e27feaad
|
475
|
MbedJSONValue key, val;
|
samux |
0:0cf0e27feaad
|
476
|
if (in.expect('"') && _parse_string(key, in) && in.expect(':') && _parse(val, in)) {
|
samux |
0:0cf0e27feaad
|
477
|
out[key.get<std::string>().c_str()] = val;
|
samux |
0:0cf0e27feaad
|
478
|
#ifdef DEBUG
|
samux |
0:0cf0e27feaad
|
479
|
printf("key: %s \r\n", key.get<std::string>().c_str());
|
samux |
0:0cf0e27feaad
|
480
|
#endif
|
samux |
0:0cf0e27feaad
|
481
|
} else {
|
samux |
0:0cf0e27feaad
|
482
|
return false;
|
samux |
0:0cf0e27feaad
|
483
|
}
|
samux |
0:0cf0e27feaad
|
484
|
} while (in.expect(','));
|
samux |
0:0cf0e27feaad
|
485
|
return in.expect('}');
|
samux |
0:0cf0e27feaad
|
486
|
}
|
samux |
0:0cf0e27feaad
|
487
|
|
samux |
0:0cf0e27feaad
|
488
|
inline bool _parse_number(MbedJSONValue& out, input& in) {
|
samux |
0:0cf0e27feaad
|
489
|
#ifdef DEBUG
|
samux |
0:0cf0e27feaad
|
490
|
printf("number detected\r\n");
|
samux |
0:0cf0e27feaad
|
491
|
#endif
|
samux |
0:0cf0e27feaad
|
492
|
std::string num_str;
|
samux |
0:0cf0e27feaad
|
493
|
while (1) {
|
samux |
0:0cf0e27feaad
|
494
|
int ch = in.getc();
|
samux |
0:0cf0e27feaad
|
495
|
if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == '.'
|
samux |
0:0cf0e27feaad
|
496
|
|| ch == 'e' || ch == 'E') {
|
samux |
0:0cf0e27feaad
|
497
|
num_str.push_back(ch);
|
samux |
0:0cf0e27feaad
|
498
|
} else {
|
samux |
0:0cf0e27feaad
|
499
|
in.ungetc();
|
samux |
0:0cf0e27feaad
|
500
|
break;
|
samux |
0:0cf0e27feaad
|
501
|
}
|
samux |
0:0cf0e27feaad
|
502
|
}
|
samux |
0:0cf0e27feaad
|
503
|
char* endp;
|
samux |
0:0cf0e27feaad
|
504
|
if (strchr(num_str.c_str(), '.') != NULL || strchr(num_str.c_str(), 'e') != NULL || strchr(num_str.c_str(), '+') != NULL)
|
samux |
0:0cf0e27feaad
|
505
|
out = MbedJSONValue(strtod(num_str.c_str(), &endp));
|
samux |
0:0cf0e27feaad
|
506
|
else
|
samux |
0:0cf0e27feaad
|
507
|
out = MbedJSONValue((int)strtod(num_str.c_str(), &endp));
|
samux |
0:0cf0e27feaad
|
508
|
return endp == num_str.c_str() + num_str.size();
|
samux |
0:0cf0e27feaad
|
509
|
}
|
samux |
0:0cf0e27feaad
|
510
|
|
samux |
0:0cf0e27feaad
|
511
|
inline bool _parse(MbedJSONValue& out, input& in) {
|
samux |
0:0cf0e27feaad
|
512
|
in.skip_ws();
|
samux |
0:0cf0e27feaad
|
513
|
int ch = in.getc();
|
samux |
0:0cf0e27feaad
|
514
|
switch (ch) {
|
samux |
0:0cf0e27feaad
|
515
|
#define IS(ch, text, val) case ch: \
|
samux |
0:0cf0e27feaad
|
516
|
if (in.match(text)) { \
|
samux |
0:0cf0e27feaad
|
517
|
out = val; \
|
samux |
0:0cf0e27feaad
|
518
|
return true; \
|
samux |
0:0cf0e27feaad
|
519
|
} else { \
|
samux |
0:0cf0e27feaad
|
520
|
return false; \
|
samux |
0:0cf0e27feaad
|
521
|
}
|
samux |
0:0cf0e27feaad
|
522
|
IS('n', "ull", MbedJSONValue());
|
samux |
0:0cf0e27feaad
|
523
|
IS('f', "alse", MbedJSONValue(false));
|
samux |
0:0cf0e27feaad
|
524
|
IS('t', "rue", MbedJSONValue(true));
|
samux |
0:0cf0e27feaad
|
525
|
#undef IS
|
samux |
0:0cf0e27feaad
|
526
|
case '"':
|
samux |
0:0cf0e27feaad
|
527
|
return _parse_string(out, in);
|
samux |
0:0cf0e27feaad
|
528
|
case '[':
|
samux |
0:0cf0e27feaad
|
529
|
return _parse_array(out, in);
|
samux |
0:0cf0e27feaad
|
530
|
case '{':
|
samux |
0:0cf0e27feaad
|
531
|
return _parse_object(out, in);
|
samux |
0:0cf0e27feaad
|
532
|
default:
|
samux |
0:0cf0e27feaad
|
533
|
if (('0' <= ch && ch <= '9') || ch == '-') {
|
samux |
0:0cf0e27feaad
|
534
|
in.ungetc();
|
samux |
0:0cf0e27feaad
|
535
|
return _parse_number(out, in);
|
samux |
0:0cf0e27feaad
|
536
|
}
|
samux |
0:0cf0e27feaad
|
537
|
break;
|
samux |
0:0cf0e27feaad
|
538
|
}
|
samux |
0:0cf0e27feaad
|
539
|
in.ungetc();
|
samux |
0:0cf0e27feaad
|
540
|
return false;
|
samux |
0:0cf0e27feaad
|
541
|
}
|
samux |
0:0cf0e27feaad
|
542
|
|
samux |
0:0cf0e27feaad
|
543
|
inline std::string parse(MbedJSONValue& out, const char * pos) {
|
samux |
0:0cf0e27feaad
|
544
|
const char * last = pos + strlen(pos);
|
samux |
0:0cf0e27feaad
|
545
|
std::string err;
|
samux |
0:0cf0e27feaad
|
546
|
pos = parse(out, pos, last, &err);
|
samux |
0:0cf0e27feaad
|
547
|
return err;
|
samux |
0:0cf0e27feaad
|
548
|
}
|
samux |
0:0cf0e27feaad
|
549
|
|
samux |
0:0cf0e27feaad
|
550
|
inline const char * parse(MbedJSONValue& out, const char * first, const char * last, std::string* err) {
|
samux |
0:0cf0e27feaad
|
551
|
input in = input(first, last);
|
samux |
0:0cf0e27feaad
|
552
|
if (! _parse(out, in) && err != NULL) {
|
samux |
0:0cf0e27feaad
|
553
|
char buf[64];
|
samux |
0:0cf0e27feaad
|
554
|
sprintf(buf, "syntax error at line %d near: ", in.line());
|
samux |
0:0cf0e27feaad
|
555
|
*err = buf;
|
samux |
0:0cf0e27feaad
|
556
|
while (1) {
|
samux |
0:0cf0e27feaad
|
557
|
int ch = in.getc();
|
samux |
0:0cf0e27feaad
|
558
|
if (ch == -1 || ch == '\n') {
|
samux |
0:0cf0e27feaad
|
559
|
break;
|
samux |
0:0cf0e27feaad
|
560
|
} else if (ch >= ' ') {
|
samux |
0:0cf0e27feaad
|
561
|
err->push_back(ch);
|
samux |
0:0cf0e27feaad
|
562
|
}
|
samux |
0:0cf0e27feaad
|
563
|
}
|
samux |
0:0cf0e27feaad
|
564
|
}
|
samux |
0:0cf0e27feaad
|
565
|
return in.cur();
|
samux |
0:0cf0e27feaad
|
566
|
}
|
samux |
0:0cf0e27feaad
|
567
|
|
samux |
0:0cf0e27feaad
|
568
|
#endif // _MbedMbedJSONValue_H_
|