Api wrapper to communicate with EVRYTHNG's Engine.

Dependencies:   EthernetInterface mbed-rtos

Dependents:   EvrythngApiExample

Committer:
vladounet
Date:
Thu Aug 30 13:25:41 2012 +0000
Revision:
1:7162d0e030f5
Parent:
0:d38d192c2f5f
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vladounet 0:d38d192c2f5f 1 /*
vladounet 0:d38d192c2f5f 2 * (c) Copyright 2012 EVRYTHNG Ltd London / Zurich
vladounet 0:d38d192c2f5f 3 * www.evrythng.com
vladounet 0:d38d192c2f5f 4 *
vladounet 0:d38d192c2f5f 5 * --- DISCLAIMER ---
vladounet 0:d38d192c2f5f 6 *
vladounet 0:d38d192c2f5f 7 * EVRYTHNG provides this source code "as is" and without warranty of any kind,
vladounet 0:d38d192c2f5f 8 * and hereby disclaims all express or implied warranties, including without
vladounet 0:d38d192c2f5f 9 * limitation warranties of merchantability, fitness for a particular purpose,
vladounet 0:d38d192c2f5f 10 * performance, accuracy, reliability, and non-infringement.
vladounet 0:d38d192c2f5f 11 *
vladounet 0:d38d192c2f5f 12 * Author: Michel Yerly
vladounet 0:d38d192c2f5f 13 *
vladounet 0:d38d192c2f5f 14 */
vladounet 0:d38d192c2f5f 15 #include "JsonParser.h"
vladounet 0:d38d192c2f5f 16 #include "string.h"
vladounet 0:d38d192c2f5f 17 #include "stdlib.h"
vladounet 0:d38d192c2f5f 18 #include "errno.h"
vladounet 0:d38d192c2f5f 19 #include "util.h"
vladounet 0:d38d192c2f5f 20
vladounet 0:d38d192c2f5f 21 //#define DEBUG_JSONTOKENIZER
vladounet 0:d38d192c2f5f 22 //#define DEBUG_JSONPARSER
vladounet 0:d38d192c2f5f 23 //#define DEBUG_JSONGET
vladounet 0:d38d192c2f5f 24
vladounet 0:d38d192c2f5f 25 using namespace std;
vladounet 0:d38d192c2f5f 26
vladounet 0:d38d192c2f5f 27 bool isDigit(char c)
vladounet 0:d38d192c2f5f 28 {
vladounet 0:d38d192c2f5f 29 return c >= '0' && c <= '9';
vladounet 0:d38d192c2f5f 30 }
vladounet 0:d38d192c2f5f 31
vladounet 0:d38d192c2f5f 32 JsonParser::JsonParser()
vladounet 0:d38d192c2f5f 33 {
vladounet 0:d38d192c2f5f 34 this->pDocument = NULL;
vladounet 0:d38d192c2f5f 35 }
vladounet 0:d38d192c2f5f 36
vladounet 0:d38d192c2f5f 37 JsonParser::~JsonParser()
vladounet 0:d38d192c2f5f 38 {
vladounet 0:d38d192c2f5f 39 if (this->pDocument) {
vladounet 0:d38d192c2f5f 40 delete this->pDocument;
vladounet 0:d38d192c2f5f 41 }
vladounet 0:d38d192c2f5f 42 }
vladounet 0:d38d192c2f5f 43
vladounet 0:d38d192c2f5f 44 int JsonParser::parse(const char* json)
vladounet 0:d38d192c2f5f 45 {
vladounet 0:d38d192c2f5f 46 this->json = json;
vladounet 0:d38d192c2f5f 47 this->json_len = strlen(json);
vladounet 0:d38d192c2f5f 48
vladounet 0:d38d192c2f5f 49 if (this->pDocument) {
vladounet 0:d38d192c2f5f 50 delete this->pDocument;
vladounet 0:d38d192c2f5f 51 this->pDocument = NULL;
vladounet 0:d38d192c2f5f 52 }
vladounet 0:d38d192c2f5f 53
vladounet 0:d38d192c2f5f 54 ctPos = 0;
vladounet 0:d38d192c2f5f 55 ctLen = 0;
vladounet 0:d38d192c2f5f 56 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 57 bool ok = true;
vladounet 0:d38d192c2f5f 58 if (json[ctPos] == '{') {
vladounet 0:d38d192c2f5f 59 if (parseObject(&pDocument) != 0) {
vladounet 0:d38d192c2f5f 60 ok = false;
vladounet 0:d38d192c2f5f 61 }
vladounet 0:d38d192c2f5f 62 } else {
vladounet 0:d38d192c2f5f 63 if (parseArray(&pDocument) != 0) ok = false;
vladounet 0:d38d192c2f5f 64 }
vladounet 0:d38d192c2f5f 65 if (ct != TOKEN_EOS) {
vladounet 0:d38d192c2f5f 66 ok = false;
vladounet 0:d38d192c2f5f 67 }
vladounet 0:d38d192c2f5f 68
vladounet 0:d38d192c2f5f 69 if (!ok) {
vladounet 0:d38d192c2f5f 70 delete pDocument;
vladounet 0:d38d192c2f5f 71 pDocument = NULL;
vladounet 0:d38d192c2f5f 72 return -1;
vladounet 0:d38d192c2f5f 73 }
vladounet 0:d38d192c2f5f 74
vladounet 0:d38d192c2f5f 75 return 0;
vladounet 0:d38d192c2f5f 76 }
vladounet 0:d38d192c2f5f 77
vladounet 0:d38d192c2f5f 78 JsonValue* JsonParser::getDocument()
vladounet 0:d38d192c2f5f 79 {
vladounet 0:d38d192c2f5f 80 return pDocument;
vladounet 0:d38d192c2f5f 81 }
vladounet 0:d38d192c2f5f 82
vladounet 0:d38d192c2f5f 83 int JsonParser::goToNextToken()
vladounet 0:d38d192c2f5f 84 {
vladounet 0:d38d192c2f5f 85
vladounet 0:d38d192c2f5f 86 #ifdef DEBUG_JSONTOKENIZER
vladounet 0:d38d192c2f5f 87
vladounet 0:d38d192c2f5f 88 dbg.printf("Token: ");
vladounet 0:d38d192c2f5f 89
vladounet 0:d38d192c2f5f 90 #endif
vladounet 0:d38d192c2f5f 91
vladounet 0:d38d192c2f5f 92 ctPos += ctLen;
vladounet 0:d38d192c2f5f 93
vladounet 0:d38d192c2f5f 94 // Skip whitespaces
vladounet 0:d38d192c2f5f 95 while (ctPos < json_len &&
vladounet 0:d38d192c2f5f 96 (json[ctPos] == ' ' || json[ctPos] == '\t' ||
vladounet 0:d38d192c2f5f 97 json[ctPos] == '\r' || json[ctPos] == '\n'))
vladounet 0:d38d192c2f5f 98 ++ctPos;
vladounet 0:d38d192c2f5f 99
vladounet 0:d38d192c2f5f 100 if (ctPos < json_len) {
vladounet 0:d38d192c2f5f 101 if (json[ctPos] == '"') {
vladounet 0:d38d192c2f5f 102 ct = TOKEN_STRING;
vladounet 0:d38d192c2f5f 103 int i = ctPos+1;
vladounet 0:d38d192c2f5f 104 while (i < json_len && json[i] != '"') {
vladounet 0:d38d192c2f5f 105 if (json[i] == '\\') {
vladounet 0:d38d192c2f5f 106 if (i+1 < json_len) {
vladounet 0:d38d192c2f5f 107 switch (json[i+1]) {
vladounet 0:d38d192c2f5f 108 case '\\':
vladounet 0:d38d192c2f5f 109 case '"':
vladounet 0:d38d192c2f5f 110 case '/':
vladounet 0:d38d192c2f5f 111 case 'b':
vladounet 0:d38d192c2f5f 112 case 'f':
vladounet 0:d38d192c2f5f 113 case 'n':
vladounet 0:d38d192c2f5f 114 case 'r':
vladounet 0:d38d192c2f5f 115 case 't':
vladounet 0:d38d192c2f5f 116 ++i;
vladounet 0:d38d192c2f5f 117 break;
vladounet 0:d38d192c2f5f 118 case 'u':
vladounet 0:d38d192c2f5f 119 i+= 5;
vladounet 0:d38d192c2f5f 120 break;
vladounet 0:d38d192c2f5f 121 default:
vladounet 0:d38d192c2f5f 122 return -1;
vladounet 0:d38d192c2f5f 123 }
vladounet 0:d38d192c2f5f 124 } else {
vladounet 0:d38d192c2f5f 125 return -1;
vladounet 0:d38d192c2f5f 126 }
vladounet 0:d38d192c2f5f 127 }
vladounet 0:d38d192c2f5f 128 ++i;
vladounet 0:d38d192c2f5f 129 }
vladounet 0:d38d192c2f5f 130 if (i >= json_len || json[i] != '"') return -1;
vladounet 0:d38d192c2f5f 131 ctLen = i - ctPos + 1;
vladounet 0:d38d192c2f5f 132 } else if (isDigit(json[ctPos]) || json[ctPos] == '-') {
vladounet 0:d38d192c2f5f 133 ct = TOKEN_NUMBER;
vladounet 0:d38d192c2f5f 134 char* e;
vladounet 0:d38d192c2f5f 135 errno = 0;
vladounet 0:d38d192c2f5f 136 ctNumberVal = strtod(json+ctPos, &e);
vladounet 0:d38d192c2f5f 137 if (errno || e - json <= 0) return -1;
vladounet 0:d38d192c2f5f 138 ctLen = (e - json) - ctPos;
vladounet 0:d38d192c2f5f 139
vladounet 0:d38d192c2f5f 140 } else if (strncmp(json+ctPos,"true",4) == 0) {
vladounet 0:d38d192c2f5f 141 ct = TOKEN_TRUE;
vladounet 0:d38d192c2f5f 142 ctLen = 4;
vladounet 0:d38d192c2f5f 143 } else if (strncmp(json+ctPos,"false",5) == 0) {
vladounet 0:d38d192c2f5f 144 ct = TOKEN_FALSE;
vladounet 0:d38d192c2f5f 145 ctLen = 5;
vladounet 0:d38d192c2f5f 146 } else if (strncmp(json+ctPos,"null",4) == 0) {
vladounet 0:d38d192c2f5f 147 ct = TOKEN_NULL;
vladounet 0:d38d192c2f5f 148 ctLen = 4;
vladounet 0:d38d192c2f5f 149 } else {
vladounet 0:d38d192c2f5f 150 ct = TOKEN_DELIMITER;
vladounet 0:d38d192c2f5f 151 ctLen = 1;
vladounet 0:d38d192c2f5f 152 }
vladounet 0:d38d192c2f5f 153 } else {
vladounet 0:d38d192c2f5f 154 ct = TOKEN_EOS;
vladounet 0:d38d192c2f5f 155 ctLen = 0;
vladounet 0:d38d192c2f5f 156 }
vladounet 0:d38d192c2f5f 157
vladounet 0:d38d192c2f5f 158 #ifdef DEBUG_JSONTOKENIZER
vladounet 0:d38d192c2f5f 159
vladounet 0:d38d192c2f5f 160 switch (ct) {
vladounet 0:d38d192c2f5f 161 case TOKEN_DELIMITER:
vladounet 0:d38d192c2f5f 162 dbg.printf("Delimtier - ");
vladounet 0:d38d192c2f5f 163 break;
vladounet 0:d38d192c2f5f 164 case TOKEN_EOS:
vladounet 0:d38d192c2f5f 165 dbg.printf("End of stream");
vladounet 0:d38d192c2f5f 166 break;
vladounet 0:d38d192c2f5f 167 case TOKEN_NUMBER:
vladounet 0:d38d192c2f5f 168 dbg.printf("Number %g - ", ctNumberVal);
vladounet 0:d38d192c2f5f 169 break;
vladounet 0:d38d192c2f5f 170 case TOKEN_STRING:
vladounet 0:d38d192c2f5f 171 dbg.printf("String - ");
vladounet 0:d38d192c2f5f 172 break;
vladounet 0:d38d192c2f5f 173 case TOKEN_FALSE:
vladounet 0:d38d192c2f5f 174 dbg.printf("False - ");
vladounet 0:d38d192c2f5f 175 break;
vladounet 0:d38d192c2f5f 176 case TOKEN_TRUE:
vladounet 0:d38d192c2f5f 177 dbg.printf("True - ");
vladounet 0:d38d192c2f5f 178 break;
vladounet 0:d38d192c2f5f 179 case TOKEN_NULL:
vladounet 0:d38d192c2f5f 180 dbg.printf("Null - ");
vladounet 0:d38d192c2f5f 181 break;
vladounet 0:d38d192c2f5f 182 }
vladounet 0:d38d192c2f5f 183 if (ct != TOKEN_EOS) {
vladounet 0:d38d192c2f5f 184 for (int i = 0; i < ctLen; ++i)
vladounet 0:d38d192c2f5f 185 dbg.printf("%c", json[ctPos+i]);
vladounet 0:d38d192c2f5f 186 }
vladounet 0:d38d192c2f5f 187 dbg.printf(" (%d,%d)\r\n", ctPos, ctLen);
vladounet 0:d38d192c2f5f 188
vladounet 0:d38d192c2f5f 189 #endif
vladounet 0:d38d192c2f5f 190
vladounet 0:d38d192c2f5f 191 return 0;
vladounet 0:d38d192c2f5f 192 }
vladounet 0:d38d192c2f5f 193
vladounet 0:d38d192c2f5f 194 int JsonParser::parseObject(JsonValue** object)
vladounet 0:d38d192c2f5f 195 {
vladounet 0:d38d192c2f5f 196
vladounet 0:d38d192c2f5f 197 #ifdef DEBUG_JSONPARSER
vladounet 0:d38d192c2f5f 198 dbg.printf("Enter parseObject\r\n");
vladounet 0:d38d192c2f5f 199 #endif
vladounet 0:d38d192c2f5f 200
vladounet 0:d38d192c2f5f 201 *object = JsonValue::createMap();
vladounet 0:d38d192c2f5f 202 map<string,JsonValue*>* m = (*object)->value.map;
vladounet 0:d38d192c2f5f 203
vladounet 0:d38d192c2f5f 204 if (ct != TOKEN_DELIMITER || json[ctPos] != '{') return -1;
vladounet 0:d38d192c2f5f 205 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 206
vladounet 0:d38d192c2f5f 207 if (ct == TOKEN_STRING) {
vladounet 0:d38d192c2f5f 208
vladounet 0:d38d192c2f5f 209 string key;
vladounet 0:d38d192c2f5f 210 key.assign(json+ctPos+1, ctLen-2);
vladounet 0:d38d192c2f5f 211
vladounet 0:d38d192c2f5f 212 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 213
vladounet 0:d38d192c2f5f 214 if (ct != TOKEN_DELIMITER || json[ctPos] != ':') return -1;
vladounet 0:d38d192c2f5f 215 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 216
vladounet 0:d38d192c2f5f 217 JsonValue* pValue;
vladounet 0:d38d192c2f5f 218 if (parseValue(&pValue) != 0) {
vladounet 0:d38d192c2f5f 219 delete pValue;
vladounet 0:d38d192c2f5f 220 return -1;
vladounet 0:d38d192c2f5f 221 }
vladounet 0:d38d192c2f5f 222 (*m)[key] = pValue;
vladounet 0:d38d192c2f5f 223
vladounet 0:d38d192c2f5f 224 while (ct == TOKEN_DELIMITER && json[ctPos] == ',') {
vladounet 0:d38d192c2f5f 225 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 226
vladounet 0:d38d192c2f5f 227 if (ct != TOKEN_STRING) return -1;
vladounet 0:d38d192c2f5f 228 key.assign(json+ctPos+1, ctLen-2);
vladounet 0:d38d192c2f5f 229 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 230
vladounet 0:d38d192c2f5f 231 if (ct != TOKEN_DELIMITER || json[ctPos] != ':') return -1;
vladounet 0:d38d192c2f5f 232 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 233
vladounet 0:d38d192c2f5f 234 if (parseValue(&pValue) != 0) {
vladounet 0:d38d192c2f5f 235 delete pValue;
vladounet 0:d38d192c2f5f 236 return -1;
vladounet 0:d38d192c2f5f 237 }
vladounet 0:d38d192c2f5f 238 (*m)[key] = pValue;
vladounet 0:d38d192c2f5f 239 }
vladounet 0:d38d192c2f5f 240 }
vladounet 0:d38d192c2f5f 241
vladounet 0:d38d192c2f5f 242 if (ct != TOKEN_DELIMITER || json[ctPos] != '}') return -1;
vladounet 0:d38d192c2f5f 243 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 244
vladounet 0:d38d192c2f5f 245 #ifdef DEBUG_JSONPARSER
vladounet 0:d38d192c2f5f 246 dbg.printf("Exit parseObject\r\n");
vladounet 0:d38d192c2f5f 247 #endif
vladounet 0:d38d192c2f5f 248 return 0;
vladounet 0:d38d192c2f5f 249 }
vladounet 0:d38d192c2f5f 250
vladounet 0:d38d192c2f5f 251 int JsonParser::parseValue(JsonValue** value)
vladounet 0:d38d192c2f5f 252 {
vladounet 0:d38d192c2f5f 253
vladounet 0:d38d192c2f5f 254 #ifdef DEBUG_JSONPARSER
vladounet 0:d38d192c2f5f 255 dbg.printf("Enter parseValue\r\n");
vladounet 0:d38d192c2f5f 256 #endif
vladounet 0:d38d192c2f5f 257
vladounet 0:d38d192c2f5f 258 switch (ct) {
vladounet 0:d38d192c2f5f 259 case TOKEN_STRING:
vladounet 0:d38d192c2f5f 260 *value = JsonValue::createString(json+ctPos+1,ctLen-2);
vladounet 0:d38d192c2f5f 261 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 262 break;
vladounet 0:d38d192c2f5f 263 case TOKEN_NUMBER:
vladounet 0:d38d192c2f5f 264 *value = JsonValue::createDouble(ctNumberVal);
vladounet 0:d38d192c2f5f 265 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 266 break;
vladounet 0:d38d192c2f5f 267 case TOKEN_NULL:
vladounet 0:d38d192c2f5f 268 *value = JsonValue::createNull();
vladounet 0:d38d192c2f5f 269 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 270 break;
vladounet 0:d38d192c2f5f 271 case TOKEN_FALSE:
vladounet 0:d38d192c2f5f 272 *value = JsonValue::createBoolean(false);
vladounet 0:d38d192c2f5f 273 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 274 break;
vladounet 0:d38d192c2f5f 275 case TOKEN_TRUE:
vladounet 0:d38d192c2f5f 276 *value = JsonValue::createBoolean(true);
vladounet 0:d38d192c2f5f 277 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 278 break;
vladounet 0:d38d192c2f5f 279 case TOKEN_DELIMITER:
vladounet 0:d38d192c2f5f 280 if (json[ctPos] == '{') {
vladounet 0:d38d192c2f5f 281 if (parseObject(value) != 0) return -1;
vladounet 0:d38d192c2f5f 282 } else if (json[ctPos] == '[') {
vladounet 0:d38d192c2f5f 283 if (parseArray(value) != 0) return -1;
vladounet 0:d38d192c2f5f 284 }
vladounet 0:d38d192c2f5f 285 break;
vladounet 0:d38d192c2f5f 286 default:
vladounet 0:d38d192c2f5f 287 *value = JsonValue::createNull();
vladounet 0:d38d192c2f5f 288 return -1;
vladounet 0:d38d192c2f5f 289 }
vladounet 0:d38d192c2f5f 290
vladounet 0:d38d192c2f5f 291 #ifdef DEBUG_JSONPARSER
vladounet 0:d38d192c2f5f 292 dbg.printf("Exit parseValue\r\n");
vladounet 0:d38d192c2f5f 293 #endif
vladounet 0:d38d192c2f5f 294
vladounet 0:d38d192c2f5f 295 return 0;
vladounet 0:d38d192c2f5f 296 }
vladounet 0:d38d192c2f5f 297
vladounet 0:d38d192c2f5f 298 int JsonParser::parseArray(JsonValue** array)
vladounet 0:d38d192c2f5f 299 {
vladounet 0:d38d192c2f5f 300
vladounet 0:d38d192c2f5f 301 #ifdef DEBUG_JSONPARSER
vladounet 0:d38d192c2f5f 302 dbg.printf("Enter parseArray\r\n");
vladounet 0:d38d192c2f5f 303 #endif
vladounet 0:d38d192c2f5f 304
vladounet 0:d38d192c2f5f 305 *array = JsonValue::createVector();
vladounet 0:d38d192c2f5f 306 vector<JsonValue*>* vec = (*array)->value.vec;
vladounet 0:d38d192c2f5f 307
vladounet 0:d38d192c2f5f 308 if (ct != TOKEN_DELIMITER || json[ctPos] != '[') return -1;
vladounet 0:d38d192c2f5f 309 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 310
vladounet 0:d38d192c2f5f 311 if (ct != TOKEN_DELIMITER || json[ctPos] != ']') {
vladounet 0:d38d192c2f5f 312
vladounet 0:d38d192c2f5f 313 JsonValue* pValue;
vladounet 0:d38d192c2f5f 314 if (parseValue(&pValue) != 0) {
vladounet 0:d38d192c2f5f 315 delete pValue;
vladounet 0:d38d192c2f5f 316 return -1;
vladounet 0:d38d192c2f5f 317 };
vladounet 0:d38d192c2f5f 318 vec->push_back(pValue);
vladounet 0:d38d192c2f5f 319
vladounet 0:d38d192c2f5f 320 while (ct == TOKEN_DELIMITER && json[ctPos] == ',') {
vladounet 0:d38d192c2f5f 321 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 322
vladounet 0:d38d192c2f5f 323 if (parseValue(&pValue) != 0) {
vladounet 0:d38d192c2f5f 324 delete pValue;
vladounet 0:d38d192c2f5f 325 return -1;
vladounet 0:d38d192c2f5f 326 };
vladounet 0:d38d192c2f5f 327 vec->push_back(pValue);
vladounet 0:d38d192c2f5f 328 }
vladounet 0:d38d192c2f5f 329 }
vladounet 0:d38d192c2f5f 330
vladounet 0:d38d192c2f5f 331 if (ct != TOKEN_DELIMITER || json[ctPos] != ']') return -1;
vladounet 0:d38d192c2f5f 332 if (goToNextToken() != 0) return -1;
vladounet 0:d38d192c2f5f 333
vladounet 0:d38d192c2f5f 334 #ifdef DEBUG_JSONPARSER
vladounet 0:d38d192c2f5f 335 dbg.printf("Exit parseArray\r\n");
vladounet 0:d38d192c2f5f 336 #endif
vladounet 0:d38d192c2f5f 337
vladounet 0:d38d192c2f5f 338 return 0;
vladounet 0:d38d192c2f5f 339 }
vladounet 0:d38d192c2f5f 340
vladounet 0:d38d192c2f5f 341 int inst = 0;
vladounet 0:d38d192c2f5f 342
vladounet 0:d38d192c2f5f 343 JsonValue::JsonValue(const char* buffer, int len)
vladounet 0:d38d192c2f5f 344 {
vladounet 0:d38d192c2f5f 345 type = VT_CHAR_PTR;
vladounet 0:d38d192c2f5f 346 value.s = new char[len+1];
vladounet 0:d38d192c2f5f 347 strncpy(value.s, buffer, len);
vladounet 0:d38d192c2f5f 348 value.s[len] = '\0';
vladounet 0:d38d192c2f5f 349 }
vladounet 0:d38d192c2f5f 350
vladounet 0:d38d192c2f5f 351 JsonValue::JsonValue(double d)
vladounet 0:d38d192c2f5f 352 {
vladounet 0:d38d192c2f5f 353 type = VT_DOUBLE;
vladounet 0:d38d192c2f5f 354 value.d = d;
vladounet 0:d38d192c2f5f 355 }
vladounet 0:d38d192c2f5f 356
vladounet 0:d38d192c2f5f 357 JsonValue::JsonValue(bool b)
vladounet 0:d38d192c2f5f 358 {
vladounet 0:d38d192c2f5f 359 type = b ? VT_CST_TRUE : VT_CST_FALSE;
vladounet 0:d38d192c2f5f 360
vladounet 0:d38d192c2f5f 361 }
vladounet 0:d38d192c2f5f 362
vladounet 0:d38d192c2f5f 363 JsonValue::JsonValue()
vladounet 0:d38d192c2f5f 364 {
vladounet 0:d38d192c2f5f 365 }
vladounet 0:d38d192c2f5f 366
vladounet 0:d38d192c2f5f 367 JsonValue::~JsonValue()
vladounet 0:d38d192c2f5f 368 {
vladounet 0:d38d192c2f5f 369 switch (type) {
vladounet 0:d38d192c2f5f 370 case VT_CHAR_PTR:
vladounet 0:d38d192c2f5f 371 delete[] value.s;
vladounet 0:d38d192c2f5f 372 break;
vladounet 0:d38d192c2f5f 373 case VT_MAP_PTR:
vladounet 0:d38d192c2f5f 374 for (map<string,JsonValue*>::iterator itr = value.map->begin(); itr != value.map->end(); itr++)
vladounet 0:d38d192c2f5f 375 delete ((*itr).second);
vladounet 0:d38d192c2f5f 376 delete value.map;
vladounet 0:d38d192c2f5f 377 break;
vladounet 0:d38d192c2f5f 378 case VT_VEC_PTR:
vladounet 0:d38d192c2f5f 379 for (vector<JsonValue*>::iterator itr = value.vec->begin(); itr != value.vec->end(); itr++)
vladounet 0:d38d192c2f5f 380 delete (*itr);
vladounet 0:d38d192c2f5f 381 delete value.vec;
vladounet 0:d38d192c2f5f 382 break;
vladounet 0:d38d192c2f5f 383 default:
vladounet 0:d38d192c2f5f 384 break;
vladounet 0:d38d192c2f5f 385 }
vladounet 0:d38d192c2f5f 386 }
vladounet 0:d38d192c2f5f 387
vladounet 0:d38d192c2f5f 388 JsonValue* JsonValue::createString(const char* buffer, int len)
vladounet 0:d38d192c2f5f 389 {
vladounet 0:d38d192c2f5f 390 return new JsonValue(buffer, len);
vladounet 0:d38d192c2f5f 391 }
vladounet 0:d38d192c2f5f 392
vladounet 0:d38d192c2f5f 393 JsonValue* JsonValue::createDouble(double d)
vladounet 0:d38d192c2f5f 394 {
vladounet 0:d38d192c2f5f 395 return new JsonValue(d);
vladounet 0:d38d192c2f5f 396 }
vladounet 0:d38d192c2f5f 397
vladounet 0:d38d192c2f5f 398 JsonValue* JsonValue::createBoolean(bool b)
vladounet 0:d38d192c2f5f 399 {
vladounet 0:d38d192c2f5f 400 return new JsonValue(b);
vladounet 0:d38d192c2f5f 401 }
vladounet 0:d38d192c2f5f 402
vladounet 0:d38d192c2f5f 403 JsonValue* JsonValue::createMap()
vladounet 0:d38d192c2f5f 404 {
vladounet 0:d38d192c2f5f 405 JsonValue* ret = new JsonValue();
vladounet 0:d38d192c2f5f 406 ret->type = VT_MAP_PTR;
vladounet 0:d38d192c2f5f 407 ret->value.map = new map<string,JsonValue*>();
vladounet 0:d38d192c2f5f 408 return ret;
vladounet 0:d38d192c2f5f 409 }
vladounet 0:d38d192c2f5f 410
vladounet 0:d38d192c2f5f 411 JsonValue* JsonValue::createVector()
vladounet 0:d38d192c2f5f 412 {
vladounet 0:d38d192c2f5f 413 JsonValue* ret = new JsonValue();
vladounet 0:d38d192c2f5f 414 ret->type = VT_VEC_PTR;
vladounet 0:d38d192c2f5f 415 ret->value.vec = new vector<JsonValue*>();
vladounet 0:d38d192c2f5f 416 return ret;
vladounet 0:d38d192c2f5f 417 }
vladounet 0:d38d192c2f5f 418
vladounet 0:d38d192c2f5f 419 JsonValue* JsonValue::createNull()
vladounet 0:d38d192c2f5f 420 {
vladounet 0:d38d192c2f5f 421 JsonValue* ret = new JsonValue();
vladounet 0:d38d192c2f5f 422 ret->type = VT_CST_NULL;
vladounet 0:d38d192c2f5f 423 return ret;
vladounet 0:d38d192c2f5f 424 }
vladounet 0:d38d192c2f5f 425
vladounet 0:d38d192c2f5f 426 void JsonValue::print()
vladounet 0:d38d192c2f5f 427 {
vladounet 0:d38d192c2f5f 428 bool c = false;
vladounet 0:d38d192c2f5f 429 switch (type) {
vladounet 0:d38d192c2f5f 430 case VT_CHAR_PTR:
vladounet 0:d38d192c2f5f 431 dbg.printf("\"%s\"", value.s);
vladounet 0:d38d192c2f5f 432 break;
vladounet 0:d38d192c2f5f 433 case VT_MAP_PTR:
vladounet 0:d38d192c2f5f 434 dbg.printf("{");
vladounet 0:d38d192c2f5f 435 for (map<string,JsonValue*>::iterator itr = value.map->begin(); itr != value.map->end(); itr++) {
vladounet 0:d38d192c2f5f 436 if (c) dbg.printf(",");
vladounet 0:d38d192c2f5f 437 else c = true;
vladounet 0:d38d192c2f5f 438 dbg.printf("\"%s\":",(*itr).first.c_str());
vladounet 0:d38d192c2f5f 439 (*itr).second->print();
vladounet 0:d38d192c2f5f 440 }
vladounet 0:d38d192c2f5f 441 dbg.printf("}");
vladounet 0:d38d192c2f5f 442 break;
vladounet 0:d38d192c2f5f 443 case VT_VEC_PTR:
vladounet 0:d38d192c2f5f 444 dbg.printf("[");
vladounet 0:d38d192c2f5f 445 for (vector<JsonValue*>::iterator itr = value.vec->begin(); itr != value.vec->end(); itr++) {
vladounet 0:d38d192c2f5f 446 if (c) dbg.printf(",");
vladounet 0:d38d192c2f5f 447 else c = true;
vladounet 0:d38d192c2f5f 448 (*itr)->print();
vladounet 0:d38d192c2f5f 449 }
vladounet 0:d38d192c2f5f 450 dbg.printf("]");
vladounet 0:d38d192c2f5f 451 break;
vladounet 0:d38d192c2f5f 452 case VT_DOUBLE:
vladounet 0:d38d192c2f5f 453 dbg.printf("%g", value.d);
vladounet 0:d38d192c2f5f 454 break;
vladounet 0:d38d192c2f5f 455 case VT_CST_TRUE:
vladounet 0:d38d192c2f5f 456 dbg.printf("true");
vladounet 0:d38d192c2f5f 457 break;
vladounet 0:d38d192c2f5f 458 case VT_CST_FALSE:
vladounet 0:d38d192c2f5f 459 dbg.printf("false");
vladounet 0:d38d192c2f5f 460 break;
vladounet 0:d38d192c2f5f 461 case VT_CST_NULL:
vladounet 0:d38d192c2f5f 462 dbg.printf("null");
vladounet 0:d38d192c2f5f 463 break;
vladounet 0:d38d192c2f5f 464 default:
vladounet 0:d38d192c2f5f 465 break;
vladounet 0:d38d192c2f5f 466 }
vladounet 0:d38d192c2f5f 467 }
vladounet 0:d38d192c2f5f 468
vladounet 0:d38d192c2f5f 469 JsonValue* JsonValue::get(const char* path)
vladounet 0:d38d192c2f5f 470 {
vladounet 0:d38d192c2f5f 471 JsonValue* pValue = this;
vladounet 0:d38d192c2f5f 472 int pos = 0;
vladounet 0:d38d192c2f5f 473 while (path != NULL && path[pos] != '\0') {
vladounet 0:d38d192c2f5f 474
vladounet 0:d38d192c2f5f 475 #ifdef DEBUG_JSONGET
vladounet 0:d38d192c2f5f 476 dbg.printf("::get ");
vladounet 0:d38d192c2f5f 477 pValue->print();
vladounet 0:d38d192c2f5f 478 dbg.printf("\r\n");
vladounet 0:d38d192c2f5f 479 #endif
vladounet 0:d38d192c2f5f 480
vladounet 0:d38d192c2f5f 481 const char* start = path+pos;
vladounet 0:d38d192c2f5f 482 const char* pSl = strchr(start, '/');
vladounet 0:d38d192c2f5f 483 int len = pSl == NULL ? strlen(start) : pSl - start;
vladounet 0:d38d192c2f5f 484 if (len <= 0) return NULL;
vladounet 0:d38d192c2f5f 485 if (pValue->type == VT_VEC_PTR) {
vladounet 0:d38d192c2f5f 486 int v = atoi(start);
vladounet 0:d38d192c2f5f 487 if (v == 0 && path[pos] != '0') {
vladounet 0:d38d192c2f5f 488 return NULL;
vladounet 0:d38d192c2f5f 489 }
vladounet 0:d38d192c2f5f 490 if (v < 0 || v >= pValue->value.vec->size()) {
vladounet 0:d38d192c2f5f 491 return NULL;
vladounet 0:d38d192c2f5f 492 }
vladounet 0:d38d192c2f5f 493 pValue = (*pValue->value.vec)[v];
vladounet 0:d38d192c2f5f 494 } else if (pValue->type == VT_MAP_PTR) {
vladounet 0:d38d192c2f5f 495 char* pKey = new char[len+1];
vladounet 0:d38d192c2f5f 496 strncpy(pKey, start, len);
vladounet 0:d38d192c2f5f 497 pKey[len] = '\0';
vladounet 0:d38d192c2f5f 498 pValue = (*pValue->value.map)[pKey];
vladounet 0:d38d192c2f5f 499 delete[] pKey;
vladounet 0:d38d192c2f5f 500 if (pValue == NULL) {
vladounet 0:d38d192c2f5f 501 return NULL;
vladounet 0:d38d192c2f5f 502 }
vladounet 0:d38d192c2f5f 503 } else {
vladounet 0:d38d192c2f5f 504 return NULL;
vladounet 0:d38d192c2f5f 505 }
vladounet 0:d38d192c2f5f 506 pos += len;
vladounet 0:d38d192c2f5f 507 if (pSl) ++pos;
vladounet 0:d38d192c2f5f 508 }
vladounet 0:d38d192c2f5f 509
vladounet 0:d38d192c2f5f 510 #ifdef DEBUG_JSONGET
vladounet 0:d38d192c2f5f 511 dbg.printf("::get ");
vladounet 0:d38d192c2f5f 512 pValue->print();
vladounet 0:d38d192c2f5f 513 dbg.printf("\r\n");
vladounet 0:d38d192c2f5f 514 #endif
vladounet 0:d38d192c2f5f 515
vladounet 0:d38d192c2f5f 516 return pValue;
vladounet 0:d38d192c2f5f 517 }
vladounet 0:d38d192c2f5f 518
vladounet 0:d38d192c2f5f 519 const double* JsonValue::getDouble(const char* path)
vladounet 0:d38d192c2f5f 520 {
vladounet 0:d38d192c2f5f 521 JsonValue* pV = get(path);
vladounet 0:d38d192c2f5f 522 if (pV != NULL && pV->type == VT_DOUBLE) {
vladounet 0:d38d192c2f5f 523 return &(pV->value.d);
vladounet 0:d38d192c2f5f 524 } else {
vladounet 0:d38d192c2f5f 525 return NULL;
vladounet 0:d38d192c2f5f 526 }
vladounet 0:d38d192c2f5f 527 }
vladounet 0:d38d192c2f5f 528
vladounet 0:d38d192c2f5f 529 const char* JsonValue::getString(const char* path)
vladounet 0:d38d192c2f5f 530 {
vladounet 0:d38d192c2f5f 531 JsonValue* pV = get(path);
vladounet 0:d38d192c2f5f 532 if (pV != NULL && pV->type == VT_CHAR_PTR) {
vladounet 0:d38d192c2f5f 533 return pV->value.s;
vladounet 0:d38d192c2f5f 534 } else {
vladounet 0:d38d192c2f5f 535 return NULL;
vladounet 0:d38d192c2f5f 536 }
vladounet 0:d38d192c2f5f 537 }
vladounet 0:d38d192c2f5f 538 const std::vector<JsonValue*>* JsonValue::getVector(const char* path)
vladounet 0:d38d192c2f5f 539 {
vladounet 0:d38d192c2f5f 540 JsonValue* pV = get(path);
vladounet 0:d38d192c2f5f 541 if (pV != NULL && pV->type == VT_VEC_PTR) {
vladounet 0:d38d192c2f5f 542 return pV->value.vec;
vladounet 0:d38d192c2f5f 543 } else {
vladounet 0:d38d192c2f5f 544 return NULL;
vladounet 0:d38d192c2f5f 545 }
vladounet 0:d38d192c2f5f 546 }
vladounet 0:d38d192c2f5f 547 const std::map<std::string,JsonValue*>* JsonValue::getMap(const char* path)
vladounet 0:d38d192c2f5f 548 {
vladounet 0:d38d192c2f5f 549 JsonValue* pV = get(path);
vladounet 0:d38d192c2f5f 550 if (pV != NULL && pV->type == VT_MAP_PTR) {
vladounet 0:d38d192c2f5f 551 return pV->value.map;
vladounet 0:d38d192c2f5f 552 } else {
vladounet 0:d38d192c2f5f 553 return NULL;
vladounet 0:d38d192c2f5f 554 }
vladounet 0:d38d192c2f5f 555 }
vladounet 0:d38d192c2f5f 556
vladounet 0:d38d192c2f5f 557 static const bool FALSE = false;
vladounet 0:d38d192c2f5f 558 static const bool TRUE = true;
vladounet 0:d38d192c2f5f 559
vladounet 0:d38d192c2f5f 560 const bool* JsonValue::getBoolean(const char* path)
vladounet 0:d38d192c2f5f 561 {
vladounet 0:d38d192c2f5f 562 JsonValue* pV = get(path);
vladounet 0:d38d192c2f5f 563 if (pV != NULL && (pV->type == VT_CST_TRUE || pV->type == VT_CST_FALSE)) {
vladounet 0:d38d192c2f5f 564 return (pV->type == VT_CST_TRUE) ? &TRUE : &FALSE;
vladounet 0:d38d192c2f5f 565 } else {
vladounet 0:d38d192c2f5f 566 return NULL;
vladounet 0:d38d192c2f5f 567 }
vladounet 0:d38d192c2f5f 568 }
vladounet 0:d38d192c2f5f 569 bool JsonValue::isNull(const char* path)
vladounet 0:d38d192c2f5f 570 {
vladounet 0:d38d192c2f5f 571 JsonValue* pV = get(path);
vladounet 0:d38d192c2f5f 572 return (pV != NULL) && (pV->type == VT_CST_NULL);
vladounet 0:d38d192c2f5f 573 }
vladounet 0:d38d192c2f5f 574