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
00001 /** 00002 * @author Samuel Mokrani 00003 * 00004 * @section LICENSE 00005 * 00006 * Copyright (c) 2011 mbed 00007 * 00008 * Permission is hereby granted, free of charge, to any person obtaining a copy 00009 * of this software and associated documentation files (the "Software"), to deal 00010 * in the Software without restriction, including without limitation the rights 00011 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00012 * copies of the Software, and to permit persons to whom the Software is 00013 * furnished to do so, subject to the following conditions: 00014 * 00015 * The above copyright notice and this permission notice shall be included in 00016 * all copies or substantial portions of the Software. 00017 * 00018 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00019 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00020 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00021 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00022 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00023 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00024 * THE SOFTWARE. 00025 * 00026 * @section DESCRIPTION 00027 * Types Abstraction. Minimalist JSON serializer and parser (inspired by picojson). Is used by MbedJSONRpc. 00028 * 00029 */ 00030 00031 #ifndef _Mbed_RPC_VALUE_H_ 00032 #define _Mbed_RPC_VALUE_H_ 00033 00034 #define NB_TOKEN 20 00035 /*!< Number maximum of MbedJSONValue in an array or an object */ 00036 00037 #include <string> 00038 #include <stdio.h> 00039 #include <stdlib.h> 00040 #include <string.h> 00041 00042 /** MbedJSONValue class 00043 * 00044 * Example: 00045 * - creation of an MbedJSONValue of type TypeObject containing two others MbedJSONValue: 00046 * -one array of one string and one integer identified by "my_array" 00047 * -a boolean identified by "my_boolean" 00048 * - serialization in JSON format of this object 00049 * @code 00050 * #include "mbed.h" 00051 * #include "MbedJSONValue.h" 00052 * #include <string> 00053 * 00054 * int main() { 00055 * 00056 * MbedJSONValue demo; 00057 * std::string s; 00058 * 00059 * //fill the object 00060 * demo["my_array"][0] = "demo_string"; 00061 * demo["my_array"][1] = 10; 00062 * demo["my_boolean"] = false; 00063 * 00064 * //serialize it into a JSON string 00065 * s = demo.serialize(); 00066 * printf("json: %s\r\n", s.c_str()); 00067 * } 00068 * 00069 * @endcode 00070 * 00071 * Example: 00072 * - creation of an MbedJSONValue from a JSON string 00073 * - extraction of different values from this existing MbedJSONValue 00074 * @code 00075 * #include "mbed.h" 00076 * #include "MbedJSONValue.h" 00077 * #include <string> 00078 * 00079 * int main() { 00080 * MbedJSONValue demo; 00081 * 00082 * const char * json = "{\"my_array\": [\"demo_string\", 10], \"my_boolean\": true}"; 00083 * 00084 * //parse the previous string and fill the object demo 00085 * parse(demo, json); 00086 * 00087 * std::string my_str; 00088 * int my_int; 00089 * bool my_bool; 00090 * 00091 * my_str = demo["my_array"][0].get<std::string>(); 00092 * my_int = demo["my_array"][1].get<int>(); 00093 * my_bool = demo["my_boolean"].get<bool>(); 00094 * 00095 * printf("my_str: %s\r\n", my_str.c_str()); 00096 * printf("my_int: %d\r\n", my_int); 00097 * printf("my_bool: %s\r\n", my_bool ? "true" : "false"); 00098 * } 00099 * @endcode 00100 */ 00101 class MbedJSONValue { 00102 public: 00103 00104 /** 00105 * \enum Type 00106 * \brief All types which can be used 00107 */ 00108 enum Type { 00109 TypeNull , /*!< Null type */ 00110 TypeBoolean , /*!< Boolean */ 00111 TypeInt , /*!< Integer */ 00112 TypeDouble , /*!< Double */ 00113 TypeString , /*!< String */ 00114 TypeArray , /*!< Array (contains MbedJSONValue) */ 00115 TypeObject /*!< Object (contains MbedJSONValue identified by a name)*/ 00116 }; 00117 00118 /** 00119 * MbedJSONValue constructor of type TypeNull 00120 */ 00121 MbedJSONValue() : _type(TypeNull ), index_array(0), index_token(0) {} 00122 00123 /** 00124 * MbedJSONValue constructor of type TypeBoolean 00125 * 00126 * @param value the object created will be initialized with this boolean 00127 */ 00128 MbedJSONValue(bool value) : _type(TypeBoolean ), index_array(0), index_token(0) { 00129 _value.asBool = value; 00130 } 00131 00132 /** 00133 * MbedJSONValue constructor of type TypeInt 00134 * 00135 * @param value the object created will be initialized with this integer 00136 */ 00137 MbedJSONValue(int value) : _type(TypeInt ), index_array(0), index_token(0) { 00138 _value.asInt = value; 00139 } 00140 00141 /** 00142 * MbedJSONValue constructor of type TypeDouble 00143 * 00144 * @param value the object created will be initialized with this double 00145 */ 00146 MbedJSONValue(double value) : _type(TypeDouble ), index_array(0), index_token(0) { 00147 _value.asDouble = value; 00148 } 00149 00150 /** 00151 * MbedJSONValue constructor of type TypeString 00152 * 00153 * @param value the object created will be initialized with this string 00154 */ 00155 MbedJSONValue(std::string const& value) : _type(TypeString ), index_array(0), index_token(0) { 00156 _value.asString = new std::string(value); 00157 } 00158 00159 /** 00160 * MbedJSONValue constructor of type TypeString 00161 * 00162 * @param value the object created will be initialized with this string 00163 */ 00164 MbedJSONValue(const char* value) : _type(TypeString ), index_array(0), index_token(0) { 00165 _value.asString = new std::string(value); 00166 } 00167 00168 /** 00169 * Copy constructor 00170 * 00171 * @param rhs object which will be copied 00172 */ 00173 MbedJSONValue(MbedJSONValue const& rhs) : _type(TypeNull ) { *this = rhs; } 00174 00175 /** 00176 * Destructor 00177 */ 00178 ~MbedJSONValue() { clean(); } 00179 00180 /** 00181 * = Operator overloading for an MbedJSONValue from an MbedJSONValue 00182 * 00183 * @param rhs object 00184 * @return a reference on the MbedJSONValue affected 00185 */ 00186 MbedJSONValue& operator=(MbedJSONValue const & rhs); 00187 00188 /** 00189 * = Operator overloading for an MbedJSONValue from an int 00190 * 00191 * @param rhs integer 00192 * @return a reference on the MbedJSONValue affected 00193 */ 00194 MbedJSONValue& operator=(int const& rhs) { return operator=(MbedJSONValue(rhs)); } 00195 00196 /** 00197 * = Operator overloading for an MbedJSONValue from a boolean 00198 * 00199 * @param rhs boolean 00200 * @return a reference on the MbedJSONValue affected 00201 */ 00202 MbedJSONValue& operator=(bool const& rhs) { return operator=(MbedJSONValue(rhs)); } 00203 00204 /** 00205 * = Operator overloading for an MbedJSONValue from a double 00206 * 00207 * @param rhs double 00208 * @return a reference on the MbedJSONValue affected 00209 */ 00210 MbedJSONValue& operator=(double const& rhs) { return operator=(MbedJSONValue(rhs)); } 00211 00212 /** 00213 * = Operator overloading for an MbedJSONValue from a string 00214 * 00215 * @param rhs string 00216 * @return a reference on the MbedJSONValue affected 00217 */ 00218 MbedJSONValue& operator=(const char* rhs) { return operator=(MbedJSONValue(std::string(rhs))); } 00219 00220 00221 /** 00222 * [] Operator overloading for an MbedJSONValue. 00223 * Each TypeObject object can contain an array of NB_TOKEN MbedJSONValue. 00224 * This operator is useful to create an array or to retrieve an MbedJSONValue of an existing array. 00225 * 00226 * @param i index of the array 00227 * @return a reference on the MbedJSONValue created or retrieved 00228 */ 00229 MbedJSONValue& operator[](int i); 00230 00231 /** 00232 * [] Operator overloading for an MbedJSONValue. 00233 * Each TypeObject MbedJSONValue can contain NB_TOKEN MbedJSONValue IDENTIFIED BY A NAME 00234 * This operator is useful to create a TypeObject MbedJSONValue or to retrieve an MbedJSONValue of an existing TypeObject. 00235 * 00236 * 00237 * @param str identifier of the sub MbedJSONValue 00238 * @return a reference on the MbedJSONValue created or retrieved 00239 */ 00240 MbedJSONValue& operator[](std::string str); 00241 00242 /** 00243 * Retrieve the value of an MbedJSONValue object. 00244 * 00245 * Let's suppose that we have an MbedJSONValue of type TypeString. 00246 * To retrieve this string, you have to do: 00247 * my_obj.get<std::string>(); 00248 * 00249 * @return A contant reference on the value of the object 00250 */ 00251 template <typename T> const T& get() const; 00252 00253 /** 00254 * Retrieve the value of an MbedJSONValue object. 00255 * 00256 * Let's suppose that we have an MbedJSONValue of type TypeInt. 00257 * To retrieve this integer, you have to do: 00258 * my_obj.get<int>(); 00259 * 00260 * @return A reference on the value of the object 00261 */ 00262 template <typename T> T& get(); 00263 00264 00265 /** 00266 * Return the type of the MbedJSONValue object 00267 * 00268 * @return type of the MbedJSONValue object 00269 */ 00270 Type const &getType() const { 00271 return _type; 00272 } 00273 00274 /** 00275 * Return the size of an MbedJSONValue object (works for TypeString, TypeArray or TypeObject) 00276 * 00277 * @return size 00278 */ 00279 int size() const; 00280 00281 /** 00282 * Check for the existence in a TypeObject object of member identified by name 00283 * 00284 * @param name Identifier 00285 * @return true if the object is of type TypeObject AND contains a member named "name", false otherwise 00286 */ 00287 bool hasMember(char * name); 00288 00289 /** 00290 * Convert an MbedJSONValue in a JSON frame 00291 * 00292 * @return JSON string 00293 */ 00294 std::string serialize(); 00295 00296 protected: 00297 00298 // object type 00299 Type _type; 00300 00301 //indexes of TypeObject and TypeArray 00302 int index_array; 00303 int index_token; 00304 00305 //an object can contain NB_TOKEN tokens. Each token have a name 00306 MbedJSONValue * token[NB_TOKEN]; 00307 std::string * token_name[NB_TOKEN]; 00308 00309 //an object can contain an array of NB_TOKEN elements 00310 MbedJSONValue * array[NB_TOKEN]; 00311 00312 // Clean up 00313 void clean(); 00314 00315 union { 00316 bool asBool; 00317 int asInt; 00318 double asDouble; 00319 std::string* asString; 00320 } _value; 00321 00322 00323 MbedJSONValue& operator[](int i) const { return *(array[i]); } 00324 MbedJSONValue& operator[](std::string k) const; 00325 00326 std::string to_str(); 00327 void serialize(std::back_insert_iterator<std::string> os); 00328 00329 }; 00330 00331 00332 #define GET(ctype, var) \ 00333 template <> inline const ctype& MbedJSONValue::get<ctype>() const { \ 00334 return var; \ 00335 } \ 00336 template <> inline ctype& MbedJSONValue::get<ctype>() { \ 00337 return var; \ 00338 } 00339 GET(bool, _value.asBool) 00340 GET(double, _value.asDouble) 00341 GET(int, _value.asInt) 00342 GET(std::string, *_value.asString) 00343 #undef GET 00344 00345 00346 //Input class for JSON parser 00347 class input { 00348 protected: 00349 const char * cur_; 00350 const char * end_; 00351 int last_ch_; 00352 bool ungot_; 00353 int line_; 00354 public: 00355 input(const char * first, const char * last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {}; 00356 00357 int getc() { 00358 if (ungot_) { 00359 ungot_ = false; 00360 return last_ch_; 00361 } 00362 if (cur_ == end_) { 00363 last_ch_ = -1; 00364 return -1; 00365 } 00366 if (last_ch_ == '\n') { 00367 line_++; 00368 } 00369 last_ch_ = *cur_++ & 0xff; 00370 return last_ch_; 00371 } 00372 00373 void ungetc() { 00374 if (last_ch_ != -1) { 00375 ungot_ = true; 00376 } 00377 } 00378 00379 const char * cur() const { 00380 return cur_; 00381 } 00382 int line() const { 00383 return line_; 00384 } 00385 void skip_ws() { 00386 while (1) { 00387 int ch = getc(); 00388 if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) { 00389 ungetc(); 00390 break; 00391 } 00392 } 00393 } 00394 int expect(int expect) { 00395 skip_ws(); 00396 if (getc() != expect) { 00397 ungetc(); 00398 return false; 00399 } 00400 return true; 00401 } 00402 bool match(const std::string& pattern) { 00403 for (std::string::const_iterator pi(pattern.begin()); 00404 pi != pattern.end(); 00405 ++pi) { 00406 if (getc() != *pi) { 00407 ungetc(); 00408 return false; 00409 } 00410 } 00411 return true; 00412 } 00413 }; 00414 00415 00416 00417 inline const char * parse(MbedJSONValue& out, const char * first, const char * last, std::string* err); 00418 00419 /** 00420 * JSON string parser and creation of an MbedJSONValue 00421 * 00422 * @param out reference of an MbedJSONValue which will be filled according to the JSON string 00423 * @param str JSON string 00424 * @return A non empty string if there is a parsing error 00425 * 00426 */ 00427 00428 inline std::string parse(MbedJSONValue& out, const char * str); 00429 inline bool _parse(MbedJSONValue& out, input& in); 00430 inline bool _parse_number(MbedJSONValue& out, input& in); 00431 inline bool _parse_string(MbedJSONValue& out, input& in); 00432 inline bool _parse_array(MbedJSONValue& out, input& in); 00433 inline bool _parse_object(MbedJSONValue& out, input& in); 00434 00435 00436 inline bool _parse_string(MbedJSONValue& out, input& in) { 00437 #ifdef DEBUG 00438 printf("string detected\r\n"); 00439 #endif 00440 out = MbedJSONValue(std::string("")); 00441 std::string& s = out.get<std::string>(); 00442 while (1) { 00443 int ch = in.getc(); 00444 if (ch < ' ') { 00445 in.ungetc(); 00446 return false; 00447 } else if (ch == '"') { 00448 return true; 00449 } else if (ch == '\\') { 00450 if ((ch = in.getc()) == -1) { 00451 return false; 00452 } 00453 switch (ch) { 00454 #define MAP(sym, val) case sym: s.push_back(val); break 00455 MAP('"', '\"'); 00456 MAP('\\', '\\'); 00457 MAP('/', '/'); 00458 MAP('b', '\b'); 00459 MAP('f', '\f'); 00460 MAP('n', '\n'); 00461 MAP('r', '\r'); 00462 MAP('t', '\t'); 00463 #undef MAP 00464 default: 00465 return false; 00466 } 00467 } else { 00468 s.push_back(ch); 00469 } 00470 } 00471 } 00472 00473 inline bool _parse_array(MbedJSONValue& out, input& in) { 00474 #ifdef DEBUG 00475 printf("array detected\r\n"); 00476 #endif 00477 int i = 0; 00478 if (in.expect(']')) { 00479 return true; 00480 } 00481 do { 00482 if (! _parse(out[i], in)) { 00483 return false; 00484 } 00485 i++; 00486 } while (in.expect(',')); 00487 return in.expect(']'); 00488 } 00489 00490 inline bool _parse_object(MbedJSONValue& out, input& in) { 00491 #ifdef DEBUG 00492 printf("object detected\r\n"); 00493 #endif 00494 if (in.expect('}')) { 00495 return true; 00496 } 00497 do { 00498 MbedJSONValue key, val; 00499 if (in.expect('"') && _parse_string(key, in) && in.expect(':') && _parse(val, in)) { 00500 out[key.get<std::string>().c_str()] = val; 00501 #ifdef DEBUG 00502 printf("key: %s \r\n", key.get<std::string>().c_str()); 00503 #endif 00504 } else { 00505 return false; 00506 } 00507 } while (in.expect(',')); 00508 return in.expect('}'); 00509 } 00510 00511 inline bool _parse_number(MbedJSONValue& out, input& in) { 00512 #ifdef DEBUG 00513 printf("number detected\r\n"); 00514 #endif 00515 std::string num_str; 00516 while (1) { 00517 int ch = in.getc(); 00518 if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == '.' 00519 || ch == 'e' || ch == 'E') { 00520 num_str.push_back(ch); 00521 } else { 00522 in.ungetc(); 00523 break; 00524 } 00525 } 00526 char* endp; 00527 if (strchr(num_str.c_str(), '.') != NULL || strchr(num_str.c_str(), 'e') != NULL || strchr(num_str.c_str(), '+') != NULL) 00528 out = MbedJSONValue(strtod(num_str.c_str(), &endp)); 00529 else 00530 out = MbedJSONValue((int)strtod(num_str.c_str(), &endp)); 00531 return endp == num_str.c_str() + num_str.size(); 00532 } 00533 00534 inline bool _parse(MbedJSONValue& out, input& in) { 00535 in.skip_ws(); 00536 int ch = in.getc(); 00537 switch (ch) { 00538 #define IS(ch, text, val) case ch: \ 00539 if (in.match(text)) { \ 00540 out = val; \ 00541 return true; \ 00542 } else { \ 00543 return false; \ 00544 } 00545 IS('n', "ull", MbedJSONValue()); 00546 IS('f', "alse", MbedJSONValue(false)); 00547 IS('t', "rue", MbedJSONValue(true)); 00548 #undef IS 00549 case '"': 00550 return _parse_string(out, in); 00551 case '[': 00552 return _parse_array(out, in); 00553 case '{': 00554 return _parse_object(out, in); 00555 default: 00556 if (('0' <= ch && ch <= '9') || ch == '-') { 00557 in.ungetc(); 00558 return _parse_number(out, in); 00559 } 00560 break; 00561 } 00562 in.ungetc(); 00563 return false; 00564 } 00565 00566 inline std::string parse(MbedJSONValue& out, const char * pos) { 00567 const char * last = pos + strlen(pos); 00568 std::string err; 00569 pos = parse(out, pos, last, &err); 00570 return err; 00571 } 00572 00573 inline const char * parse(MbedJSONValue& out, const char * first, const char * last, std::string* err) { 00574 input in = input(first, last); 00575 if (! _parse(out, in) && err != NULL) { 00576 char buf[64]; 00577 sprintf(buf, "syntax error at line %d near: ", in.line()); 00578 *err = buf; 00579 while (1) { 00580 int ch = in.getc(); 00581 if (ch == -1 || ch == '\n') { 00582 break; 00583 } else if (ch >= ' ') { 00584 err->push_back(ch); 00585 } 00586 } 00587 } 00588 return in.cur(); 00589 } 00590 00591 #endif // _MbedMbedJSONValue_H_
Generated on Fri Jul 15 2022 13:30:12 by
1.7.2
