Minimalist JSON parser and serializer (inspired by picojson). Used by MbedJSONRpc. (Original by Samuel Mokrani)

Dependents:   City_Game_JSON City_Game_JSON

Fork of MbedJSONValue by Samuel Mokrani

Committer:
dwini
Date:
Thu Nov 24 20:25:42 2016 +0000
Revision:
6:c21b9ffd9628
Parent:
4:10a99cdf7846
Child:
7:a2fabe322eff
Replace stdio.h and stdlib.h with cstdio and cstdlib to fix problem of library not compiling with offline toolchain.

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