NCDValue.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  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. #include "NCDValue_maptree.h"
  37. #include <structure/SAvl_impl.h>
  38. static int ncdvalue_comparator (void *unused, void *vv1, void *vv2)
  39. {
  40. NCDValue *v1 = vv1;
  41. NCDValue *v2 = vv2;
  42. return NCDValue_Compare(v1, v2);
  43. }
  44. static void value_assert (NCDValue *o)
  45. {
  46. switch (o->type) {
  47. case NCDVALUE_STRING:
  48. case NCDVALUE_LIST:
  49. case NCDVALUE_MAP:
  50. case NCDVALUE_VAR:
  51. return;
  52. default:
  53. ASSERT(0);
  54. }
  55. }
  56. int NCDValue_InitCopy (NCDValue *o, NCDValue *v)
  57. {
  58. value_assert(v);
  59. switch (v->type) {
  60. case NCDVALUE_STRING: {
  61. return NCDValue_InitStringBin(o, v->string, v->string_len);
  62. } break;
  63. case NCDVALUE_LIST: {
  64. NCDValue_InitList(o);
  65. for (LinkedList1Node *n = LinkedList1_GetFirst(&v->list); n; n = LinkedList1Node_Next(n)) {
  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. NCDValue_Free(o);
  79. return 0;
  80. } break;
  81. case NCDVALUE_MAP: {
  82. NCDValue_InitMap(o);
  83. for (NCDValue *ekey = NCDValue_MapFirstKey(v); ekey; ekey = NCDValue_MapNextKey(v, ekey)) {
  84. NCDValue *eval = NCDValue_MapKeyValue(v, ekey);
  85. NCDValue tmp_key;
  86. NCDValue tmp_val;
  87. if (!NCDValue_InitCopy(&tmp_key, ekey)) {
  88. goto mapfail;
  89. }
  90. if (!NCDValue_InitCopy(&tmp_val, eval)) {
  91. NCDValue_Free(&tmp_key);
  92. goto mapfail;
  93. }
  94. if (!NCDValue_MapInsert(o, tmp_key, tmp_val)) {
  95. NCDValue_Free(&tmp_key);
  96. NCDValue_Free(&tmp_val);
  97. goto mapfail;
  98. }
  99. }
  100. return 1;
  101. mapfail:
  102. NCDValue_Free(o);
  103. return 0;
  104. } break;
  105. case NCDVALUE_VAR: {
  106. return NCDValue_InitVar(o, v->var_name);
  107. } break;
  108. default:
  109. ASSERT(0);
  110. }
  111. return 0;
  112. }
  113. void NCDValue_Free (NCDValue *o)
  114. {
  115. switch (o->type) {
  116. case NCDVALUE_STRING: {
  117. free(o->string);
  118. } break;
  119. case NCDVALUE_LIST: {
  120. LinkedList1Node *n;
  121. while (n = LinkedList1_GetFirst(&o->list)) {
  122. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  123. NCDValue_Free(&e->v);
  124. LinkedList1_Remove(&o->list, &e->list_node);
  125. free(e);
  126. }
  127. } break;
  128. case NCDVALUE_MAP: {
  129. NCDMapElement *e;
  130. while (e = NCDValue__MapTree_GetFirst(&o->map_tree, 0)) {
  131. NCDValue__MapTree_Remove(&o->map_tree, 0, e);
  132. NCDValue_Free(&e->key);
  133. NCDValue_Free(&e->val);
  134. free(e);
  135. }
  136. } break;
  137. case NCDVALUE_VAR: {
  138. free(o->var_name);
  139. } break;
  140. default:
  141. ASSERT(0);
  142. }
  143. }
  144. int NCDValue_Type (NCDValue *o)
  145. {
  146. value_assert(o);
  147. return o->type;
  148. }
  149. int NCDValue_IsString (NCDValue *o)
  150. {
  151. value_assert(o);
  152. return o->type == NCDVALUE_STRING;
  153. }
  154. int NCDValue_IsStringNoNulls (NCDValue *o)
  155. {
  156. return NCDValue_IsString(o) && NCDValue_StringHasNoNulls(o);
  157. }
  158. int NCDValue_InitString (NCDValue *o, const char *str)
  159. {
  160. return NCDValue_InitStringBin(o, (const uint8_t *)str, strlen(str));
  161. }
  162. int NCDValue_InitStringBin (NCDValue *o, const uint8_t *str, size_t len)
  163. {
  164. if (len == SIZE_MAX) {
  165. return 0;
  166. }
  167. if (!(o->string = malloc(len + 1))) {
  168. return 0;
  169. }
  170. memcpy(o->string, str, len);
  171. o->string[len] = '\0';
  172. o->string_len = len;
  173. o->type = NCDVALUE_STRING;
  174. return 1;
  175. }
  176. char * NCDValue_StringValue (NCDValue *o)
  177. {
  178. ASSERT(o->type == NCDVALUE_STRING)
  179. return (char *)o->string;
  180. }
  181. size_t NCDValue_StringLength (NCDValue *o)
  182. {
  183. ASSERT(o->type == NCDVALUE_STRING)
  184. return o->string_len;
  185. }
  186. int NCDValue_StringHasNoNulls (NCDValue *o)
  187. {
  188. ASSERT(o->type == NCDVALUE_STRING)
  189. return strlen((char *)o->string) == o->string_len;
  190. }
  191. int NCDValue_StringHasNulls (NCDValue *o)
  192. {
  193. ASSERT(o->type == NCDVALUE_STRING)
  194. return !NCDValue_StringHasNoNulls(o);
  195. }
  196. int NCDValue_StringEquals (NCDValue *o, const char *str)
  197. {
  198. ASSERT(o->type == NCDVALUE_STRING)
  199. return NCDValue_StringHasNoNulls(o) && !strcmp((const char *)o->string, str);
  200. }
  201. int NCDValue_IsList (NCDValue *o)
  202. {
  203. value_assert(o);
  204. return o->type == NCDVALUE_LIST;
  205. }
  206. void NCDValue_InitList (NCDValue *o)
  207. {
  208. LinkedList1_Init(&o->list);
  209. o->list_count = 0;
  210. o->type = NCDVALUE_LIST;
  211. }
  212. int NCDValue_ListAppend (NCDValue *o, NCDValue v)
  213. {
  214. value_assert(o);
  215. value_assert(&v);
  216. ASSERT(o->type == NCDVALUE_LIST)
  217. if (o->list_count == SIZE_MAX) {
  218. return 0;
  219. }
  220. NCDListElement *e = malloc(sizeof(*e));
  221. if (!e) {
  222. return 0;
  223. }
  224. LinkedList1_Append(&o->list, &e->list_node);
  225. o->list_count++;
  226. e->v = v;
  227. return 1;
  228. }
  229. int NCDValue_ListPrepend (NCDValue *o, NCDValue v)
  230. {
  231. value_assert(o);
  232. value_assert(&v);
  233. ASSERT(o->type == NCDVALUE_LIST)
  234. if (o->list_count == SIZE_MAX) {
  235. return 0;
  236. }
  237. NCDListElement *e = malloc(sizeof(*e));
  238. if (!e) {
  239. return 0;
  240. }
  241. LinkedList1_Prepend(&o->list, &e->list_node);
  242. o->list_count++;
  243. e->v = v;
  244. return 1;
  245. }
  246. int NCDValue_ListAppendList (NCDValue *o, NCDValue l)
  247. {
  248. value_assert(o);
  249. value_assert(&l);
  250. ASSERT(o->type == NCDVALUE_LIST)
  251. ASSERT(l.type == NCDVALUE_LIST)
  252. if (l.list_count > SIZE_MAX - o->list_count) {
  253. return 0;
  254. }
  255. LinkedList1Node *n;
  256. while (n = LinkedList1_GetFirst(&l.list)) {
  257. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  258. LinkedList1_Remove(&l.list, &e->list_node);
  259. LinkedList1_Append(&o->list, &e->list_node);
  260. }
  261. o->list_count += l.list_count;
  262. return 1;
  263. }
  264. size_t NCDValue_ListCount (NCDValue *o)
  265. {
  266. value_assert(o);
  267. ASSERT(o->type == NCDVALUE_LIST)
  268. return o->list_count;
  269. }
  270. NCDValue * NCDValue_ListFirst (NCDValue *o)
  271. {
  272. value_assert(o);
  273. ASSERT(o->type == NCDVALUE_LIST)
  274. LinkedList1Node *ln = LinkedList1_GetFirst(&o->list);
  275. if (!ln) {
  276. return NULL;
  277. }
  278. NCDListElement *e = UPPER_OBJECT(ln, NCDListElement, list_node);
  279. return &e->v;
  280. }
  281. NCDValue * NCDValue_ListNext (NCDValue *o, NCDValue *ev)
  282. {
  283. value_assert(o);
  284. ASSERT(o->type == NCDVALUE_LIST)
  285. NCDListElement *cur_e = UPPER_OBJECT(ev, NCDListElement, v);
  286. LinkedList1Node *ln = LinkedList1Node_Next(&cur_e->list_node);
  287. if (!ln) {
  288. return NULL;
  289. }
  290. NCDListElement *e = UPPER_OBJECT(ln, NCDListElement, list_node);
  291. return &e->v;
  292. }
  293. int NCDValue_ListRead (NCDValue *o, int num, ...)
  294. {
  295. value_assert(o);
  296. ASSERT(o->type == NCDVALUE_LIST)
  297. ASSERT(num >= 0)
  298. if (num != NCDValue_ListCount(o)) {
  299. return 0;
  300. }
  301. va_list ap;
  302. va_start(ap, num);
  303. for (LinkedList1Node *n = LinkedList1_GetFirst(&o->list); n; n = LinkedList1Node_Next(n)) {
  304. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  305. NCDValue **dest = va_arg(ap, NCDValue **);
  306. *dest = &e->v;
  307. }
  308. va_end(ap);
  309. return 1;
  310. }
  311. int NCDValue_ListReadHead (NCDValue *o, int num, ...)
  312. {
  313. value_assert(o);
  314. ASSERT(o->type == NCDVALUE_LIST)
  315. ASSERT(num >= 0)
  316. if (num > NCDValue_ListCount(o)) {
  317. return 0;
  318. }
  319. va_list ap;
  320. va_start(ap, num);
  321. LinkedList1Node *n = LinkedList1_GetFirst(&o->list);
  322. while (num > 0) {
  323. ASSERT(n)
  324. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  325. NCDValue **dest = va_arg(ap, NCDValue **);
  326. *dest = &e->v;
  327. n = LinkedList1Node_Next(n);
  328. num--;
  329. }
  330. va_end(ap);
  331. return 1;
  332. }
  333. NCDValue * NCDValue_ListGet (NCDValue *o, size_t pos)
  334. {
  335. value_assert(o);
  336. ASSERT(o->type == NCDVALUE_LIST)
  337. ASSERT(pos < o->list_count)
  338. NCDValue *e = NCDValue_ListFirst(o);
  339. while (e) {
  340. if (pos == 0) {
  341. break;
  342. }
  343. pos--;
  344. e = NCDValue_ListNext(o, e);
  345. }
  346. ASSERT(e)
  347. return e;
  348. }
  349. NCDValue NCDValue_ListShift (NCDValue *o)
  350. {
  351. value_assert(o);
  352. ASSERT(o->type == NCDVALUE_LIST)
  353. ASSERT(o->list_count > 0)
  354. NCDListElement *e = UPPER_OBJECT(LinkedList1_GetFirst(&o->list), NCDListElement, list_node);
  355. NCDValue v = e->v;
  356. LinkedList1_Remove(&o->list, &e->list_node);
  357. o->list_count--;
  358. free(e);
  359. return v;
  360. }
  361. NCDValue NCDValue_ListRemove (NCDValue *o, NCDValue *ev)
  362. {
  363. value_assert(o);
  364. ASSERT(o->type == NCDVALUE_LIST)
  365. ASSERT(o->list_count > 0)
  366. NCDListElement *e = UPPER_OBJECT(ev, NCDListElement, v);
  367. NCDValue v = e->v;
  368. LinkedList1_Remove(&o->list, &e->list_node);
  369. o->list_count--;
  370. free(e);
  371. return v;
  372. }
  373. int NCDValue_IsMap (NCDValue *o)
  374. {
  375. value_assert(o);
  376. return o->type == NCDVALUE_MAP;
  377. }
  378. void NCDValue_InitMap (NCDValue *o)
  379. {
  380. o->type = NCDVALUE_MAP;
  381. NCDValue__MapTree_Init(&o->map_tree);
  382. o->map_count = 0;
  383. }
  384. size_t NCDValue_MapCount (NCDValue *o)
  385. {
  386. value_assert(o);
  387. ASSERT(o->type == NCDVALUE_MAP)
  388. return o->map_count;
  389. }
  390. NCDValue * NCDValue_MapFirstKey (NCDValue *o)
  391. {
  392. value_assert(o);
  393. ASSERT(o->type == NCDVALUE_MAP)
  394. NCDMapElement *e = NCDValue__MapTree_GetFirst(&o->map_tree, 0);
  395. if (!e) {
  396. return NULL;
  397. }
  398. value_assert(&e->key);
  399. value_assert(&e->val);
  400. return &e->key;
  401. }
  402. NCDValue * NCDValue_MapNextKey (NCDValue *o, NCDValue *ekey)
  403. {
  404. value_assert(o);
  405. ASSERT(o->type == NCDVALUE_MAP)
  406. NCDMapElement *e0 = UPPER_OBJECT(ekey, NCDMapElement, key);
  407. value_assert(&e0->key);
  408. value_assert(&e0->val);
  409. NCDMapElement *e = NCDValue__MapTree_GetNext(&o->map_tree, 0, e0);
  410. if (!e) {
  411. return NULL;
  412. }
  413. value_assert(&e->key);
  414. value_assert(&e->val);
  415. return &e->key;
  416. }
  417. NCDValue * NCDValue_MapKeyValue (NCDValue *o, NCDValue *ekey)
  418. {
  419. value_assert(o);
  420. ASSERT(o->type == NCDVALUE_MAP)
  421. NCDMapElement *e = UPPER_OBJECT(ekey, NCDMapElement, key);
  422. value_assert(&e->key);
  423. value_assert(&e->val);
  424. return &e->val;
  425. }
  426. NCDValue * NCDValue_MapFindKey (NCDValue *o, NCDValue *key)
  427. {
  428. value_assert(o);
  429. ASSERT(o->type == NCDVALUE_MAP)
  430. value_assert(key);
  431. NCDMapElement *e = NCDValue__MapTree_LookupExact(&o->map_tree, 0, key);
  432. if (!e) {
  433. return NULL;
  434. }
  435. value_assert(&e->key);
  436. value_assert(&e->val);
  437. ASSERT(!NCDValue_Compare(&e->key, key))
  438. return &e->key;
  439. }
  440. NCDValue * NCDValue_MapInsert (NCDValue *o, NCDValue key, NCDValue val)
  441. {
  442. value_assert(o);
  443. ASSERT(o->type == NCDVALUE_MAP)
  444. value_assert(&key);
  445. value_assert(&val);
  446. ASSERT(!NCDValue_MapFindKey(o, &key))
  447. if (o->map_count == SIZE_MAX) {
  448. return NULL;
  449. }
  450. NCDMapElement *e = malloc(sizeof(*e));
  451. if (!e) {
  452. return NULL;
  453. }
  454. e->key = key;
  455. e->val = val;
  456. int res = NCDValue__MapTree_Insert(&o->map_tree, 0, e, NULL);
  457. ASSERT(res)
  458. o->map_count++;
  459. return &e->key;
  460. }
  461. void NCDValue_MapRemove (NCDValue *o, NCDValue *ekey, NCDValue *out_key, NCDValue *out_val)
  462. {
  463. value_assert(o);
  464. ASSERT(o->type == NCDVALUE_MAP)
  465. ASSERT(out_key)
  466. ASSERT(out_val)
  467. ASSERT(o->map_count > 0)
  468. NCDMapElement *e = UPPER_OBJECT(ekey, NCDMapElement, key);
  469. value_assert(&e->key);
  470. value_assert(&e->val);
  471. NCDValue__MapTree_Remove(&o->map_tree, 0, e);
  472. *out_key = e->key;
  473. *out_val = e->val;
  474. o->map_count--;
  475. free(e);
  476. }
  477. NCDValue * NCDValue_MapFindValueByString (NCDValue *o, const char *key_str)
  478. {
  479. value_assert(o);
  480. ASSERT(o->type == NCDVALUE_MAP)
  481. ASSERT(key_str)
  482. NCDValue key;
  483. key.type = NCDVALUE_STRING;
  484. key.string = (uint8_t *)key_str;
  485. key.string_len = strlen(key_str);
  486. NCDValue *ekey = NCDValue_MapFindKey(o, &key);
  487. if (!ekey) {
  488. return NULL;
  489. }
  490. return NCDValue_MapKeyValue(o, ekey);
  491. }
  492. int NCDValue_IsVar (NCDValue *o)
  493. {
  494. value_assert(o);
  495. return o->type == NCDVALUE_VAR;
  496. }
  497. int NCDValue_InitVar (NCDValue *o, const char *var_name)
  498. {
  499. ASSERT(var_name)
  500. if (!(o->var_name = strdup(var_name))) {
  501. return 0;
  502. }
  503. o->type = NCDVALUE_VAR;
  504. return 1;
  505. }
  506. const char * NCDValue_VarName (NCDValue *o)
  507. {
  508. value_assert(o);
  509. ASSERT(o->type == NCDVALUE_VAR)
  510. return o->var_name;
  511. }
  512. int NCDValue_Compare (NCDValue *o, NCDValue *v)
  513. {
  514. value_assert(o);
  515. value_assert(v);
  516. int cmp = (o->type > v->type) - (o->type < v->type);
  517. if (cmp) {
  518. return cmp;
  519. }
  520. ASSERT(o->type == v->type)
  521. if (o->type == NCDVALUE_STRING) {
  522. size_t min_len = o->string_len < v->string_len ? o->string_len : v->string_len;
  523. int cmp = memcmp(o->string, v->string, min_len);
  524. if (cmp) {
  525. return (cmp > 0) - (cmp < 0);
  526. }
  527. return (o->string_len > v->string_len) - (o->string_len < v->string_len);
  528. }
  529. if (o->type == NCDVALUE_LIST) {
  530. NCDValue *x = NCDValue_ListFirst(o);
  531. NCDValue *y = NCDValue_ListFirst(v);
  532. while (1) {
  533. if (!x && y) {
  534. return -1;
  535. }
  536. if (x && !y) {
  537. return 1;
  538. }
  539. if (!x && !y) {
  540. return 0;
  541. }
  542. int res = NCDValue_Compare(x, y);
  543. if (res) {
  544. return res;
  545. }
  546. x = NCDValue_ListNext(o, x);
  547. y = NCDValue_ListNext(v, y);
  548. }
  549. }
  550. if (o->type == NCDVALUE_MAP) {
  551. NCDValue *key1 = NCDValue_MapFirstKey(o);
  552. NCDValue *key2 = NCDValue_MapFirstKey(v);
  553. while (1) {
  554. if (!key1 && key2) {
  555. return -1;
  556. }
  557. if (key1 && !key2) {
  558. return 1;
  559. }
  560. if (!key1 && !key2) {
  561. return 0;
  562. }
  563. int res = NCDValue_Compare(key1, key2);
  564. if (res) {
  565. return res;
  566. }
  567. NCDValue *val1 = NCDValue_MapKeyValue(o, key1);
  568. NCDValue *val2 = NCDValue_MapKeyValue(v, key2);
  569. res = NCDValue_Compare(val1, val2);
  570. if (res) {
  571. return res;
  572. }
  573. key1 = NCDValue_MapNextKey(o, key1);
  574. key2 = NCDValue_MapNextKey(v, key2);
  575. }
  576. }
  577. if (o->type == NCDVALUE_VAR) {
  578. int res = strcmp(o->var_name, v->var_name);
  579. return (res > 0) - (res < 0);
  580. }
  581. ASSERT(0)
  582. return 0;
  583. }