Freeman Oldman / NUCLEO_STM32F401RE_CC3000_ILI9341
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers JsonParser.h Source File

JsonParser.h

00001 /*
00002  *
00003  *  Compact JSON format parsing lib (native cross-platform c++)
00004  *
00005  *  Copyright (C) 2013 Victor Laskin (victor.laskin@gmail.com)
00006  *  Details: http://vitiy.info/?p=102
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *  1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  *  2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in
00015  *    the documentation and/or other materials provided with the
00016  *    distribution.
00017  *  3. The names of the authors may not be used to endorse or promote
00018  *    products derived from this software without specific prior
00019  *    written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
00022  *  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00023  *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  *  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
00025  *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00027  *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00028  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00029  *  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00030  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00031  *  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032  *
00033  */
00034 
00035 
00036 #include <string>
00037 #include <vector>
00038 #include <stdlib.h>
00039 
00040 #ifndef MVJSON_H_
00041 #define MVJSON_H_
00042 
00043 using namespace std;
00044 
00045 namespace JSON {
00046 
00047 /// JSON node types
00048 enum MVJSON_TYPE
00049 {
00050     MVJSON_TYPE_NULL,
00051     MVJSON_TYPE_OBJECT,
00052     MVJSON_TYPE_ARRAY,
00053     MVJSON_TYPE_STRING,
00054     MVJSON_TYPE_INT,
00055     MVJSON_TYPE_DOUBLE,
00056     MVJSON_TYPE_BOOL
00057 };
00058 
00059 class MVJSONUtils {
00060 protected:
00061 
00062     // string parsing functions
00063     inline static int stringToInt(const string & s);                                            ///< convert string to int
00064     inline static double stringToDouble(const string & s);                                      ///< convert string to float
00065     inline static bool symbolToBeTrimmed(const char& c);                                        ///< check if symbol is space, tab or new line break
00066     inline static string trim(const string & text);                                             ///< trim spaces, tabs and line break
00067     inline static void replace(string & target, const string & oldStr, const string & newStr);  ///< replace all occurrences of substring
00068     inline static void splitInHalf(const string & s, const string & separator, string & begin, string & end);   ///< second half (output)
00069     inline static void splitList(const string & s,  vector<string> & parts);
00070 };
00071 
00072 
00073 class MVJSONNode;
00074 
00075 /// JSON Value
00076 class MVJSONValue : public MVJSONUtils {
00077 public:
00078     MVJSONValue(string name, MVJSON_TYPE valueType);
00079     MVJSONValue(string name, bool value);
00080     MVJSONValue(string name, string value);
00081     MVJSONValue(string name, int value);
00082     MVJSONValue(string name, double value);
00083     MVJSONValue(string name, MVJSONNode* value);
00084     virtual ~MVJSONValue();
00085 
00086     string name;                            ///< value name [optional]
00087     MVJSON_TYPE valueType;                  ///< type of node
00088 
00089     string stringValue;                     ///< value if data has string type
00090     bool boolValue;                         ///< value if data has bool type
00091     int intValue;                           ///< value if data has int type
00092     double doubleValue;                     ///< value if data has double type
00093     MVJSONNode* objValue;                   ///< value if data has object type
00094 
00095     vector<MVJSONValue*> arrayValue;        ///< array of values
00096 
00097     double getFieldDouble(string name);     ///< get value of double field of VALUE OBJECT (objValue)
00098     int getFieldInt(string name);           ///< get value of int field of VALUE OBJECT (objValue)
00099     string getFieldString(string name);     ///< get value of string field of VALUE OBJECT (objValue)
00100     bool getFieldBool(string name);         ///< get value of bool field of VALUE OBJECT (objValue)
00101 
00102     inline MVJSONValue* at(unsigned int i){ return arrayValue.at(i); }
00103     inline int size() { if (valueType == MVJSON_TYPE_ARRAY) return arrayValue.size(); else return 1; }
00104 private:
00105     void init(MVJSON_TYPE valueType);
00106 };
00107 
00108 /// JSON Node (Object)
00109 class MVJSONNode {
00110 public:
00111 
00112     virtual ~MVJSONNode();
00113 
00114     vector<MVJSONValue*> values;            ///< values (props)
00115 
00116     bool hasField(string name);             ///< check that object has field
00117     MVJSONValue* getField(string name);     ///< get field by name
00118 
00119     double getFieldDouble(string name);     ///< get value of double field
00120     int getFieldInt(string name);           ///< get value of int field
00121     string getFieldString(string name);     ///< get value of string field
00122     bool getFieldBool(string name);         ///< get value of bool field
00123 };
00124 
00125 /// Compact JSON parser (based on specification: http://www.json.org/)
00126 class MVJSONReader : public MVJSONUtils {
00127 public:
00128     MVJSONReader(const string & source);    ///< constructor from json source
00129     virtual ~MVJSONReader();
00130 
00131     MVJSONNode* root;                       ///< root object (if its null - parsing was failed)
00132 
00133 private:
00134     MVJSONValue* parseValue(string text, bool hasNoName);                   ///< parse value
00135     MVJSONNode* parse(string text);                                         ///< parse node
00136 
00137 
00138 };
00139 
00140 
00141 
00142 // ------------------- inlined string processing functions ------------->
00143 
00144 
00145 inline int MVJSONUtils::stringToInt(const string & s)
00146 {
00147     return atoi(s.c_str());
00148 }
00149 
00150 
00151 inline double MVJSONUtils::stringToDouble(const string & s)
00152 {
00153     return atof(s.c_str());
00154 }
00155 
00156 
00157 inline bool MVJSONUtils::symbolToBeTrimmed(const char& c   ///< the char to test
00158 )
00159 {
00160     if (c == ' ') return true;
00161     if (c == '\n') return true;
00162     if (c == '\r') return true;
00163     if (c == '\t') return true;
00164     return false;
00165 }
00166 
00167 
00168 inline string  MVJSONUtils::trim(const string & text  ///< the text to trim
00169 )
00170 {
00171     if (text.length() == 0) return "";
00172     int start = 0;
00173     while ((start < text.length()) && (symbolToBeTrimmed(text[start]))) start++;
00174     int end = text.length() - 1;
00175     while ((end > 0) && (symbolToBeTrimmed(text[end]))) end--;
00176     if (start > end) return "";
00177 
00178     return text.substr(start, end - start + 1);
00179 }
00180 
00181 inline void MVJSONUtils::splitInHalf(const string & s,                      ///< source string to split up
00182                                       const string & separator,             ///< separator string)
00183                                       string & begin,                       ///< first part (output)
00184                                       string & end                          ///< second half (output)
00185 )
00186 {
00187     int pos = s.find(separator);
00188     if (pos == string::npos) { begin = s; end = ""; return; }
00189 
00190     begin = s.substr(0, pos);
00191     end = s.substr(pos + separator.length(), s.length() - pos - separator.length());
00192 }
00193 
00194 /// split string by "," - ignore content inside of "{", "}", "[", "]" and quotations "...."
00195 /// also take \" into account
00196 /// (Code should be cleared of comments beforehand)
00197 inline void MVJSONUtils::splitList(const string & s,                ///< string to be splitted
00198                                     vector<string> & parts          ///< result parts
00199 )
00200 {
00201 
00202     bool isNotInQuotes = true;
00203     int b1 = 0;
00204     int b2 = 0;
00205     int lastPos = 0;
00206 
00207     const char* start = s.c_str();
00208     const char* ps = start;
00209 
00210     while (*ps) // *ps != 0
00211     {
00212         if ((*ps == ',') && (isNotInQuotes) && (b1 == 0) && (b2 == 0))
00213         {
00214             parts.push_back(s.substr(lastPos, ps - start - lastPos));
00215             lastPos = ps - start + 1;
00216         }
00217 
00218         if (isNotInQuotes)
00219         {
00220             if (*ps == '{') b1++;
00221             if (*ps == '}') b1--;
00222             if (*ps == '[') b2++;
00223             if (*ps == ']') b2--;
00224         }
00225 
00226         if (*ps == '"')
00227         {
00228             isNotInQuotes = !isNotInQuotes;
00229             if (ps != start)
00230                 if (*(ps-1) == '\\')
00231                     isNotInQuotes = !isNotInQuotes;
00232         }
00233 
00234         ps++;
00235     }
00236 
00237     parts.push_back(s.substr(lastPos, s.length() - lastPos));
00238 }
00239 
00240 inline void MVJSONUtils::replace(string & target,           ///< text to be modified
00241                                   const string & oldStr,        ///< old string
00242                                   const string & newStr     ///< new string
00243 )
00244 {
00245     unsigned int pos = 0;
00246     unsigned int oldLen = oldStr.length();
00247     unsigned int newLen = newStr.length();
00248 
00249     for (;;)
00250     {
00251         pos = target.find(oldStr, pos);
00252         if (pos == string::npos) break;
00253         target.replace(pos, oldLen, newStr);
00254         pos += newLen;
00255     }
00256 }
00257 
00258 
00259 } /* namespace F2 */
00260 #endif /* MVJSON_H_ */
00261