pick up wakaama files from https://github.com/eclipse/wakaama

Committer:
terencez
Date:
Wed Apr 19 11:30:02 2017 +0000
Revision:
0:1fa43ab66921
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
terencez 0:1fa43ab66921 1 /*******************************************************************************
terencez 0:1fa43ab66921 2 *
terencez 0:1fa43ab66921 3 * Copyright (c) 2015 Intel Corporation and others.
terencez 0:1fa43ab66921 4 * All rights reserved. This program and the accompanying materials
terencez 0:1fa43ab66921 5 * are made available under the terms of the Eclipse Public License v1.0
terencez 0:1fa43ab66921 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
terencez 0:1fa43ab66921 7 *
terencez 0:1fa43ab66921 8 * The Eclipse Public License is available at
terencez 0:1fa43ab66921 9 * http://www.eclipse.org/legal/epl-v10.html
terencez 0:1fa43ab66921 10 * The Eclipse Distribution License is available at
terencez 0:1fa43ab66921 11 * http://www.eclipse.org/org/documents/edl-v10.php.
terencez 0:1fa43ab66921 12 *
terencez 0:1fa43ab66921 13 * Contributors:
terencez 0:1fa43ab66921 14 * David Navarro, Intel Corporation - initial API and implementation
terencez 0:1fa43ab66921 15 *
terencez 0:1fa43ab66921 16 *******************************************************************************/
terencez 0:1fa43ab66921 17
terencez 0:1fa43ab66921 18
terencez 0:1fa43ab66921 19 #include "internals.h"
terencez 0:1fa43ab66921 20 #include <stdlib.h>
terencez 0:1fa43ab66921 21 #include <string.h>
terencez 0:1fa43ab66921 22 #include <stdio.h>
terencez 0:1fa43ab66921 23 #include <inttypes.h>
terencez 0:1fa43ab66921 24
terencez 0:1fa43ab66921 25
terencez 0:1fa43ab66921 26 #ifdef LWM2M_SUPPORT_JSON
terencez 0:1fa43ab66921 27
terencez 0:1fa43ab66921 28 #define PRV_JSON_BUFFER_SIZE 1024
terencez 0:1fa43ab66921 29
terencez 0:1fa43ab66921 30 #define JSON_MIN_ARRAY_LEN 21 // e":[{"n":"N","v":X}]}
terencez 0:1fa43ab66921 31 #define JSON_MIN_BASE_LEN 7 // n":"N",
terencez 0:1fa43ab66921 32 #define JSON_ITEM_MAX_SIZE 36 // with ten characters for value
terencez 0:1fa43ab66921 33 #define JSON_MIN_BX_LEN 5 // bt":1
terencez 0:1fa43ab66921 34
terencez 0:1fa43ab66921 35 #define JSON_FALSE_STRING "false"
terencez 0:1fa43ab66921 36 #define JSON_TRUE_STRING "true"
terencez 0:1fa43ab66921 37
terencez 0:1fa43ab66921 38 #define JSON_RES_ITEM_URI "{\"n\":\""
terencez 0:1fa43ab66921 39 #define JSON_RES_ITEM_URI_SIZE 6
terencez 0:1fa43ab66921 40 #define JSON_ITEM_BOOL_TRUE "\",\"bv\":true},"
terencez 0:1fa43ab66921 41 #define JSON_ITEM_BOOL_TRUE_SIZE 13
terencez 0:1fa43ab66921 42 #define JSON_ITEM_BOOL_FALSE "\",\"bv\":false},"
terencez 0:1fa43ab66921 43 #define JSON_ITEM_BOOL_FALSE_SIZE 14
terencez 0:1fa43ab66921 44 #define JSON_ITEM_NUM "\",\"v\":"
terencez 0:1fa43ab66921 45 #define JSON_ITEM_NUM_SIZE 6
terencez 0:1fa43ab66921 46 #define JSON_ITEM_NUM_END "},"
terencez 0:1fa43ab66921 47 #define JSON_ITEM_NUM_END_SIZE 2
terencez 0:1fa43ab66921 48 #define JSON_ITEM_STRING_BEGIN "\",\"sv\":\""
terencez 0:1fa43ab66921 49 #define JSON_ITEM_STRING_BEGIN_SIZE 8
terencez 0:1fa43ab66921 50 #define JSON_ITEM_STRING_END "\"},"
terencez 0:1fa43ab66921 51 #define JSON_ITEM_STRING_END_SIZE 3
terencez 0:1fa43ab66921 52
terencez 0:1fa43ab66921 53 #define JSON_BN_HEADER_1 "{\"bn\":\""
terencez 0:1fa43ab66921 54 #define JSON_BN_HEADER_1_SIZE 7
terencez 0:1fa43ab66921 55 #define JSON_BN_HEADER_2 "\",\"e\":["
terencez 0:1fa43ab66921 56 #define JSON_BN_HEADER_2_SIZE 7
terencez 0:1fa43ab66921 57 #define JSON_HEADER "{\"e\":["
terencez 0:1fa43ab66921 58 #define JSON_HEADER_SIZE 6
terencez 0:1fa43ab66921 59 #define JSON_FOOTER "]}"
terencez 0:1fa43ab66921 60 #define JSON_FOOTER_SIZE 2
terencez 0:1fa43ab66921 61
terencez 0:1fa43ab66921 62
terencez 0:1fa43ab66921 63 #define _GO_TO_NEXT_CHAR(I,B,L) \
terencez 0:1fa43ab66921 64 { \
terencez 0:1fa43ab66921 65 I++; \
terencez 0:1fa43ab66921 66 I += prv_skipSpace(B+I, L-I); \
terencez 0:1fa43ab66921 67 if (I == L) goto error; \
terencez 0:1fa43ab66921 68 }
terencez 0:1fa43ab66921 69
terencez 0:1fa43ab66921 70 typedef enum
terencez 0:1fa43ab66921 71 {
terencez 0:1fa43ab66921 72 _STEP_START,
terencez 0:1fa43ab66921 73 _STEP_TOKEN,
terencez 0:1fa43ab66921 74 _STEP_ANY_SEPARATOR,
terencez 0:1fa43ab66921 75 _STEP_SEPARATOR,
terencez 0:1fa43ab66921 76 _STEP_QUOTED_VALUE,
terencez 0:1fa43ab66921 77 _STEP_VALUE,
terencez 0:1fa43ab66921 78 _STEP_DONE
terencez 0:1fa43ab66921 79 } _itemState;
terencez 0:1fa43ab66921 80
terencez 0:1fa43ab66921 81 typedef enum
terencez 0:1fa43ab66921 82 {
terencez 0:1fa43ab66921 83 _TYPE_UNSET,
terencez 0:1fa43ab66921 84 _TYPE_FALSE,
terencez 0:1fa43ab66921 85 _TYPE_TRUE,
terencez 0:1fa43ab66921 86 _TYPE_FLOAT,
terencez 0:1fa43ab66921 87 _TYPE_STRING
terencez 0:1fa43ab66921 88 } _type;
terencez 0:1fa43ab66921 89
terencez 0:1fa43ab66921 90 typedef struct
terencez 0:1fa43ab66921 91 {
terencez 0:1fa43ab66921 92 uint16_t ids[4];
terencez 0:1fa43ab66921 93 _type type;
terencez 0:1fa43ab66921 94 uint8_t * value;
terencez 0:1fa43ab66921 95 size_t valueLen;
terencez 0:1fa43ab66921 96 } _record_t;
terencez 0:1fa43ab66921 97
terencez 0:1fa43ab66921 98 static int prv_isReserved(char sign)
terencez 0:1fa43ab66921 99 {
terencez 0:1fa43ab66921 100 if (sign == '['
terencez 0:1fa43ab66921 101 || sign == '{'
terencez 0:1fa43ab66921 102 || sign == ']'
terencez 0:1fa43ab66921 103 || sign == '}'
terencez 0:1fa43ab66921 104 || sign == ':'
terencez 0:1fa43ab66921 105 || sign == ','
terencez 0:1fa43ab66921 106 || sign == '"')
terencez 0:1fa43ab66921 107 {
terencez 0:1fa43ab66921 108 return 1;
terencez 0:1fa43ab66921 109 }
terencez 0:1fa43ab66921 110
terencez 0:1fa43ab66921 111 return 0;
terencez 0:1fa43ab66921 112 }
terencez 0:1fa43ab66921 113
terencez 0:1fa43ab66921 114 static int prv_isWhiteSpace(uint8_t sign)
terencez 0:1fa43ab66921 115 {
terencez 0:1fa43ab66921 116 if (sign == 0x20
terencez 0:1fa43ab66921 117 || sign == 0x09
terencez 0:1fa43ab66921 118 || sign == 0x0A
terencez 0:1fa43ab66921 119 || sign == 0x0D)
terencez 0:1fa43ab66921 120 {
terencez 0:1fa43ab66921 121 return 1;
terencez 0:1fa43ab66921 122 }
terencez 0:1fa43ab66921 123
terencez 0:1fa43ab66921 124 return 0;
terencez 0:1fa43ab66921 125 }
terencez 0:1fa43ab66921 126
terencez 0:1fa43ab66921 127 static size_t prv_skipSpace(uint8_t * buffer,
terencez 0:1fa43ab66921 128 size_t bufferLen)
terencez 0:1fa43ab66921 129 {
terencez 0:1fa43ab66921 130 size_t i;
terencez 0:1fa43ab66921 131
terencez 0:1fa43ab66921 132 i = 0;
terencez 0:1fa43ab66921 133 while ((i < bufferLen)
terencez 0:1fa43ab66921 134 && prv_isWhiteSpace(buffer[i]))
terencez 0:1fa43ab66921 135 {
terencez 0:1fa43ab66921 136 i++;
terencez 0:1fa43ab66921 137 }
terencez 0:1fa43ab66921 138
terencez 0:1fa43ab66921 139 return i;
terencez 0:1fa43ab66921 140 }
terencez 0:1fa43ab66921 141
terencez 0:1fa43ab66921 142 static int prv_split(uint8_t * buffer,
terencez 0:1fa43ab66921 143 size_t bufferLen,
terencez 0:1fa43ab66921 144 int * tokenStartP,
terencez 0:1fa43ab66921 145 int * tokenLenP,
terencez 0:1fa43ab66921 146 int * valueStartP,
terencez 0:1fa43ab66921 147 int * valueLenP)
terencez 0:1fa43ab66921 148 {
terencez 0:1fa43ab66921 149 size_t index;
terencez 0:1fa43ab66921 150 _itemState step;
terencez 0:1fa43ab66921 151
terencez 0:1fa43ab66921 152 index = 0;
terencez 0:1fa43ab66921 153 step = _STEP_START;
terencez 0:1fa43ab66921 154
terencez 0:1fa43ab66921 155 index = prv_skipSpace(buffer + index, bufferLen - index);
terencez 0:1fa43ab66921 156 if (index == bufferLen) return -1;
terencez 0:1fa43ab66921 157
terencez 0:1fa43ab66921 158 while ((index < bufferLen)
terencez 0:1fa43ab66921 159 && (buffer[index] != ','))
terencez 0:1fa43ab66921 160 {
terencez 0:1fa43ab66921 161 switch (step)
terencez 0:1fa43ab66921 162 {
terencez 0:1fa43ab66921 163 case _STEP_START:
terencez 0:1fa43ab66921 164 if (buffer[index] != '"') return -1;
terencez 0:1fa43ab66921 165 *tokenStartP = index+1;
terencez 0:1fa43ab66921 166 step = _STEP_TOKEN;
terencez 0:1fa43ab66921 167 break;
terencez 0:1fa43ab66921 168
terencez 0:1fa43ab66921 169 case _STEP_TOKEN:
terencez 0:1fa43ab66921 170 if (buffer[index] == '"')
terencez 0:1fa43ab66921 171 {
terencez 0:1fa43ab66921 172 *tokenLenP = index - *tokenStartP;
terencez 0:1fa43ab66921 173 step = _STEP_ANY_SEPARATOR;
terencez 0:1fa43ab66921 174 }
terencez 0:1fa43ab66921 175 break;
terencez 0:1fa43ab66921 176
terencez 0:1fa43ab66921 177 case _STEP_ANY_SEPARATOR:
terencez 0:1fa43ab66921 178 if (buffer[index] != ':') return -1;
terencez 0:1fa43ab66921 179 step = _STEP_SEPARATOR;
terencez 0:1fa43ab66921 180 break;
terencez 0:1fa43ab66921 181
terencez 0:1fa43ab66921 182 case _STEP_SEPARATOR:
terencez 0:1fa43ab66921 183 if (buffer[index] == '"')
terencez 0:1fa43ab66921 184 {
terencez 0:1fa43ab66921 185 *valueStartP = index;
terencez 0:1fa43ab66921 186 step = _STEP_QUOTED_VALUE;
terencez 0:1fa43ab66921 187 } else if (!prv_isReserved(buffer[index]))
terencez 0:1fa43ab66921 188 {
terencez 0:1fa43ab66921 189 *valueStartP = index;
terencez 0:1fa43ab66921 190 step = _STEP_VALUE;
terencez 0:1fa43ab66921 191 } else
terencez 0:1fa43ab66921 192 {
terencez 0:1fa43ab66921 193 return -1;
terencez 0:1fa43ab66921 194 }
terencez 0:1fa43ab66921 195 break;
terencez 0:1fa43ab66921 196
terencez 0:1fa43ab66921 197 case _STEP_QUOTED_VALUE:
terencez 0:1fa43ab66921 198 if (buffer[index] == '"' && buffer[index-1] != '\\' )
terencez 0:1fa43ab66921 199 {
terencez 0:1fa43ab66921 200 *valueLenP = index - *valueStartP + 1;
terencez 0:1fa43ab66921 201 step = _STEP_DONE;
terencez 0:1fa43ab66921 202 }
terencez 0:1fa43ab66921 203 break;
terencez 0:1fa43ab66921 204
terencez 0:1fa43ab66921 205 case _STEP_VALUE:
terencez 0:1fa43ab66921 206 if (prv_isWhiteSpace(buffer[index]))
terencez 0:1fa43ab66921 207 {
terencez 0:1fa43ab66921 208 *valueLenP = index - *valueStartP;
terencez 0:1fa43ab66921 209 step = _STEP_DONE;
terencez 0:1fa43ab66921 210 }
terencez 0:1fa43ab66921 211 break;
terencez 0:1fa43ab66921 212
terencez 0:1fa43ab66921 213 case _STEP_DONE:
terencez 0:1fa43ab66921 214 default:
terencez 0:1fa43ab66921 215 return -1;
terencez 0:1fa43ab66921 216 }
terencez 0:1fa43ab66921 217
terencez 0:1fa43ab66921 218 index++;
terencez 0:1fa43ab66921 219 if (step == _STEP_START
terencez 0:1fa43ab66921 220 || step == _STEP_ANY_SEPARATOR
terencez 0:1fa43ab66921 221 || step == _STEP_SEPARATOR
terencez 0:1fa43ab66921 222 || step == _STEP_DONE)
terencez 0:1fa43ab66921 223 {
terencez 0:1fa43ab66921 224 index += prv_skipSpace(buffer + index, bufferLen - index);
terencez 0:1fa43ab66921 225 }
terencez 0:1fa43ab66921 226 }
terencez 0:1fa43ab66921 227
terencez 0:1fa43ab66921 228 if (step == _STEP_VALUE)
terencez 0:1fa43ab66921 229 {
terencez 0:1fa43ab66921 230 *valueLenP = index - *valueStartP;
terencez 0:1fa43ab66921 231 step = _STEP_DONE;
terencez 0:1fa43ab66921 232 }
terencez 0:1fa43ab66921 233
terencez 0:1fa43ab66921 234 if (step != _STEP_DONE) return -1;
terencez 0:1fa43ab66921 235
terencez 0:1fa43ab66921 236 return (int)index;
terencez 0:1fa43ab66921 237 }
terencez 0:1fa43ab66921 238
terencez 0:1fa43ab66921 239 static int prv_countItems(uint8_t * buffer,
terencez 0:1fa43ab66921 240 size_t bufferLen)
terencez 0:1fa43ab66921 241 {
terencez 0:1fa43ab66921 242 int count;
terencez 0:1fa43ab66921 243 size_t index;
terencez 0:1fa43ab66921 244 int in;
terencez 0:1fa43ab66921 245
terencez 0:1fa43ab66921 246 count = 0;
terencez 0:1fa43ab66921 247 index = 0;
terencez 0:1fa43ab66921 248 in = 0;
terencez 0:1fa43ab66921 249
terencez 0:1fa43ab66921 250 while (index < bufferLen)
terencez 0:1fa43ab66921 251 {
terencez 0:1fa43ab66921 252 if (in == 0)
terencez 0:1fa43ab66921 253 {
terencez 0:1fa43ab66921 254 if (buffer[index] != '{') return -1;
terencez 0:1fa43ab66921 255 in = 1;
terencez 0:1fa43ab66921 256 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 257 }
terencez 0:1fa43ab66921 258 else
terencez 0:1fa43ab66921 259 {
terencez 0:1fa43ab66921 260 if (buffer[index] == '{') return -1;
terencez 0:1fa43ab66921 261 if (buffer[index] == '}')
terencez 0:1fa43ab66921 262 {
terencez 0:1fa43ab66921 263 in = 0;
terencez 0:1fa43ab66921 264 count++;
terencez 0:1fa43ab66921 265 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 266 if (buffer[index] == ']')
terencez 0:1fa43ab66921 267 {
terencez 0:1fa43ab66921 268 break;
terencez 0:1fa43ab66921 269 }
terencez 0:1fa43ab66921 270 if (buffer[index] != ',') return -1;
terencez 0:1fa43ab66921 271 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 272 }
terencez 0:1fa43ab66921 273 else
terencez 0:1fa43ab66921 274 {
terencez 0:1fa43ab66921 275 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 276 }
terencez 0:1fa43ab66921 277 }
terencez 0:1fa43ab66921 278 }
terencez 0:1fa43ab66921 279 if (in == 1) return -1;
terencez 0:1fa43ab66921 280
terencez 0:1fa43ab66921 281 return count;
terencez 0:1fa43ab66921 282
terencez 0:1fa43ab66921 283 error:
terencez 0:1fa43ab66921 284 return -1;
terencez 0:1fa43ab66921 285 }
terencez 0:1fa43ab66921 286
terencez 0:1fa43ab66921 287 static int prv_parseItem(uint8_t * buffer,
terencez 0:1fa43ab66921 288 size_t bufferLen,
terencez 0:1fa43ab66921 289 _record_t * recordP)
terencez 0:1fa43ab66921 290 {
terencez 0:1fa43ab66921 291 size_t index;
terencez 0:1fa43ab66921 292
terencez 0:1fa43ab66921 293 memset(recordP->ids, 0xFF, 4*sizeof(uint16_t));
terencez 0:1fa43ab66921 294 recordP->type = _TYPE_UNSET;
terencez 0:1fa43ab66921 295 recordP->value = NULL;
terencez 0:1fa43ab66921 296 recordP->valueLen = 0;
terencez 0:1fa43ab66921 297
terencez 0:1fa43ab66921 298 index = 0;
terencez 0:1fa43ab66921 299 do
terencez 0:1fa43ab66921 300 {
terencez 0:1fa43ab66921 301 int tokenStart;
terencez 0:1fa43ab66921 302 int tokenLen;
terencez 0:1fa43ab66921 303 int valueStart;
terencez 0:1fa43ab66921 304 int valueLen;
terencez 0:1fa43ab66921 305 int next;
terencez 0:1fa43ab66921 306
terencez 0:1fa43ab66921 307 next = prv_split(buffer+index, bufferLen-index, &tokenStart, &tokenLen, &valueStart, &valueLen);
terencez 0:1fa43ab66921 308 if (next < 0) return -1;
terencez 0:1fa43ab66921 309
terencez 0:1fa43ab66921 310 switch (tokenLen)
terencez 0:1fa43ab66921 311 {
terencez 0:1fa43ab66921 312 case 1:
terencez 0:1fa43ab66921 313 {
terencez 0:1fa43ab66921 314 switch (buffer[index+tokenStart])
terencez 0:1fa43ab66921 315 {
terencez 0:1fa43ab66921 316 case 'n':
terencez 0:1fa43ab66921 317 {
terencez 0:1fa43ab66921 318 int i;
terencez 0:1fa43ab66921 319 int j;
terencez 0:1fa43ab66921 320
terencez 0:1fa43ab66921 321 if (recordP->ids[0] != LWM2M_MAX_ID) return -1;
terencez 0:1fa43ab66921 322
terencez 0:1fa43ab66921 323 // Check for " around URI
terencez 0:1fa43ab66921 324 if (valueLen < 3
terencez 0:1fa43ab66921 325 || buffer[index+valueStart] != '"'
terencez 0:1fa43ab66921 326 || buffer[index+valueStart+valueLen-1] != '"')
terencez 0:1fa43ab66921 327 {
terencez 0:1fa43ab66921 328 return -1;
terencez 0:1fa43ab66921 329 }
terencez 0:1fa43ab66921 330 // Ignore starting /
terencez 0:1fa43ab66921 331 if (buffer[index + valueStart + 1] == '/')
terencez 0:1fa43ab66921 332 {
terencez 0:1fa43ab66921 333 if (valueLen < 4)
terencez 0:1fa43ab66921 334 {
terencez 0:1fa43ab66921 335 return -1;
terencez 0:1fa43ab66921 336 }
terencez 0:1fa43ab66921 337 valueStart += 1;
terencez 0:1fa43ab66921 338 valueLen -= 1;
terencez 0:1fa43ab66921 339 }
terencez 0:1fa43ab66921 340 i = 0;
terencez 0:1fa43ab66921 341 j = 0;
terencez 0:1fa43ab66921 342 do {
terencez 0:1fa43ab66921 343 uint32_t readId;
terencez 0:1fa43ab66921 344
terencez 0:1fa43ab66921 345 readId = 0;
terencez 0:1fa43ab66921 346 i++;
terencez 0:1fa43ab66921 347 while (i < valueLen-1 && buffer[index+valueStart+i] != '/')
terencez 0:1fa43ab66921 348 {
terencez 0:1fa43ab66921 349 if (buffer[index+valueStart+i] < '0'
terencez 0:1fa43ab66921 350 || buffer[index+valueStart+i] > '9')
terencez 0:1fa43ab66921 351 {
terencez 0:1fa43ab66921 352 return -1;
terencez 0:1fa43ab66921 353 }
terencez 0:1fa43ab66921 354 readId *= 10;
terencez 0:1fa43ab66921 355 readId += buffer[index+valueStart+i] - '0';
terencez 0:1fa43ab66921 356 if (readId > LWM2M_MAX_ID) return -1;
terencez 0:1fa43ab66921 357 i++;
terencez 0:1fa43ab66921 358 }
terencez 0:1fa43ab66921 359 recordP->ids[j] = readId;
terencez 0:1fa43ab66921 360 j++;
terencez 0:1fa43ab66921 361 } while (i < valueLen-1 && j < 4 && buffer[index+valueStart+i] == '/');
terencez 0:1fa43ab66921 362 if (i < valueLen-1 ) return -1;
terencez 0:1fa43ab66921 363 }
terencez 0:1fa43ab66921 364 break;
terencez 0:1fa43ab66921 365
terencez 0:1fa43ab66921 366 case 'v':
terencez 0:1fa43ab66921 367 if (recordP->type != _TYPE_UNSET) return -1;
terencez 0:1fa43ab66921 368 recordP->type = _TYPE_FLOAT;
terencez 0:1fa43ab66921 369 recordP->value = buffer + index + valueStart;
terencez 0:1fa43ab66921 370 recordP->valueLen = valueLen;
terencez 0:1fa43ab66921 371 break;
terencez 0:1fa43ab66921 372
terencez 0:1fa43ab66921 373 case 't':
terencez 0:1fa43ab66921 374 // TODO: support time
terencez 0:1fa43ab66921 375 break;
terencez 0:1fa43ab66921 376
terencez 0:1fa43ab66921 377 default:
terencez 0:1fa43ab66921 378 return -1;
terencez 0:1fa43ab66921 379 }
terencez 0:1fa43ab66921 380 }
terencez 0:1fa43ab66921 381 break;
terencez 0:1fa43ab66921 382
terencez 0:1fa43ab66921 383 case 2:
terencez 0:1fa43ab66921 384 {
terencez 0:1fa43ab66921 385 // "bv", "ov", or "sv"
terencez 0:1fa43ab66921 386 if (buffer[index+tokenStart+1] != 'v') return -1;
terencez 0:1fa43ab66921 387 switch (buffer[index+tokenStart])
terencez 0:1fa43ab66921 388 {
terencez 0:1fa43ab66921 389 case 'b':
terencez 0:1fa43ab66921 390 if (recordP->type != _TYPE_UNSET) return -1;
terencez 0:1fa43ab66921 391 if (0 == lwm2m_strncmp(JSON_TRUE_STRING, (char *)buffer + index + valueStart, valueLen))
terencez 0:1fa43ab66921 392 {
terencez 0:1fa43ab66921 393 recordP->type = _TYPE_TRUE;
terencez 0:1fa43ab66921 394 }
terencez 0:1fa43ab66921 395 else if (0 == lwm2m_strncmp(JSON_FALSE_STRING, (char *)buffer + index + valueStart, valueLen))
terencez 0:1fa43ab66921 396 {
terencez 0:1fa43ab66921 397 recordP->type = _TYPE_FALSE;
terencez 0:1fa43ab66921 398 }
terencez 0:1fa43ab66921 399 else
terencez 0:1fa43ab66921 400 {
terencez 0:1fa43ab66921 401 return -1;
terencez 0:1fa43ab66921 402 }
terencez 0:1fa43ab66921 403 break;
terencez 0:1fa43ab66921 404
terencez 0:1fa43ab66921 405 case 'o':
terencez 0:1fa43ab66921 406 if (recordP->type != _TYPE_UNSET) return -1;
terencez 0:1fa43ab66921 407 // TODO: support object link
terencez 0:1fa43ab66921 408 break;
terencez 0:1fa43ab66921 409
terencez 0:1fa43ab66921 410 case 's':
terencez 0:1fa43ab66921 411 if (recordP->type != _TYPE_UNSET) return -1;
terencez 0:1fa43ab66921 412 // Check for " around value
terencez 0:1fa43ab66921 413 if (valueLen < 2
terencez 0:1fa43ab66921 414 || buffer[index+valueStart] != '"'
terencez 0:1fa43ab66921 415 || buffer[index+valueStart+valueLen-1] != '"')
terencez 0:1fa43ab66921 416 {
terencez 0:1fa43ab66921 417 return -1;
terencez 0:1fa43ab66921 418 }
terencez 0:1fa43ab66921 419 recordP->type = _TYPE_STRING;
terencez 0:1fa43ab66921 420 recordP->value = buffer + index + valueStart + 1;
terencez 0:1fa43ab66921 421 recordP->valueLen = valueLen - 2;
terencez 0:1fa43ab66921 422 break;
terencez 0:1fa43ab66921 423
terencez 0:1fa43ab66921 424 default:
terencez 0:1fa43ab66921 425 return -1;
terencez 0:1fa43ab66921 426 }
terencez 0:1fa43ab66921 427 }
terencez 0:1fa43ab66921 428 break;
terencez 0:1fa43ab66921 429
terencez 0:1fa43ab66921 430 default:
terencez 0:1fa43ab66921 431 return -1;
terencez 0:1fa43ab66921 432 }
terencez 0:1fa43ab66921 433
terencez 0:1fa43ab66921 434 index += next + 1;
terencez 0:1fa43ab66921 435 } while (index < bufferLen);
terencez 0:1fa43ab66921 436
terencez 0:1fa43ab66921 437 return 0;
terencez 0:1fa43ab66921 438 }
terencez 0:1fa43ab66921 439
terencez 0:1fa43ab66921 440 static bool prv_convertValue(_record_t * recordP,
terencez 0:1fa43ab66921 441 lwm2m_data_t * targetP)
terencez 0:1fa43ab66921 442 {
terencez 0:1fa43ab66921 443 switch (recordP->type)
terencez 0:1fa43ab66921 444 {
terencez 0:1fa43ab66921 445 case _TYPE_FALSE:
terencez 0:1fa43ab66921 446 lwm2m_data_encode_bool(false, targetP);
terencez 0:1fa43ab66921 447 break;
terencez 0:1fa43ab66921 448 case _TYPE_TRUE:
terencez 0:1fa43ab66921 449 lwm2m_data_encode_bool(true, targetP);
terencez 0:1fa43ab66921 450 break;
terencez 0:1fa43ab66921 451 case _TYPE_FLOAT:
terencez 0:1fa43ab66921 452 {
terencez 0:1fa43ab66921 453 size_t i;
terencez 0:1fa43ab66921 454
terencez 0:1fa43ab66921 455 i = 0;
terencez 0:1fa43ab66921 456 while (i < recordP->valueLen
terencez 0:1fa43ab66921 457 && recordP->value[i] != '.')
terencez 0:1fa43ab66921 458 {
terencez 0:1fa43ab66921 459 i++;
terencez 0:1fa43ab66921 460 }
terencez 0:1fa43ab66921 461 if (i == recordP->valueLen)
terencez 0:1fa43ab66921 462 {
terencez 0:1fa43ab66921 463 int64_t value;
terencez 0:1fa43ab66921 464
terencez 0:1fa43ab66921 465 if ( 1 != utils_plainTextToInt64(recordP->value,
terencez 0:1fa43ab66921 466 recordP->valueLen,
terencez 0:1fa43ab66921 467 &value))
terencez 0:1fa43ab66921 468 {
terencez 0:1fa43ab66921 469 return false;
terencez 0:1fa43ab66921 470 }
terencez 0:1fa43ab66921 471
terencez 0:1fa43ab66921 472 lwm2m_data_encode_int(value, targetP);
terencez 0:1fa43ab66921 473 }
terencez 0:1fa43ab66921 474 else
terencez 0:1fa43ab66921 475 {
terencez 0:1fa43ab66921 476 double value;
terencez 0:1fa43ab66921 477
terencez 0:1fa43ab66921 478 if ( 1 != utils_plainTextToFloat64(recordP->value,
terencez 0:1fa43ab66921 479 recordP->valueLen,
terencez 0:1fa43ab66921 480 &value))
terencez 0:1fa43ab66921 481 {
terencez 0:1fa43ab66921 482 return false;
terencez 0:1fa43ab66921 483 }
terencez 0:1fa43ab66921 484
terencez 0:1fa43ab66921 485 lwm2m_data_encode_float(value, targetP);
terencez 0:1fa43ab66921 486 }
terencez 0:1fa43ab66921 487 }
terencez 0:1fa43ab66921 488 break;
terencez 0:1fa43ab66921 489
terencez 0:1fa43ab66921 490 case _TYPE_STRING:
terencez 0:1fa43ab66921 491 lwm2m_data_encode_opaque(recordP->value, recordP->valueLen, targetP);
terencez 0:1fa43ab66921 492 targetP->type = LWM2M_TYPE_STRING;
terencez 0:1fa43ab66921 493 break;
terencez 0:1fa43ab66921 494
terencez 0:1fa43ab66921 495 case _TYPE_UNSET:
terencez 0:1fa43ab66921 496 default:
terencez 0:1fa43ab66921 497 return false;
terencez 0:1fa43ab66921 498 }
terencez 0:1fa43ab66921 499
terencez 0:1fa43ab66921 500 return true;
terencez 0:1fa43ab66921 501 }
terencez 0:1fa43ab66921 502
terencez 0:1fa43ab66921 503 static lwm2m_data_t * prv_findDataItem(lwm2m_data_t * listP,
terencez 0:1fa43ab66921 504 int count,
terencez 0:1fa43ab66921 505 uint16_t id)
terencez 0:1fa43ab66921 506 {
terencez 0:1fa43ab66921 507 int i;
terencez 0:1fa43ab66921 508
terencez 0:1fa43ab66921 509 i = 0;
terencez 0:1fa43ab66921 510 while (i < count)
terencez 0:1fa43ab66921 511 {
terencez 0:1fa43ab66921 512 if (listP[i].type != LWM2M_TYPE_UNDEFINED && listP[i].id == id)
terencez 0:1fa43ab66921 513 {
terencez 0:1fa43ab66921 514 return listP + i;
terencez 0:1fa43ab66921 515 }
terencez 0:1fa43ab66921 516 i++;
terencez 0:1fa43ab66921 517 }
terencez 0:1fa43ab66921 518
terencez 0:1fa43ab66921 519 return NULL;
terencez 0:1fa43ab66921 520 }
terencez 0:1fa43ab66921 521
terencez 0:1fa43ab66921 522 static uri_depth_t prv_decreaseLevel(uri_depth_t level)
terencez 0:1fa43ab66921 523 {
terencez 0:1fa43ab66921 524 switch(level)
terencez 0:1fa43ab66921 525 {
terencez 0:1fa43ab66921 526 case URI_DEPTH_OBJECT:
terencez 0:1fa43ab66921 527 return URI_DEPTH_OBJECT_INSTANCE;
terencez 0:1fa43ab66921 528 case URI_DEPTH_OBJECT_INSTANCE:
terencez 0:1fa43ab66921 529 return URI_DEPTH_RESOURCE;
terencez 0:1fa43ab66921 530 case URI_DEPTH_RESOURCE:
terencez 0:1fa43ab66921 531 return URI_DEPTH_RESOURCE_INSTANCE;
terencez 0:1fa43ab66921 532 case URI_DEPTH_RESOURCE_INSTANCE:
terencez 0:1fa43ab66921 533 return URI_DEPTH_RESOURCE_INSTANCE;
terencez 0:1fa43ab66921 534 default:
terencez 0:1fa43ab66921 535 return URI_DEPTH_RESOURCE;
terencez 0:1fa43ab66921 536 }
terencez 0:1fa43ab66921 537 }
terencez 0:1fa43ab66921 538
terencez 0:1fa43ab66921 539 static lwm2m_data_t * prv_extendData(lwm2m_data_t * parentP)
terencez 0:1fa43ab66921 540 {
terencez 0:1fa43ab66921 541 lwm2m_data_t * newP;
terencez 0:1fa43ab66921 542
terencez 0:1fa43ab66921 543 newP = lwm2m_data_new(parentP->value.asChildren.count + 1);
terencez 0:1fa43ab66921 544 if (newP == NULL) return NULL;
terencez 0:1fa43ab66921 545 if (parentP->value.asChildren.array != NULL)
terencez 0:1fa43ab66921 546 {
terencez 0:1fa43ab66921 547 memcpy(newP, parentP->value.asChildren.array, parentP->value.asChildren.count * sizeof(lwm2m_data_t));
terencez 0:1fa43ab66921 548 lwm2m_free(parentP->value.asChildren.array); // do not use lwm2m_data_free() to keep pointed values
terencez 0:1fa43ab66921 549 }
terencez 0:1fa43ab66921 550 parentP->value.asChildren.array = newP;
terencez 0:1fa43ab66921 551 parentP->value.asChildren.count += 1;
terencez 0:1fa43ab66921 552
terencez 0:1fa43ab66921 553 return newP + parentP->value.asChildren.count - 1;
terencez 0:1fa43ab66921 554 }
terencez 0:1fa43ab66921 555
terencez 0:1fa43ab66921 556 static int prv_convertRecord(lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 557 _record_t * recordArray,
terencez 0:1fa43ab66921 558 int count,
terencez 0:1fa43ab66921 559 lwm2m_data_t ** dataP)
terencez 0:1fa43ab66921 560 {
terencez 0:1fa43ab66921 561 int index;
terencez 0:1fa43ab66921 562 int freeIndex;
terencez 0:1fa43ab66921 563 lwm2m_data_t * rootP;
terencez 0:1fa43ab66921 564 int size;
terencez 0:1fa43ab66921 565 uri_depth_t rootLevel;
terencez 0:1fa43ab66921 566
terencez 0:1fa43ab66921 567 if (uriP == NULL)
terencez 0:1fa43ab66921 568 {
terencez 0:1fa43ab66921 569 size = count;
terencez 0:1fa43ab66921 570 *dataP = lwm2m_data_new(count);
terencez 0:1fa43ab66921 571 if (NULL == *dataP) return -1;
terencez 0:1fa43ab66921 572 rootLevel = URI_DEPTH_OBJECT;
terencez 0:1fa43ab66921 573 rootP = *dataP;
terencez 0:1fa43ab66921 574 }
terencez 0:1fa43ab66921 575 else
terencez 0:1fa43ab66921 576 {
terencez 0:1fa43ab66921 577 lwm2m_data_t * parentP;
terencez 0:1fa43ab66921 578 size = 1;
terencez 0:1fa43ab66921 579
terencez 0:1fa43ab66921 580 *dataP = lwm2m_data_new(1);
terencez 0:1fa43ab66921 581 if (NULL == *dataP) return -1;
terencez 0:1fa43ab66921 582 (*dataP)->type = LWM2M_TYPE_OBJECT;
terencez 0:1fa43ab66921 583 (*dataP)->id = uriP->objectId;
terencez 0:1fa43ab66921 584 rootLevel = URI_DEPTH_OBJECT_INSTANCE;
terencez 0:1fa43ab66921 585 parentP = *dataP;
terencez 0:1fa43ab66921 586 if (LWM2M_URI_IS_SET_INSTANCE(uriP))
terencez 0:1fa43ab66921 587 {
terencez 0:1fa43ab66921 588 parentP->value.asChildren.count = 1;
terencez 0:1fa43ab66921 589 parentP->value.asChildren.array = lwm2m_data_new(1);
terencez 0:1fa43ab66921 590 if (NULL == parentP->value.asChildren.array) goto error;
terencez 0:1fa43ab66921 591 parentP = parentP->value.asChildren.array;
terencez 0:1fa43ab66921 592 parentP->type = LWM2M_TYPE_OBJECT_INSTANCE;
terencez 0:1fa43ab66921 593 parentP->id = uriP->instanceId;
terencez 0:1fa43ab66921 594 rootLevel = URI_DEPTH_RESOURCE;
terencez 0:1fa43ab66921 595 if (LWM2M_URI_IS_SET_RESOURCE(uriP))
terencez 0:1fa43ab66921 596 {
terencez 0:1fa43ab66921 597 parentP->value.asChildren.count = 1;
terencez 0:1fa43ab66921 598 parentP->value.asChildren.array = lwm2m_data_new(1);
terencez 0:1fa43ab66921 599 if (NULL == parentP->value.asChildren.array) goto error;
terencez 0:1fa43ab66921 600 parentP = parentP->value.asChildren.array;
terencez 0:1fa43ab66921 601 parentP->type = LWM2M_TYPE_UNDEFINED;
terencez 0:1fa43ab66921 602 parentP->id = uriP->resourceId;
terencez 0:1fa43ab66921 603 rootLevel = URI_DEPTH_RESOURCE_INSTANCE;
terencez 0:1fa43ab66921 604 }
terencez 0:1fa43ab66921 605 }
terencez 0:1fa43ab66921 606 parentP->value.asChildren.count = count;
terencez 0:1fa43ab66921 607 parentP->value.asChildren.array = lwm2m_data_new(count);
terencez 0:1fa43ab66921 608 if (NULL == parentP->value.asChildren.array) goto error;
terencez 0:1fa43ab66921 609 rootP = parentP->value.asChildren.array;
terencez 0:1fa43ab66921 610 }
terencez 0:1fa43ab66921 611
terencez 0:1fa43ab66921 612 freeIndex = 0;
terencez 0:1fa43ab66921 613 for (index = 0 ; index < count ; index++)
terencez 0:1fa43ab66921 614 {
terencez 0:1fa43ab66921 615 lwm2m_data_t * targetP;
terencez 0:1fa43ab66921 616 int resSegmentIndex;
terencez 0:1fa43ab66921 617 int i;
terencez 0:1fa43ab66921 618
terencez 0:1fa43ab66921 619 // check URI depth
terencez 0:1fa43ab66921 620 // resSegmentIndex is set to the resource segment position
terencez 0:1fa43ab66921 621 switch(rootLevel)
terencez 0:1fa43ab66921 622 {
terencez 0:1fa43ab66921 623 case URI_DEPTH_OBJECT:
terencez 0:1fa43ab66921 624 resSegmentIndex = 2;
terencez 0:1fa43ab66921 625 break;
terencez 0:1fa43ab66921 626 case URI_DEPTH_OBJECT_INSTANCE:
terencez 0:1fa43ab66921 627 resSegmentIndex = 1;
terencez 0:1fa43ab66921 628 break;
terencez 0:1fa43ab66921 629 case URI_DEPTH_RESOURCE:
terencez 0:1fa43ab66921 630 resSegmentIndex = 0;
terencez 0:1fa43ab66921 631 break;
terencez 0:1fa43ab66921 632 case URI_DEPTH_RESOURCE_INSTANCE:
terencez 0:1fa43ab66921 633 resSegmentIndex = -1;
terencez 0:1fa43ab66921 634 break;
terencez 0:1fa43ab66921 635 default:
terencez 0:1fa43ab66921 636 goto error;
terencez 0:1fa43ab66921 637 }
terencez 0:1fa43ab66921 638 for (i = 0 ; i <= resSegmentIndex ; i++)
terencez 0:1fa43ab66921 639 {
terencez 0:1fa43ab66921 640 if (recordArray[index].ids[i] == LWM2M_MAX_ID) goto error;
terencez 0:1fa43ab66921 641 }
terencez 0:1fa43ab66921 642 if (resSegmentIndex < 2)
terencez 0:1fa43ab66921 643 {
terencez 0:1fa43ab66921 644 if (recordArray[index].ids[resSegmentIndex + 2] != LWM2M_MAX_ID) goto error;
terencez 0:1fa43ab66921 645 }
terencez 0:1fa43ab66921 646
terencez 0:1fa43ab66921 647 targetP = prv_findDataItem(rootP, count, recordArray[index].ids[0]);
terencez 0:1fa43ab66921 648 if (targetP == NULL)
terencez 0:1fa43ab66921 649 {
terencez 0:1fa43ab66921 650 targetP = rootP + freeIndex;
terencez 0:1fa43ab66921 651 freeIndex++;
terencez 0:1fa43ab66921 652 targetP->id = recordArray[index].ids[0];
terencez 0:1fa43ab66921 653 targetP->type = utils_depthToDatatype(rootLevel);
terencez 0:1fa43ab66921 654 }
terencez 0:1fa43ab66921 655 if (recordArray[index].ids[1] != LWM2M_MAX_ID)
terencez 0:1fa43ab66921 656 {
terencez 0:1fa43ab66921 657 lwm2m_data_t * parentP;
terencez 0:1fa43ab66921 658 uri_depth_t level;
terencez 0:1fa43ab66921 659
terencez 0:1fa43ab66921 660 parentP = targetP;
terencez 0:1fa43ab66921 661 level = prv_decreaseLevel(rootLevel);
terencez 0:1fa43ab66921 662 for (i = 1 ; i <= resSegmentIndex ; i++)
terencez 0:1fa43ab66921 663 {
terencez 0:1fa43ab66921 664 targetP = prv_findDataItem(parentP->value.asChildren.array, parentP->value.asChildren.count, recordArray[index].ids[i]);
terencez 0:1fa43ab66921 665 if (targetP == NULL)
terencez 0:1fa43ab66921 666 {
terencez 0:1fa43ab66921 667 targetP = prv_extendData(parentP);
terencez 0:1fa43ab66921 668 if (targetP == NULL) goto error;
terencez 0:1fa43ab66921 669 targetP->id = recordArray[index].ids[i];
terencez 0:1fa43ab66921 670 targetP->type = utils_depthToDatatype(level);
terencez 0:1fa43ab66921 671 }
terencez 0:1fa43ab66921 672 level = prv_decreaseLevel(level);
terencez 0:1fa43ab66921 673 parentP = targetP;
terencez 0:1fa43ab66921 674 }
terencez 0:1fa43ab66921 675 if (recordArray[index].ids[resSegmentIndex + 1] != LWM2M_MAX_ID)
terencez 0:1fa43ab66921 676 {
terencez 0:1fa43ab66921 677 targetP->type = LWM2M_TYPE_MULTIPLE_RESOURCE;
terencez 0:1fa43ab66921 678 targetP = prv_extendData(targetP);
terencez 0:1fa43ab66921 679 if (targetP == NULL) goto error;
terencez 0:1fa43ab66921 680 targetP->id = recordArray[index].ids[resSegmentIndex + 1];
terencez 0:1fa43ab66921 681 targetP->type = LWM2M_TYPE_UNDEFINED;
terencez 0:1fa43ab66921 682 }
terencez 0:1fa43ab66921 683 }
terencez 0:1fa43ab66921 684
terencez 0:1fa43ab66921 685 if (true != prv_convertValue(recordArray + index, targetP)) goto error;
terencez 0:1fa43ab66921 686 }
terencez 0:1fa43ab66921 687
terencez 0:1fa43ab66921 688 return size;
terencez 0:1fa43ab66921 689
terencez 0:1fa43ab66921 690 error:
terencez 0:1fa43ab66921 691 lwm2m_data_free(size, *dataP);
terencez 0:1fa43ab66921 692 *dataP = NULL;
terencez 0:1fa43ab66921 693
terencez 0:1fa43ab66921 694 return -1;
terencez 0:1fa43ab66921 695 }
terencez 0:1fa43ab66921 696
terencez 0:1fa43ab66921 697 static int prv_dataStrip(int size,
terencez 0:1fa43ab66921 698 lwm2m_data_t * dataP,
terencez 0:1fa43ab66921 699 lwm2m_data_t ** resultP)
terencez 0:1fa43ab66921 700 {
terencez 0:1fa43ab66921 701 int i;
terencez 0:1fa43ab66921 702 int j;
terencez 0:1fa43ab66921 703 int realSize;
terencez 0:1fa43ab66921 704
terencez 0:1fa43ab66921 705 realSize = 0;
terencez 0:1fa43ab66921 706 for (i = 0 ; i < size ; i++)
terencez 0:1fa43ab66921 707 {
terencez 0:1fa43ab66921 708 if (dataP[i].type != LWM2M_TYPE_UNDEFINED)
terencez 0:1fa43ab66921 709 {
terencez 0:1fa43ab66921 710 realSize++;
terencez 0:1fa43ab66921 711 }
terencez 0:1fa43ab66921 712 }
terencez 0:1fa43ab66921 713
terencez 0:1fa43ab66921 714 *resultP = lwm2m_data_new(realSize);
terencez 0:1fa43ab66921 715 if (*resultP == NULL) return -1;
terencez 0:1fa43ab66921 716
terencez 0:1fa43ab66921 717 j = 0;
terencez 0:1fa43ab66921 718 for (i = 0 ; i < size ; i++)
terencez 0:1fa43ab66921 719 {
terencez 0:1fa43ab66921 720 if (dataP[i].type != LWM2M_TYPE_UNDEFINED)
terencez 0:1fa43ab66921 721 {
terencez 0:1fa43ab66921 722 memcpy((*resultP) + j, dataP + i, sizeof(lwm2m_data_t));
terencez 0:1fa43ab66921 723
terencez 0:1fa43ab66921 724 if (dataP[i].type == LWM2M_TYPE_OBJECT
terencez 0:1fa43ab66921 725 || dataP[i].type == LWM2M_TYPE_OBJECT_INSTANCE
terencez 0:1fa43ab66921 726 || dataP[i].type == LWM2M_TYPE_MULTIPLE_RESOURCE)
terencez 0:1fa43ab66921 727 {
terencez 0:1fa43ab66921 728 int childLen;
terencez 0:1fa43ab66921 729
terencez 0:1fa43ab66921 730 childLen = prv_dataStrip(dataP[i].value.asChildren.count, dataP[i].value.asChildren.array, &((*resultP)[j].value.asChildren.array));
terencez 0:1fa43ab66921 731 if (childLen <= 0)
terencez 0:1fa43ab66921 732 {
terencez 0:1fa43ab66921 733 // skip this one
terencez 0:1fa43ab66921 734 j--;
terencez 0:1fa43ab66921 735 }
terencez 0:1fa43ab66921 736 else
terencez 0:1fa43ab66921 737 {
terencez 0:1fa43ab66921 738 (*resultP)[j].value.asChildren.count = childLen;
terencez 0:1fa43ab66921 739 }
terencez 0:1fa43ab66921 740 }
terencez 0:1fa43ab66921 741 else
terencez 0:1fa43ab66921 742 {
terencez 0:1fa43ab66921 743 dataP[i].value.asBuffer.buffer = NULL;
terencez 0:1fa43ab66921 744 }
terencez 0:1fa43ab66921 745
terencez 0:1fa43ab66921 746 j++;
terencez 0:1fa43ab66921 747 }
terencez 0:1fa43ab66921 748 }
terencez 0:1fa43ab66921 749
terencez 0:1fa43ab66921 750 return realSize;
terencez 0:1fa43ab66921 751 }
terencez 0:1fa43ab66921 752
terencez 0:1fa43ab66921 753 int json_parse(lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 754 uint8_t * buffer,
terencez 0:1fa43ab66921 755 size_t bufferLen,
terencez 0:1fa43ab66921 756 lwm2m_data_t ** dataP)
terencez 0:1fa43ab66921 757 {
terencez 0:1fa43ab66921 758 size_t index;
terencez 0:1fa43ab66921 759 int count = 0;
terencez 0:1fa43ab66921 760 bool eFound = false;
terencez 0:1fa43ab66921 761 bool bnFound = false;
terencez 0:1fa43ab66921 762 bool btFound = false;
terencez 0:1fa43ab66921 763 int bnStart;
terencez 0:1fa43ab66921 764 int bnLen;
terencez 0:1fa43ab66921 765 _record_t * recordArray;
terencez 0:1fa43ab66921 766 lwm2m_data_t * parsedP;
terencez 0:1fa43ab66921 767
terencez 0:1fa43ab66921 768 LOG_ARG("bufferLen: %d, buffer: \"%s\"", bufferLen, (char *)buffer);
terencez 0:1fa43ab66921 769 LOG_URI(uriP);
terencez 0:1fa43ab66921 770 *dataP = NULL;
terencez 0:1fa43ab66921 771 recordArray = NULL;
terencez 0:1fa43ab66921 772 parsedP = NULL;
terencez 0:1fa43ab66921 773
terencez 0:1fa43ab66921 774 index = prv_skipSpace(buffer, bufferLen);
terencez 0:1fa43ab66921 775 if (index == bufferLen) return -1;
terencez 0:1fa43ab66921 776
terencez 0:1fa43ab66921 777 if (buffer[index] != '{') return -1;
terencez 0:1fa43ab66921 778 do
terencez 0:1fa43ab66921 779 {
terencez 0:1fa43ab66921 780 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 781 if (buffer[index] != '"') goto error;
terencez 0:1fa43ab66921 782 if (index++ >= bufferLen) goto error;
terencez 0:1fa43ab66921 783 switch (buffer[index])
terencez 0:1fa43ab66921 784 {
terencez 0:1fa43ab66921 785 case 'e':
terencez 0:1fa43ab66921 786 {
terencez 0:1fa43ab66921 787 int recordIndex;
terencez 0:1fa43ab66921 788
terencez 0:1fa43ab66921 789 if (bufferLen-index < JSON_MIN_ARRAY_LEN) goto error;
terencez 0:1fa43ab66921 790 index++;
terencez 0:1fa43ab66921 791 if (buffer[index] != '"') goto error;
terencez 0:1fa43ab66921 792 if (eFound == true) goto error;
terencez 0:1fa43ab66921 793 eFound = true;
terencez 0:1fa43ab66921 794
terencez 0:1fa43ab66921 795 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 796 if (buffer[index] != ':') goto error;
terencez 0:1fa43ab66921 797 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 798 if (buffer[index] != '[') goto error;
terencez 0:1fa43ab66921 799 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 800 count = prv_countItems(buffer + index, bufferLen - index);
terencez 0:1fa43ab66921 801 if (count <= 0) goto error;
terencez 0:1fa43ab66921 802 recordArray = (_record_t*)lwm2m_malloc(count * sizeof(_record_t));
terencez 0:1fa43ab66921 803 if (recordArray == NULL) goto error;
terencez 0:1fa43ab66921 804 // at this point we are sure buffer[index] is '{' and all { and } are matching
terencez 0:1fa43ab66921 805 recordIndex = 0;
terencez 0:1fa43ab66921 806 while (recordIndex < count)
terencez 0:1fa43ab66921 807 {
terencez 0:1fa43ab66921 808 int itemLen;
terencez 0:1fa43ab66921 809
terencez 0:1fa43ab66921 810 if (buffer[index] != '{') goto error;
terencez 0:1fa43ab66921 811 itemLen = 0;
terencez 0:1fa43ab66921 812 while (buffer[index + itemLen] != '}') itemLen++;
terencez 0:1fa43ab66921 813 if (0 != prv_parseItem(buffer + index + 1, itemLen - 1, recordArray + recordIndex))
terencez 0:1fa43ab66921 814 {
terencez 0:1fa43ab66921 815 goto error;
terencez 0:1fa43ab66921 816 }
terencez 0:1fa43ab66921 817 recordIndex++;
terencez 0:1fa43ab66921 818 index += itemLen;
terencez 0:1fa43ab66921 819 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 820 switch (buffer[index])
terencez 0:1fa43ab66921 821 {
terencez 0:1fa43ab66921 822 case ',':
terencez 0:1fa43ab66921 823 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 824 break;
terencez 0:1fa43ab66921 825 case ']':
terencez 0:1fa43ab66921 826 if (recordIndex == count) break;
terencez 0:1fa43ab66921 827 // else this is an error
terencez 0:1fa43ab66921 828 default:
terencez 0:1fa43ab66921 829 goto error;
terencez 0:1fa43ab66921 830 }
terencez 0:1fa43ab66921 831 }
terencez 0:1fa43ab66921 832 if (buffer[index] != ']') goto error;
terencez 0:1fa43ab66921 833 }
terencez 0:1fa43ab66921 834 break;
terencez 0:1fa43ab66921 835
terencez 0:1fa43ab66921 836 case 'b':
terencez 0:1fa43ab66921 837 if (bufferLen-index < JSON_MIN_BX_LEN) goto error;
terencez 0:1fa43ab66921 838 index++;
terencez 0:1fa43ab66921 839 switch (buffer[index])
terencez 0:1fa43ab66921 840 {
terencez 0:1fa43ab66921 841 case 't':
terencez 0:1fa43ab66921 842 index++;
terencez 0:1fa43ab66921 843 if (buffer[index] != '"') goto error;
terencez 0:1fa43ab66921 844 if (btFound == true) goto error;
terencez 0:1fa43ab66921 845 btFound = true;
terencez 0:1fa43ab66921 846
terencez 0:1fa43ab66921 847 // TODO: handle timed values
terencez 0:1fa43ab66921 848 // temp: skip this token
terencez 0:1fa43ab66921 849 while(index < bufferLen && buffer[index] != ',' && buffer[index] != '}') index++;
terencez 0:1fa43ab66921 850 if (index == bufferLen) goto error;
terencez 0:1fa43ab66921 851 index--;
terencez 0:1fa43ab66921 852 // end temp
terencez 0:1fa43ab66921 853 break;
terencez 0:1fa43ab66921 854 case 'n':
terencez 0:1fa43ab66921 855 {
terencez 0:1fa43ab66921 856 int next;
terencez 0:1fa43ab66921 857 int tokenStart;
terencez 0:1fa43ab66921 858 int tokenLen;
terencez 0:1fa43ab66921 859 int itemLen;
terencez 0:1fa43ab66921 860
terencez 0:1fa43ab66921 861 index++;
terencez 0:1fa43ab66921 862 if (buffer[index] != '"') goto error;
terencez 0:1fa43ab66921 863 if (bnFound == true) goto error;
terencez 0:1fa43ab66921 864 bnFound = true;
terencez 0:1fa43ab66921 865 index -= 3;
terencez 0:1fa43ab66921 866 itemLen = 0;
terencez 0:1fa43ab66921 867 while (buffer[index + itemLen] != '}'
terencez 0:1fa43ab66921 868 && buffer[index + itemLen] != ','
terencez 0:1fa43ab66921 869 && index + itemLen < bufferLen)
terencez 0:1fa43ab66921 870 {
terencez 0:1fa43ab66921 871 itemLen++;
terencez 0:1fa43ab66921 872 }
terencez 0:1fa43ab66921 873 if (index + itemLen == bufferLen) goto error;
terencez 0:1fa43ab66921 874 next = prv_split(buffer+index, itemLen, &tokenStart, &tokenLen, &bnStart, &bnLen);
terencez 0:1fa43ab66921 875 if (next < 0) goto error;
terencez 0:1fa43ab66921 876 bnStart += index;
terencez 0:1fa43ab66921 877 index += next - 1;
terencez 0:1fa43ab66921 878 }
terencez 0:1fa43ab66921 879 break;
terencez 0:1fa43ab66921 880 default:
terencez 0:1fa43ab66921 881 goto error;
terencez 0:1fa43ab66921 882 }
terencez 0:1fa43ab66921 883 break;
terencez 0:1fa43ab66921 884
terencez 0:1fa43ab66921 885 default:
terencez 0:1fa43ab66921 886 goto error;
terencez 0:1fa43ab66921 887 }
terencez 0:1fa43ab66921 888
terencez 0:1fa43ab66921 889 _GO_TO_NEXT_CHAR(index, buffer, bufferLen);
terencez 0:1fa43ab66921 890 } while (buffer[index] == ',');
terencez 0:1fa43ab66921 891
terencez 0:1fa43ab66921 892 if (buffer[index] != '}') goto error;
terencez 0:1fa43ab66921 893
terencez 0:1fa43ab66921 894 if (eFound == true)
terencez 0:1fa43ab66921 895 {
terencez 0:1fa43ab66921 896 lwm2m_uri_t baseURI;
terencez 0:1fa43ab66921 897 lwm2m_uri_t * baseUriP;
terencez 0:1fa43ab66921 898 lwm2m_data_t * resultP;
terencez 0:1fa43ab66921 899 int size;
terencez 0:1fa43ab66921 900
terencez 0:1fa43ab66921 901 memset(&baseURI, 0, sizeof(lwm2m_uri_t));
terencez 0:1fa43ab66921 902 if (bnFound == false)
terencez 0:1fa43ab66921 903 {
terencez 0:1fa43ab66921 904 baseUriP = uriP;
terencez 0:1fa43ab66921 905 }
terencez 0:1fa43ab66921 906 else
terencez 0:1fa43ab66921 907 {
terencez 0:1fa43ab66921 908 int res;
terencez 0:1fa43ab66921 909
terencez 0:1fa43ab66921 910 // we ignore the request URI and use the bn one.
terencez 0:1fa43ab66921 911
terencez 0:1fa43ab66921 912 // Check for " around URI
terencez 0:1fa43ab66921 913 if (bnLen < 3
terencez 0:1fa43ab66921 914 || buffer[bnStart] != '"'
terencez 0:1fa43ab66921 915 || buffer[bnStart+bnLen-1] != '"')
terencez 0:1fa43ab66921 916 {
terencez 0:1fa43ab66921 917 goto error;
terencez 0:1fa43ab66921 918 }
terencez 0:1fa43ab66921 919 bnStart += 1;
terencez 0:1fa43ab66921 920 bnLen -= 2;
terencez 0:1fa43ab66921 921
terencez 0:1fa43ab66921 922 if (bnLen == 1)
terencez 0:1fa43ab66921 923 {
terencez 0:1fa43ab66921 924 if (buffer[bnStart] != '/') goto error;
terencez 0:1fa43ab66921 925 baseUriP = NULL;
terencez 0:1fa43ab66921 926 }
terencez 0:1fa43ab66921 927 else
terencez 0:1fa43ab66921 928 {
terencez 0:1fa43ab66921 929 res = lwm2m_stringToUri((char *)buffer + bnStart, bnLen, &baseURI);
terencez 0:1fa43ab66921 930 if (res < 0 || res != bnLen) goto error;
terencez 0:1fa43ab66921 931 baseUriP = &baseURI;
terencez 0:1fa43ab66921 932 }
terencez 0:1fa43ab66921 933 }
terencez 0:1fa43ab66921 934
terencez 0:1fa43ab66921 935 count = prv_convertRecord(baseUriP, recordArray, count, &parsedP);
terencez 0:1fa43ab66921 936 lwm2m_free(recordArray);
terencez 0:1fa43ab66921 937 recordArray = NULL;
terencez 0:1fa43ab66921 938
terencez 0:1fa43ab66921 939 if (count > 0 && uriP != NULL)
terencez 0:1fa43ab66921 940 {
terencez 0:1fa43ab66921 941 if (parsedP->type != LWM2M_TYPE_OBJECT || parsedP->id != uriP->objectId) goto error;
terencez 0:1fa43ab66921 942 if (!LWM2M_URI_IS_SET_INSTANCE(uriP))
terencez 0:1fa43ab66921 943 {
terencez 0:1fa43ab66921 944 size = parsedP->value.asChildren.count;
terencez 0:1fa43ab66921 945 resultP = parsedP->value.asChildren.array;
terencez 0:1fa43ab66921 946 }
terencez 0:1fa43ab66921 947 else
terencez 0:1fa43ab66921 948 {
terencez 0:1fa43ab66921 949 int i;
terencez 0:1fa43ab66921 950
terencez 0:1fa43ab66921 951 resultP = NULL;
terencez 0:1fa43ab66921 952 // be permissive and allow full object JSON when requesting for a single instance
terencez 0:1fa43ab66921 953 for (i = 0 ; i < (int)parsedP->value.asChildren.count && resultP == NULL; i++)
terencez 0:1fa43ab66921 954 {
terencez 0:1fa43ab66921 955 lwm2m_data_t * targetP;
terencez 0:1fa43ab66921 956
terencez 0:1fa43ab66921 957 targetP = parsedP->value.asChildren.array + i;
terencez 0:1fa43ab66921 958 if (targetP->id == uriP->instanceId)
terencez 0:1fa43ab66921 959 {
terencez 0:1fa43ab66921 960 resultP = targetP->value.asChildren.array;
terencez 0:1fa43ab66921 961 size = targetP->value.asChildren.count;
terencez 0:1fa43ab66921 962 }
terencez 0:1fa43ab66921 963 }
terencez 0:1fa43ab66921 964 if (resultP == NULL) goto error;
terencez 0:1fa43ab66921 965 if (LWM2M_URI_IS_SET_RESOURCE(uriP))
terencez 0:1fa43ab66921 966 {
terencez 0:1fa43ab66921 967 lwm2m_data_t * resP;
terencez 0:1fa43ab66921 968
terencez 0:1fa43ab66921 969 resP = NULL;
terencez 0:1fa43ab66921 970 for (i = 0 ; i < size && resP == NULL; i++)
terencez 0:1fa43ab66921 971 {
terencez 0:1fa43ab66921 972 lwm2m_data_t * targetP;
terencez 0:1fa43ab66921 973
terencez 0:1fa43ab66921 974 targetP = resultP + i;
terencez 0:1fa43ab66921 975 if (targetP->id == uriP->resourceId)
terencez 0:1fa43ab66921 976 {
terencez 0:1fa43ab66921 977 if (targetP->type == LWM2M_TYPE_MULTIPLE_RESOURCE)
terencez 0:1fa43ab66921 978 {
terencez 0:1fa43ab66921 979 resP = targetP->value.asChildren.array;
terencez 0:1fa43ab66921 980 size = targetP->value.asChildren.count;
terencez 0:1fa43ab66921 981 }
terencez 0:1fa43ab66921 982 else
terencez 0:1fa43ab66921 983 {
terencez 0:1fa43ab66921 984 size = prv_dataStrip(1, targetP, &resP);
terencez 0:1fa43ab66921 985 if (size <= 0) goto error;
terencez 0:1fa43ab66921 986 lwm2m_data_free(count, parsedP);
terencez 0:1fa43ab66921 987 parsedP = NULL;
terencez 0:1fa43ab66921 988 }
terencez 0:1fa43ab66921 989 }
terencez 0:1fa43ab66921 990 }
terencez 0:1fa43ab66921 991 if (resP == NULL) goto error;
terencez 0:1fa43ab66921 992 resultP = resP;
terencez 0:1fa43ab66921 993 }
terencez 0:1fa43ab66921 994 }
terencez 0:1fa43ab66921 995 }
terencez 0:1fa43ab66921 996 else
terencez 0:1fa43ab66921 997 {
terencez 0:1fa43ab66921 998 resultP = parsedP;
terencez 0:1fa43ab66921 999 size = count;
terencez 0:1fa43ab66921 1000 }
terencez 0:1fa43ab66921 1001
terencez 0:1fa43ab66921 1002 if (parsedP != NULL)
terencez 0:1fa43ab66921 1003 {
terencez 0:1fa43ab66921 1004 lwm2m_data_t * tempP;
terencez 0:1fa43ab66921 1005
terencez 0:1fa43ab66921 1006 size = prv_dataStrip(size, resultP, &tempP);
terencez 0:1fa43ab66921 1007 if (size <= 0) goto error;
terencez 0:1fa43ab66921 1008 lwm2m_data_free(count, parsedP);
terencez 0:1fa43ab66921 1009 resultP = tempP;
terencez 0:1fa43ab66921 1010 }
terencez 0:1fa43ab66921 1011 count = size;
terencez 0:1fa43ab66921 1012 *dataP = resultP;
terencez 0:1fa43ab66921 1013 }
terencez 0:1fa43ab66921 1014
terencez 0:1fa43ab66921 1015 LOG_ARG("Parsing successful. count: %d", count);
terencez 0:1fa43ab66921 1016 return count;
terencez 0:1fa43ab66921 1017
terencez 0:1fa43ab66921 1018 error:
terencez 0:1fa43ab66921 1019 LOG("Parsing failed");
terencez 0:1fa43ab66921 1020 if (parsedP != NULL)
terencez 0:1fa43ab66921 1021 {
terencez 0:1fa43ab66921 1022 lwm2m_data_free(count, parsedP);
terencez 0:1fa43ab66921 1023 parsedP = NULL;
terencez 0:1fa43ab66921 1024 }
terencez 0:1fa43ab66921 1025 if (recordArray != NULL)
terencez 0:1fa43ab66921 1026 {
terencez 0:1fa43ab66921 1027 lwm2m_free(recordArray);
terencez 0:1fa43ab66921 1028 }
terencez 0:1fa43ab66921 1029 return -1;
terencez 0:1fa43ab66921 1030 }
terencez 0:1fa43ab66921 1031
terencez 0:1fa43ab66921 1032 static int prv_serializeValue(lwm2m_data_t * tlvP,
terencez 0:1fa43ab66921 1033 uint8_t * buffer,
terencez 0:1fa43ab66921 1034 size_t bufferLen)
terencez 0:1fa43ab66921 1035 {
terencez 0:1fa43ab66921 1036 int res;
terencez 0:1fa43ab66921 1037 int head;
terencez 0:1fa43ab66921 1038
terencez 0:1fa43ab66921 1039 switch (tlvP->type)
terencez 0:1fa43ab66921 1040 {
terencez 0:1fa43ab66921 1041 case LWM2M_TYPE_STRING:
terencez 0:1fa43ab66921 1042 if (bufferLen < JSON_ITEM_STRING_BEGIN_SIZE) return -1;
terencez 0:1fa43ab66921 1043 memcpy(buffer, JSON_ITEM_STRING_BEGIN, JSON_ITEM_STRING_BEGIN_SIZE);
terencez 0:1fa43ab66921 1044 head = JSON_ITEM_STRING_BEGIN_SIZE;
terencez 0:1fa43ab66921 1045
terencez 0:1fa43ab66921 1046 if (bufferLen - head < tlvP->value.asBuffer.length) return -1;
terencez 0:1fa43ab66921 1047 memcpy(buffer + head, tlvP->value.asBuffer.buffer, tlvP->value.asBuffer.length);
terencez 0:1fa43ab66921 1048 head += tlvP->value.asBuffer.length;
terencez 0:1fa43ab66921 1049
terencez 0:1fa43ab66921 1050 if (bufferLen - head < JSON_ITEM_STRING_END_SIZE) return -1;
terencez 0:1fa43ab66921 1051 memcpy(buffer + head, JSON_ITEM_STRING_END, JSON_ITEM_STRING_END_SIZE);
terencez 0:1fa43ab66921 1052 head += JSON_ITEM_STRING_END_SIZE;
terencez 0:1fa43ab66921 1053
terencez 0:1fa43ab66921 1054 break;
terencez 0:1fa43ab66921 1055
terencez 0:1fa43ab66921 1056 case LWM2M_TYPE_INTEGER:
terencez 0:1fa43ab66921 1057 {
terencez 0:1fa43ab66921 1058 int64_t value;
terencez 0:1fa43ab66921 1059
terencez 0:1fa43ab66921 1060 if (0 == lwm2m_data_decode_int(tlvP, &value)) return -1;
terencez 0:1fa43ab66921 1061
terencez 0:1fa43ab66921 1062 if (bufferLen < JSON_ITEM_NUM_SIZE) return -1;
terencez 0:1fa43ab66921 1063 memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE);
terencez 0:1fa43ab66921 1064 head = JSON_ITEM_NUM_SIZE;
terencez 0:1fa43ab66921 1065
terencez 0:1fa43ab66921 1066 res = utils_intToText(value, buffer + head, bufferLen - head);
terencez 0:1fa43ab66921 1067 if (res <= 0) return -1;
terencez 0:1fa43ab66921 1068 head += res;
terencez 0:1fa43ab66921 1069
terencez 0:1fa43ab66921 1070 if (bufferLen - head < JSON_ITEM_NUM_END_SIZE) return -1;
terencez 0:1fa43ab66921 1071 memcpy(buffer + head, JSON_ITEM_NUM_END, JSON_ITEM_NUM_END_SIZE);
terencez 0:1fa43ab66921 1072 head += JSON_ITEM_NUM_END_SIZE;
terencez 0:1fa43ab66921 1073 }
terencez 0:1fa43ab66921 1074 break;
terencez 0:1fa43ab66921 1075
terencez 0:1fa43ab66921 1076 case LWM2M_TYPE_FLOAT:
terencez 0:1fa43ab66921 1077 {
terencez 0:1fa43ab66921 1078 double value;
terencez 0:1fa43ab66921 1079
terencez 0:1fa43ab66921 1080 if (0 == lwm2m_data_decode_float(tlvP, &value)) return -1;
terencez 0:1fa43ab66921 1081
terencez 0:1fa43ab66921 1082 if (bufferLen < JSON_ITEM_NUM_SIZE) return -1;
terencez 0:1fa43ab66921 1083 memcpy(buffer, JSON_ITEM_NUM, JSON_ITEM_NUM_SIZE);
terencez 0:1fa43ab66921 1084 head = JSON_ITEM_NUM_SIZE;
terencez 0:1fa43ab66921 1085
terencez 0:1fa43ab66921 1086 res = utils_floatToText(value, buffer + head, bufferLen - head);
terencez 0:1fa43ab66921 1087 if (res <= 0) return -1;
terencez 0:1fa43ab66921 1088 head += res;
terencez 0:1fa43ab66921 1089
terencez 0:1fa43ab66921 1090 if (bufferLen - head < JSON_ITEM_NUM_END_SIZE) return -1;
terencez 0:1fa43ab66921 1091 memcpy(buffer + head, JSON_ITEM_NUM_END, JSON_ITEM_NUM_END_SIZE);
terencez 0:1fa43ab66921 1092 head += JSON_ITEM_NUM_END_SIZE;
terencez 0:1fa43ab66921 1093 }
terencez 0:1fa43ab66921 1094 break;
terencez 0:1fa43ab66921 1095
terencez 0:1fa43ab66921 1096 case LWM2M_TYPE_BOOLEAN:
terencez 0:1fa43ab66921 1097 {
terencez 0:1fa43ab66921 1098 bool value;
terencez 0:1fa43ab66921 1099
terencez 0:1fa43ab66921 1100 if (0 == lwm2m_data_decode_bool(tlvP, &value)) return -1;
terencez 0:1fa43ab66921 1101
terencez 0:1fa43ab66921 1102 if (value == true)
terencez 0:1fa43ab66921 1103 {
terencez 0:1fa43ab66921 1104 if (bufferLen < JSON_ITEM_BOOL_TRUE_SIZE) return -1;
terencez 0:1fa43ab66921 1105 memcpy(buffer, JSON_ITEM_BOOL_TRUE, JSON_ITEM_BOOL_TRUE_SIZE);
terencez 0:1fa43ab66921 1106 head = JSON_ITEM_BOOL_TRUE_SIZE;
terencez 0:1fa43ab66921 1107 }
terencez 0:1fa43ab66921 1108 else
terencez 0:1fa43ab66921 1109 {
terencez 0:1fa43ab66921 1110 if (bufferLen < JSON_ITEM_BOOL_FALSE_SIZE) return -1;
terencez 0:1fa43ab66921 1111 memcpy(buffer, JSON_ITEM_BOOL_FALSE, JSON_ITEM_BOOL_FALSE_SIZE);
terencez 0:1fa43ab66921 1112 head = JSON_ITEM_BOOL_FALSE_SIZE;
terencez 0:1fa43ab66921 1113 }
terencez 0:1fa43ab66921 1114 }
terencez 0:1fa43ab66921 1115 break;
terencez 0:1fa43ab66921 1116
terencez 0:1fa43ab66921 1117 case LWM2M_TYPE_OPAQUE:
terencez 0:1fa43ab66921 1118 if (bufferLen < JSON_ITEM_STRING_BEGIN_SIZE) return -1;
terencez 0:1fa43ab66921 1119 memcpy(buffer, JSON_ITEM_STRING_BEGIN, JSON_ITEM_STRING_BEGIN_SIZE);
terencez 0:1fa43ab66921 1120 head = JSON_ITEM_STRING_BEGIN_SIZE;
terencez 0:1fa43ab66921 1121
terencez 0:1fa43ab66921 1122 res = utils_base64Encode(tlvP->value.asBuffer.buffer, tlvP->value.asBuffer.length, buffer+head, bufferLen - head);
terencez 0:1fa43ab66921 1123 if (res == 0) return -1;
terencez 0:1fa43ab66921 1124 head += res;
terencez 0:1fa43ab66921 1125
terencez 0:1fa43ab66921 1126 if (bufferLen - head < JSON_ITEM_STRING_END_SIZE) return -1;
terencez 0:1fa43ab66921 1127 memcpy(buffer + head, JSON_ITEM_STRING_END, JSON_ITEM_STRING_END_SIZE);
terencez 0:1fa43ab66921 1128 head += JSON_ITEM_STRING_END_SIZE;
terencez 0:1fa43ab66921 1129 break;
terencez 0:1fa43ab66921 1130
terencez 0:1fa43ab66921 1131 case LWM2M_TYPE_OBJECT_LINK:
terencez 0:1fa43ab66921 1132 // TODO: implement
terencez 0:1fa43ab66921 1133 return -1;
terencez 0:1fa43ab66921 1134
terencez 0:1fa43ab66921 1135 default:
terencez 0:1fa43ab66921 1136 return -1;
terencez 0:1fa43ab66921 1137 }
terencez 0:1fa43ab66921 1138
terencez 0:1fa43ab66921 1139 return head;
terencez 0:1fa43ab66921 1140 }
terencez 0:1fa43ab66921 1141
terencez 0:1fa43ab66921 1142 int prv_serializeData(lwm2m_data_t * tlvP,
terencez 0:1fa43ab66921 1143 uint8_t * parentUriStr,
terencez 0:1fa43ab66921 1144 size_t parentUriLen,
terencez 0:1fa43ab66921 1145 uint8_t * buffer,
terencez 0:1fa43ab66921 1146 size_t bufferLen)
terencez 0:1fa43ab66921 1147 {
terencez 0:1fa43ab66921 1148 int head;
terencez 0:1fa43ab66921 1149 int res;
terencez 0:1fa43ab66921 1150
terencez 0:1fa43ab66921 1151 head = 0;
terencez 0:1fa43ab66921 1152
terencez 0:1fa43ab66921 1153 switch (tlvP->type)
terencez 0:1fa43ab66921 1154 {
terencez 0:1fa43ab66921 1155 case LWM2M_TYPE_OBJECT:
terencez 0:1fa43ab66921 1156 case LWM2M_TYPE_OBJECT_INSTANCE:
terencez 0:1fa43ab66921 1157 case LWM2M_TYPE_MULTIPLE_RESOURCE:
terencez 0:1fa43ab66921 1158 {
terencez 0:1fa43ab66921 1159 uint8_t uriStr[URI_MAX_STRING_LEN];
terencez 0:1fa43ab66921 1160 size_t uriLen;
terencez 0:1fa43ab66921 1161 size_t index;
terencez 0:1fa43ab66921 1162
terencez 0:1fa43ab66921 1163 if (parentUriLen > 0)
terencez 0:1fa43ab66921 1164 {
terencez 0:1fa43ab66921 1165 if (URI_MAX_STRING_LEN < parentUriLen) return -1;
terencez 0:1fa43ab66921 1166 memcpy(uriStr, parentUriStr, parentUriLen);
terencez 0:1fa43ab66921 1167 uriLen = parentUriLen;
terencez 0:1fa43ab66921 1168 }
terencez 0:1fa43ab66921 1169 else
terencez 0:1fa43ab66921 1170 {
terencez 0:1fa43ab66921 1171 uriLen = 0;
terencez 0:1fa43ab66921 1172 }
terencez 0:1fa43ab66921 1173 res = utils_intToText(tlvP->id, uriStr + uriLen, URI_MAX_STRING_LEN - uriLen);
terencez 0:1fa43ab66921 1174 if (res <= 0) return -1;
terencez 0:1fa43ab66921 1175 uriLen += res;
terencez 0:1fa43ab66921 1176 uriStr[uriLen] = '/';
terencez 0:1fa43ab66921 1177 uriLen++;
terencez 0:1fa43ab66921 1178
terencez 0:1fa43ab66921 1179 head = 0;
terencez 0:1fa43ab66921 1180 for (index = 0 ; index < tlvP->value.asChildren.count; index++)
terencez 0:1fa43ab66921 1181 {
terencez 0:1fa43ab66921 1182 res = prv_serializeData(tlvP->value.asChildren.array + index, uriStr, uriLen, buffer + head, bufferLen - head);
terencez 0:1fa43ab66921 1183 if (res < 0) return -1;
terencez 0:1fa43ab66921 1184 head += res;
terencez 0:1fa43ab66921 1185 }
terencez 0:1fa43ab66921 1186 }
terencez 0:1fa43ab66921 1187 break;
terencez 0:1fa43ab66921 1188
terencez 0:1fa43ab66921 1189 default:
terencez 0:1fa43ab66921 1190 if (bufferLen < JSON_RES_ITEM_URI_SIZE) return -1;
terencez 0:1fa43ab66921 1191 memcpy(buffer, JSON_RES_ITEM_URI, JSON_RES_ITEM_URI_SIZE);
terencez 0:1fa43ab66921 1192 head = JSON_RES_ITEM_URI_SIZE;
terencez 0:1fa43ab66921 1193
terencez 0:1fa43ab66921 1194 if (parentUriLen > 0)
terencez 0:1fa43ab66921 1195 {
terencez 0:1fa43ab66921 1196 if (bufferLen - head < parentUriLen) return -1;
terencez 0:1fa43ab66921 1197 memcpy(buffer + head, parentUriStr, parentUriLen);
terencez 0:1fa43ab66921 1198 head += parentUriLen;
terencez 0:1fa43ab66921 1199 }
terencez 0:1fa43ab66921 1200
terencez 0:1fa43ab66921 1201 res = utils_intToText(tlvP->id, buffer + head, bufferLen - head);
terencez 0:1fa43ab66921 1202 if (res <= 0) return -1;
terencez 0:1fa43ab66921 1203 head += res;
terencez 0:1fa43ab66921 1204
terencez 0:1fa43ab66921 1205 res = prv_serializeValue(tlvP, buffer + head, bufferLen - head);
terencez 0:1fa43ab66921 1206 if (res < 0) return -1;
terencez 0:1fa43ab66921 1207 head += res;
terencez 0:1fa43ab66921 1208 break;
terencez 0:1fa43ab66921 1209 }
terencez 0:1fa43ab66921 1210
terencez 0:1fa43ab66921 1211 return head;
terencez 0:1fa43ab66921 1212 }
terencez 0:1fa43ab66921 1213
terencez 0:1fa43ab66921 1214 static int prv_findAndCheckData(lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 1215 uri_depth_t level,
terencez 0:1fa43ab66921 1216 size_t size,
terencez 0:1fa43ab66921 1217 lwm2m_data_t * tlvP,
terencez 0:1fa43ab66921 1218 lwm2m_data_t ** targetP)
terencez 0:1fa43ab66921 1219 {
terencez 0:1fa43ab66921 1220 size_t index;
terencez 0:1fa43ab66921 1221 int result;
terencez 0:1fa43ab66921 1222
terencez 0:1fa43ab66921 1223 if (size == 0) return 0;
terencez 0:1fa43ab66921 1224
terencez 0:1fa43ab66921 1225 if (size > 1)
terencez 0:1fa43ab66921 1226 {
terencez 0:1fa43ab66921 1227 if (tlvP[0].type == LWM2M_TYPE_OBJECT || tlvP[0].type == LWM2M_TYPE_OBJECT_INSTANCE)
terencez 0:1fa43ab66921 1228 {
terencez 0:1fa43ab66921 1229 for (index = 0; index < size; index++)
terencez 0:1fa43ab66921 1230 {
terencez 0:1fa43ab66921 1231 if (tlvP[index].type != tlvP[0].type)
terencez 0:1fa43ab66921 1232 {
terencez 0:1fa43ab66921 1233 *targetP = NULL;
terencez 0:1fa43ab66921 1234 return -1;
terencez 0:1fa43ab66921 1235 }
terencez 0:1fa43ab66921 1236 }
terencez 0:1fa43ab66921 1237 }
terencez 0:1fa43ab66921 1238 else
terencez 0:1fa43ab66921 1239 {
terencez 0:1fa43ab66921 1240 for (index = 0; index < size; index++)
terencez 0:1fa43ab66921 1241 {
terencez 0:1fa43ab66921 1242 if (tlvP[index].type == LWM2M_TYPE_OBJECT || tlvP[index].type == LWM2M_TYPE_OBJECT_INSTANCE)
terencez 0:1fa43ab66921 1243 {
terencez 0:1fa43ab66921 1244 *targetP = NULL;
terencez 0:1fa43ab66921 1245 return -1;
terencez 0:1fa43ab66921 1246 }
terencez 0:1fa43ab66921 1247 }
terencez 0:1fa43ab66921 1248 }
terencez 0:1fa43ab66921 1249 }
terencez 0:1fa43ab66921 1250
terencez 0:1fa43ab66921 1251 *targetP = NULL;
terencez 0:1fa43ab66921 1252 result = -1;
terencez 0:1fa43ab66921 1253 switch (level)
terencez 0:1fa43ab66921 1254 {
terencez 0:1fa43ab66921 1255 case URI_DEPTH_OBJECT:
terencez 0:1fa43ab66921 1256 if (tlvP[0].type == LWM2M_TYPE_OBJECT)
terencez 0:1fa43ab66921 1257 {
terencez 0:1fa43ab66921 1258 *targetP = tlvP;
terencez 0:1fa43ab66921 1259 result = (int)size;
terencez 0:1fa43ab66921 1260 }
terencez 0:1fa43ab66921 1261 break;
terencez 0:1fa43ab66921 1262
terencez 0:1fa43ab66921 1263 case URI_DEPTH_OBJECT_INSTANCE:
terencez 0:1fa43ab66921 1264 switch (tlvP[0].type)
terencez 0:1fa43ab66921 1265 {
terencez 0:1fa43ab66921 1266 case LWM2M_TYPE_OBJECT:
terencez 0:1fa43ab66921 1267 for (index = 0; index < size; index++)
terencez 0:1fa43ab66921 1268 {
terencez 0:1fa43ab66921 1269 if (tlvP[index].id == uriP->objectId)
terencez 0:1fa43ab66921 1270 {
terencez 0:1fa43ab66921 1271 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP);
terencez 0:1fa43ab66921 1272 }
terencez 0:1fa43ab66921 1273 }
terencez 0:1fa43ab66921 1274 break;
terencez 0:1fa43ab66921 1275 case LWM2M_TYPE_OBJECT_INSTANCE:
terencez 0:1fa43ab66921 1276 *targetP = tlvP;
terencez 0:1fa43ab66921 1277 result = (int)size;
terencez 0:1fa43ab66921 1278 break;
terencez 0:1fa43ab66921 1279 default:
terencez 0:1fa43ab66921 1280 break;
terencez 0:1fa43ab66921 1281 }
terencez 0:1fa43ab66921 1282 break;
terencez 0:1fa43ab66921 1283
terencez 0:1fa43ab66921 1284 case URI_DEPTH_RESOURCE:
terencez 0:1fa43ab66921 1285 switch (tlvP[0].type)
terencez 0:1fa43ab66921 1286 {
terencez 0:1fa43ab66921 1287 case LWM2M_TYPE_OBJECT:
terencez 0:1fa43ab66921 1288 for (index = 0; index < size; index++)
terencez 0:1fa43ab66921 1289 {
terencez 0:1fa43ab66921 1290 if (tlvP[index].id == uriP->objectId)
terencez 0:1fa43ab66921 1291 {
terencez 0:1fa43ab66921 1292 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP);
terencez 0:1fa43ab66921 1293 }
terencez 0:1fa43ab66921 1294 }
terencez 0:1fa43ab66921 1295 break;
terencez 0:1fa43ab66921 1296 case LWM2M_TYPE_OBJECT_INSTANCE:
terencez 0:1fa43ab66921 1297 for (index = 0; index < size; index++)
terencez 0:1fa43ab66921 1298 {
terencez 0:1fa43ab66921 1299 if (tlvP[index].id == uriP->instanceId)
terencez 0:1fa43ab66921 1300 {
terencez 0:1fa43ab66921 1301 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP);
terencez 0:1fa43ab66921 1302 }
terencez 0:1fa43ab66921 1303 }
terencez 0:1fa43ab66921 1304 break;
terencez 0:1fa43ab66921 1305 default:
terencez 0:1fa43ab66921 1306 *targetP = tlvP;
terencez 0:1fa43ab66921 1307 result = (int)size;
terencez 0:1fa43ab66921 1308 break;
terencez 0:1fa43ab66921 1309 }
terencez 0:1fa43ab66921 1310 break;
terencez 0:1fa43ab66921 1311
terencez 0:1fa43ab66921 1312 case URI_DEPTH_RESOURCE_INSTANCE:
terencez 0:1fa43ab66921 1313 switch (tlvP[0].type)
terencez 0:1fa43ab66921 1314 {
terencez 0:1fa43ab66921 1315 case LWM2M_TYPE_OBJECT:
terencez 0:1fa43ab66921 1316 for (index = 0; index < size; index++)
terencez 0:1fa43ab66921 1317 {
terencez 0:1fa43ab66921 1318 if (tlvP[index].id == uriP->objectId)
terencez 0:1fa43ab66921 1319 {
terencez 0:1fa43ab66921 1320 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP);
terencez 0:1fa43ab66921 1321 }
terencez 0:1fa43ab66921 1322 }
terencez 0:1fa43ab66921 1323 break;
terencez 0:1fa43ab66921 1324 case LWM2M_TYPE_OBJECT_INSTANCE:
terencez 0:1fa43ab66921 1325 for (index = 0; index < size; index++)
terencez 0:1fa43ab66921 1326 {
terencez 0:1fa43ab66921 1327 if (tlvP[index].id == uriP->instanceId)
terencez 0:1fa43ab66921 1328 {
terencez 0:1fa43ab66921 1329 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP);
terencez 0:1fa43ab66921 1330 }
terencez 0:1fa43ab66921 1331 }
terencez 0:1fa43ab66921 1332 break;
terencez 0:1fa43ab66921 1333 case LWM2M_TYPE_MULTIPLE_RESOURCE:
terencez 0:1fa43ab66921 1334 for (index = 0; index < size; index++)
terencez 0:1fa43ab66921 1335 {
terencez 0:1fa43ab66921 1336 if (tlvP[index].id == uriP->resourceId)
terencez 0:1fa43ab66921 1337 {
terencez 0:1fa43ab66921 1338 return prv_findAndCheckData(uriP, level, tlvP[index].value.asChildren.count, tlvP[index].value.asChildren.array, targetP);
terencez 0:1fa43ab66921 1339 }
terencez 0:1fa43ab66921 1340 }
terencez 0:1fa43ab66921 1341 break;
terencez 0:1fa43ab66921 1342 default:
terencez 0:1fa43ab66921 1343 *targetP = tlvP;
terencez 0:1fa43ab66921 1344 result = (int)size;
terencez 0:1fa43ab66921 1345 break;
terencez 0:1fa43ab66921 1346 }
terencez 0:1fa43ab66921 1347 break;
terencez 0:1fa43ab66921 1348
terencez 0:1fa43ab66921 1349 default:
terencez 0:1fa43ab66921 1350 break;
terencez 0:1fa43ab66921 1351 }
terencez 0:1fa43ab66921 1352
terencez 0:1fa43ab66921 1353 return result;
terencez 0:1fa43ab66921 1354 }
terencez 0:1fa43ab66921 1355
terencez 0:1fa43ab66921 1356 int json_serialize(lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 1357 int size,
terencez 0:1fa43ab66921 1358 lwm2m_data_t * tlvP,
terencez 0:1fa43ab66921 1359 uint8_t ** bufferP)
terencez 0:1fa43ab66921 1360 {
terencez 0:1fa43ab66921 1361 int index;
terencez 0:1fa43ab66921 1362 size_t head;
terencez 0:1fa43ab66921 1363 uint8_t bufferJSON[PRV_JSON_BUFFER_SIZE];
terencez 0:1fa43ab66921 1364 uint8_t baseUriStr[URI_MAX_STRING_LEN];
terencez 0:1fa43ab66921 1365 int baseUriLen;
terencez 0:1fa43ab66921 1366 uri_depth_t rootLevel;
terencez 0:1fa43ab66921 1367 int num;
terencez 0:1fa43ab66921 1368 lwm2m_data_t * targetP;
terencez 0:1fa43ab66921 1369
terencez 0:1fa43ab66921 1370 LOG_ARG("size: %d", size);
terencez 0:1fa43ab66921 1371 LOG_URI(uriP);
terencez 0:1fa43ab66921 1372 if (size != 0 && tlvP == NULL) return -1;
terencez 0:1fa43ab66921 1373
terencez 0:1fa43ab66921 1374 baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, &rootLevel);
terencez 0:1fa43ab66921 1375 if (baseUriLen < 0) return -1;
terencez 0:1fa43ab66921 1376
terencez 0:1fa43ab66921 1377 num = prv_findAndCheckData(uriP, rootLevel, size, tlvP, &targetP);
terencez 0:1fa43ab66921 1378 if (num < 0) return -1;
terencez 0:1fa43ab66921 1379
terencez 0:1fa43ab66921 1380 while (num == 1
terencez 0:1fa43ab66921 1381 && (targetP->type == LWM2M_TYPE_OBJECT
terencez 0:1fa43ab66921 1382 || targetP->type == LWM2M_TYPE_OBJECT_INSTANCE
terencez 0:1fa43ab66921 1383 || targetP->type == LWM2M_TYPE_MULTIPLE_RESOURCE))
terencez 0:1fa43ab66921 1384 {
terencez 0:1fa43ab66921 1385 int res;
terencez 0:1fa43ab66921 1386
terencez 0:1fa43ab66921 1387 res = utils_intToText(targetP->id, baseUriStr + baseUriLen, URI_MAX_STRING_LEN - baseUriLen);
terencez 0:1fa43ab66921 1388 if (res <= 0) return 0;
terencez 0:1fa43ab66921 1389 baseUriLen += res;
terencez 0:1fa43ab66921 1390 if (baseUriLen >= URI_MAX_STRING_LEN -1) return 0;
terencez 0:1fa43ab66921 1391 num = targetP->value.asChildren.count;
terencez 0:1fa43ab66921 1392 targetP = targetP->value.asChildren.array;
terencez 0:1fa43ab66921 1393 baseUriStr[baseUriLen] = '/';
terencez 0:1fa43ab66921 1394 baseUriLen++;
terencez 0:1fa43ab66921 1395 }
terencez 0:1fa43ab66921 1396
terencez 0:1fa43ab66921 1397 if (baseUriLen > 0)
terencez 0:1fa43ab66921 1398 {
terencez 0:1fa43ab66921 1399 memcpy(bufferJSON, JSON_BN_HEADER_1, JSON_BN_HEADER_1_SIZE);
terencez 0:1fa43ab66921 1400 head = JSON_BN_HEADER_1_SIZE;
terencez 0:1fa43ab66921 1401 memcpy(bufferJSON + head, baseUriStr, baseUriLen);
terencez 0:1fa43ab66921 1402 head += baseUriLen;
terencez 0:1fa43ab66921 1403 memcpy(bufferJSON + head, JSON_BN_HEADER_2, JSON_BN_HEADER_2_SIZE);
terencez 0:1fa43ab66921 1404 head += JSON_BN_HEADER_2_SIZE;
terencez 0:1fa43ab66921 1405 }
terencez 0:1fa43ab66921 1406 else
terencez 0:1fa43ab66921 1407 {
terencez 0:1fa43ab66921 1408 memcpy(bufferJSON, JSON_HEADER, JSON_HEADER_SIZE);
terencez 0:1fa43ab66921 1409 head = JSON_HEADER_SIZE;
terencez 0:1fa43ab66921 1410 }
terencez 0:1fa43ab66921 1411
terencez 0:1fa43ab66921 1412 for (index = 0 ; index < num && head < PRV_JSON_BUFFER_SIZE ; index++)
terencez 0:1fa43ab66921 1413 {
terencez 0:1fa43ab66921 1414 int res;
terencez 0:1fa43ab66921 1415
terencez 0:1fa43ab66921 1416 res = prv_serializeData(targetP + index, NULL, 0, bufferJSON + head, PRV_JSON_BUFFER_SIZE - head);
terencez 0:1fa43ab66921 1417 if (res < 0) return 0;
terencez 0:1fa43ab66921 1418 head += res;
terencez 0:1fa43ab66921 1419 }
terencez 0:1fa43ab66921 1420
terencez 0:1fa43ab66921 1421 if (head + JSON_FOOTER_SIZE - 1 > PRV_JSON_BUFFER_SIZE) return 0;
terencez 0:1fa43ab66921 1422
terencez 0:1fa43ab66921 1423 if (num > 0) head = head - 1;
terencez 0:1fa43ab66921 1424
terencez 0:1fa43ab66921 1425 memcpy(bufferJSON + head, JSON_FOOTER, JSON_FOOTER_SIZE);
terencez 0:1fa43ab66921 1426 head = head + JSON_FOOTER_SIZE;
terencez 0:1fa43ab66921 1427
terencez 0:1fa43ab66921 1428 *bufferP = (uint8_t *)lwm2m_malloc(head);
terencez 0:1fa43ab66921 1429 if (*bufferP == NULL) return 0;
terencez 0:1fa43ab66921 1430 memcpy(*bufferP, bufferJSON, head);
terencez 0:1fa43ab66921 1431
terencez 0:1fa43ab66921 1432 return head;
terencez 0:1fa43ab66921 1433 }
terencez 0:1fa43ab66921 1434
terencez 0:1fa43ab66921 1435 #endif
terencez 0:1fa43ab66921 1436