NCDValue.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /**
  2. * @file NCDValue.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <stdarg.h>
  32. #include <inttypes.h>
  33. #include <misc/debug.h>
  34. #include <misc/offset.h>
  35. #include <ncd/NCDValue.h>
  36. static int ncdvalue_comparator (void *unused, void *vv1, void *vv2)
  37. {
  38. NCDValue *v1 = vv1;
  39. NCDValue *v2 = vv2;
  40. return NCDValue_Compare(v1, v2);
  41. }
  42. static void value_assert (NCDValue *o)
  43. {
  44. switch (o->type) {
  45. case NCDVALUE_STRING:
  46. case NCDVALUE_LIST:
  47. case NCDVALUE_MAP:
  48. return;
  49. default:
  50. ASSERT(0);
  51. }
  52. }
  53. int NCDValue_InitCopy (NCDValue *o, NCDValue *v)
  54. {
  55. value_assert(v);
  56. switch (v->type) {
  57. case NCDVALUE_STRING: {
  58. return NCDValue_InitStringBin(o, v->string, v->string_len);
  59. } break;
  60. case NCDVALUE_LIST: {
  61. NCDValue_InitList(o);
  62. LinkedList2Iterator it;
  63. LinkedList2Iterator_InitForward(&it, &v->list);
  64. LinkedList2Node *n;
  65. while (n = LinkedList2Iterator_Next(&it)) {
  66. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  67. NCDValue tmp;
  68. if (!NCDValue_InitCopy(&tmp, &e->v)) {
  69. goto fail;
  70. }
  71. if (!NCDValue_ListAppend(o, tmp)) {
  72. NCDValue_Free(&tmp);
  73. goto fail;
  74. }
  75. }
  76. return 1;
  77. fail:
  78. LinkedList2Iterator_Free(&it);
  79. NCDValue_Free(o);
  80. return 0;
  81. } break;
  82. case NCDVALUE_MAP: {
  83. NCDValue_InitMap(o);
  84. for (NCDValue *ekey = NCDValue_MapFirstKey(v); ekey; ekey = NCDValue_MapNextKey(v, ekey)) {
  85. NCDValue *eval = NCDValue_MapKeyValue(v, ekey);
  86. NCDValue tmp_key;
  87. NCDValue tmp_val;
  88. if (!NCDValue_InitCopy(&tmp_key, ekey)) {
  89. goto mapfail;
  90. }
  91. if (!NCDValue_InitCopy(&tmp_val, eval)) {
  92. NCDValue_Free(&tmp_key);
  93. goto mapfail;
  94. }
  95. if (!NCDValue_MapInsert(o, tmp_key, tmp_val)) {
  96. NCDValue_Free(&tmp_key);
  97. NCDValue_Free(&tmp_val);
  98. goto mapfail;
  99. }
  100. }
  101. return 1;
  102. mapfail:
  103. NCDValue_Free(o);
  104. return 0;
  105. } break;
  106. default:
  107. ASSERT(0);
  108. }
  109. return 0;
  110. }
  111. void NCDValue_Free (NCDValue *o)
  112. {
  113. switch (o->type) {
  114. case NCDVALUE_STRING: {
  115. free(o->string);
  116. } break;
  117. case NCDVALUE_LIST: {
  118. LinkedList2Node *n;
  119. while (n = LinkedList2_GetFirst(&o->list)) {
  120. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  121. NCDValue_Free(&e->v);
  122. LinkedList2_Remove(&o->list, &e->list_node);
  123. free(e);
  124. }
  125. } break;
  126. case NCDVALUE_MAP: {
  127. BAVLNode *tn;
  128. while (tn = BAVL_GetFirst(&o->map_tree)) {
  129. NCDMapElement *e = UPPER_OBJECT(tn, NCDMapElement, map_tree_node);
  130. BAVL_Remove(&o->map_tree, &e->map_tree_node);
  131. NCDValue_Free(&e->key);
  132. NCDValue_Free(&e->val);
  133. free(e);
  134. }
  135. } break;
  136. default:
  137. ASSERT(0);
  138. }
  139. }
  140. int NCDValue_Type (NCDValue *o)
  141. {
  142. value_assert(o);
  143. return o->type;
  144. }
  145. int NCDValue_IsString (NCDValue *o)
  146. {
  147. value_assert(o);
  148. return o->type == NCDVALUE_STRING;
  149. }
  150. int NCDValue_IsStringNoNulls (NCDValue *o)
  151. {
  152. return NCDValue_IsString(o) && NCDValue_StringHasNoNulls(o);
  153. }
  154. int NCDValue_InitString (NCDValue *o, const char *str)
  155. {
  156. return NCDValue_InitStringBin(o, (const uint8_t *)str, strlen(str));
  157. }
  158. int NCDValue_InitStringBin (NCDValue *o, const uint8_t *str, size_t len)
  159. {
  160. if (len == SIZE_MAX) {
  161. return 0;
  162. }
  163. if (!(o->string = malloc(len + 1))) {
  164. return 0;
  165. }
  166. memcpy(o->string, str, len);
  167. o->string[len] = '\0';
  168. o->string_len = len;
  169. o->type = NCDVALUE_STRING;
  170. return 1;
  171. }
  172. char * NCDValue_StringValue (NCDValue *o)
  173. {
  174. ASSERT(o->type == NCDVALUE_STRING)
  175. return (char *)o->string;
  176. }
  177. size_t NCDValue_StringLength (NCDValue *o)
  178. {
  179. ASSERT(o->type == NCDVALUE_STRING)
  180. return o->string_len;
  181. }
  182. int NCDValue_StringHasNoNulls (NCDValue *o)
  183. {
  184. ASSERT(o->type == NCDVALUE_STRING)
  185. return strlen((char *)o->string) == o->string_len;
  186. }
  187. int NCDValue_StringHasNulls (NCDValue *o)
  188. {
  189. ASSERT(o->type == NCDVALUE_STRING)
  190. return !NCDValue_StringHasNoNulls(o);
  191. }
  192. int NCDValue_StringEquals (NCDValue *o, const char *str)
  193. {
  194. ASSERT(o->type == NCDVALUE_STRING)
  195. return NCDValue_StringHasNoNulls(o) && !strcmp(o->string, str);
  196. }
  197. int NCDValue_IsList (NCDValue *o)
  198. {
  199. value_assert(o);
  200. return o->type == NCDVALUE_LIST;
  201. }
  202. void NCDValue_InitList (NCDValue *o)
  203. {
  204. LinkedList2_Init(&o->list);
  205. o->list_count = 0;
  206. o->type = NCDVALUE_LIST;
  207. }
  208. int NCDValue_ListAppend (NCDValue *o, NCDValue v)
  209. {
  210. value_assert(o);
  211. value_assert(&v);
  212. ASSERT(o->type == NCDVALUE_LIST)
  213. if (o->list_count == SIZE_MAX) {
  214. return 0;
  215. }
  216. NCDListElement *e = malloc(sizeof(*e));
  217. if (!e) {
  218. return 0;
  219. }
  220. LinkedList2_Append(&o->list, &e->list_node);
  221. o->list_count++;
  222. e->v = v;
  223. return 1;
  224. }
  225. int NCDValue_ListAppendList (NCDValue *o, NCDValue l)
  226. {
  227. value_assert(o);
  228. value_assert(&l);
  229. ASSERT(o->type == NCDVALUE_LIST)
  230. ASSERT(l.type == NCDVALUE_LIST)
  231. if (l.list_count > SIZE_MAX - o->list_count) {
  232. return 0;
  233. }
  234. LinkedList2Node *n;
  235. while (n = LinkedList2_GetFirst(&l.list)) {
  236. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  237. LinkedList2_Remove(&l.list, &e->list_node);
  238. LinkedList2_Append(&o->list, &e->list_node);
  239. }
  240. o->list_count += l.list_count;
  241. return 1;
  242. }
  243. size_t NCDValue_ListCount (NCDValue *o)
  244. {
  245. value_assert(o);
  246. ASSERT(o->type == NCDVALUE_LIST)
  247. return o->list_count;
  248. }
  249. NCDValue * NCDValue_ListFirst (NCDValue *o)
  250. {
  251. value_assert(o);
  252. ASSERT(o->type == NCDVALUE_LIST)
  253. if (LinkedList2_IsEmpty(&o->list)) {
  254. return NULL;
  255. }
  256. NCDListElement *e = UPPER_OBJECT(LinkedList2_GetFirst(&o->list), NCDListElement, list_node);
  257. return &e->v;
  258. }
  259. NCDValue * NCDValue_ListNext (NCDValue *o, NCDValue *ev)
  260. {
  261. value_assert(o);
  262. ASSERT(o->type == NCDVALUE_LIST)
  263. NCDListElement *e = UPPER_OBJECT(ev, NCDListElement, v);
  264. LinkedList2Iterator it;
  265. LinkedList2Iterator_Init(&it, &o->list, 1, &e->list_node);
  266. LinkedList2Iterator_Next(&it);
  267. LinkedList2Node *nen = LinkedList2Iterator_Next(&it);
  268. LinkedList2Iterator_Free(&it);
  269. if (!nen) {
  270. return NULL;
  271. }
  272. NCDListElement *ne = UPPER_OBJECT(nen, NCDListElement, list_node);
  273. return &ne->v;
  274. }
  275. int NCDValue_ListRead (NCDValue *o, int num, ...)
  276. {
  277. value_assert(o);
  278. ASSERT(o->type == NCDVALUE_LIST)
  279. ASSERT(num >= 0)
  280. if (num != NCDValue_ListCount(o)) {
  281. return 0;
  282. }
  283. va_list ap;
  284. va_start(ap, num);
  285. LinkedList2Iterator it;
  286. LinkedList2Iterator_InitForward(&it, &o->list);
  287. LinkedList2Node *n;
  288. while (n = LinkedList2Iterator_Next(&it)) {
  289. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  290. NCDValue **dest = va_arg(ap, NCDValue **);
  291. *dest = &e->v;
  292. }
  293. va_end(ap);
  294. return 1;
  295. }
  296. int NCDValue_ListReadHead (NCDValue *o, int num, ...)
  297. {
  298. value_assert(o);
  299. ASSERT(o->type == NCDVALUE_LIST)
  300. ASSERT(num >= 0)
  301. if (num > NCDValue_ListCount(o)) {
  302. return 0;
  303. }
  304. va_list ap;
  305. va_start(ap, num);
  306. LinkedList2Node *n = LinkedList2_GetFirst(&o->list);
  307. while (num > 0) {
  308. ASSERT(n)
  309. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  310. NCDValue **dest = va_arg(ap, NCDValue **);
  311. *dest = &e->v;
  312. n = LinkedList2Node_Next(n);
  313. num--;
  314. }
  315. va_end(ap);
  316. return 1;
  317. }
  318. NCDValue * NCDValue_ListGet (NCDValue *o, size_t pos)
  319. {
  320. value_assert(o);
  321. ASSERT(o->type == NCDVALUE_LIST)
  322. ASSERT(pos < o->list_count)
  323. NCDValue *e = NCDValue_ListFirst(o);
  324. while (e) {
  325. if (pos == 0) {
  326. break;
  327. }
  328. pos--;
  329. e = NCDValue_ListNext(o, e);
  330. }
  331. ASSERT(e)
  332. return e;
  333. }
  334. NCDValue NCDValue_ListShift (NCDValue *o)
  335. {
  336. value_assert(o);
  337. ASSERT(o->type == NCDVALUE_LIST)
  338. ASSERT(o->list_count > 0)
  339. NCDListElement *e = UPPER_OBJECT(LinkedList2_GetFirst(&o->list), NCDListElement, list_node);
  340. NCDValue v = e->v;
  341. LinkedList2_Remove(&o->list, &e->list_node);
  342. o->list_count--;
  343. free(e);
  344. return v;
  345. }
  346. NCDValue NCDValue_ListRemove (NCDValue *o, NCDValue *ev)
  347. {
  348. value_assert(o);
  349. ASSERT(o->type == NCDVALUE_LIST)
  350. ASSERT(o->list_count > 0)
  351. NCDListElement *e = UPPER_OBJECT(ev, NCDListElement, v);
  352. NCDValue v = e->v;
  353. LinkedList2_Remove(&o->list, &e->list_node);
  354. o->list_count--;
  355. free(e);
  356. return v;
  357. }
  358. int NCDValue_IsMap (NCDValue *o)
  359. {
  360. value_assert(o);
  361. return o->type == NCDVALUE_MAP;
  362. }
  363. void NCDValue_InitMap (NCDValue *o)
  364. {
  365. o->type = NCDVALUE_MAP;
  366. BAVL_Init(&o->map_tree, OFFSET_DIFF(NCDMapElement, key, map_tree_node), ncdvalue_comparator, NULL);
  367. o->map_count = 0;
  368. }
  369. size_t NCDValue_MapCount (NCDValue *o)
  370. {
  371. value_assert(o);
  372. ASSERT(o->type == NCDVALUE_MAP)
  373. return o->map_count;
  374. }
  375. NCDValue * NCDValue_MapFirstKey (NCDValue *o)
  376. {
  377. value_assert(o);
  378. ASSERT(o->type == NCDVALUE_MAP)
  379. BAVLNode *tn = BAVL_GetFirst(&o->map_tree);
  380. if (!tn) {
  381. return NULL;
  382. }
  383. NCDMapElement *e = UPPER_OBJECT(tn, NCDMapElement, map_tree_node);
  384. value_assert(&e->key);
  385. value_assert(&e->val);
  386. return &e->key;
  387. }
  388. NCDValue * NCDValue_MapNextKey (NCDValue *o, NCDValue *ekey)
  389. {
  390. value_assert(o);
  391. ASSERT(o->type == NCDVALUE_MAP)
  392. NCDMapElement *e = UPPER_OBJECT(ekey, NCDMapElement, key);
  393. value_assert(&e->key);
  394. value_assert(&e->val);
  395. BAVLNode *tn = BAVL_GetNext(&o->map_tree, &e->map_tree_node);
  396. if (!tn) {
  397. return NULL;
  398. }
  399. NCDMapElement *ne = UPPER_OBJECT(tn, NCDMapElement, map_tree_node);
  400. value_assert(&ne->key);
  401. value_assert(&ne->val);
  402. return &ne->key;
  403. }
  404. NCDValue * NCDValue_MapKeyValue (NCDValue *o, NCDValue *ekey)
  405. {
  406. value_assert(o);
  407. ASSERT(o->type == NCDVALUE_MAP)
  408. NCDMapElement *e = UPPER_OBJECT(ekey, NCDMapElement, key);
  409. value_assert(&e->key);
  410. value_assert(&e->val);
  411. return &e->val;
  412. }
  413. NCDValue * NCDValue_MapFindKey (NCDValue *o, NCDValue *key)
  414. {
  415. value_assert(o);
  416. ASSERT(o->type == NCDVALUE_MAP)
  417. value_assert(key);
  418. BAVLNode *tn = BAVL_LookupExact(&o->map_tree, key);
  419. if (!tn) {
  420. return NULL;
  421. }
  422. NCDMapElement *e = UPPER_OBJECT(tn, NCDMapElement, map_tree_node);
  423. value_assert(&e->key);
  424. value_assert(&e->val);
  425. ASSERT(!NCDValue_Compare(&e->key, key))
  426. return &e->key;
  427. }
  428. NCDValue * NCDValue_MapInsert (NCDValue *o, NCDValue key, NCDValue val)
  429. {
  430. value_assert(o);
  431. ASSERT(o->type == NCDVALUE_MAP)
  432. value_assert(&key);
  433. value_assert(&val);
  434. ASSERT(!NCDValue_MapFindKey(o, &key))
  435. if (o->map_count == SIZE_MAX) {
  436. return NULL;
  437. }
  438. NCDMapElement *e = malloc(sizeof(*e));
  439. if (!e) {
  440. return NULL;
  441. }
  442. e->key = key;
  443. e->val = val;
  444. int res = BAVL_Insert(&o->map_tree, &e->map_tree_node, NULL);
  445. ASSERT(res)
  446. o->map_count++;
  447. return &e->key;
  448. }
  449. void NCDValue_MapRemove (NCDValue *o, NCDValue *ekey, NCDValue *out_key, NCDValue *out_val)
  450. {
  451. value_assert(o);
  452. ASSERT(o->type == NCDVALUE_MAP)
  453. ASSERT(out_key)
  454. ASSERT(out_val)
  455. ASSERT(o->map_count > 0)
  456. NCDMapElement *e = UPPER_OBJECT(ekey, NCDMapElement, key);
  457. value_assert(&e->key);
  458. value_assert(&e->val);
  459. BAVL_Remove(&o->map_tree, &e->map_tree_node);
  460. *out_key = e->key;
  461. *out_val = e->val;
  462. o->map_count--;
  463. free(e);
  464. }
  465. NCDValue * NCDValue_MapFindValueByString (NCDValue *o, const char *key_str)
  466. {
  467. value_assert(o);
  468. ASSERT(o->type == NCDVALUE_MAP)
  469. ASSERT(key_str)
  470. NCDValue key;
  471. key.type = NCDVALUE_STRING;
  472. key.string = (char *)key_str;
  473. key.string_len = strlen(key_str);
  474. NCDValue *ekey = NCDValue_MapFindKey(o, &key);
  475. if (!ekey) {
  476. return NULL;
  477. }
  478. return NCDValue_MapKeyValue(o, ekey);
  479. }
  480. int NCDValue_Compare (NCDValue *o, NCDValue *v)
  481. {
  482. value_assert(o);
  483. value_assert(v);
  484. int cmp = (o->type > v->type) - (o->type < v->type);
  485. if (cmp) {
  486. return cmp;
  487. }
  488. ASSERT(o->type == v->type)
  489. if (o->type == NCDVALUE_STRING) {
  490. size_t min_len = o->string_len < v->string_len ? o->string_len : v->string_len;
  491. int cmp = memcmp(o->string, v->string, min_len);
  492. if (cmp) {
  493. return (cmp > 0) - (cmp < 0);
  494. }
  495. return (o->string_len > v->string_len) - (o->string_len < v->string_len);
  496. }
  497. if (o->type == NCDVALUE_LIST) {
  498. NCDValue *x = NCDValue_ListFirst(o);
  499. NCDValue *y = NCDValue_ListFirst(v);
  500. while (1) {
  501. if (!x && y) {
  502. return -1;
  503. }
  504. if (x && !y) {
  505. return 1;
  506. }
  507. if (!x && !y) {
  508. return 0;
  509. }
  510. int res = NCDValue_Compare(x, y);
  511. if (res) {
  512. return res;
  513. }
  514. x = NCDValue_ListNext(o, x);
  515. y = NCDValue_ListNext(v, y);
  516. }
  517. }
  518. if (o->type == NCDVALUE_MAP) {
  519. NCDValue *key1 = NCDValue_MapFirstKey(o);
  520. NCDValue *key2 = NCDValue_MapFirstKey(v);
  521. while (1) {
  522. if (!key1 && key2) {
  523. return -1;
  524. }
  525. if (key1 && !key2) {
  526. return 1;
  527. }
  528. if (!key1 && !key2) {
  529. return 0;
  530. }
  531. int res = NCDValue_Compare(key1, key2);
  532. if (res) {
  533. return res;
  534. }
  535. NCDValue *val1 = NCDValue_MapKeyValue(o, key1);
  536. NCDValue *val2 = NCDValue_MapKeyValue(v, key2);
  537. res = NCDValue_Compare(val1, val2);
  538. if (res) {
  539. return res;
  540. }
  541. key1 = NCDValue_MapNextKey(o, key1);
  542. key2 = NCDValue_MapNextKey(v, key2);
  543. }
  544. }
  545. ASSERT(0)
  546. }