Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
json.c
00001 /******************************************************************************* 00002 * 00003 * Copyright (c) 2015 Intel Corporation and others. 00004 * All rights reserved. This program and the accompanying materials 00005 * are made available under the terms of the Eclipse Public License v1.0 00006 * and Eclipse Distribution License v1.0 which accompany this distribution. 00007 * 00008 * The Eclipse Public License is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * The Eclipse Distribution License is available at 00011 * http://www.eclipse.org/org/documents/edl-v10.php. 00012 * 00013 * Contributors: 00014 * David Navarro, Intel Corporation - initial API and implementation 00015 * 00016 *******************************************************************************/ 00017 00018 00019 #include "internals.h" 00020 #include <stdlib.h> 00021 #include <string.h> 00022 #include <stdio.h> 00023 #include <inttypes.h> 00024 00025 00026 #ifdef LWM2M_SUPPORT_JSON 00027 00028 #define PRV_JSON_BUFFER_SIZE 1024 00029 00030 #define JSON_MIN_ARRAY_LEN 21 // e":[{"n":"N","v":X}]} 00031 #define JSON_MIN_BASE_LEN 7 // n":"N", 00032 #define JSON_ITEM_MAX_SIZE 36 // with ten characters for value 00033 #define JSON_MIN_BX_LEN 5 // bt":1 00034 00035 #define JSON_FALSE_STRING "false" 00036 #define JSON_TRUE_STRING "true" 00037 00038 #define JSON_RES_ITEM_URI "{\"n\":\"" 00039 #define JSON_RES_ITEM_URI_SIZE 6 00040 #define JSON_ITEM_BOOL_TRUE "\",\"bv\":true}," 00041 #define JSON_ITEM_BOOL_TRUE_SIZE 13 00042 #define JSON_ITEM_BOOL_FALSE "\",\"bv\":false}," 00043 #define JSON_ITEM_BOOL_FALSE_SIZE 14 00044 #define JSON_ITEM_NUM "\",\"v\":" 00045 #define JSON_ITEM_NUM_SIZE 6 00046 #define JSON_ITEM_NUM_END "}," 00047 #define JSON_ITEM_NUM_END_SIZE 2 00048 #define JSON_ITEM_STRING_BEGIN "\",\"sv\":\"" 00049 #define JSON_ITEM_STRING_BEGIN_SIZE 8 00050 #define JSON_ITEM_STRING_END "\"}," 00051 #define JSON_ITEM_STRING_END_SIZE 3 00052 00053 #define JSON_BN_HEADER_1 "{\"bn\":\"" 00054 #define JSON_BN_HEADER_1_SIZE 7 00055 #define JSON_BN_HEADER_2 "\",\"e\":[" 00056 #define JSON_BN_HEADER_2_SIZE 7 00057 #define JSON_HEADER "{\"e\":[" 00058 #define JSON_HEADER_SIZE 6 00059 #define JSON_FOOTER "]}" 00060 #define JSON_FOOTER_SIZE 2 00061 00062 00063 #define _GO_TO_NEXT_CHAR(I,B,L) \ 00064 { \ 00065 I++; \ 00066 I += prv_skipSpace(B+I, L-I); \ 00067 if (I == L) goto error; \ 00068 } 00069 00070 typedef enum 00071 { 00072 _STEP_START, 00073 _STEP_TOKEN, 00074 _STEP_ANY_SEPARATOR, 00075 _STEP_SEPARATOR, 00076 _STEP_QUOTED_VALUE, 00077 _STEP_VALUE, 00078 _STEP_DONE 00079 } _itemState; 00080 00081 typedef enum 00082 { 00083 _TYPE_UNSET, 00084 _TYPE_FALSE, 00085 _TYPE_TRUE, 00086 _TYPE_FLOAT, 00087 _TYPE_STRING 00088 } _type; 00089 00090 typedef struct 00091 { 00092 uint16_t ids[4]; 00093 _type type; 00094 uint8_t * value; 00095 size_t valueLen; 00096 } _record_t; 00097 00098 static int prv_isReserved(char sign) 00099 { 00100 if (sign == '[' 00101 || sign == '{' 00102 || sign == ']' 00103 || sign == '}' 00104 || sign == ':' 00105 || sign == ',' 00106 || sign == '"') 00107 { 00108 return 1; 00109 } 00110 00111 return 0; 00112 } 00113 00114 static int prv_isWhiteSpace(uint8_t sign) 00115 { 00116 if (sign == 0x20 00117 || sign == 0x09 00118 || sign == 0x0A 00119 || sign == 0x0D) 00120 { 00121 return 1; 00122 } 00123 00124 return 0; 00125 } 00126 00127 static size_t prv_skipSpace(uint8_t * buffer, 00128 size_t bufferLen) 00129 { 00130 size_t i; 00131 00132 i = 0; 00133 while ((i < bufferLen) 00134 && prv_isWhiteSpace(buffer[i])) 00135 { 00136 i++; 00137 } 00138 00139 return i; 00140 } 00141 00142 static int prv_split(uint8_t * buffer, 00143 size_t bufferLen, 00144 int * tokenStartP, 00145 int * tokenLenP, 00146 int * valueStartP, 00147 int * valueLenP) 00148 { 00149 size_t index; 00150 _itemState step; 00151 00152 index = 0; 00153 step = _STEP_START; 00154 00155 index = prv_skipSpace(buffer + index, bufferLen - index); 00156 if (index == bufferLen) return -1; 00157 00158 while ((index < bufferLen) 00159 && (buffer[index] != ',')) 00160 { 00161 switch (step) 00162 { 00163 case _STEP_START: 00164 if (buffer[index] != '"') return -1; 00165 *tokenStartP = index+1; 00166 step = _STEP_TOKEN; 00167 break; 00168 00169 case _STEP_TOKEN: 00170 if (buffer[index] == '"') 00171 { 00172 *tokenLenP = index - *tokenStartP; 00173 step = _STEP_ANY_SEPARATOR; 00174 } 00175 break; 00176 00177 case _STEP_ANY_SEPARATOR: 00178 if (buffer[index] != ':') return -1; 00179 step = _STEP_SEPARATOR; 00180 break; 00181 00182 case _STEP_SEPARATOR: 00183 if (buffer[index] == '"') 00184 { 00185 *valueStartP = index; 00186 step = _STEP_QUOTED_VALUE; 00187 } else if (!prv_isReserved(buffer[index])) 00188 { 00189 *valueStartP = index; 00190 step = _STEP_VALUE; 00191 } else 00192 { 00193 return -1; 00194 } 00195 break; 00196 00197 case _STEP_QUOTED_VALUE: 00198 if (buffer[index] == '"' && buffer[index-1] != '\\' ) 00199 { 00200 *valueLenP = index - *valueStartP + 1; 00201 step = _STEP_DONE; 00202 } 00203 break; 00204 00205 case _STEP_VALUE: 00206 if (prv_isWhiteSpace(buffer[index])) 00207 { 00208 *valueLenP = index - *valueStartP; 00209 step = _STEP_DONE; 00210 } 00211 break; 00212 00213 case _STEP_DONE: 00214 default: 00215 return -1; 00216 } 00217 00218 index++; 00219 if (step == _STEP_START 00220 || step == _STEP_ANY_SEPARATOR 00221 || step == _STEP_SEPARATOR 00222 || step == _STEP_DONE) 00223 { 00224 index += prv_skipSpace(buffer + index, bufferLen - index); 00225 } 00226 } 00227 00228 if (step == _STEP_VALUE) 00229 { 00230 *valueLenP = index - *valueStartP; 00231 step = _STEP_DONE; 00232 } 00233 00234 if (step != _STEP_DONE) return -1; 00235 00236 return (int)index; 00237 } 00238 00239 static int prv_countItems(uint8_t * buffer, 00240 size_t bufferLen) 00241 { 00242 int count; 00243 size_t index; 00244 int in; 00245 00246 count = 0; 00247 index = 0; 00248 in = 0; 00249 00250 while (index < bufferLen) 00251 { 00252 if (in == 0) 00253 { 00254 if (buffer[index] != '{') return -1; 00255 in = 1; 00256 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00257 } 00258 else 00259 { 00260 if (buffer[index] == '{') return -1; 00261 if (buffer[index] == '}') 00262 { 00263 in = 0; 00264 count++; 00265 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00266 if (buffer[index] == ']') 00267 { 00268 break; 00269 } 00270 if (buffer[index] != ',') return -1; 00271 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00272 } 00273 else 00274 { 00275 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00276 } 00277 } 00278 } 00279 if (in == 1) return -1; 00280 00281 return count; 00282 00283 error: 00284 return -1; 00285 } 00286 00287 static int prv_parseItem(uint8_t * buffer, 00288 size_t bufferLen, 00289 _record_t * recordP) 00290 { 00291 size_t index; 00292 00293 memset(recordP->ids, 0xFF, 4*sizeof(uint16_t)); 00294 recordP->type = _TYPE_UNSET; 00295 recordP->value = NULL; 00296 recordP->valueLen = 0; 00297 00298 index = 0; 00299 do 00300 { 00301 int tokenStart; 00302 int tokenLen; 00303 int valueStart; 00304 int valueLen; 00305 int next; 00306 00307 next = prv_split(buffer+index, bufferLen-index, &tokenStart, &tokenLen, &valueStart, &valueLen); 00308 if (next < 0) return -1; 00309 00310 switch (tokenLen) 00311 { 00312 case 1: 00313 { 00314 switch (buffer[index+tokenStart]) 00315 { 00316 case 'n': 00317 { 00318 int i; 00319 int j; 00320 00321 if (recordP->ids[0] != LWM2M_MAX_ID) return -1; 00322 00323 // Check for " around URI 00324 if (valueLen < 3 00325 || buffer[index+valueStart] != '"' 00326 || buffer[index+valueStart+valueLen-1] != '"') 00327 { 00328 return -1; 00329 } 00330 // Ignore starting / 00331 if (buffer[index + valueStart + 1] == '/') 00332 { 00333 if (valueLen < 4) 00334 { 00335 return -1; 00336 } 00337 valueStart += 1; 00338 valueLen -= 1; 00339 } 00340 i = 0; 00341 j = 0; 00342 do { 00343 uint32_t readId; 00344 00345 readId = 0; 00346 i++; 00347 while (i < valueLen-1 && buffer[index+valueStart+i] != '/') 00348 { 00349 if (buffer[index+valueStart+i] < '0' 00350 || buffer[index+valueStart+i] > '9') 00351 { 00352 return -1; 00353 } 00354 readId *= 10; 00355 readId += buffer[index+valueStart+i] - '0'; 00356 if (readId > LWM2M_MAX_ID) return -1; 00357 i++; 00358 } 00359 recordP->ids[j] = readId; 00360 j++; 00361 } while (i < valueLen-1 && j < 4 && buffer[index+valueStart+i] == '/'); 00362 if (i < valueLen-1 ) return -1; 00363 } 00364 break; 00365 00366 case 'v': 00367 if (recordP->type != _TYPE_UNSET) return -1; 00368 recordP->type = _TYPE_FLOAT; 00369 recordP->value = buffer + index + valueStart; 00370 recordP->valueLen = valueLen; 00371 break; 00372 00373 case 't': 00374 // TODO: support time 00375 break; 00376 00377 default: 00378 return -1; 00379 } 00380 } 00381 break; 00382 00383 case 2: 00384 { 00385 // "bv", "ov", or "sv" 00386 if (buffer[index+tokenStart+1] != 'v') return -1; 00387 switch (buffer[index+tokenStart]) 00388 { 00389 case 'b': 00390 if (recordP->type != _TYPE_UNSET) return -1; 00391 if (0 == lwm2m_strncmp(JSON_TRUE_STRING, (char *)buffer + index + valueStart, valueLen)) 00392 { 00393 recordP->type = _TYPE_TRUE; 00394 } 00395 else if (0 == lwm2m_strncmp(JSON_FALSE_STRING, (char *)buffer + index + valueStart, valueLen)) 00396 { 00397 recordP->type = _TYPE_FALSE; 00398 } 00399 else 00400 { 00401 return -1; 00402 } 00403 break; 00404 00405 case 'o': 00406 if (recordP->type != _TYPE_UNSET) return -1; 00407 // TODO: support object link 00408 break; 00409 00410 case 's': 00411 if (recordP->type != _TYPE_UNSET) return -1; 00412 // Check for " around value 00413 if (valueLen < 2 00414 || buffer[index+valueStart] != '"' 00415 || buffer[index+valueStart+valueLen-1] != '"') 00416 { 00417 return -1; 00418 } 00419 recordP->type = _TYPE_STRING; 00420 recordP->value = buffer + index + valueStart + 1; 00421 recordP->valueLen = valueLen - 2; 00422 break; 00423 00424 default: 00425 return -1; 00426 } 00427 } 00428 break; 00429 00430 default: 00431 return -1; 00432 } 00433 00434 index += next + 1; 00435 } while (index < bufferLen); 00436 00437 return 0; 00438 } 00439 00440 static bool prv_convertValue(_record_t * recordP, 00441 lwm2m_data_t * targetP) 00442 { 00443 switch (recordP->type) 00444 { 00445 case _TYPE_FALSE: 00446 lwm2m_data_encode_bool(false, targetP); 00447 break; 00448 case _TYPE_TRUE: 00449 lwm2m_data_encode_bool(true, targetP); 00450 break; 00451 case _TYPE_FLOAT: 00452 { 00453 size_t i; 00454 00455 i = 0; 00456 while (i < recordP->valueLen 00457 && recordP->value[i] != '.') 00458 { 00459 i++; 00460 } 00461 if (i == recordP->valueLen) 00462 { 00463 int64_t value; 00464 00465 if ( 1 != utils_plainTextToInt64(recordP->value, 00466 recordP->valueLen, 00467 &value)) 00468 { 00469 return false; 00470 } 00471 00472 lwm2m_data_encode_int(value, targetP); 00473 } 00474 else 00475 { 00476 double value; 00477 00478 if ( 1 != utils_plainTextToFloat64(recordP->value, 00479 recordP->valueLen, 00480 &value)) 00481 { 00482 return false; 00483 } 00484 00485 lwm2m_data_encode_float(value, targetP); 00486 } 00487 } 00488 break; 00489 00490 case _TYPE_STRING: 00491 lwm2m_data_encode_opaque(recordP->value, recordP->valueLen, targetP); 00492 targetP->type = LWM2M_TYPE_STRING; 00493 break; 00494 00495 case _TYPE_UNSET: 00496 default: 00497 return false; 00498 } 00499 00500 return true; 00501 } 00502 00503 static lwm2m_data_t * prv_findDataItem(lwm2m_data_t * listP, 00504 int count, 00505 uint16_t id) 00506 { 00507 int i; 00508 00509 i = 0; 00510 while (i < count) 00511 { 00512 if (listP[i].type != LWM2M_TYPE_UNDEFINED && listP[i].id == id) 00513 { 00514 return listP + i; 00515 } 00516 i++; 00517 } 00518 00519 return NULL; 00520 } 00521 00522 static uri_depth_t prv_decreaseLevel(uri_depth_t level) 00523 { 00524 switch(level) 00525 { 00526 case URI_DEPTH_OBJECT: 00527 return URI_DEPTH_OBJECT_INSTANCE; 00528 case URI_DEPTH_OBJECT_INSTANCE: 00529 return URI_DEPTH_RESOURCE; 00530 case URI_DEPTH_RESOURCE: 00531 return URI_DEPTH_RESOURCE_INSTANCE; 00532 case URI_DEPTH_RESOURCE_INSTANCE: 00533 return URI_DEPTH_RESOURCE_INSTANCE; 00534 default: 00535 return URI_DEPTH_RESOURCE; 00536 } 00537 } 00538 00539 static lwm2m_data_t * prv_extendData(lwm2m_data_t * parentP) 00540 { 00541 lwm2m_data_t * newP; 00542 00543 newP = lwm2m_data_new(parentP->value.asChildren.count + 1); 00544 if (newP == NULL) return NULL; 00545 if (parentP->value.asChildren.array != NULL) 00546 { 00547 memcpy(newP, parentP->value.asChildren.array, parentP->value.asChildren.count * sizeof(lwm2m_data_t)); 00548 lwm2m_free(parentP->value.asChildren.array); // do not use lwm2m_data_free() to keep pointed values 00549 } 00550 parentP->value.asChildren.array = newP; 00551 parentP->value.asChildren.count += 1; 00552 00553 return newP + parentP->value.asChildren.count - 1; 00554 } 00555 00556 static int prv_convertRecord(lwm2m_uri_t * uriP, 00557 _record_t * recordArray, 00558 int count, 00559 lwm2m_data_t ** dataP) 00560 { 00561 int index; 00562 int freeIndex; 00563 lwm2m_data_t * rootP; 00564 int size; 00565 uri_depth_t rootLevel; 00566 00567 if (uriP == NULL) 00568 { 00569 size = count; 00570 *dataP = lwm2m_data_new(count); 00571 if (NULL == *dataP) return -1; 00572 rootLevel = URI_DEPTH_OBJECT; 00573 rootP = *dataP; 00574 } 00575 else 00576 { 00577 lwm2m_data_t * parentP; 00578 size = 1; 00579 00580 *dataP = lwm2m_data_new(1); 00581 if (NULL == *dataP) return -1; 00582 (*dataP)->type = LWM2M_TYPE_OBJECT; 00583 (*dataP)->id = uriP->objectId; 00584 rootLevel = URI_DEPTH_OBJECT_INSTANCE; 00585 parentP = *dataP; 00586 if (LWM2M_URI_IS_SET_INSTANCE(uriP)) 00587 { 00588 parentP->value.asChildren.count = 1; 00589 parentP->value.asChildren.array = lwm2m_data_new(1); 00590 if (NULL == parentP->value.asChildren.array) goto error; 00591 parentP = parentP->value.asChildren.array; 00592 parentP->type = LWM2M_TYPE_OBJECT_INSTANCE; 00593 parentP->id = uriP->instanceId; 00594 rootLevel = URI_DEPTH_RESOURCE; 00595 if (LWM2M_URI_IS_SET_RESOURCE(uriP)) 00596 { 00597 parentP->value.asChildren.count = 1; 00598 parentP->value.asChildren.array = lwm2m_data_new(1); 00599 if (NULL == parentP->value.asChildren.array) goto error; 00600 parentP = parentP->value.asChildren.array; 00601 parentP->type = LWM2M_TYPE_UNDEFINED; 00602 parentP->id = uriP->resourceId; 00603 rootLevel = URI_DEPTH_RESOURCE_INSTANCE; 00604 } 00605 } 00606 parentP->value.asChildren.count = count; 00607 parentP->value.asChildren.array = lwm2m_data_new(count); 00608 if (NULL == parentP->value.asChildren.array) goto error; 00609 rootP = parentP->value.asChildren.array; 00610 } 00611 00612 freeIndex = 0; 00613 for (index = 0 ; index < count ; index++) 00614 { 00615 lwm2m_data_t * targetP; 00616 int resSegmentIndex; 00617 int i; 00618 00619 // check URI depth 00620 // resSegmentIndex is set to the resource segment position 00621 switch(rootLevel) 00622 { 00623 case URI_DEPTH_OBJECT: 00624 resSegmentIndex = 2; 00625 break; 00626 case URI_DEPTH_OBJECT_INSTANCE: 00627 resSegmentIndex = 1; 00628 break; 00629 case URI_DEPTH_RESOURCE: 00630 resSegmentIndex = 0; 00631 break; 00632 case URI_DEPTH_RESOURCE_INSTANCE: 00633 resSegmentIndex = -1; 00634 break; 00635 default: 00636 goto error; 00637 } 00638 for (i = 0 ; i <= resSegmentIndex ; i++) 00639 { 00640 if (recordArray[index].ids[i] == LWM2M_MAX_ID) goto error; 00641 } 00642 if (resSegmentIndex < 2) 00643 { 00644 if (recordArray[index].ids[resSegmentIndex + 2] != LWM2M_MAX_ID) goto error; 00645 } 00646 00647 targetP = prv_findDataItem(rootP, count, recordArray[index].ids[0]); 00648 if (targetP == NULL) 00649 { 00650 targetP = rootP + freeIndex; 00651 freeIndex++; 00652 targetP->id = recordArray[index].ids[0]; 00653 targetP->type = utils_depthToDatatype(rootLevel); 00654 } 00655 if (recordArray[index].ids[1] != LWM2M_MAX_ID) 00656 { 00657 lwm2m_data_t * parentP; 00658 uri_depth_t level; 00659 00660 parentP = targetP; 00661 level = prv_decreaseLevel(rootLevel); 00662 for (i = 1 ; i <= resSegmentIndex ; i++) 00663 { 00664 targetP = prv_findDataItem(parentP->value.asChildren.array, parentP->value.asChildren.count, recordArray[index].ids[i]); 00665 if (targetP == NULL) 00666 { 00667 targetP = prv_extendData(parentP); 00668 if (targetP == NULL) goto error; 00669 targetP->id = recordArray[index].ids[i]; 00670 targetP->type = utils_depthToDatatype(level); 00671 } 00672 level = prv_decreaseLevel(level); 00673 parentP = targetP; 00674 } 00675 if (recordArray[index].ids[resSegmentIndex + 1] != LWM2M_MAX_ID) 00676 { 00677 targetP->type = LWM2M_TYPE_MULTIPLE_RESOURCE; 00678 targetP = prv_extendData(targetP); 00679 if (targetP == NULL) goto error; 00680 targetP->id = recordArray[index].ids[resSegmentIndex + 1]; 00681 targetP->type = LWM2M_TYPE_UNDEFINED; 00682 } 00683 } 00684 00685 if (true != prv_convertValue(recordArray + index, targetP)) goto error; 00686 } 00687 00688 return size; 00689 00690 error: 00691 lwm2m_data_free(size, *dataP); 00692 *dataP = NULL; 00693 00694 return -1; 00695 } 00696 00697 static int prv_dataStrip(int size, 00698 lwm2m_data_t * dataP, 00699 lwm2m_data_t ** resultP) 00700 { 00701 int i; 00702 int j; 00703 int realSize; 00704 00705 realSize = 0; 00706 for (i = 0 ; i < size ; i++) 00707 { 00708 if (dataP[i].type != LWM2M_TYPE_UNDEFINED) 00709 { 00710 realSize++; 00711 } 00712 } 00713 00714 *resultP = lwm2m_data_new(realSize); 00715 if (*resultP == NULL) return -1; 00716 00717 j = 0; 00718 for (i = 0 ; i < size ; i++) 00719 { 00720 if (dataP[i].type != LWM2M_TYPE_UNDEFINED) 00721 { 00722 memcpy((*resultP) + j, dataP + i, sizeof(lwm2m_data_t)); 00723 00724 if (dataP[i].type == LWM2M_TYPE_OBJECT 00725 || dataP[i].type == LWM2M_TYPE_OBJECT_INSTANCE 00726 || dataP[i].type == LWM2M_TYPE_MULTIPLE_RESOURCE) 00727 { 00728 int childLen; 00729 00730 childLen = prv_dataStrip(dataP[i].value.asChildren.count, dataP[i].value.asChildren.array, &((*resultP)[j].value.asChildren.array)); 00731 if (childLen <= 0) 00732 { 00733 // skip this one 00734 j--; 00735 } 00736 else 00737 { 00738 (*resultP)[j].value.asChildren.count = childLen; 00739 } 00740 } 00741 else 00742 { 00743 dataP[i].value.asBuffer.buffer = NULL; 00744 } 00745 00746 j++; 00747 } 00748 } 00749 00750 return realSize; 00751 } 00752 00753 int json_parse(lwm2m_uri_t * uriP, 00754 uint8_t * buffer, 00755 size_t bufferLen, 00756 lwm2m_data_t ** dataP) 00757 { 00758 size_t index; 00759 int count = 0; 00760 bool eFound = false; 00761 bool bnFound = false; 00762 bool btFound = false; 00763 int bnStart; 00764 int bnLen; 00765 _record_t * recordArray; 00766 lwm2m_data_t * parsedP; 00767 00768 LOG_ARG("bufferLen: %d, buffer: \"%s\"", bufferLen, (char *)buffer); 00769 LOG_URI(uriP); 00770 *dataP = NULL; 00771 recordArray = NULL; 00772 parsedP = NULL; 00773 00774 index = prv_skipSpace(buffer, bufferLen); 00775 if (index == bufferLen) return -1; 00776 00777 if (buffer[index] != '{') return -1; 00778 do 00779 { 00780 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00781 if (buffer[index] != '"') goto error; 00782 if (index++ >= bufferLen) goto error; 00783 switch (buffer[index]) 00784 { 00785 case 'e': 00786 { 00787 int recordIndex; 00788 00789 if (bufferLen-index < JSON_MIN_ARRAY_LEN) goto error; 00790 index++; 00791 if (buffer[index] != '"') goto error; 00792 if (eFound == true) goto error; 00793 eFound = true; 00794 00795 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00796 if (buffer[index] != ':') goto error; 00797 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00798 if (buffer[index] != '[') goto error; 00799 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00800 count = prv_countItems(buffer + index, bufferLen - index); 00801 if (count <= 0) goto error; 00802 recordArray = (_record_t*)lwm2m_malloc(count * sizeof(_record_t)); 00803 if (recordArray == NULL) goto error; 00804 // at this point we are sure buffer[index] is '{' and all { and } are matching 00805 recordIndex = 0; 00806 while (recordIndex < count) 00807 { 00808 int itemLen; 00809 00810 if (buffer[index] != '{') goto error; 00811 itemLen = 0; 00812 while (buffer[index + itemLen] != '}') itemLen++; 00813 if (0 != prv_parseItem(buffer + index + 1, itemLen - 1, recordArray + recordIndex)) 00814 { 00815 goto error; 00816 } 00817 recordIndex++; 00818 index += itemLen; 00819 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00820 switch (buffer[index]) 00821 { 00822 case ',': 00823 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00824 break; 00825 case ']': 00826 if (recordIndex == count) break; 00827 // else this is an error 00828 default: 00829 goto error; 00830 } 00831 } 00832 if (buffer[index] != ']') goto error; 00833 } 00834 break; 00835 00836 case 'b': 00837 if (bufferLen-index < JSON_MIN_BX_LEN) goto error; 00838 index++; 00839 switch (buffer[index]) 00840 { 00841 case 't': 00842 index++; 00843 if (buffer[index] != '"') goto error; 00844 if (btFound == true) goto error; 00845 btFound = true; 00846 00847 // TODO: handle timed values 00848 // temp: skip this token 00849 while(index < bufferLen && buffer[index] != ',' && buffer[index] != '}') index++; 00850 if (index == bufferLen) goto error; 00851 index--; 00852 // end temp 00853 break; 00854 case 'n': 00855 { 00856 int next; 00857 int tokenStart; 00858 int tokenLen; 00859 int itemLen; 00860 00861 index++; 00862 if (buffer[index] != '"') goto error; 00863 if (bnFound == true) goto error; 00864 bnFound = true; 00865 index -= 3; 00866 itemLen = 0; 00867 while (buffer[index + itemLen] != '}' 00868 && buffer[index + itemLen] != ',' 00869 && index + itemLen < bufferLen) 00870 { 00871 itemLen++; 00872 } 00873 if (index + itemLen == bufferLen) goto error; 00874 next = prv_split(buffer+index, itemLen, &tokenStart, &tokenLen, &bnStart, &bnLen); 00875 if (next < 0) goto error; 00876 bnStart += index; 00877 index += next - 1; 00878 } 00879 break; 00880 default: 00881 goto error; 00882 } 00883 break; 00884 00885 default: 00886 goto error; 00887 } 00888 00889 _GO_TO_NEXT_CHAR(index, buffer, bufferLen); 00890 } while (buffer[index] == ','); 00891 00892 if (buffer[index] != '}') goto error; 00893 00894 if (eFound == true) 00895 { 00896 lwm2m_uri_t baseURI; 00897 lwm2m_uri_t * baseUriP; 00898 lwm2m_data_t * resultP; 00899 int size; 00900 00901 memset(&baseURI, 0, sizeof(lwm2m_uri_t)); 00902 if (bnFound == false) 00903 { 00904 baseUriP = uriP; 00905 } 00906 else 00907 { 00908 int res; 00909 00910 // we ignore the request URI and use the bn one. 00911 00912 // Check for " around URI 00913 if (bnLen < 3 00914 || buffer[bnStart] != '"' 00915 || buffer[bnStart+bnLen-1] != '"') 00916 { 00917 goto error; 00918 } 00919 bnStart += 1; 00920 bnLen -= 2; 00921 00922 if (bnLen == 1) 00923 { 00924 if (buffer[bnStart] != '/') goto error; 00925 baseUriP = NULL; 00926 } 00927 else 00928 { 00929 res = lwm2m_stringToUri((char *)buffer + bnStart, bnLen, &baseURI); 00930 if (res < 0 || res != bnLen) goto error; 00931 baseUriP = &baseURI; 00932 } 00933 } 00934 00935 count = prv_convertRecord(baseUriP, recordArray, count, &parsedP); 00936 lwm2m_free(recordArray); 00937 recordArray = NULL; 00938 00939 if (count > 0 && uriP != NULL) 00940 { 00941 if (parsedP->type != LWM2M_TYPE_OBJECT || parsedP->id != uriP->objectId) goto error; 00942 if (!LWM2M_URI_IS_SET_INSTANCE(uriP)) 00943 { 00944 size = parsedP->value.asChildren.count; 00945 resultP = parsedP->value.asChildren.array; 00946 } 00947 else 00948 { 00949 int i; 00950 00951 resultP = NULL; 00952 // be permissive and allow full object JSON when requesting for a single instance 00953 for (i = 0 ; i < (int)parsedP->value.asChildren.count && resultP == NULL; i++) 00954 { 00955 lwm2m_data_t * targetP; 00956 00957 targetP = parsedP->value.asChildren.array + i; 00958 if (targetP->id == uriP->instanceId) 00959 { 00960 resultP = targetP->value.asChildren.array; 00961 size = targetP->value.asChildren.count; 00962 } 00963 } 00964 if (resultP == NULL) goto error; 00965 if (LWM2M_URI_IS_SET_RESOURCE(uriP)) 00966 { 00967 lwm2m_data_t * resP; 00968 00969 resP = NULL; 00970 for (i = 0 ; i < size && resP == NULL; i++) 00971 { 00972 lwm2m_data_t * targetP; 00973 00974 targetP = resultP + i; 00975 if (targetP->id == uriP->resourceId) 00976 { 00977 if (targetP->type == LWM2M_TYPE_MULTIPLE_RESOURCE) 00978 { 00979 resP = targetP->value.asChildren.array; 00980 size = targetP->value.asChildren.count; 00981 } 00982 else 00983 { 00984 size = prv_dataStrip(1, targetP, &resP); 00985 if (size <= 0) goto error; 00986 lwm2m_data_free(count, parsedP); 00987 parsedP = NULL; 00988 } 00989 } 00990 } 00991 if (resP == NULL) goto error; 00992 resultP = resP; 00993 } 00994 } 00995 } 00996 else 00997 { 00998 resultP = parsedP; 00999 size = count; 01000 } 01001 01002 if (parsedP != NULL) 01003 { 01004 lwm2m_data_t * tempP; 01005 01006 size = prv_dataStrip(size, resultP, &tempP); 01007 if (size <= 0) goto error; 01008 lwm2m_data_free(count, parsedP); 01009 resultP = tempP; 01010 } 01011 count = size; 01012 *dataP = resultP; 01013 } 01014 01015 LOG_ARG("Parsing successful. count: %d", count); 01016 return count; 01017 01018 error: 01019 LOG("Parsing failed"); 01020 if (parsedP != NULL) 01021 { 01022 lwm2m_data_free(count, parsedP); 01023 parsedP = NULL; 01024 } 01025 if (recordArray != NULL) 01026 { 01027 lwm2m_free(recordArray); 01028 } 01029 return -1; 01030 } 01031 01032 static int prv_serializeValue(lwm2m_data_t * tlvP, 01033 uint8_t * buffer, 01034 size_t bufferLen) 01035 { 01036 int res; 01037 int head; 01038 01039 switch (tlvP->type) 01040 { 01041 case LWM2M_TYPE_STRING: 01042 if (bufferLen < JSON_ITEM_STRING_BEGIN_SIZE) return -1; 01043 memcpy(buffer, JSON_ITEM_STRING_BEGIN, JSON_ITEM_STRING_BEGIN_SIZE); 01044 head = JSON_ITEM_STRING_BEGIN_SIZE; 01045 01046 if (bufferLen - head < tlvP->value.asBuffer.length) return -1; 01047 memcpy(buffer + head, tlvP->value.asBuffer.buffer, tlvP->value.asBuffer.length); 01048 head += tlvP->value.asBuffer.length; 01049 01050 if (bufferLen - head < JSON_ITEM_STRING_END_SIZE) return -1; 01051 memcpy(buffer + head, JSON_ITEM_STRING_END, JSON_ITEM_STRING_END_SIZE); 01052 head += JSON_ITEM_STRING_END_SIZE; 01053 01054 break; 01055 01056 case LWM2M_TYPE_INTEGER: 01057 { 01058 int64_t value; 01059 01060 if (0 == lwm2m_data_decode_int(tlvP, &value)) return -1; 01061 01062 if (bufferLen < JSON_ITEM_NUM_SIZE) return -1; 01063 memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE); 01064 head = JSON_ITEM_NUM_SIZE; 01065 01066 res = utils_intToText(value, buffer + head, bufferLen - head); 01067 if (res <= 0) return -1; 01068 head += res; 01069 01070 if (bufferLen - head < JSON_ITEM_NUM_END_SIZE) return -1; 01071 memcpy(buffer + head, JSON_ITEM_NUM_END, JSON_ITEM_NUM_END_SIZE); 01072 head += JSON_ITEM_NUM_END_SIZE; 01073 } 01074 break; 01075 01076 case LWM2M_TYPE_FLOAT: 01077 { 01078 double value; 01079 01080 if (0 == lwm2m_data_decode_float(tlvP, &value)) return -1; 01081 01082 if (bufferLen < JSON_ITEM_NUM_SIZE) return -1; 01083 memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE); 01084 head = JSON_ITEM_NUM_SIZE; 01085 01086 res = utils_floatToText(value, buffer + head, bufferLen - head); 01087 if (res <= 0) return -1; 01088 head += res; 01089 01090 if (bufferLen - head < JSON_ITEM_NUM_END_SIZE) return -1; 01091 memcpy(buffer + head, JSON_ITEM_NUM_END, JSON_ITEM_NUM_END_SIZE); 01092 head += JSON_ITEM_NUM_END_SIZE; 01093 } 01094 break; 01095 01096 case LWM2M_TYPE_BOOLEAN: 01097 { 01098 bool value; 01099 01100 if (0 == lwm2m_data_decode_bool(tlvP, &value)) return -1; 01101 01102 if (value == true) 01103 { 01104 if (bufferLen < JSON_ITEM_BOOL_TRUE_SIZE) return -1; 01105 memcpy(buffer, JSON_ITEM_BOOL_TRUE, JSON_ITEM_BOOL_TRUE_SIZE); 01106 head = JSON_ITEM_BOOL_TRUE_SIZE; 01107 } 01108 else 01109 { 01110 if (bufferLen < JSON_ITEM_BOOL_FALSE_SIZE) return -1; 01111 memcpy(buffer, JSON_ITEM_BOOL_FALSE, JSON_ITEM_BOOL_FALSE_SIZE); 01112 head = JSON_ITEM_BOOL_FALSE_SIZE; 01113 } 01114 } 01115 break; 01116 01117 case LWM2M_TYPE_OPAQUE: 01118 if (bufferLen < JSON_ITEM_STRING_BEGIN_SIZE) return -1; 01119 memcpy(buffer, JSON_ITEM_STRING_BEGIN, JSON_ITEM_STRING_BEGIN_SIZE); 01120 head = JSON_ITEM_STRING_BEGIN_SIZE; 01121 01122 res = utils_base64Encode(tlvP->value.asBuffer.buffer, tlvP->value.asBuffer.length, buffer+head, bufferLen - head); 01123 if (res == 0) return -1; 01124 head += res; 01125 01126 if (bufferLen - head < JSON_ITEM_STRING_END_SIZE) return -1; 01127 memcpy(buffer + head, JSON_ITEM_STRING_END, JSON_ITEM_STRING_END_SIZE); 01128 head += JSON_ITEM_STRING_END_SIZE; 01129 break; 01130 01131 case LWM2M_TYPE_OBJECT_LINK: 01132 // TODO: implement 01133 return -1; 01134 01135 default: 01136 return -1; 01137 } 01138 01139 return head; 01140 } 01141 01142 int prv_serializeData(lwm2m_data_t * tlvP, 01143 uint8_t * parentUriStr, 01144 size_t parentUriLen, 01145 uint8_t * buffer, 01146 size_t bufferLen) 01147 { 01148 int head; 01149 int res; 01150 01151 head = 0; 01152 01153 switch (tlvP->type) 01154 { 01155 case LWM2M_TYPE_OBJECT: 01156 case LWM2M_TYPE_OBJECT_INSTANCE: 01157 case LWM2M_TYPE_MULTIPLE_RESOURCE: 01158 { 01159 uint8_t uriStr[URI_MAX_STRING_LEN]; 01160 size_t uriLen; 01161 size_t index; 01162 01163 if (parentUriLen > 0) 01164 { 01165 if (URI_MAX_STRING_LEN < parentUriLen) return -1; 01166 memcpy(uriStr, parentUriStr, parentUriLen); 01167 uriLen = parentUriLen; 01168 } 01169 else 01170 { 01171 uriLen = 0; 01172 } 01173 res = utils_intToText(tlvP->id, uriStr + uriLen, URI_MAX_STRING_LEN - uriLen); 01174 if (res <= 0) return -1; 01175 uriLen += res; 01176 uriStr[uriLen] = '/'; 01177 uriLen++; 01178 01179 head = 0; 01180 for (index = 0 ; index < tlvP->value.asChildren.count; index++) 01181 { 01182 res = prv_serializeData(tlvP->value.asChildren.array + index, uriStr, uriLen, buffer + head, bufferLen - head); 01183 if (res < 0) return -1; 01184 head += res; 01185 } 01186 } 01187 break; 01188 01189 default: 01190 if (bufferLen < JSON_RES_ITEM_URI_SIZE) return -1; 01191 memcpy(buffer, JSON_RES_ITEM_URI, JSON_RES_ITEM_URI_SIZE); 01192 head = JSON_RES_ITEM_URI_SIZE; 01193 01194 if (parentUriLen > 0) 01195 { 01196 if (bufferLen - head < parentUriLen) return -1; 01197 memcpy(buffer + head, parentUriStr, parentUriLen); 01198 head += parentUriLen; 01199 } 01200 01201 res = utils_intToText(tlvP->id, buffer + head, bufferLen - head); 01202 if (res <= 0) return -1; 01203 head += res; 01204 01205 res = prv_serializeValue(tlvP, buffer + head, bufferLen - head); 01206 if (res < 0) return -1; 01207 head += res; 01208 break; 01209 } 01210 01211 return head; 01212 } 01213 01214 static int prv_findAndCheckData(lwm2m_uri_t * uriP, 01215 uri_depth_t level, 01216 size_t size, 01217 lwm2m_data_t * tlvP, 01218 lwm2m_data_t ** targetP) 01219 { 01220 size_t index; 01221 int result; 01222 01223 if (size == 0) return 0; 01224 01225 if (size > 1) 01226 { 01227 if (tlvP[0].type == LWM2M_TYPE_OBJECT || tlvP[0].type == LWM2M_TYPE_OBJECT_INSTANCE) 01228 { 01229 for (index = 0; index < size; index++) 01230 { 01231 if (tlvP[index].type != tlvP[0].type) 01232 { 01233 *targetP = NULL; 01234 return -1; 01235 } 01236 } 01237 } 01238 else 01239 { 01240 for (index = 0; index < size; index++) 01241 { 01242 if (tlvP[index].type == LWM2M_TYPE_OBJECT || tlvP[index].type == LWM2M_TYPE_OBJECT_INSTANCE) 01243 { 01244 *targetP = NULL; 01245 return -1; 01246 } 01247 } 01248 } 01249 } 01250 01251 *targetP = NULL; 01252 result = -1; 01253 switch (level) 01254 { 01255 case URI_DEPTH_OBJECT: 01256 if (tlvP[0].type == LWM2M_TYPE_OBJECT) 01257 { 01258 *targetP = tlvP; 01259 result = (int)size; 01260 } 01261 break; 01262 01263 case URI_DEPTH_OBJECT_INSTANCE: 01264 switch (tlvP[0].type) 01265 { 01266 case LWM2M_TYPE_OBJECT: 01267 for (index = 0; index < size; index++) 01268 { 01269 if (tlvP[index].id == uriP->objectId) 01270 { 01271 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP); 01272 } 01273 } 01274 break; 01275 case LWM2M_TYPE_OBJECT_INSTANCE: 01276 *targetP = tlvP; 01277 result = (int)size; 01278 break; 01279 default: 01280 break; 01281 } 01282 break; 01283 01284 case URI_DEPTH_RESOURCE: 01285 switch (tlvP[0].type) 01286 { 01287 case LWM2M_TYPE_OBJECT: 01288 for (index = 0; index < size; index++) 01289 { 01290 if (tlvP[index].id == uriP->objectId) 01291 { 01292 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP); 01293 } 01294 } 01295 break; 01296 case LWM2M_TYPE_OBJECT_INSTANCE: 01297 for (index = 0; index < size; index++) 01298 { 01299 if (tlvP[index].id == uriP->instanceId) 01300 { 01301 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP); 01302 } 01303 } 01304 break; 01305 default: 01306 *targetP = tlvP; 01307 result = (int)size; 01308 break; 01309 } 01310 break; 01311 01312 case URI_DEPTH_RESOURCE_INSTANCE: 01313 switch (tlvP[0].type) 01314 { 01315 case LWM2M_TYPE_OBJECT: 01316 for (index = 0; index < size; index++) 01317 { 01318 if (tlvP[index].id == uriP->objectId) 01319 { 01320 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP); 01321 } 01322 } 01323 break; 01324 case LWM2M_TYPE_OBJECT_INSTANCE: 01325 for (index = 0; index < size; index++) 01326 { 01327 if (tlvP[index].id == uriP->instanceId) 01328 { 01329 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP); 01330 } 01331 } 01332 break; 01333 case LWM2M_TYPE_MULTIPLE_RESOURCE: 01334 for (index = 0; index < size; index++) 01335 { 01336 if (tlvP[index].id == uriP->resourceId) 01337 { 01338 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP); 01339 } 01340 } 01341 break; 01342 default: 01343 *targetP = tlvP; 01344 result = (int)size; 01345 break; 01346 } 01347 break; 01348 01349 default: 01350 break; 01351 } 01352 01353 return result; 01354 } 01355 01356 int json_serialize(lwm2m_uri_t * uriP, 01357 int size, 01358 lwm2m_data_t * tlvP, 01359 uint8_t ** bufferP) 01360 { 01361 int index; 01362 size_t head; 01363 uint8_t bufferJSON[PRV_JSON_BUFFER_SIZE]; 01364 uint8_t baseUriStr[URI_MAX_STRING_LEN]; 01365 int baseUriLen; 01366 uri_depth_t rootLevel; 01367 int num; 01368 lwm2m_data_t * targetP; 01369 01370 LOG_ARG("size: %d", size); 01371 LOG_URI(uriP); 01372 if (size != 0 && tlvP == NULL) return -1; 01373 01374 baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, &rootLevel); 01375 if (baseUriLen < 0) return -1; 01376 01377 num = prv_findAndCheckData(uriP, rootLevel, size, tlvP, &targetP); 01378 if (num < 0) return -1; 01379 01380 while (num == 1 01381 && (targetP->type == LWM2M_TYPE_OBJECT 01382 || targetP->type == LWM2M_TYPE_OBJECT_INSTANCE 01383 || targetP->type == LWM2M_TYPE_MULTIPLE_RESOURCE)) 01384 { 01385 int res; 01386 01387 res = utils_intToText(targetP->id, baseUriStr + baseUriLen, URI_MAX_STRING_LEN - baseUriLen); 01388 if (res <= 0) return 0; 01389 baseUriLen += res; 01390 if (baseUriLen >= URI_MAX_STRING_LEN -1) return 0; 01391 num = targetP->value.asChildren.count; 01392 targetP = targetP->value.asChildren.array; 01393 baseUriStr[baseUriLen] = '/'; 01394 baseUriLen++; 01395 } 01396 01397 if (baseUriLen > 0) 01398 { 01399 memcpy(bufferJSON, JSON_BN_HEADER_1, JSON_BN_HEADER_1_SIZE); 01400 head = JSON_BN_HEADER_1_SIZE; 01401 memcpy(bufferJSON + head, baseUriStr, baseUriLen); 01402 head += baseUriLen; 01403 memcpy(bufferJSON + head, JSON_BN_HEADER_2, JSON_BN_HEADER_2_SIZE); 01404 head += JSON_BN_HEADER_2_SIZE; 01405 } 01406 else 01407 { 01408 memcpy(bufferJSON, JSON_HEADER, JSON_HEADER_SIZE); 01409 head = JSON_HEADER_SIZE; 01410 } 01411 01412 for (index = 0 ; index < num && head < PRV_JSON_BUFFER_SIZE ; index++) 01413 { 01414 int res; 01415 01416 res = prv_serializeData(targetP + index, NULL, 0, bufferJSON + head, PRV_JSON_BUFFER_SIZE - head); 01417 if (res < 0) return 0; 01418 head += res; 01419 } 01420 01421 if (head + JSON_FOOTER_SIZE - 1 > PRV_JSON_BUFFER_SIZE) return 0; 01422 01423 if (num > 0) head = head - 1; 01424 01425 memcpy(bufferJSON + head, JSON_FOOTER, JSON_FOOTER_SIZE); 01426 head = head + JSON_FOOTER_SIZE; 01427 01428 *bufferP = (uint8_t *)lwm2m_malloc(head); 01429 if (*bufferP == NULL) return 0; 01430 memcpy(*bufferP, bufferJSON, head); 01431 01432 return head; 01433 } 01434 01435 #endif 01436
Generated on Sun Jul 17 2022 20:01:04 by
1.7.2