MbedJSONValue Fork and Delete Array
Fork of MbedJSONValue by
MbedJSONValue.h@0:0cf0e27feaad, 2011-09-22 (annotated)
- Committer:
- samux
- Date:
- Thu Sep 22 10:35:59 2011 +0000
- Revision:
- 0:0cf0e27feaad
- Child:
- 1:effaca3e3f84
Who changed what in which revision?
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_ |