Replace #include <stdio.h> with #include <cstdio> to solve gcc4mbed compiler problem
Fork of MbedJSONValue by
Revision 0:0cf0e27feaad, committed 2011-09-22
- Comitter:
- samux
- Date:
- Thu Sep 22 10:35:59 2011 +0000
- Child:
- 1:effaca3e3f84
- Commit message:
Changed in this revision
| MbedJSONValue.cpp | Show annotated file Show diff for this revision Revisions of this file |
| MbedJSONValue.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedJSONValue.cpp Thu Sep 22 10:35:59 2011 +0000
@@ -0,0 +1,245 @@
+#include "MbedJSONValue.h"
+
+# include <stdlib.h>
+# include <stdio.h>
+
+// Clean up
+void MbedJSONValue::clean() {
+ switch (_type) {
+ case TypeString:
+ delete _value.asString;
+ break;
+ case TypeArray:
+ for (int i = 0; i < index_array; i++)
+ delete array[i];
+ index_array = 0;
+ break;
+ case TypeObject:
+ for (int i = 0; i < index_token; i++) {
+ delete token[i];
+ delete token_name[i];
+ }
+ index_token = 0;
+ break;
+ default:
+ break;
+ }
+ _type = TypeNull;
+ _type = TypeNull;
+}
+
+bool MbedJSONValue::hasMember(char * name)
+{
+ for(int i = 0; i < index_token; i++)
+ if( !strcmp(name, (*(token_name[i])).c_str() ))
+ return true;
+ return false;
+}
+
+
+void copy(const std::string& s, std::back_insert_iterator<std::string> oi) {
+ std::copy(s.begin(), s.end(), oi);
+}
+
+void serialize_str(const std::string& s, std::back_insert_iterator<std::string> oi) {
+ *oi++ = '"';
+ for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
+ switch (*i) {
+#define MAP(val, sym) case val: copy(sym, oi); break
+ MAP('"', "\\\"");
+ MAP('\\', "\\\\");
+ MAP('/', "\\/");
+ MAP('\b', "\\b");
+ MAP('\f', "\\f");
+ MAP('\n', "\\n");
+ MAP('\r', "\\r");
+ MAP('\t', "\\t");
+#undef MAP
+ default:
+ if ((unsigned char)*i < 0x20 || *i == 0x7f) {
+ char buf[7];
+ sprintf(buf, "\\u%04x", *i & 0xff);
+ copy(buf, buf + 6, oi);
+ } else {
+ *oi++ = *i;
+ }
+ break;
+ }
+ }
+ *oi++ = '"';
+}
+
+std::string MbedJSONValue::serialize(){
+ std::string s;
+ serialize(std::back_inserter(s));
+ return s;
+}
+
+std::string MbedJSONValue::to_str(){
+ switch (_type) {
+ case TypeNull:
+ return "null";
+ case TypeBoolean:
+ return _value.asBool ? "true" : "false";
+ case TypeInt: {
+ char buf[10];
+ sprintf(buf, "%d", _value.asInt);
+ return buf;
+ }
+ case TypeDouble: {
+ char buf[10];
+ sprintf(buf, "%f", _value.asDouble);
+ return buf;
+ }
+ default:
+ break;
+ }
+ return NULL;
+}
+
+
+
+void MbedJSONValue::serialize(std::back_insert_iterator<std::string> oi) {
+ switch (_type) {
+ case TypeString:
+ serialize_str(*_value.asString, oi);
+ break;
+ case TypeArray: {
+ *oi++ = '[';
+ for (int i = 0; i < index_array; i++) {
+ if (i)
+ *oi++ = ',';
+ (*this)[i].serialize(oi);
+ }
+ *oi++ = ']';
+ break;
+ }
+ case TypeObject: {
+ *oi++ = '{';
+ for (int i = 0; i < index_token; i++) {
+ if (i)
+ *oi++ = ',';
+ serialize_str(*(token_name[i]), oi);
+ *oi++ = ':';
+ (*(token[i])).serialize(oi);
+ }
+ *oi++ = '}';
+ break;
+ }
+ default:
+ copy(to_str(), oi);
+ break;
+ }
+}
+
+
+
+MbedJSONValue& MbedJSONValue::operator[](int i) {
+ _type = TypeArray;
+ if (i < NB_TOKEN && index_array == i ) {
+#ifdef DEBUG
+ printf("will add an element to the array\r\n");
+#endif
+ array[i] = new MbedJSONValue();
+ index_array++;
+ return *(array[i]);
+ }
+ if (i < NB_TOKEN && index_array > i)
+ return *(array[i]);
+
+ //if the user is not doing something wrong, this code is never executed!!
+ return *(new MbedJSONValue());
+}
+
+MbedJSONValue& MbedJSONValue::operator[](std::string k) {
+ _type = TypeObject;
+ for (int i = 0; i < index_token; i++) {
+#ifdef DEBUG
+ printf("k: %s\r\n", k.c_str());
+ printf("str: %s\r\n", token_name[i]->c_str());
+#endif
+ //existing token
+ if (!strcmp(k.c_str(), token_name[i]->c_str())) {
+#ifdef DEBUG
+ printf("token found: %d\r\n", i);
+#endif
+ return *(token[i]);
+ }
+ }
+
+ if(index_token >= NB_TOKEN)
+ index_token = NB_TOKEN - 1;
+ //non existing token
+ token_name[index_token] = new std::string(k);
+ token[index_token] = new MbedJSONValue();
+ index_token++;
+ return *(token[index_token - 1]);
+}
+
+MbedJSONValue& MbedJSONValue::operator[](std::string k) const
+{
+ for (int i = 0; i < index_token; i++) {
+#ifdef DEBUG
+ printf("k: %s\r\n", k.c_str());
+ printf("str: %s\r\n", token_name[i]->c_str());
+#endif
+ if (!strcmp(k.c_str(), token_name[i]->c_str())) {
+#ifdef DEBUG
+ printf("token found: %d\r\n", i);
+#endif
+ return *(token[i]);
+ }
+ }
+
+ //if the user is not doing something wrong, this code is never executed!!
+ return *(new MbedJSONValue());
+}
+
+
+// Operators
+MbedJSONValue& MbedJSONValue::operator=(MbedJSONValue const& rhs) {
+ if (this != &rhs) {
+ clean();
+ _type = rhs._type;
+ switch (_type) {
+ case TypeBoolean:
+ _value.asBool = rhs._value.asBool;
+ break;
+ case TypeInt:
+ _value.asInt = rhs._value.asInt;
+ break;
+ case TypeDouble:
+ _value.asDouble = rhs._value.asDouble;
+ break;
+ case TypeString:
+ _value.asString = new std::string(*rhs._value.asString);
+ break;
+ case TypeArray:
+ for (int i = 0; i < rhs.index_array; i++)
+ (*this)[i] = rhs[i];
+ case TypeObject:
+ for (int i = 0; i < rhs.index_token; i++)
+ (*this)[*(rhs.token_name[i])] = rhs[*(rhs.token_name[i])];
+ default:
+ break;
+ }
+ }
+ return *this;
+}
+
+
+// Works for strings, arrays, and structs.
+int MbedJSONValue::size() const {
+ switch (_type) {
+ case TypeString:
+ return int(_value.asString->size());
+ case TypeArray:
+ return index_array;
+ case TypeObject:
+ return index_token;
+ default:
+ break;
+ }
+ return -1;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedJSONValue.h Thu Sep 22 10:35:59 2011 +0000
@@ -0,0 +1,568 @@
+/**
+* @author Samuel Mokrani
+*
+* @section LICENSE
+*
+* Copyright (c) 2011 mbed
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+* @section DESCRIPTION
+* Types Abstraction. JSON serializer and parser. (inspired by picojson). Is used by MbedJSONRpc.
+*
+*/
+
+#ifndef _Mbed_RPC_VALUE_H_
+#define _Mbed_RPC_VALUE_H_
+
+#define NB_TOKEN 20
+/*!< Number maximum of MbedJSONValue in an array or an object */
+
+#include <string>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/** MbedJSONValue class
+ *
+ * Example:
+ * - creation of an MbedJSONValue of type TypeObject containing two others MbedJSONValue:
+ * -one array of one string and one integer identified by "my_array"
+ * -a boolean identified by "my_boolean"
+ * - serialization in JSON format of this object
+ * @code
+ * MbedJSONValue demo;
+ * std::string s;
+ *
+ * //fill the object
+ * demo["my_array"][0] = "demo_string";
+ * demo["my_array"][1] = 10;
+ * demo["my_boolean"] = true;
+ *
+ * //serialize it into a JSON string
+ * s = demo.serialize();
+ *
+ *
+ * @endcode
+ *
+ * Example:
+ * - creation of an MbedJSONValue from a JSON string
+ * - extraction of different values from this existing MbedJSONValue
+ * @code
+ *
+ * MbedJSONValue demo;
+ *
+ * const char * json = "{\"my_array\": [\"demo_string\", 10], \"my_boolean\": true}";
+ *
+ * //parse the previous string and fill the object demo
+ * parse(demo, json);
+ *
+ * std::string my_str;
+ * int my_int;
+ * bool my_bool;
+ *
+ * my_str = demo["my_array"][0];
+ * my_int = demo["my_array"][1];
+ * my_bool = demo["my_boolean"];
+ *
+ * @endcode
+ */
+class MbedJSONValue {
+public:
+
+ /**
+ * \enum Type
+ * \brief All types which can be used
+ */
+ enum Type {
+ TypeNull, /*!< Null type */
+ TypeBoolean, /*!< Boolean */
+ TypeInt, /*!< Integer */
+ TypeDouble, /*!< Double */
+ TypeString, /*!< String */
+ TypeArray, /*!< Array of Type */
+ TypeObject /*!< Object */
+ };
+
+ /**
+ * MbedJSONValue constructor of type TypeNull
+ */
+ MbedJSONValue() : _type(TypeNull), index_array(0), index_token(0) {}
+
+ /**
+ * MbedJSONValue constructor of type TypeBoolean
+ *
+ * @param value the object created will be initialized with this boolean
+ */
+ MbedJSONValue(bool value) : _type(TypeBoolean), index_array(0), index_token(0) {
+ _value.asBool = value;
+ }
+
+ /**
+ * MbedJSONValue constructor of type TypeInt
+ *
+ * @param value the object created will be initialized with this integer
+ */
+ MbedJSONValue(int value) : _type(TypeInt), index_array(0), index_token(0) {
+ _value.asInt = value;
+ }
+
+ /**
+ * MbedJSONValue constructor of type TypeDouble
+ *
+ * @param value the object created will be initialized with this double
+ */
+ MbedJSONValue(double value) : _type(TypeDouble), index_array(0), index_token(0) {
+ _value.asDouble = value;
+ }
+
+ /**
+ * MbedJSONValue constructor of type TypeString
+ *
+ * @param value the object created will be initialized with this string
+ */
+ MbedJSONValue(std::string const& value) : _type(TypeString), index_array(0), index_token(0) {
+ _value.asString = new std::string(value);
+ }
+
+ /**
+ * MbedJSONValue constructor of type TypeString
+ *
+ * @param value the object created will be initialized with this string
+ */
+ MbedJSONValue(const char* value) : _type(TypeString), index_array(0), index_token(0) {
+ _value.asString = new std::string(value);
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param rhs object which will be copied
+ */
+ MbedJSONValue(MbedJSONValue const& rhs) : _type(TypeNull) { *this = rhs; }
+
+ /**
+ * Destructor
+ */
+ ~MbedJSONValue() { clean(); }
+
+ /**
+ * = Operator overloading for an MbedJSONValue from an MbedJSONValue
+ *
+ * @param rhs object
+ * @return a reference on the MbedJSONValue affected
+ */
+ MbedJSONValue& operator=(MbedJSONValue const & rhs);
+
+ /**
+ * = Operator overloading for an MbedJSONValue from an int
+ *
+ * @param rhs integer
+ * @return a reference on the MbedJSONValue affected
+ */
+ MbedJSONValue& operator=(int const& rhs) { return operator=(MbedJSONValue(rhs)); }
+
+ /**
+ * = Operator overloading for an MbedJSONValue from a double
+ *
+ * @param rhs double
+ * @return a reference on the MbedJSONValue affected
+ */
+ MbedJSONValue& operator=(double const& rhs) { return operator=(MbedJSONValue(rhs)); }
+
+ /**
+ * = Operator overloading for an MbedJSONValue from a string
+ *
+ * @param rhs string
+ * @return a reference on the MbedJSONValue affected
+ */
+ MbedJSONValue& operator=(const char* rhs) { return operator=(MbedJSONValue(std::string(rhs))); }
+
+
+ /**
+ * [] Operator overloading for an MbedJSONValue.
+ * Each TypeObject object can contain an array of NB_TOKEN MbedJSONValue.
+ * This operator is useful to create an array or to retrieve an MbedJSONValue of an existing array.
+ *
+ * @param i index of the array
+ * @return a reference on the MbedJSONValue created or retrieved
+ */
+ MbedJSONValue& operator[](int i);
+
+ /**
+ * [] Operator overloading for an MbedJSONValue.
+ * Each TypeObject MbedJSONValue can contain NB_TOKEN MbedJSONValue IDENTIFIED BY A NAME
+ * This operator is useful to create a TypeObject MbedJSONValue or to retrieve an MbedJSONValue of an existing TypeObject.
+ *
+ *
+ * @param str identifier of the sub MbedJSONValue
+ * @return a reference on the MbedJSONValue created or retrieved
+ */
+ MbedJSONValue& operator[](std::string str);
+
+ /**
+ * Retrieve the value of an MbedJSONValue object.
+ *
+ * Let's suppose that we have an MbedJSONValue of type TypeString.
+ * To retrieve this string, you have to do:
+ * my_obj.get<std::string>();
+ *
+ * @return A contant reference on the value of the object
+ */
+ template <typename T> const T& get() const;
+
+ /**
+ * Retrieve the value of an MbedJSONValue object.
+ *
+ * Let's suppose that we have an MbedJSONValue of type TypeInt.
+ * To retrieve this integer, you have to do:
+ * my_obj.get<int>();
+ *
+ * @return A reference on the value of the object
+ */
+ template <typename T> T& get();
+
+
+ /**
+ * Return the type of the MbedJSONValue object
+ *
+ * @return type of the MbedJSONValue object
+ */
+ Type const &getType() const {
+ return _type;
+ }
+
+ /**
+ * Return the size of an MbedJSONValue object (works for TypeString, TypeArray or TypeObject)
+ *
+ * @return size
+ */
+ int size() const;
+
+ /**
+ * Check for the existence in a TypeObject object of member identified by name
+ *
+ * @param name Identifier
+ * @return true if the object is of type TypeObject AND contains a member named "name", false otherwise
+ */
+ bool hasMember(char * name);
+
+ /**
+ * Convert an MbedJSONValue in a JSON frame
+ *
+ * @return JSON string
+ */
+ std::string serialize();
+
+protected:
+
+ // object type
+ Type _type;
+
+ //indexes of TypeObject and TypeArray
+ int index_array;
+ int index_token;
+
+ //an object can contain NB_TOKEN tokens. Each token have a name
+ MbedJSONValue * token[NB_TOKEN];
+ std::string * token_name[NB_TOKEN];
+
+ //an object can contain an array of NB_TOKEN elements
+ MbedJSONValue * array[NB_TOKEN];
+
+ // Clean up
+ void clean();
+
+ union {
+ bool asBool;
+ int asInt;
+ double asDouble;
+ std::string* asString;
+ } _value;
+
+
+ MbedJSONValue& operator[](int i) const { return *(array[i]); }
+ MbedJSONValue& operator[](std::string k) const;
+
+ std::string to_str();
+ void serialize(std::back_insert_iterator<std::string> os);
+
+};
+
+
+#define GET(ctype, var) \
+ template <> inline const ctype& MbedJSONValue::get<ctype>() const { \
+ return var; \
+ } \
+ template <> inline ctype& MbedJSONValue::get<ctype>() { \
+ return var; \
+ }
+GET(bool, _value.asBool)
+GET(double, _value.asDouble)
+GET(int, _value.asInt)
+GET(std::string, *_value.asString)
+#undef GET
+
+
+//Input class for JSON parser
+class input {
+protected:
+ const char * cur_;
+ const char * end_;
+ int last_ch_;
+ bool ungot_;
+ int line_;
+public:
+ input(const char * first, const char * last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {};
+
+ int getc() {
+ if (ungot_) {
+ ungot_ = false;
+ return last_ch_;
+ }
+ if (cur_ == end_) {
+ last_ch_ = -1;
+ return -1;
+ }
+ if (last_ch_ == '\n') {
+ line_++;
+ }
+ last_ch_ = *cur_++ & 0xff;
+ return last_ch_;
+ }
+
+ void ungetc() {
+ if (last_ch_ != -1) {
+ ungot_ = true;
+ }
+ }
+
+ const char * cur() const {
+ return cur_;
+ }
+ int line() const {
+ return line_;
+ }
+ void skip_ws() {
+ while (1) {
+ int ch = getc();
+ if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
+ ungetc();
+ break;
+ }
+ }
+ }
+ int expect(int expect) {
+ skip_ws();
+ if (getc() != expect) {
+ ungetc();
+ return false;
+ }
+ return true;
+ }
+ bool match(const std::string& pattern) {
+ for (std::string::const_iterator pi(pattern.begin());
+ pi != pattern.end();
+ ++pi) {
+ if (getc() != *pi) {
+ ungetc();
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+
+
+inline const char * parse(MbedJSONValue& out, const char * first, const char * last, std::string* err);
+
+/**
+* JSON string parser and creation of an MbedJSONValue
+*
+* @param out reference of an MbedJSONValue which will be filled according to the JSON string
+* @param str JSON string
+* @return A non empty string if there is a parsing error
+*
+*/
+
+inline std::string parse(MbedJSONValue& out, const char * str);
+inline bool _parse(MbedJSONValue& out, input& in);
+inline bool _parse_number(MbedJSONValue& out, input& in);
+inline bool _parse_string(MbedJSONValue& out, input& in);
+inline bool _parse_array(MbedJSONValue& out, input& in);
+inline bool _parse_object(MbedJSONValue& out, input& in);
+
+
+inline bool _parse_string(MbedJSONValue& out, input& in) {
+#ifdef DEBUG
+ printf("string detected\r\n");
+#endif
+ out = MbedJSONValue(std::string(""));
+ std::string& s = out.get<std::string>();
+ while (1) {
+ int ch = in.getc();
+ if (ch < ' ') {
+ in.ungetc();
+ return false;
+ } else if (ch == '"') {
+ return true;
+ } else if (ch == '\\') {
+ if ((ch = in.getc()) == -1) {
+ return false;
+ }
+ switch (ch) {
+#define MAP(sym, val) case sym: s.push_back(val); break
+ MAP('"', '\"');
+ MAP('\\', '\\');
+ MAP('/', '/');
+ MAP('b', '\b');
+ MAP('f', '\f');
+ MAP('n', '\n');
+ MAP('r', '\r');
+ MAP('t', '\t');
+#undef MAP
+ default:
+ return false;
+ }
+ } else {
+ s.push_back(ch);
+ }
+ }
+}
+
+inline bool _parse_array(MbedJSONValue& out, input& in) {
+#ifdef DEBUG
+ printf("array detected\r\n");
+#endif
+ int i = 0;
+ if (in.expect(']')) {
+ return true;
+ }
+ do {
+ if (! _parse(out[i], in)) {
+ return false;
+ }
+ i++;
+ } while (in.expect(','));
+ return in.expect(']');
+}
+
+inline bool _parse_object(MbedJSONValue& out, input& in) {
+#ifdef DEBUG
+ printf("object detected\r\n");
+#endif
+ if (in.expect('}')) {
+ return true;
+ }
+ do {
+ MbedJSONValue key, val;
+ if (in.expect('"') && _parse_string(key, in) && in.expect(':') && _parse(val, in)) {
+ out[key.get<std::string>().c_str()] = val;
+#ifdef DEBUG
+ printf("key: %s \r\n", key.get<std::string>().c_str());
+#endif
+ } else {
+ return false;
+ }
+ } while (in.expect(','));
+ return in.expect('}');
+}
+
+inline bool _parse_number(MbedJSONValue& out, input& in) {
+#ifdef DEBUG
+ printf("number detected\r\n");
+#endif
+ std::string num_str;
+ while (1) {
+ int ch = in.getc();
+ if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == '.'
+ || ch == 'e' || ch == 'E') {
+ num_str.push_back(ch);
+ } else {
+ in.ungetc();
+ break;
+ }
+ }
+ char* endp;
+ if (strchr(num_str.c_str(), '.') != NULL || strchr(num_str.c_str(), 'e') != NULL || strchr(num_str.c_str(), '+') != NULL)
+ out = MbedJSONValue(strtod(num_str.c_str(), &endp));
+ else
+ out = MbedJSONValue((int)strtod(num_str.c_str(), &endp));
+ return endp == num_str.c_str() + num_str.size();
+}
+
+inline bool _parse(MbedJSONValue& out, input& in) {
+ in.skip_ws();
+ int ch = in.getc();
+ switch (ch) {
+#define IS(ch, text, val) case ch: \
+ if (in.match(text)) { \
+ out = val; \
+ return true; \
+ } else { \
+ return false; \
+ }
+ IS('n', "ull", MbedJSONValue());
+ IS('f', "alse", MbedJSONValue(false));
+ IS('t', "rue", MbedJSONValue(true));
+#undef IS
+ case '"':
+ return _parse_string(out, in);
+ case '[':
+ return _parse_array(out, in);
+ case '{':
+ return _parse_object(out, in);
+ default:
+ if (('0' <= ch && ch <= '9') || ch == '-') {
+ in.ungetc();
+ return _parse_number(out, in);
+ }
+ break;
+ }
+ in.ungetc();
+ return false;
+}
+
+inline std::string parse(MbedJSONValue& out, const char * pos) {
+ const char * last = pos + strlen(pos);
+ std::string err;
+ pos = parse(out, pos, last, &err);
+ return err;
+}
+
+inline const char * parse(MbedJSONValue& out, const char * first, const char * last, std::string* err) {
+ input in = input(first, last);
+ if (! _parse(out, in) && err != NULL) {
+ char buf[64];
+ sprintf(buf, "syntax error at line %d near: ", in.line());
+ *err = buf;
+ while (1) {
+ int ch = in.getc();
+ if (ch == -1 || ch == '\n') {
+ break;
+ } else if (ch >= ' ') {
+ err->push_back(ch);
+ }
+ }
+ }
+ return in.cur();
+}
+
+#endif // _MbedMbedJSONValue_H_
