Api wrapper to communicate with EVRYTHNG's Engine.
Dependencies: EthernetInterface mbed-rtos
Dependents: EvrythngApiExample
JsonParser.cpp@1:7162d0e030f5, 2012-08-30 (annotated)
- 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?
User | Revision | Line number | New 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 |