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