NCDVal.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. /**
  2. * @file NCDVal.c
  3. * @author Ambroz Bizjak <[email protected]>
  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 <string.h>
  30. #include <limits.h>
  31. #include <stdlib.h>
  32. #include <stddef.h>
  33. #include <stdarg.h>
  34. #include <misc/bsize.h>
  35. #include "NCDVal.h"
  36. static void * NCDValMem__BufAt (NCDValMem *o, NCDVal__idx idx)
  37. {
  38. ASSERT(idx < o->used)
  39. return (o->buf ? o->buf : o->fastbuf) + idx;
  40. }
  41. static NCDVal__idx NCDValMem__Alloc (NCDValMem *o, bsize_t alloc_size, NCDVal__idx align)
  42. {
  43. if (alloc_size.is_overflow) {
  44. return -1;
  45. }
  46. NCDVal__idx mod = o->used % align;
  47. NCDVal__idx align_extra = mod ? (align - mod) : 0;
  48. if (alloc_size.value > NCDVAL_MAXIDX - align_extra) {
  49. return -1;
  50. }
  51. NCDVal__idx aligned_alloc_size = align_extra + alloc_size.value;
  52. if (aligned_alloc_size > o->size - o->used) {
  53. NCDVal__idx newsize = (o->buf ? o->size : NCDVAL_FIRST_SIZE);
  54. while (aligned_alloc_size > newsize - o->used) {
  55. if (newsize > NCDVAL_MAXIDX / 2) {
  56. return -1;
  57. }
  58. newsize *= 2;
  59. }
  60. char *newbuf;
  61. if (!o->buf) {
  62. newbuf = malloc(newsize);
  63. if (!newbuf) {
  64. return -1;
  65. }
  66. memcpy(newbuf, o->fastbuf, o->used);
  67. } else {
  68. newbuf = realloc(o->buf, newsize);
  69. if (!newbuf) {
  70. return -1;
  71. }
  72. }
  73. o->buf = newbuf;
  74. o->size = newsize;
  75. }
  76. NCDVal__idx idx = o->used + align_extra;
  77. o->used += aligned_alloc_size;
  78. return idx;
  79. }
  80. static NCDValRef NCDVal__Ref (NCDValMem *mem, NCDVal__idx idx)
  81. {
  82. ASSERT(idx >= 0 || idx == -1)
  83. ASSERT(idx == -1 || mem)
  84. NCDValRef ref = {mem, idx};
  85. return ref;
  86. }
  87. static void NCDVal__AssertMem (NCDValMem *mem)
  88. {
  89. ASSERT(mem)
  90. ASSERT(mem->size >= 0)
  91. ASSERT(mem->used >= 0)
  92. ASSERT(mem->used <= mem->size)
  93. ASSERT(mem->buf || mem->size == NCDVAL_FASTBUF_SIZE)
  94. ASSERT(!mem->buf || mem->size >= NCDVAL_FIRST_SIZE)
  95. }
  96. static void NCDVal__AssertValOnly (NCDValMem *mem, NCDVal__idx idx)
  97. {
  98. ASSERT(idx >= 0)
  99. ASSERT(idx + sizeof(uint8_t) <= mem->used)
  100. #ifndef NDEBUG
  101. uint8_t *type_ptr = NCDValMem__BufAt(mem, idx);
  102. switch (*type_ptr) {
  103. case NCDVAL_STRING: {
  104. ASSERT(idx + sizeof(struct NCDVal__string) <= mem->used)
  105. struct NCDVal__string *str_e = NCDValMem__BufAt(mem, idx);
  106. ASSERT(str_e->length >= 0)
  107. ASSERT(idx + sizeof(struct NCDVal__string) + str_e->length + 1 <= mem->used)
  108. } break;
  109. case NCDVAL_LIST: {
  110. ASSERT(idx + sizeof(struct NCDVal__list) <= mem->used)
  111. struct NCDVal__list *list_e = NCDValMem__BufAt(mem, idx);
  112. ASSERT(list_e->maxcount >= 0)
  113. ASSERT(list_e->count >= 0)
  114. ASSERT(list_e->count <= list_e->maxcount)
  115. ASSERT(idx + sizeof(struct NCDVal__list) + list_e->maxcount * sizeof(NCDVal__idx) <= mem->used)
  116. } break;
  117. case NCDVAL_MAP: {
  118. ASSERT(idx + sizeof(struct NCDVal__map) <= mem->used)
  119. struct NCDVal__map *map_e = NCDValMem__BufAt(mem, idx);
  120. ASSERT(map_e->maxcount >= 0)
  121. ASSERT(map_e->count >= 0)
  122. ASSERT(map_e->count <= map_e->maxcount)
  123. ASSERT(idx + sizeof(struct NCDVal__map) + map_e->maxcount * sizeof(struct NCDVal__mapelem) <= mem->used)
  124. } break;
  125. default: ASSERT(0);
  126. }
  127. #endif
  128. }
  129. static void NCDVal__AssertVal (NCDValRef val)
  130. {
  131. NCDVal__AssertMem(val.mem);
  132. NCDVal__AssertValOnly(val.mem, val.idx);
  133. }
  134. static NCDValMapElem NCDVal__MapElem (NCDVal__idx elemidx)
  135. {
  136. ASSERT(elemidx >= 0 || elemidx == -1)
  137. NCDValMapElem me = {elemidx};
  138. return me;
  139. }
  140. static void NCDVal__MapAssertElem (NCDValRef map, NCDValMapElem me)
  141. {
  142. ASSERT(NCDVal_IsMap(map))
  143. ASSERT(me.elemidx >= map.idx + offsetof(struct NCDVal__map, elems))
  144. ASSERT(me.elemidx < map.idx + offsetof(struct NCDVal__map, elems) + NCDVal_MapCount(map) * sizeof(struct NCDVal__mapelem))
  145. struct NCDVal__mapelem *me_e = NCDValMem__BufAt(map.mem, me.elemidx);
  146. NCDVal__AssertValOnly(map.mem, me_e->key_idx);
  147. NCDVal__AssertValOnly(map.mem, me_e->val_idx);
  148. }
  149. #include "NCDVal_maptree.h"
  150. #include <structure/CAvl_impl.h>
  151. void NCDValMem_Init (NCDValMem *o)
  152. {
  153. o->buf = NULL;
  154. o->size = NCDVAL_FASTBUF_SIZE;
  155. o->used = 0;
  156. }
  157. void NCDValMem_Free (NCDValMem *o)
  158. {
  159. free(o->buf);
  160. }
  161. void NCDVal_Assert (NCDValRef val)
  162. {
  163. ASSERT(val.idx == -1 || (NCDVal__AssertVal(val), 1))
  164. }
  165. int NCDVal_IsInvalid (NCDValRef val)
  166. {
  167. NCDVal_Assert(val);
  168. return val.idx < 0;
  169. }
  170. int NCDVal_Type (NCDValRef val)
  171. {
  172. NCDVal__AssertVal(val);
  173. uint8_t *type_ptr = NCDValMem__BufAt(val.mem, val.idx);
  174. return *type_ptr;
  175. }
  176. NCDValRef NCDVal_NewInvalid (void)
  177. {
  178. NCDValRef ref = {NULL, -1};
  179. return ref;
  180. }
  181. NCDValRef NCDVal_NewCopy (NCDValMem *mem, NCDValRef val)
  182. {
  183. NCDVal__AssertMem(mem);
  184. NCDVal__AssertVal(val);
  185. switch (NCDVal_Type(val)) {
  186. case NCDVAL_STRING: {
  187. return NCDVal_NewStringBin(mem, (const uint8_t *)NCDVal_StringValue(val), NCDVal_StringLength(val));
  188. } break;
  189. case NCDVAL_LIST: {
  190. size_t count = NCDVal_ListCount(val);
  191. NCDValRef copy = NCDVal_NewList(mem, count);
  192. if (NCDVal_IsInvalid(copy)) {
  193. goto fail;
  194. }
  195. for (size_t i = 0; i < count; i++) {
  196. NCDValRef elem_copy = NCDVal_NewCopy(mem, NCDVal_ListGet(val, i));
  197. if (NCDVal_IsInvalid(elem_copy)) {
  198. goto fail;
  199. }
  200. NCDVal_ListAppend(copy, elem_copy);
  201. }
  202. return copy;
  203. } break;
  204. case NCDVAL_MAP: {
  205. size_t count = NCDVal_MapCount(val);
  206. NCDValRef copy = NCDVal_NewMap(mem, count);
  207. if (NCDVal_IsInvalid(copy)) {
  208. goto fail;
  209. }
  210. for (NCDValMapElem e = NCDVal_MapFirst(val); !NCDVal_MapElemInvalid(e); e = NCDVal_MapNext(val, e)) {
  211. NCDValRef key_copy = NCDVal_NewCopy(mem, NCDVal_MapElemKey(val, e));
  212. NCDValRef val_copy = NCDVal_NewCopy(mem, NCDVal_MapElemVal(val, e));
  213. if (NCDVal_IsInvalid(key_copy) || NCDVal_IsInvalid(val_copy)) {
  214. goto fail;
  215. }
  216. int res = NCDVal_MapInsert(copy, key_copy, val_copy);
  217. ASSERT(res)
  218. }
  219. return copy;
  220. } break;
  221. default: ASSERT(0);
  222. }
  223. ASSERT(0);
  224. fail:
  225. return NCDVal_NewInvalid();
  226. }
  227. int NCDVal_Compare (NCDValRef val1, NCDValRef val2)
  228. {
  229. NCDVal__AssertVal(val1);
  230. NCDVal__AssertVal(val2);
  231. int type1 = NCDVal_Type(val1);
  232. int type2 = NCDVal_Type(val2);
  233. if (type1 != type2) {
  234. return (type1 > type2) - (type1 < type2);
  235. }
  236. switch (type1) {
  237. case NCDVAL_STRING: {
  238. size_t len1 = NCDVal_StringLength(val1);
  239. size_t len2 = NCDVal_StringLength(val2);
  240. size_t min_len = len1 < len2 ? len1 : len2;
  241. int cmp = memcmp(NCDVal_StringValue(val1), NCDVal_StringValue(val2), min_len);
  242. if (cmp) {
  243. return (cmp > 0) - (cmp < 0);
  244. }
  245. return (len1 > len2) - (len1 < len2);
  246. } break;
  247. case NCDVAL_LIST: {
  248. size_t count1 = NCDVal_ListCount(val1);
  249. size_t count2 = NCDVal_ListCount(val2);
  250. size_t min_count = count1 < count2 ? count1 : count2;
  251. for (size_t i = 0; i < min_count; i++) {
  252. NCDValRef ev1 = NCDVal_ListGet(val1, i);
  253. NCDValRef ev2 = NCDVal_ListGet(val2, i);
  254. int cmp = NCDVal_Compare(ev1, ev2);
  255. if (cmp) {
  256. return cmp;
  257. }
  258. }
  259. return (count1 > count2) - (count1 < count2);
  260. } break;
  261. case NCDVAL_MAP: {
  262. NCDValMapElem e1 = NCDVal_MapFirst(val1);
  263. NCDValMapElem e2 = NCDVal_MapFirst(val2);
  264. while (1) {
  265. int inv1 = NCDVal_MapElemInvalid(e1);
  266. int inv2 = NCDVal_MapElemInvalid(e2);
  267. if (inv1 + inv2 < 2) {
  268. return inv2 - inv1;
  269. }
  270. NCDValRef key1 = NCDVal_MapElemKey(val1, e1);
  271. NCDValRef key2 = NCDVal_MapElemKey(val2, e2);
  272. int cmp = NCDVal_Compare(key1, key2);
  273. if (cmp) {
  274. return cmp;
  275. }
  276. NCDValRef value1 = NCDVal_MapElemVal(val1, e1);
  277. NCDValRef value2 = NCDVal_MapElemVal(val2, e2);
  278. cmp = NCDVal_Compare(value1, value2);
  279. if (cmp) {
  280. return cmp;
  281. }
  282. e1 = NCDVal_MapNext(val1, e1);
  283. e2 = NCDVal_MapNext(val2, e2);
  284. }
  285. } break;
  286. default:
  287. ASSERT(0);
  288. return 0;
  289. }
  290. }
  291. NCDValSafeRef NCDVal_ToSafe (NCDValRef val)
  292. {
  293. NCDVal_Assert(val);
  294. NCDValSafeRef sval = {val.idx};
  295. return sval;
  296. }
  297. NCDValRef NCDVal_FromSafe (NCDValMem *mem, NCDValSafeRef sval)
  298. {
  299. NCDVal__AssertMem(mem);
  300. ASSERT(sval.idx == -1 || (NCDVal__AssertValOnly(mem, sval.idx), 1))
  301. NCDValRef val = {mem, sval.idx};
  302. return val;
  303. }
  304. NCDValRef NCDVal_Moved (NCDValMem *mem, NCDValRef val)
  305. {
  306. NCDVal__AssertMem(mem);
  307. ASSERT(val.idx == -1 || (NCDVal__AssertValOnly(mem, val.idx), 1))
  308. NCDValRef val2 = {mem, val.idx};
  309. return val2;
  310. }
  311. int NCDVal_IsString (NCDValRef val)
  312. {
  313. NCDVal__AssertVal(val);
  314. return NCDVal_Type(val) == NCDVAL_STRING;
  315. }
  316. int NCDVal_IsStringNoNulls (NCDValRef val)
  317. {
  318. NCDVal__AssertVal(val);
  319. return NCDVal_Type(val) == NCDVAL_STRING && strlen(NCDVal_StringValue(val)) == NCDVal_StringLength(val);
  320. }
  321. NCDValRef NCDVal_NewString (NCDValMem *mem, const char *data)
  322. {
  323. NCDVal__AssertMem(mem);
  324. ASSERT(data)
  325. return NCDVal_NewStringBin(mem, (const uint8_t *)data, strlen(data));
  326. }
  327. NCDValRef NCDVal_NewStringBin (NCDValMem *mem, const uint8_t *data, size_t len)
  328. {
  329. NCDVal__AssertMem(mem);
  330. ASSERT(len == 0 || data)
  331. if (len == SIZE_MAX) {
  332. goto fail;
  333. }
  334. bsize_t size = bsize_add(bsize_fromsize(sizeof(struct NCDVal__string)), bsize_fromsize(len + 1));
  335. NCDVal__idx idx = NCDValMem__Alloc(mem, size, __alignof(struct NCDVal__string));
  336. if (idx < 0) {
  337. goto fail;
  338. }
  339. struct NCDVal__string *str_e = NCDValMem__BufAt(mem, idx);
  340. str_e->type = NCDVAL_STRING;
  341. str_e->length = len;
  342. if (len > 0) {
  343. memcpy(str_e->data, data, len);
  344. }
  345. str_e->data[len] = '\0';
  346. return NCDVal__Ref(mem, idx);
  347. fail:
  348. return NCDVal_NewInvalid();
  349. }
  350. const char * NCDVal_StringValue (NCDValRef string)
  351. {
  352. ASSERT(NCDVal_IsString(string))
  353. struct NCDVal__string *str_e = NCDValMem__BufAt(string.mem, string.idx);
  354. return str_e->data;
  355. }
  356. size_t NCDVal_StringLength (NCDValRef string)
  357. {
  358. ASSERT(NCDVal_IsString(string))
  359. struct NCDVal__string *str_e = NCDValMem__BufAt(string.mem, string.idx);
  360. return str_e->length;
  361. }
  362. int NCDVal_StringHasNulls (NCDValRef string)
  363. {
  364. ASSERT(NCDVal_IsString(string))
  365. return strlen(NCDVal_StringValue(string)) != NCDVal_StringLength(string);
  366. }
  367. int NCDVal_StringEquals (NCDValRef string, const char *data)
  368. {
  369. ASSERT(NCDVal_IsString(string))
  370. ASSERT(data)
  371. return !NCDVal_StringHasNulls(string) && !strcmp(NCDVal_StringValue(string), data);
  372. }
  373. int NCDVal_IsList (NCDValRef val)
  374. {
  375. NCDVal__AssertVal(val);
  376. return NCDVal_Type(val) == NCDVAL_LIST;
  377. }
  378. NCDValRef NCDVal_NewList (NCDValMem *mem, size_t maxcount)
  379. {
  380. NCDVal__AssertMem(mem);
  381. bsize_t size = bsize_add(bsize_fromsize(sizeof(struct NCDVal__list)), bsize_mul(bsize_fromsize(maxcount), bsize_fromsize(sizeof(NCDVal__idx))));
  382. NCDVal__idx idx = NCDValMem__Alloc(mem, size, __alignof(struct NCDVal__list));
  383. if (idx < 0) {
  384. goto fail;
  385. }
  386. struct NCDVal__list *list_e = NCDValMem__BufAt(mem, idx);
  387. list_e->type = NCDVAL_LIST;
  388. list_e->maxcount = maxcount;
  389. list_e->count = 0;
  390. return NCDVal__Ref(mem, idx);
  391. fail:
  392. return NCDVal_NewInvalid();
  393. }
  394. void NCDVal_ListAppend (NCDValRef list, NCDValRef elem)
  395. {
  396. ASSERT(NCDVal_IsList(list))
  397. ASSERT(NCDVal_ListCount(list) < NCDVal_ListMaxCount(list))
  398. ASSERT(elem.mem == list.mem)
  399. NCDVal__AssertValOnly(list.mem, elem.idx);
  400. struct NCDVal__list *list_e = NCDValMem__BufAt(list.mem, list.idx);
  401. list_e->elem_indices[list_e->count++] = elem.idx;
  402. }
  403. size_t NCDVal_ListCount (NCDValRef list)
  404. {
  405. ASSERT(NCDVal_IsList(list))
  406. struct NCDVal__list *list_e = NCDValMem__BufAt(list.mem, list.idx);
  407. return list_e->count;
  408. }
  409. size_t NCDVal_ListMaxCount (NCDValRef list)
  410. {
  411. ASSERT(NCDVal_IsList(list))
  412. struct NCDVal__list *list_e = NCDValMem__BufAt(list.mem, list.idx);
  413. return list_e->maxcount;
  414. }
  415. NCDValRef NCDVal_ListGet (NCDValRef list, size_t pos)
  416. {
  417. ASSERT(NCDVal_IsList(list))
  418. ASSERT(pos < NCDVal_ListCount(list))
  419. struct NCDVal__list *list_e = NCDValMem__BufAt(list.mem, list.idx);
  420. ASSERT(pos < list_e->count)
  421. NCDVal__AssertValOnly(list.mem, list_e->elem_indices[pos]);
  422. return NCDVal__Ref(list.mem, list_e->elem_indices[pos]);
  423. }
  424. int NCDVal_ListRead (NCDValRef list, int num, ...)
  425. {
  426. ASSERT(NCDVal_IsList(list))
  427. ASSERT(num >= 0)
  428. size_t count = NCDVal_ListCount(list);
  429. if (num != count) {
  430. return 0;
  431. }
  432. va_list ap;
  433. va_start(ap, num);
  434. for (size_t i = 0; i < num; i++) {
  435. NCDValRef elem = NCDVal_ListGet(list, i);
  436. NCDValRef *dest = va_arg(ap, NCDValRef *);
  437. *dest = elem;
  438. }
  439. va_end(ap);
  440. return 1;
  441. }
  442. int NCDVal_ListReadHead (NCDValRef list, int num, ...)
  443. {
  444. ASSERT(NCDVal_IsList(list))
  445. ASSERT(num >= 0)
  446. size_t count = NCDVal_ListCount(list);
  447. if (num > count) {
  448. return 0;
  449. }
  450. va_list ap;
  451. va_start(ap, num);
  452. for (size_t i = 0; i < num; i++) {
  453. NCDValRef elem = NCDVal_ListGet(list, i);
  454. NCDValRef *dest = va_arg(ap, NCDValRef *);
  455. *dest = elem;
  456. }
  457. va_end(ap);
  458. return 1;
  459. }
  460. int NCDVal_IsMap (NCDValRef val)
  461. {
  462. NCDVal__AssertVal(val);
  463. return NCDVal_Type(val) == NCDVAL_MAP;
  464. }
  465. NCDValRef NCDVal_NewMap (NCDValMem *mem, size_t maxcount)
  466. {
  467. NCDVal__AssertMem(mem);
  468. bsize_t size = bsize_add(bsize_fromsize(sizeof(struct NCDVal__map)), bsize_mul(bsize_fromsize(maxcount), bsize_fromsize(sizeof(struct NCDVal__mapelem))));
  469. NCDVal__idx idx = NCDValMem__Alloc(mem, size, __alignof(struct NCDVal__map));
  470. if (idx < 0) {
  471. goto fail;
  472. }
  473. struct NCDVal__map *map_e = NCDValMem__BufAt(mem, idx);
  474. map_e->type = NCDVAL_MAP;
  475. map_e->maxcount = maxcount;
  476. map_e->count = 0;
  477. NCDVal__MapTree_Init(&map_e->tree);
  478. return NCDVal__Ref(mem, idx);
  479. fail:
  480. return NCDVal_NewInvalid();
  481. }
  482. int NCDVal_MapInsert (NCDValRef map, NCDValRef key, NCDValRef val)
  483. {
  484. ASSERT(NCDVal_IsMap(map))
  485. ASSERT(NCDVal_MapCount(map) < NCDVal_MapMaxCount(map))
  486. ASSERT(key.mem == map.mem)
  487. ASSERT(val.mem == map.mem)
  488. NCDVal__AssertValOnly(map.mem, key.idx);
  489. NCDVal__AssertValOnly(map.mem, val.idx);
  490. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  491. NCDVal__idx elemidx = map.idx + offsetof(struct NCDVal__map, elems) + map_e->count * sizeof(struct NCDVal__mapelem);
  492. struct NCDVal__mapelem *me_e = NCDValMem__BufAt(map.mem, elemidx);
  493. ASSERT(me_e == &map_e->elems[map_e->count])
  494. me_e->key_idx = key.idx;
  495. me_e->val_idx = val.idx;
  496. int res = NCDVal__MapTree_Insert(&map_e->tree, map.mem, NCDVal__MapTree_Deref(map.mem, elemidx), NULL);
  497. if (!res) {
  498. return 0;
  499. }
  500. map_e->count++;
  501. return 1;
  502. }
  503. size_t NCDVal_MapCount (NCDValRef map)
  504. {
  505. ASSERT(NCDVal_IsMap(map))
  506. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  507. return map_e->count;
  508. }
  509. size_t NCDVal_MapMaxCount (NCDValRef map)
  510. {
  511. ASSERT(NCDVal_IsMap(map))
  512. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  513. return map_e->maxcount;
  514. }
  515. int NCDVal_MapElemInvalid (NCDValMapElem me)
  516. {
  517. ASSERT(me.elemidx >= 0 || me.elemidx == -1)
  518. return me.elemidx < 0;
  519. }
  520. NCDValMapElem NCDVal_MapFirst (NCDValRef map)
  521. {
  522. ASSERT(NCDVal_IsMap(map))
  523. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  524. NCDVal__MapTreeNode ref = NCDVal__MapTree_GetFirst(&map_e->tree, map.mem);
  525. return NCDVal__MapElem(ref.link);
  526. }
  527. NCDValMapElem NCDVal_MapNext (NCDValRef map, NCDValMapElem me)
  528. {
  529. NCDVal__MapAssertElem(map, me);
  530. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  531. NCDVal__MapTreeNode ref = NCDVal__MapTree_GetNext(&map_e->tree, map.mem, NCDVal__MapTree_Deref(map.mem, me.elemidx));
  532. return NCDVal__MapElem(ref.link);
  533. }
  534. NCDValRef NCDVal_MapElemKey (NCDValRef map, NCDValMapElem me)
  535. {
  536. NCDVal__MapAssertElem(map, me);
  537. struct NCDVal__mapelem *me_e = NCDValMem__BufAt(map.mem, me.elemidx);
  538. NCDVal__AssertValOnly(map.mem, me_e->key_idx);
  539. NCDVal__AssertValOnly(map.mem, me_e->val_idx);
  540. return NCDVal__Ref(map.mem, me_e->key_idx);
  541. }
  542. NCDValRef NCDVal_MapElemVal (NCDValRef map, NCDValMapElem me)
  543. {
  544. NCDVal__MapAssertElem(map, me);
  545. struct NCDVal__mapelem *me_e = NCDValMem__BufAt(map.mem, me.elemidx);
  546. NCDVal__AssertValOnly(map.mem, me_e->key_idx);
  547. NCDVal__AssertValOnly(map.mem, me_e->val_idx);
  548. return NCDVal__Ref(map.mem, me_e->val_idx);
  549. }
  550. NCDValMapElem NCDVal_MapFindKey (NCDValRef map, NCDValRef key)
  551. {
  552. ASSERT(NCDVal_IsMap(map))
  553. NCDVal__AssertVal(key);
  554. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  555. NCDVal__MapTreeNode ref = NCDVal__MapTree_LookupExact(&map_e->tree, map.mem, key);
  556. return NCDVal__MapElem(ref.link);
  557. }