Revision 2016.05.03

Dependents:   WIZwiki-REST_mc

Fork of MbedJSONValue by Midnight Cow

Committer:
joon874
Date:
Tue May 03 02:14:45 2016 +0000
Revision:
7:174bc7a49aa2
Parent:
6:f8bec9cada34
Child:
8:2fe7e09ac67f
Revision 2016.05.03

Who changed what in which revision?

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