core_json.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890
  1. /*
  2. * coreJSON
  3. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * SPDX-License-Identifier: MIT
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  8. * this software and associated documentation files (the "Software"), to deal in
  9. * the Software without restriction, including without limitation the rights to
  10. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  11. * the Software, and to permit persons to whom the Software is furnished to do so,
  12. * subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in all
  15. * copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  19. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. /**
  25. * @file core_json.c
  26. * @brief The source file that implements the user-facing functions in core_json.h.
  27. */
  28. #include <limits.h>
  29. #include <stddef.h>
  30. #include <stdint.h>
  31. #include "core_json.h"
  32. /** @cond DO_NOT_DOCUMENT */
  33. /* A compromise to satisfy both MISRA and CBMC */
  34. typedef union
  35. {
  36. char c;
  37. uint8_t u;
  38. } char_;
  39. #if ( CHAR_MIN == 0 )
  40. #define isascii_( x ) ( ( x ) <= '\x7F' )
  41. #else
  42. #define isascii_( x ) ( ( x ) >= '\0' )
  43. #endif
  44. #define iscntrl_( x ) ( isascii_( x ) && ( ( x ) < ' ' ) )
  45. #define isdigit_( x ) ( ( ( x ) >= '0' ) && ( ( x ) <= '9' ) )
  46. /* NB. This is whitespace as defined by the JSON standard (ECMA-404). */
  47. #define isspace_( x ) \
  48. ( ( ( x ) == ' ' ) || ( ( x ) == '\t' ) || \
  49. ( ( x ) == '\n' ) || ( ( x ) == '\r' ) )
  50. #define isOpenBracket_( x ) ( ( ( x ) == '{' ) || ( ( x ) == '[' ) )
  51. #define isCloseBracket_( x ) ( ( ( x ) == '}' ) || ( ( x ) == ']' ) )
  52. #define isCurlyPair_( x, y ) ( ( ( x ) == '{' ) && ( ( y ) == '}' ) )
  53. #define isSquarePair_( x, y ) ( ( ( x ) == '[' ) && ( ( y ) == ']' ) )
  54. #define isMatchingBracket_( x, y ) ( isCurlyPair_( x, y ) || isSquarePair_( x, y ) )
  55. #define isSquareOpen_( x ) ( ( x ) == '[' )
  56. #define isSquareClose_( x ) ( ( x ) == ']' )
  57. #define isCurlyOpen_( x ) ( ( x ) == '{' )
  58. #define isCurlyClose_( x ) ( ( x ) == '}' )
  59. /**
  60. * @brief Advance buffer index beyond whitespace.
  61. *
  62. * @param[in] buf The buffer to parse.
  63. * @param[in,out] start The index at which to begin.
  64. * @param[in] max The size of the buffer.
  65. */
  66. static void skipSpace( const char * buf,
  67. size_t * start,
  68. size_t max )
  69. {
  70. size_t i = 0U;
  71. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  72. for( i = *start; i < max; i++ )
  73. {
  74. if( !isspace_( buf[ i ] ) )
  75. {
  76. break;
  77. }
  78. }
  79. *start = i;
  80. }
  81. /**
  82. * @brief Count the leading 1s in a byte.
  83. *
  84. * The high-order 1 bits of the first byte in a UTF-8 encoding
  85. * indicate the number of additional bytes to follow.
  86. *
  87. * @return the count
  88. */
  89. static size_t countHighBits( uint8_t c )
  90. {
  91. uint8_t n = c;
  92. size_t i = 0;
  93. while( ( n & 0x80U ) != 0U )
  94. {
  95. i++;
  96. n = ( n & 0x7FU ) << 1U;
  97. }
  98. return i;
  99. }
  100. /**
  101. * @brief Is the value a legal Unicode code point and encoded with
  102. * the fewest bytes?
  103. *
  104. * The last Unicode code point is 0x10FFFF.
  105. *
  106. * Unicode 3.1 disallows UTF-8 interpretation of non-shortest form sequences.
  107. * 1 byte encodes 0 through 7 bits
  108. * 2 bytes encode 8 through 5+6 = 11 bits
  109. * 3 bytes encode 12 through 4+6+6 = 16 bits
  110. * 4 bytes encode 17 through 3+6+6+6 = 21 bits
  111. *
  112. * Unicode 3.2 disallows UTF-8 code point values in the surrogate range,
  113. * [U+D800 to U+DFFF].
  114. *
  115. * @note Disallow ASCII, as this is called only for multibyte sequences.
  116. */
  117. static bool shortestUTF8( size_t length,
  118. uint32_t value )
  119. {
  120. bool ret = false;
  121. uint32_t min = 0U, max = 0U;
  122. coreJSON_ASSERT( ( length >= 2U ) && ( length <= 4U ) );
  123. switch( length )
  124. {
  125. case 2:
  126. min = ( uint32_t ) 1 << 7U;
  127. max = ( ( uint32_t ) 1 << 11U ) - 1U;
  128. break;
  129. case 3:
  130. min = ( uint32_t ) 1 << 11U;
  131. max = ( ( uint32_t ) 1 << 16U ) - 1U;
  132. break;
  133. default:
  134. min = ( uint32_t ) 1 << 16U;
  135. max = 0x10FFFFU;
  136. break;
  137. }
  138. if( ( value >= min ) && ( value <= max ) &&
  139. ( ( value < 0xD800U ) || ( value > 0xDFFFU ) ) )
  140. {
  141. ret = true;
  142. }
  143. return ret;
  144. }
  145. /**
  146. * @brief Advance buffer index beyond a UTF-8 code point.
  147. *
  148. * @param[in] buf The buffer to parse.
  149. * @param[in,out] start The index at which to begin.
  150. * @param[in] max The size of the buffer.
  151. *
  152. * @return true if a valid code point was present;
  153. * false otherwise.
  154. *
  155. * 00-7F Single-byte character
  156. * 80-BF Trailing byte
  157. * C0-DF Leading byte of two-byte character
  158. * E0-EF Leading byte of three-byte character
  159. * F0-F7 Leading byte of four-byte character
  160. * F8-FB Illegal (formerly leading byte of five-byte character)
  161. * FC-FD Illegal (formerly leading byte of six-byte character)
  162. * FE-FF Illegal
  163. *
  164. * The octet values C0, C1, and F5 to FF are illegal, since C0 and C1
  165. * would introduce a non-shortest sequence, and F5 or above would
  166. * introduce a value greater than the last code point, 0x10FFFF.
  167. */
  168. static bool skipUTF8MultiByte( const char * buf,
  169. size_t * start,
  170. size_t max )
  171. {
  172. bool ret = false;
  173. size_t i = 0U, bitCount = 0U, j = 0U;
  174. uint32_t value = 0U;
  175. char_ c;
  176. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  177. i = *start;
  178. coreJSON_ASSERT( i < max );
  179. coreJSON_ASSERT( !isascii_( buf[ i ] ) );
  180. c.c = buf[ i ];
  181. if( ( c.u > 0xC1U ) && ( c.u < 0xF5U ) )
  182. {
  183. bitCount = countHighBits( c.u );
  184. value = ( ( uint32_t ) c.u ) & ( ( ( uint32_t ) 1 << ( 7U - bitCount ) ) - 1U );
  185. /* The bit count is 1 greater than the number of bytes,
  186. * e.g., when j is 2, we skip one more byte. */
  187. for( j = bitCount - 1U; j > 0U; j-- )
  188. {
  189. i++;
  190. if( i >= max )
  191. {
  192. break;
  193. }
  194. c.c = buf[ i ];
  195. /* Additional bytes must match 10xxxxxx. */
  196. if( ( c.u & 0xC0U ) != 0x80U )
  197. {
  198. break;
  199. }
  200. value = ( value << 6U ) | ( c.u & 0x3FU );
  201. }
  202. if( ( j == 0U ) && ( shortestUTF8( bitCount, value ) == true ) )
  203. {
  204. *start = i + 1U;
  205. ret = true;
  206. }
  207. }
  208. return ret;
  209. }
  210. /**
  211. * @brief Advance buffer index beyond an ASCII or UTF-8 code point.
  212. *
  213. * @param[in] buf The buffer to parse.
  214. * @param[in,out] start The index at which to begin.
  215. * @param[in] max The size of the buffer.
  216. *
  217. * @return true if a valid code point was present;
  218. * false otherwise.
  219. */
  220. static bool skipUTF8( const char * buf,
  221. size_t * start,
  222. size_t max )
  223. {
  224. bool ret = false;
  225. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  226. if( *start < max )
  227. {
  228. if( isascii_( buf[ *start ] ) )
  229. {
  230. *start += 1U;
  231. ret = true;
  232. }
  233. else
  234. {
  235. ret = skipUTF8MultiByte( buf, start, max );
  236. }
  237. }
  238. return ret;
  239. }
  240. /**
  241. * @brief Convert a hexadecimal character to an integer.
  242. *
  243. * @param[in] c The character to convert.
  244. *
  245. * @return the integer value upon success or NOT_A_HEX_CHAR on failure.
  246. */
  247. #define NOT_A_HEX_CHAR ( 0x10U )
  248. static uint8_t hexToInt( char c )
  249. {
  250. char_ n;
  251. n.c = c;
  252. if( ( c >= 'a' ) && ( c <= 'f' ) )
  253. {
  254. n.c -= 'a';
  255. n.u += 10U;
  256. }
  257. else if( ( c >= 'A' ) && ( c <= 'F' ) )
  258. {
  259. n.c -= 'A';
  260. n.u += 10U;
  261. }
  262. else if( isdigit_( c ) )
  263. {
  264. n.c -= '0';
  265. }
  266. else
  267. {
  268. n.u = NOT_A_HEX_CHAR;
  269. }
  270. return n.u;
  271. }
  272. /**
  273. * @brief Advance buffer index beyond a single \u Unicode
  274. * escape sequence and output the value.
  275. *
  276. * @param[in] buf The buffer to parse.
  277. * @param[in,out] start The index at which to begin.
  278. * @param[in] max The size of the buffer.
  279. * @param[out] outValue The value of the hex digits.
  280. *
  281. * @return true if a valid escape sequence was present;
  282. * false otherwise.
  283. */
  284. static bool skipOneHexEscape( const char * buf,
  285. size_t * start,
  286. size_t max,
  287. uint16_t * outValue )
  288. {
  289. bool ret = false;
  290. size_t i = 0U, end = 0U;
  291. uint16_t value = 0U;
  292. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) && ( outValue != NULL ) );
  293. i = *start;
  294. #define HEX_ESCAPE_LENGTH ( 6U ) /* e.g., \u1234 */
  295. /* MISRA Ref 14.3.1 [Configuration dependent invariant] */
  296. /* More details at: https://github.com/FreeRTOS/coreJSON/blob/main/MISRA.md#rule-143 */
  297. /* coverity[misra_c_2012_rule_14_3_violation] */
  298. end = i + HEX_ESCAPE_LENGTH;
  299. if( ( end > i ) && ( end < max ) && ( buf[ i ] == '\\' ) && ( buf[ i + 1U ] == 'u' ) )
  300. {
  301. for( i += 2U; i < end; i++ )
  302. {
  303. uint8_t n = hexToInt( buf[ i ] );
  304. if( n == NOT_A_HEX_CHAR )
  305. {
  306. break;
  307. }
  308. value = ( value << 4U ) | n;
  309. }
  310. }
  311. if( i == end )
  312. {
  313. ret = true;
  314. *outValue = value;
  315. *start = i;
  316. }
  317. return ret;
  318. }
  319. /**
  320. * @brief Advance buffer index beyond one or a pair of \u Unicode escape sequences.
  321. *
  322. * @param[in] buf The buffer to parse.
  323. * @param[in,out] start The index at which to begin.
  324. * @param[in] max The size of the buffer.
  325. *
  326. * Surrogate pairs are two escape sequences that together denote
  327. * a code point outside the Basic Multilingual Plane. They must
  328. * occur as a pair with the first "high" value in [U+D800, U+DBFF],
  329. * and the second "low" value in [U+DC00, U+DFFF].
  330. *
  331. * @return true if a valid escape sequence was present;
  332. * false otherwise.
  333. */
  334. #define isHighSurrogate( x ) ( ( ( x ) >= 0xD800U ) && ( ( x ) <= 0xDBFFU ) )
  335. #define isLowSurrogate( x ) ( ( ( x ) >= 0xDC00U ) && ( ( x ) <= 0xDFFFU ) )
  336. static bool skipHexEscape( const char * buf,
  337. size_t * start,
  338. size_t max )
  339. {
  340. bool ret = false;
  341. size_t i = 0U;
  342. uint16_t value = 0U;
  343. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  344. i = *start;
  345. if( skipOneHexEscape( buf, &i, max, &value ) == true )
  346. {
  347. if( isHighSurrogate( value ) )
  348. {
  349. if( ( skipOneHexEscape( buf, &i, max, &value ) == true ) &&
  350. ( isLowSurrogate( value ) ) )
  351. {
  352. ret = true;
  353. }
  354. }
  355. else if( isLowSurrogate( value ) )
  356. {
  357. /* premature low surrogate */
  358. }
  359. else
  360. {
  361. ret = true;
  362. }
  363. }
  364. if( ret == true )
  365. {
  366. *start = i;
  367. }
  368. return ret;
  369. }
  370. /**
  371. * @brief Advance buffer index beyond an escape sequence.
  372. *
  373. * @param[in] buf The buffer to parse.
  374. * @param[in,out] start The index at which to begin.
  375. * @param[in] max The size of the buffer.
  376. *
  377. * @return true if a valid escape sequence was present;
  378. * false otherwise.
  379. */
  380. static bool skipEscape( const char * buf,
  381. size_t * start,
  382. size_t max )
  383. {
  384. bool ret = false;
  385. size_t i = 0U;
  386. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  387. i = *start;
  388. if( ( i < ( max - 1U ) ) && ( buf[ i ] == '\\' ) )
  389. {
  390. char c = buf[ i + 1U ];
  391. switch( c )
  392. {
  393. case 'u':
  394. ret = skipHexEscape( buf, &i, max );
  395. break;
  396. case '"':
  397. case '\\':
  398. case '/':
  399. case 'b':
  400. case 'f':
  401. case 'n':
  402. case 'r':
  403. case 't':
  404. i += 2U;
  405. ret = true;
  406. break;
  407. default:
  408. break;
  409. }
  410. }
  411. if( ret == true )
  412. {
  413. *start = i;
  414. }
  415. return ret;
  416. }
  417. /**
  418. * @brief Advance buffer index beyond a double-quoted string.
  419. *
  420. * @param[in] buf The buffer to parse.
  421. * @param[in,out] start The index at which to begin.
  422. * @param[in] max The size of the buffer.
  423. *
  424. * @return true if a valid string was present;
  425. * false otherwise.
  426. */
  427. static bool skipString( const char * buf,
  428. size_t * start,
  429. size_t max )
  430. {
  431. bool ret = false;
  432. size_t i = 0;
  433. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  434. i = *start;
  435. if( ( i < max ) && ( buf[ i ] == '"' ) )
  436. {
  437. i++;
  438. while( i < max )
  439. {
  440. if( buf[ i ] == '"' )
  441. {
  442. ret = true;
  443. i++;
  444. break;
  445. }
  446. if( buf[ i ] == '\\' )
  447. {
  448. if( skipEscape( buf, &i, max ) != true )
  449. {
  450. break;
  451. }
  452. }
  453. /* An unescaped control character is not allowed. */
  454. else if( iscntrl_( buf[ i ] ) )
  455. {
  456. break;
  457. }
  458. else if( skipUTF8( buf, &i, max ) != true )
  459. {
  460. break;
  461. }
  462. else
  463. {
  464. /* MISRA 15.7 */
  465. }
  466. }
  467. }
  468. if( ret == true )
  469. {
  470. *start = i;
  471. }
  472. return ret;
  473. }
  474. /**
  475. * @brief Compare the leading n bytes of two character sequences.
  476. *
  477. * @param[in] a first character sequence
  478. * @param[in] b second character sequence
  479. * @param[in] n number of bytes
  480. *
  481. * @return true if the sequences are the same;
  482. * false otherwise
  483. */
  484. static bool strnEq( const char * a,
  485. const char * b,
  486. size_t n )
  487. {
  488. size_t i = 0U;
  489. coreJSON_ASSERT( ( a != NULL ) && ( b != NULL ) );
  490. for( i = 0; i < n; i++ )
  491. {
  492. if( a[ i ] != b[ i ] )
  493. {
  494. break;
  495. }
  496. }
  497. return ( i == n ) ? true : false;
  498. }
  499. /**
  500. * @brief Advance buffer index beyond a literal.
  501. *
  502. * @param[in] buf The buffer to parse.
  503. * @param[in,out] start The index at which to begin.
  504. * @param[in] max The size of the buffer.
  505. * @param[in] literal The type of literal.
  506. * @param[in] length The length of the literal.
  507. *
  508. * @return true if the literal was present;
  509. * false otherwise.
  510. */
  511. static bool skipLiteral( const char * buf,
  512. size_t * start,
  513. size_t max,
  514. const char * literal,
  515. size_t length )
  516. {
  517. bool ret = false;
  518. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  519. coreJSON_ASSERT( literal != NULL );
  520. if( ( *start < max ) && ( length <= ( max - *start ) ) )
  521. {
  522. ret = strnEq( &buf[ *start ], literal, length );
  523. }
  524. if( ret == true )
  525. {
  526. *start += length;
  527. }
  528. return ret;
  529. }
  530. /**
  531. * @brief Advance buffer index beyond a JSON literal.
  532. *
  533. * @param[in] buf The buffer to parse.
  534. * @param[in,out] start The index at which to begin.
  535. * @param[in] max The size of the buffer.
  536. *
  537. * @return true if a valid literal was present;
  538. * false otherwise.
  539. */
  540. static bool skipAnyLiteral( const char * buf,
  541. size_t * start,
  542. size_t max )
  543. {
  544. bool ret = false;
  545. #define skipLit_( x ) \
  546. ( skipLiteral( buf, start, max, ( x ), ( sizeof( x ) - 1UL ) ) == true )
  547. if( skipLit_( "true" ) )
  548. {
  549. ret = true;
  550. }
  551. else if( skipLit_( "false" ) )
  552. {
  553. ret = true;
  554. }
  555. else if( skipLit_( "null" ) )
  556. {
  557. ret = true;
  558. }
  559. else
  560. {
  561. ret = false;
  562. }
  563. return ret;
  564. }
  565. /**
  566. * @brief Advance buffer index beyond one or more digits.
  567. * Optionally, output the integer value of the digits.
  568. *
  569. * @param[in] buf The buffer to parse.
  570. * @param[in,out] start The index at which to begin.
  571. * @param[in] max The size of the buffer.
  572. * @param[out] outValue The integer value of the digits.
  573. *
  574. * @note outValue may be NULL. If not NULL, and the output
  575. * exceeds ~2 billion, then -1 is output.
  576. *
  577. * @return true if a digit was present;
  578. * false otherwise.
  579. */
  580. #define MAX_FACTOR ( MAX_INDEX_VALUE / 10 )
  581. static bool skipDigits( const char * buf,
  582. size_t * start,
  583. size_t max,
  584. int32_t * outValue )
  585. {
  586. bool ret = false;
  587. size_t i = 0U, saveStart = 0U;
  588. int32_t value = 0;
  589. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  590. saveStart = *start;
  591. for( i = *start; i < max; i++ )
  592. {
  593. if( !isdigit_( buf[ i ] ) )
  594. {
  595. break;
  596. }
  597. if( ( outValue != NULL ) && ( value > -1 ) )
  598. {
  599. int8_t n = ( int8_t ) hexToInt( buf[ i ] );
  600. if( value <= MAX_FACTOR )
  601. {
  602. value = ( value * 10 ) + n;
  603. }
  604. else
  605. {
  606. value = -1;
  607. }
  608. }
  609. }
  610. if( i > saveStart )
  611. {
  612. ret = true;
  613. *start = i;
  614. if( outValue != NULL )
  615. {
  616. *outValue = value;
  617. }
  618. }
  619. return ret;
  620. }
  621. /**
  622. * @brief Advance buffer index beyond the decimal portion of a number.
  623. *
  624. * @param[in] buf The buffer to parse.
  625. * @param[in,out] start The index at which to begin.
  626. * @param[in] max The size of the buffer.
  627. */
  628. static void skipDecimals( const char * buf,
  629. size_t * start,
  630. size_t max )
  631. {
  632. size_t i = 0U;
  633. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  634. i = *start;
  635. if( ( i < max ) && ( buf[ i ] == '.' ) )
  636. {
  637. i++;
  638. if( skipDigits( buf, &i, max, NULL ) == true )
  639. {
  640. *start = i;
  641. }
  642. }
  643. }
  644. /**
  645. * @brief Advance buffer index beyond the exponent portion of a number.
  646. *
  647. * @param[in] buf The buffer to parse.
  648. * @param[in,out] start The index at which to begin.
  649. * @param[in] max The size of the buffer.
  650. */
  651. static void skipExponent( const char * buf,
  652. size_t * start,
  653. size_t max )
  654. {
  655. size_t i = 0U;
  656. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  657. i = *start;
  658. if( ( i < max ) && ( ( buf[ i ] == 'e' ) || ( buf[ i ] == 'E' ) ) )
  659. {
  660. i++;
  661. if( ( i < max ) && ( ( buf[ i ] == '-' ) || ( buf[ i ] == '+' ) ) )
  662. {
  663. i++;
  664. }
  665. if( skipDigits( buf, &i, max, NULL ) == true )
  666. {
  667. *start = i;
  668. }
  669. }
  670. }
  671. /**
  672. * @brief Advance buffer index beyond a number.
  673. *
  674. * @param[in] buf The buffer to parse.
  675. * @param[in,out] start The index at which to begin.
  676. * @param[in] max The size of the buffer.
  677. *
  678. * @return true if a valid number was present;
  679. * false otherwise.
  680. */
  681. static bool skipNumber( const char * buf,
  682. size_t * start,
  683. size_t max )
  684. {
  685. bool ret = false;
  686. size_t i = 0U;
  687. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  688. i = *start;
  689. if( ( i < max ) && ( buf[ i ] == '-' ) )
  690. {
  691. i++;
  692. }
  693. if( i < max )
  694. {
  695. /* JSON disallows superfluous leading zeroes, so an
  696. * initial zero must either be alone, or followed by
  697. * a decimal or exponent.
  698. *
  699. * Should there be a digit after the zero, that digit
  700. * will not be skipped by this function, and later parsing
  701. * will judge this an illegal document. */
  702. if( buf[ i ] == '0' )
  703. {
  704. ret = true;
  705. i++;
  706. }
  707. else
  708. {
  709. ret = skipDigits( buf, &i, max, NULL );
  710. }
  711. }
  712. if( ret == true )
  713. {
  714. skipDecimals( buf, &i, max );
  715. skipExponent( buf, &i, max );
  716. *start = i;
  717. }
  718. return ret;
  719. }
  720. /**
  721. * @brief Advance buffer index beyond a scalar value.
  722. *
  723. * @param[in] buf The buffer to parse.
  724. * @param[in,out] start The index at which to begin.
  725. * @param[in] max The size of the buffer.
  726. *
  727. * @return true if a scalar value was present;
  728. * false otherwise.
  729. */
  730. static bool skipAnyScalar( const char * buf,
  731. size_t * start,
  732. size_t max )
  733. {
  734. bool ret = false;
  735. if( skipString( buf, start, max ) == true )
  736. {
  737. ret = true;
  738. }
  739. else if( skipAnyLiteral( buf, start, max ) == true )
  740. {
  741. ret = true;
  742. }
  743. else if( skipNumber( buf, start, max ) == true )
  744. {
  745. ret = true;
  746. }
  747. else
  748. {
  749. ret = false;
  750. }
  751. return ret;
  752. }
  753. /**
  754. * @brief Advance buffer index beyond a comma separator
  755. * and surrounding whitespace.
  756. *
  757. * JSON uses a comma to separate values in an array and key-value
  758. * pairs in an object. JSON does not permit a trailing comma.
  759. *
  760. * @param[in] buf The buffer to parse.
  761. * @param[in,out] start The index at which to begin.
  762. * @param[in] max The size of the buffer.
  763. *
  764. * @return true if a non-terminal comma was present;
  765. * false otherwise.
  766. */
  767. static bool skipSpaceAndComma( const char * buf,
  768. size_t * start,
  769. size_t max )
  770. {
  771. bool ret = false;
  772. size_t i = 0U;
  773. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  774. skipSpace( buf, start, max );
  775. i = *start;
  776. if( ( i < max ) && ( buf[ i ] == ',' ) )
  777. {
  778. i++;
  779. skipSpace( buf, &i, max );
  780. if( ( i < max ) && !isCloseBracket_( buf[ i ] ) )
  781. {
  782. ret = true;
  783. *start = i;
  784. }
  785. }
  786. return ret;
  787. }
  788. /**
  789. * @brief Advance buffer index beyond the scalar values of an array.
  790. *
  791. * @param[in] buf The buffer to parse.
  792. * @param[in,out] start The index at which to begin.
  793. * @param[in] max The size of the buffer.
  794. *
  795. * @note Stops advance if a value is an object or array.
  796. */
  797. static bool skipArrayScalars( const char * buf,
  798. size_t * start,
  799. size_t max )
  800. {
  801. size_t i = 0U;
  802. bool ret = true;
  803. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  804. i = *start;
  805. while( i < max )
  806. {
  807. if( skipAnyScalar( buf, &i, max ) != true )
  808. {
  809. break;
  810. }
  811. if( skipSpaceAndComma( buf, &i, max ) != true )
  812. {
  813. /* After parsing a scalar, we must either have a comma (followed by more content)
  814. * or be at a closing bracket. If neither, the array is malformed. */
  815. if( ( i >= max ) || !isSquareClose_( buf[ i ] ) )
  816. {
  817. ret = false;
  818. }
  819. break;
  820. }
  821. }
  822. *start = i;
  823. return ret;
  824. }
  825. /**
  826. * @brief Advance buffer index beyond the scalar key-value pairs
  827. * of an object.
  828. *
  829. * In JSON, objects consist of comma-separated key-value pairs.
  830. * A key is always a string (a scalar) while a value may be a
  831. * scalar, an object, or an array. A colon must appear between
  832. * each key and value.
  833. *
  834. * @param[in] buf The buffer to parse.
  835. * @param[in,out] start The index at which to begin.
  836. * @param[in] max The size of the buffer.
  837. *
  838. * @return true if a valid scalar key-value pairs were present;
  839. * false otherwise.
  840. *
  841. * @note Stops advance if a value is an object or array.
  842. */
  843. static bool skipObjectScalars( const char * buf,
  844. size_t * start,
  845. size_t max )
  846. {
  847. size_t i = 0U;
  848. bool comma = false;
  849. bool ret = true;
  850. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  851. i = *start;
  852. while( i < max )
  853. {
  854. if( skipString( buf, &i, max ) != true )
  855. {
  856. ret = false;
  857. break;
  858. }
  859. skipSpace( buf, &i, max );
  860. if( ( i < max ) && ( buf[ i ] != ':' ) )
  861. {
  862. ret = false;
  863. break;
  864. }
  865. i++;
  866. skipSpace( buf, &i, max );
  867. if( ( i < max ) && isOpenBracket_( buf[ i ] ) )
  868. {
  869. *start = i;
  870. break;
  871. }
  872. if( skipAnyScalar( buf, &i, max ) != true )
  873. {
  874. ret = false;
  875. break;
  876. }
  877. comma = skipSpaceAndComma( buf, &i, max );
  878. *start = i;
  879. if( comma != true )
  880. {
  881. break;
  882. }
  883. }
  884. return ret;
  885. }
  886. /**
  887. * @brief Advance buffer index beyond one or more scalars.
  888. *
  889. * @param[in] buf The buffer to parse.
  890. * @param[in,out] start The index at which to begin.
  891. * @param[in] max The size of the buffer.
  892. * @param[in] mode The first character of an array '[' or object '{'.
  893. *
  894. * @return true if a valid scalers were present;
  895. * false otherwise.
  896. */
  897. static bool skipScalars( const char * buf,
  898. size_t * start,
  899. size_t max,
  900. char mode )
  901. {
  902. size_t i = 0U;
  903. bool modeIsOpenBracket = ( bool ) isOpenBracket_( mode );
  904. bool ret = true;
  905. /* assert function may be implemented in macro using a # or ## operator.
  906. * Using a local variable here to prevent macro replacement is subjected
  907. * to macro itself. */
  908. coreJSON_ASSERT( modeIsOpenBracket != false );
  909. /* Adding this line to avoid unused variable warning in release mode. */
  910. ( void ) modeIsOpenBracket;
  911. skipSpace( buf, start, max );
  912. i = *start;
  913. if( i < max )
  914. {
  915. if( mode == '[' )
  916. {
  917. if( !isSquareClose_( buf[ i ] ) )
  918. {
  919. ret = skipArrayScalars( buf, start, max );
  920. }
  921. }
  922. else
  923. {
  924. if( !isCurlyClose_( buf[ i ] ) )
  925. {
  926. ret = skipObjectScalars( buf, start, max );
  927. }
  928. }
  929. }
  930. return ret;
  931. }
  932. /**
  933. * @brief Advance buffer index beyond a collection and handle nesting.
  934. *
  935. * A stack is used to continue parsing the prior collection type
  936. * when a nested collection is finished.
  937. *
  938. * @param[in] buf The buffer to parse.
  939. * @param[in,out] start The index at which to begin.
  940. * @param[in] max The size of the buffer.
  941. *
  942. * @return #JSONSuccess if the buffer contents are a valid JSON collection;
  943. * #JSONIllegalDocument if the buffer contents are NOT valid JSON;
  944. * #JSONMaxDepthExceeded if object and array nesting exceeds a threshold;
  945. * #JSONPartial if the buffer contents are potentially valid but incomplete.
  946. */
  947. #ifndef JSON_MAX_DEPTH
  948. #define JSON_MAX_DEPTH 32
  949. #endif
  950. static JSONStatus_t skipCollection( const char * buf,
  951. size_t * start,
  952. size_t max )
  953. {
  954. JSONStatus_t ret = JSONPartial;
  955. char c, stack[ JSON_MAX_DEPTH ];
  956. int16_t depth = -1;
  957. size_t i = 0U;
  958. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  959. i = *start;
  960. while( i < max )
  961. {
  962. c = buf[ i ];
  963. i++;
  964. switch( c )
  965. {
  966. case '{':
  967. case '[':
  968. depth++;
  969. if( depth >= JSON_MAX_DEPTH )
  970. {
  971. ret = JSONMaxDepthExceeded;
  972. break;
  973. }
  974. stack[ depth ] = c;
  975. if( skipScalars( buf, &i, max, stack[ depth ] ) != true )
  976. {
  977. ret = JSONIllegalDocument;
  978. }
  979. break;
  980. case '}':
  981. case ']':
  982. if( ( depth > 0 ) && ( depth < JSON_MAX_DEPTH ) &&
  983. isMatchingBracket_( stack[ depth ], c ) )
  984. {
  985. depth--;
  986. if( skipSpaceAndComma( buf, &i, max ) == true )
  987. {
  988. if( skipScalars( buf, &i, max, stack[ depth ] ) != true )
  989. {
  990. ret = JSONIllegalDocument;
  991. }
  992. }
  993. else
  994. {
  995. /* After closing a nested collection, if there is no comma found when calling
  996. * skipSpaceAndComma, then we must be at the end of the parent collection. */
  997. if( ( i < max ) && !isMatchingBracket_( stack[ depth ], buf[ i ] ) )
  998. {
  999. ret = JSONIllegalDocument;
  1000. }
  1001. }
  1002. break;
  1003. }
  1004. ret = ( ( depth == 0 ) && isMatchingBracket_( stack[ depth ], c ) ) ?
  1005. JSONSuccess : JSONIllegalDocument;
  1006. break;
  1007. default:
  1008. ret = JSONIllegalDocument;
  1009. break;
  1010. }
  1011. if( ret != JSONPartial )
  1012. {
  1013. break;
  1014. }
  1015. }
  1016. if( ret == JSONSuccess )
  1017. {
  1018. *start = i;
  1019. }
  1020. return ret;
  1021. }
  1022. /** @endcond */
  1023. /**
  1024. * See core_json.h for docs.
  1025. *
  1026. * Verify that the entire buffer contains exactly one scalar
  1027. * or collection within optional whitespace.
  1028. */
  1029. JSONStatus_t JSON_Validate( const char * buf,
  1030. size_t max )
  1031. {
  1032. JSONStatus_t ret;
  1033. size_t i = 0U;
  1034. if( buf == NULL )
  1035. {
  1036. ret = JSONNullParameter;
  1037. }
  1038. else if( max == 0U )
  1039. {
  1040. ret = JSONBadParameter;
  1041. }
  1042. else
  1043. {
  1044. skipSpace( buf, &i, max );
  1045. /** @cond DO_NOT_DOCUMENT */
  1046. #ifndef JSON_VALIDATE_COLLECTIONS_ONLY
  1047. if( skipAnyScalar( buf, &i, max ) == true )
  1048. {
  1049. ret = JSONSuccess;
  1050. }
  1051. else
  1052. #endif
  1053. /** @endcond */
  1054. {
  1055. ret = skipCollection( buf, &i, max );
  1056. }
  1057. }
  1058. if( ( ret == JSONSuccess ) && ( i < max ) )
  1059. {
  1060. skipSpace( buf, &i, max );
  1061. if( i != max )
  1062. {
  1063. ret = JSONIllegalDocument;
  1064. }
  1065. }
  1066. return ret;
  1067. }
  1068. /** @cond DO_NOT_DOCUMENT */
  1069. /**
  1070. * @brief Output index and length for the next value.
  1071. *
  1072. * Also advances the buffer index beyond the value.
  1073. * The value may be a scalar or a collection.
  1074. * The start index should point to the beginning of the value.
  1075. *
  1076. * @param[in] buf The buffer to parse.
  1077. * @param[in,out] start The index at which to begin.
  1078. * @param[in] max The size of the buffer.
  1079. * @param[out] value A pointer to receive the index of the value.
  1080. * @param[out] valueLength A pointer to receive the length of the value.
  1081. *
  1082. * @return true if a value was present;
  1083. * false otherwise.
  1084. */
  1085. static bool nextValue( const char * buf,
  1086. size_t * start,
  1087. size_t max,
  1088. size_t * value,
  1089. size_t * valueLength )
  1090. {
  1091. bool ret = true;
  1092. size_t i = 0U, valueStart = 0U;
  1093. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  1094. coreJSON_ASSERT( ( value != NULL ) && ( valueLength != NULL ) );
  1095. i = *start;
  1096. valueStart = i;
  1097. if( skipAnyScalar( buf, &i, max ) == true )
  1098. {
  1099. *value = valueStart;
  1100. *valueLength = i - valueStart;
  1101. }
  1102. else if( skipCollection( buf, &i, max ) == JSONSuccess )
  1103. {
  1104. *value = valueStart;
  1105. *valueLength = i - valueStart;
  1106. }
  1107. else
  1108. {
  1109. ret = false;
  1110. }
  1111. if( ret == true )
  1112. {
  1113. *start = i;
  1114. }
  1115. return ret;
  1116. }
  1117. /**
  1118. * @brief Output indexes for the next key-value pair of an object.
  1119. *
  1120. * Also advances the buffer index beyond the key-value pair.
  1121. * The value may be a scalar or a collection.
  1122. *
  1123. * @param[in] buf The buffer to parse.
  1124. * @param[in,out] start The index at which to begin.
  1125. * @param[in] max The size of the buffer.
  1126. * @param[out] key A pointer to receive the index of the key.
  1127. * @param[out] keyLength A pointer to receive the length of the key.
  1128. * @param[out] value A pointer to receive the index of the value.
  1129. * @param[out] valueLength A pointer to receive the length of the value.
  1130. *
  1131. * @return true if a key-value pair was present;
  1132. * false otherwise.
  1133. */
  1134. static bool nextKeyValuePair( const char * buf,
  1135. size_t * start,
  1136. size_t max,
  1137. size_t * key,
  1138. size_t * keyLength,
  1139. size_t * value,
  1140. size_t * valueLength )
  1141. {
  1142. bool ret = true;
  1143. size_t i = 0U, keyStart = 0U;
  1144. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  1145. coreJSON_ASSERT( ( key != NULL ) && ( keyLength != NULL ) );
  1146. coreJSON_ASSERT( ( value != NULL ) && ( valueLength != NULL ) );
  1147. i = *start;
  1148. keyStart = i;
  1149. if( skipString( buf, &i, max ) == true )
  1150. {
  1151. *key = keyStart + 1U;
  1152. *keyLength = i - keyStart - 2U;
  1153. }
  1154. else
  1155. {
  1156. ret = false;
  1157. }
  1158. if( ret == true )
  1159. {
  1160. skipSpace( buf, &i, max );
  1161. if( ( i < max ) && ( buf[ i ] == ':' ) )
  1162. {
  1163. i++;
  1164. skipSpace( buf, &i, max );
  1165. }
  1166. else
  1167. {
  1168. ret = false;
  1169. }
  1170. }
  1171. if( ret == true )
  1172. {
  1173. ret = nextValue( buf, &i, max, value, valueLength );
  1174. }
  1175. if( ret == true )
  1176. {
  1177. *start = i;
  1178. }
  1179. return ret;
  1180. }
  1181. /**
  1182. * @brief Find a key in a JSON object and output a pointer to its value.
  1183. *
  1184. * @param[in] buf The buffer to search.
  1185. * @param[in] max size of the buffer.
  1186. * @param[in] query The object keys and array indexes to search for.
  1187. * @param[in] queryLength Length of the key.
  1188. * @param[out] outValue A pointer to receive the index of the value found.
  1189. * @param[out] outValueLength A pointer to receive the length of the value found.
  1190. *
  1191. * Iterate over the key-value pairs of an object, looking for a matching key.
  1192. *
  1193. * @return true if the query is matched and the value output;
  1194. * false otherwise.
  1195. *
  1196. * @note Parsing stops upon finding a match.
  1197. */
  1198. static bool objectSearch( const char * buf,
  1199. size_t max,
  1200. const char * query,
  1201. size_t queryLength,
  1202. size_t * outValue,
  1203. size_t * outValueLength )
  1204. {
  1205. bool ret = false;
  1206. size_t i = 0U, key = 0U, keyLength = 0U, value = 0U, valueLength = 0U;
  1207. coreJSON_ASSERT( ( buf != NULL ) && ( query != NULL ) );
  1208. coreJSON_ASSERT( ( outValue != NULL ) && ( outValueLength != NULL ) );
  1209. skipSpace( buf, &i, max );
  1210. if( ( i < max ) && ( buf[ i ] == '{' ) )
  1211. {
  1212. i++;
  1213. skipSpace( buf, &i, max );
  1214. while( i < max )
  1215. {
  1216. if( nextKeyValuePair( buf, &i, max, &key, &keyLength,
  1217. &value, &valueLength ) != true )
  1218. {
  1219. break;
  1220. }
  1221. if( ( queryLength == keyLength ) &&
  1222. ( strnEq( query, &buf[ key ], keyLength ) == true ) )
  1223. {
  1224. ret = true;
  1225. break;
  1226. }
  1227. if( skipSpaceAndComma( buf, &i, max ) != true )
  1228. {
  1229. break;
  1230. }
  1231. }
  1232. }
  1233. if( ret == true )
  1234. {
  1235. *outValue = value;
  1236. *outValueLength = valueLength;
  1237. }
  1238. return ret;
  1239. }
  1240. /**
  1241. * @brief Find an index in a JSON array and output a pointer to its value.
  1242. *
  1243. * @param[in] buf The buffer to search.
  1244. * @param[in] max size of the buffer.
  1245. * @param[in] queryIndex The index to search for.
  1246. * @param[out] outValue A pointer to receive the index of the value found.
  1247. * @param[out] outValueLength A pointer to receive the length of the value found.
  1248. *
  1249. * Iterate over the values of an array, looking for a matching index.
  1250. *
  1251. * @return true if the queryIndex is found and the value output;
  1252. * false otherwise.
  1253. *
  1254. * @note Parsing stops upon finding a match.
  1255. */
  1256. static bool arraySearch( const char * buf,
  1257. size_t max,
  1258. uint32_t queryIndex,
  1259. size_t * outValue,
  1260. size_t * outValueLength )
  1261. {
  1262. bool ret = false;
  1263. size_t i = 0U, value = 0U, valueLength = 0U;
  1264. uint32_t currentIndex = 0U;
  1265. coreJSON_ASSERT( buf != NULL );
  1266. coreJSON_ASSERT( ( outValue != NULL ) && ( outValueLength != NULL ) );
  1267. skipSpace( buf, &i, max );
  1268. if( ( i < max ) && ( buf[ i ] == '[' ) )
  1269. {
  1270. i++;
  1271. skipSpace( buf, &i, max );
  1272. while( i < max )
  1273. {
  1274. if( nextValue( buf, &i, max, &value, &valueLength ) != true )
  1275. {
  1276. break;
  1277. }
  1278. if( currentIndex == queryIndex )
  1279. {
  1280. ret = true;
  1281. break;
  1282. }
  1283. if( ( skipSpaceAndComma( buf, &i, max ) != true ) ||
  1284. ( currentIndex == UINT32_MAX ) )
  1285. {
  1286. break;
  1287. }
  1288. currentIndex++;
  1289. }
  1290. }
  1291. if( ret == true )
  1292. {
  1293. *outValue = value;
  1294. *outValueLength = valueLength;
  1295. }
  1296. return ret;
  1297. }
  1298. /**
  1299. * @brief Advance buffer index beyond a query part.
  1300. *
  1301. * The part is the portion of the query which is not
  1302. * a separator or array index.
  1303. *
  1304. * @param[in] buf The buffer to parse.
  1305. * @param[in,out] start The index at which to begin.
  1306. * @param[in] max The size of the buffer.
  1307. * @param[out] outLength The length of the query part.
  1308. *
  1309. * @return true if a valid string was present;
  1310. * false otherwise.
  1311. */
  1312. #ifndef JSON_QUERY_KEY_SEPARATOR
  1313. #define JSON_QUERY_KEY_SEPARATOR '.'
  1314. #endif
  1315. #define isSeparator_( x ) ( ( x ) == JSON_QUERY_KEY_SEPARATOR )
  1316. static bool skipQueryPart( const char * buf,
  1317. size_t * start,
  1318. size_t max,
  1319. size_t * outLength )
  1320. {
  1321. bool ret = false;
  1322. size_t i = 0U;
  1323. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( outLength != NULL ) );
  1324. coreJSON_ASSERT( max > 0U );
  1325. i = *start;
  1326. while( ( i < max ) &&
  1327. !isSeparator_( buf[ i ] ) &&
  1328. !isSquareOpen_( buf[ i ] ) )
  1329. {
  1330. i++;
  1331. }
  1332. if( i > *start )
  1333. {
  1334. ret = true;
  1335. *outLength = i - *start;
  1336. *start = i;
  1337. }
  1338. return ret;
  1339. }
  1340. /**
  1341. * @brief Handle a nested search by iterating over the parts of the query.
  1342. *
  1343. * @param[in] buf The buffer to search.
  1344. * @param[in] max size of the buffer.
  1345. * @param[in] query The object keys and array indexes to search for.
  1346. * @param[in] queryLength Length of the key.
  1347. * @param[out] outValue A pointer to receive the index of the value found.
  1348. * @param[out] outValueLength A pointer to receive the length of the value found.
  1349. *
  1350. * @return #JSONSuccess if the query is matched and the value output;
  1351. * #JSONBadParameter if the query is empty, or any part is empty,
  1352. * or an index is too large to convert;
  1353. * #JSONNotFound if the query is NOT found.
  1354. *
  1355. * @note Parsing stops upon finding a match.
  1356. */
  1357. static JSONStatus_t multiSearch( const char * buf,
  1358. size_t max,
  1359. const char * query,
  1360. size_t queryLength,
  1361. size_t * outValue,
  1362. size_t * outValueLength )
  1363. {
  1364. JSONStatus_t ret = JSONSuccess;
  1365. size_t i = 0U, start = 0U, queryStart = 0U, value = 0U, length = max;
  1366. coreJSON_ASSERT( ( buf != NULL ) && ( query != NULL ) );
  1367. coreJSON_ASSERT( ( outValue != NULL ) && ( outValueLength != NULL ) );
  1368. coreJSON_ASSERT( ( max > 0U ) && ( queryLength > 0U ) );
  1369. while( i < queryLength )
  1370. {
  1371. bool found = false;
  1372. if( isSquareOpen_( query[ i ] ) )
  1373. {
  1374. int32_t queryIndex = -1;
  1375. i++;
  1376. ( void ) skipDigits( query, &i, queryLength, &queryIndex );
  1377. if( ( queryIndex < 0 ) ||
  1378. ( i >= queryLength ) || !isSquareClose_( query[ i ] ) )
  1379. {
  1380. ret = JSONBadParameter;
  1381. break;
  1382. }
  1383. i++;
  1384. found = arraySearch( &buf[ start ], length, ( uint32_t ) queryIndex, &value, &length );
  1385. }
  1386. else
  1387. {
  1388. size_t keyLength = 0;
  1389. queryStart = i;
  1390. if( ( skipQueryPart( query, &i, queryLength, &keyLength ) != true ) ||
  1391. /* catch an empty key part or a trailing separator */
  1392. ( i == ( queryLength - 1U ) ) )
  1393. {
  1394. ret = JSONBadParameter;
  1395. break;
  1396. }
  1397. found = objectSearch( &buf[ start ], length, &query[ queryStart ], keyLength, &value, &length );
  1398. }
  1399. if( found == false )
  1400. {
  1401. ret = JSONNotFound;
  1402. break;
  1403. }
  1404. start += value;
  1405. if( ( i < queryLength ) && isSeparator_( query[ i ] ) )
  1406. {
  1407. i++;
  1408. }
  1409. }
  1410. if( ret == JSONSuccess )
  1411. {
  1412. *outValue = start;
  1413. *outValueLength = length;
  1414. }
  1415. return ret;
  1416. }
  1417. /**
  1418. * @brief Return a JSON type based on a separator character or
  1419. * the first character of a value.
  1420. *
  1421. * @param[in] c The character to classify.
  1422. *
  1423. * @return an enum of JSONTypes_t
  1424. */
  1425. static JSONTypes_t getType( char c )
  1426. {
  1427. JSONTypes_t t;
  1428. switch( c )
  1429. {
  1430. case '"':
  1431. t = JSONString;
  1432. break;
  1433. case '{':
  1434. t = JSONObject;
  1435. break;
  1436. case '[':
  1437. t = JSONArray;
  1438. break;
  1439. case 't':
  1440. t = JSONTrue;
  1441. break;
  1442. case 'f':
  1443. t = JSONFalse;
  1444. break;
  1445. case 'n':
  1446. t = JSONNull;
  1447. break;
  1448. default:
  1449. t = JSONNumber;
  1450. break;
  1451. }
  1452. return t;
  1453. }
  1454. /** @endcond */
  1455. /**
  1456. * See core_json.h for docs.
  1457. */
  1458. JSONStatus_t JSON_SearchConst( const char * buf,
  1459. size_t max,
  1460. const char * query,
  1461. size_t queryLength,
  1462. const char ** outValue,
  1463. size_t * outValueLength,
  1464. JSONTypes_t * outType )
  1465. {
  1466. JSONStatus_t ret;
  1467. size_t value = 0U;
  1468. if( ( buf == NULL ) || ( query == NULL ) ||
  1469. ( outValue == NULL ) || ( outValueLength == NULL ) )
  1470. {
  1471. ret = JSONNullParameter;
  1472. }
  1473. else if( ( max == 0U ) || ( queryLength == 0U ) )
  1474. {
  1475. ret = JSONBadParameter;
  1476. }
  1477. else
  1478. {
  1479. ret = multiSearch( buf, max, query, queryLength, &value, outValueLength );
  1480. }
  1481. if( ret == JSONSuccess )
  1482. {
  1483. JSONTypes_t t = getType( buf[ value ] );
  1484. if( t == JSONString )
  1485. {
  1486. /* strip the surrounding quotes */
  1487. value++;
  1488. *outValueLength -= 2U;
  1489. }
  1490. *outValue = &buf[ value ];
  1491. if( outType != NULL )
  1492. {
  1493. *outType = t;
  1494. }
  1495. }
  1496. return ret;
  1497. }
  1498. /**
  1499. * See core_json.h for docs.
  1500. */
  1501. JSONStatus_t JSON_SearchT( char * buf,
  1502. size_t max,
  1503. const char * query,
  1504. size_t queryLength,
  1505. char ** outValue,
  1506. size_t * outValueLength,
  1507. JSONTypes_t * outType )
  1508. {
  1509. /* MISRA Ref 11.3.1 [Pointer conversion] */
  1510. /* More details at: https://github.com/FreeRTOS/coreJSON/blob/main/MISRA.md#rule-113 */
  1511. /* coverity[misra_c_2012_rule_11_3_violation] */
  1512. return JSON_SearchConst( ( const char * ) buf, max, query, queryLength, ( const char ** ) outValue, outValueLength, outType );
  1513. }
  1514. /** @cond DO_NOT_DOCUMENT */
  1515. /**
  1516. * @brief Output the next key-value pair or value from a collection.
  1517. *
  1518. * @param[in] buf The buffer to search.
  1519. * @param[in] max size of the buffer.
  1520. * @param[in] start The index at which the collection begins.
  1521. * @param[in,out] next The index at which to seek the next value.
  1522. * @param[out] outKey A pointer to receive the index of the value found.
  1523. * @param[out] outKeyLength A pointer to receive the length of the value found.
  1524. * @param[out] outValue A pointer to receive the index of the value found.
  1525. * @param[out] outValueLength A pointer to receive the length of the value found.
  1526. *
  1527. * @return #JSONSuccess if a value is output;
  1528. * #JSONIllegalDocument if the buffer does not begin with '[' or '{';
  1529. * #JSONNotFound if there are no further values in the collection.
  1530. */
  1531. static JSONStatus_t iterate( const char * buf,
  1532. size_t max,
  1533. size_t * start,
  1534. size_t * next,
  1535. size_t * outKey,
  1536. size_t * outKeyLength,
  1537. size_t * outValue,
  1538. size_t * outValueLength )
  1539. {
  1540. JSONStatus_t ret = JSONNotFound;
  1541. bool found = false;
  1542. coreJSON_ASSERT( ( buf != NULL ) && ( max > 0U ) );
  1543. coreJSON_ASSERT( ( start != NULL ) && ( next != NULL ) );
  1544. coreJSON_ASSERT( ( outKey != NULL ) && ( outKeyLength != NULL ) );
  1545. coreJSON_ASSERT( ( outValue != NULL ) && ( outValueLength != NULL ) );
  1546. if( *start < max )
  1547. {
  1548. switch( buf[ *start ] )
  1549. {
  1550. case '[':
  1551. found = nextValue( buf, next, max, outValue, outValueLength );
  1552. if( found == true )
  1553. {
  1554. *outKey = 0;
  1555. *outKeyLength = 0;
  1556. }
  1557. break;
  1558. case '{':
  1559. found = nextKeyValuePair( buf, next, max, outKey, outKeyLength,
  1560. outValue, outValueLength );
  1561. break;
  1562. default:
  1563. ret = JSONIllegalDocument;
  1564. break;
  1565. }
  1566. }
  1567. if( found == true )
  1568. {
  1569. ret = JSONSuccess;
  1570. ( void ) skipSpaceAndComma( buf, next, max );
  1571. }
  1572. return ret;
  1573. }
  1574. /** @endcond */
  1575. /**
  1576. * See core_json.h for docs.
  1577. */
  1578. JSONStatus_t JSON_Iterate( const char * buf,
  1579. size_t max,
  1580. size_t * start,
  1581. size_t * next,
  1582. JSONPair_t * outPair )
  1583. {
  1584. JSONStatus_t ret;
  1585. size_t key = 0U, keyLength = 0U, value = 0U, valueLength = 0U;
  1586. if( ( buf == NULL ) || ( start == NULL ) || ( next == NULL ) ||
  1587. ( outPair == NULL ) )
  1588. {
  1589. ret = JSONNullParameter;
  1590. }
  1591. else if( ( max == 0U ) || ( *start >= max ) || ( *next > max ) )
  1592. {
  1593. ret = JSONBadParameter;
  1594. }
  1595. else
  1596. {
  1597. skipSpace( buf, start, max );
  1598. if( *next <= *start )
  1599. {
  1600. *next = *start + 1U;
  1601. skipSpace( buf, next, max );
  1602. }
  1603. ret = iterate( buf, max, start, next, &key, &keyLength,
  1604. &value, &valueLength );
  1605. }
  1606. if( ret == JSONSuccess )
  1607. {
  1608. JSONTypes_t t = getType( buf[ value ] );
  1609. if( t == JSONString )
  1610. {
  1611. /* strip the surrounding quotes */
  1612. value++;
  1613. valueLength -= 2U;
  1614. }
  1615. outPair->key = ( key == 0U ) ? NULL : &buf[ key ];
  1616. outPair->keyLength = keyLength;
  1617. outPair->value = &buf[ value ];
  1618. outPair->valueLength = valueLength;
  1619. outPair->jsonType = t;
  1620. }
  1621. return ret;
  1622. }