The code from https://github.com/vpcola/Nucleo
Diff: JsonParser.h
- Revision:
- 0:5464d5e415e5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/JsonParser.h Wed Oct 08 11:00:24 2014 +0000 @@ -0,0 +1,261 @@ +/* + * + * Compact JSON format parsing lib (native cross-platform c++) + * + * Copyright (C) 2013 Victor Laskin (victor.laskin@gmail.com) + * Details: http://vitiy.info/?p=102 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include <string> +#include <vector> +#include <stdlib.h> + +#ifndef MVJSON_H_ +#define MVJSON_H_ + +using namespace std; + +namespace JSON { + +/// JSON node types +enum MVJSON_TYPE +{ + MVJSON_TYPE_NULL, + MVJSON_TYPE_OBJECT, + MVJSON_TYPE_ARRAY, + MVJSON_TYPE_STRING, + MVJSON_TYPE_INT, + MVJSON_TYPE_DOUBLE, + MVJSON_TYPE_BOOL +}; + +class MVJSONUtils { +protected: + + // string parsing functions + inline static int stringToInt(const string & s); ///< convert string to int + inline static double stringToDouble(const string & s); ///< convert string to float + inline static bool symbolToBeTrimmed(const char& c); ///< check if symbol is space, tab or new line break + inline static string trim(const string & text); ///< trim spaces, tabs and line break + inline static void replace(string & target, const string & oldStr, const string & newStr); ///< replace all occurrences of substring + inline static void splitInHalf(const string & s, const string & separator, string & begin, string & end); ///< second half (output) + inline static void splitList(const string & s, vector<string> & parts); +}; + + +class MVJSONNode; + +/// JSON Value +class MVJSONValue : public MVJSONUtils { +public: + MVJSONValue(string name, MVJSON_TYPE valueType); + MVJSONValue(string name, bool value); + MVJSONValue(string name, string value); + MVJSONValue(string name, int value); + MVJSONValue(string name, double value); + MVJSONValue(string name, MVJSONNode* value); + virtual ~MVJSONValue(); + + string name; ///< value name [optional] + MVJSON_TYPE valueType; ///< type of node + + string stringValue; ///< value if data has string type + bool boolValue; ///< value if data has bool type + int intValue; ///< value if data has int type + double doubleValue; ///< value if data has double type + MVJSONNode* objValue; ///< value if data has object type + + vector<MVJSONValue*> arrayValue; ///< array of values + + double getFieldDouble(string name); ///< get value of double field of VALUE OBJECT (objValue) + int getFieldInt(string name); ///< get value of int field of VALUE OBJECT (objValue) + string getFieldString(string name); ///< get value of string field of VALUE OBJECT (objValue) + bool getFieldBool(string name); ///< get value of bool field of VALUE OBJECT (objValue) + + inline MVJSONValue* at(unsigned int i){ return arrayValue.at(i); } + inline int size() { if (valueType == MVJSON_TYPE_ARRAY) return arrayValue.size(); else return 1; } +private: + void init(MVJSON_TYPE valueType); +}; + +/// JSON Node (Object) +class MVJSONNode { +public: + + virtual ~MVJSONNode(); + + vector<MVJSONValue*> values; ///< values (props) + + bool hasField(string name); ///< check that object has field + MVJSONValue* getField(string name); ///< get field by name + + double getFieldDouble(string name); ///< get value of double field + int getFieldInt(string name); ///< get value of int field + string getFieldString(string name); ///< get value of string field + bool getFieldBool(string name); ///< get value of bool field +}; + +/// Compact JSON parser (based on specification: http://www.json.org/) +class MVJSONReader : public MVJSONUtils { +public: + MVJSONReader(const string & source); ///< constructor from json source + virtual ~MVJSONReader(); + + MVJSONNode* root; ///< root object (if its null - parsing was failed) + +private: + MVJSONValue* parseValue(string text, bool hasNoName); ///< parse value + MVJSONNode* parse(string text); ///< parse node + + +}; + + + +// ------------------- inlined string processing functions -------------> + + +inline int MVJSONUtils::stringToInt(const string & s) +{ + return atoi(s.c_str()); +} + + +inline double MVJSONUtils::stringToDouble(const string & s) +{ + return atof(s.c_str()); +} + + +inline bool MVJSONUtils::symbolToBeTrimmed(const char& c ///< the char to test +) +{ + if (c == ' ') return true; + if (c == '\n') return true; + if (c == '\r') return true; + if (c == '\t') return true; + return false; +} + + +inline string MVJSONUtils::trim(const string & text ///< the text to trim +) +{ + if (text.length() == 0) return ""; + int start = 0; + while ((start < text.length()) && (symbolToBeTrimmed(text[start]))) start++; + int end = text.length() - 1; + while ((end > 0) && (symbolToBeTrimmed(text[end]))) end--; + if (start > end) return ""; + + return text.substr(start, end - start + 1); +} + +inline void MVJSONUtils::splitInHalf(const string & s, ///< source string to split up + const string & separator, ///< separator string) + string & begin, ///< first part (output) + string & end ///< second half (output) +) +{ + int pos = s.find(separator); + if (pos == string::npos) { begin = s; end = ""; return; } + + begin = s.substr(0, pos); + end = s.substr(pos + separator.length(), s.length() - pos - separator.length()); +} + +/// split string by "," - ignore content inside of "{", "}", "[", "]" and quotations "...." +/// also take \" into account +/// (Code should be cleared of comments beforehand) +inline void MVJSONUtils::splitList(const string & s, ///< string to be splitted + vector<string> & parts ///< result parts +) +{ + + bool isNotInQuotes = true; + int b1 = 0; + int b2 = 0; + int lastPos = 0; + + const char* start = s.c_str(); + const char* ps = start; + + while (*ps) // *ps != 0 + { + if ((*ps == ',') && (isNotInQuotes) && (b1 == 0) && (b2 == 0)) + { + parts.push_back(s.substr(lastPos, ps - start - lastPos)); + lastPos = ps - start + 1; + } + + if (isNotInQuotes) + { + if (*ps == '{') b1++; + if (*ps == '}') b1--; + if (*ps == '[') b2++; + if (*ps == ']') b2--; + } + + if (*ps == '"') + { + isNotInQuotes = !isNotInQuotes; + if (ps != start) + if (*(ps-1) == '\\') + isNotInQuotes = !isNotInQuotes; + } + + ps++; + } + + parts.push_back(s.substr(lastPos, s.length() - lastPos)); +} + +inline void MVJSONUtils::replace(string & target, ///< text to be modified + const string & oldStr, ///< old string + const string & newStr ///< new string +) +{ + unsigned int pos = 0; + unsigned int oldLen = oldStr.length(); + unsigned int newLen = newStr.length(); + + for (;;) + { + pos = target.find(oldStr, pos); + if (pos == string::npos) break; + target.replace(pos, oldLen, newStr); + pos += newLen; + } +} + + +} /* namespace F2 */ +#endif /* MVJSON_H_ */ +