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