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