NCDVal.c 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576
  1. /**
  2. * @file NCDVal.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 <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 <misc/balloc.h>
  36. #include <misc/strdup.h>
  37. #include <misc/offset.h>
  38. #include <base/BLog.h>
  39. #include "NCDVal.h"
  40. #include <generated/blog_channel_NCDVal.h>
  41. //#define NCDVAL_TEST_EXTERNAL_STRINGS
  42. #define TYPE_MASK_EXTERNAL_TYPE ((1 << 3) - 1)
  43. #define TYPE_MASK_INTERNAL_TYPE ((1 << 5) - 1)
  44. #define TYPE_SHIFT_DEPTH 5
  45. #define IDSTRING_TYPE (NCDVAL_STRING | (1 << 3))
  46. #define EXTERNALSTRING_TYPE (NCDVAL_STRING | (2 << 3))
  47. static int make_type (int internal_type, int depth)
  48. {
  49. ASSERT(internal_type == NCDVAL_STRING ||
  50. internal_type == NCDVAL_LIST ||
  51. internal_type == NCDVAL_MAP ||
  52. internal_type == IDSTRING_TYPE ||
  53. internal_type == EXTERNALSTRING_TYPE)
  54. ASSERT(depth >= 0)
  55. ASSERT(depth <= NCDVAL_MAX_DEPTH)
  56. return (internal_type | (depth << TYPE_SHIFT_DEPTH));
  57. }
  58. static int get_external_type (int type)
  59. {
  60. return (type & TYPE_MASK_EXTERNAL_TYPE);
  61. }
  62. static int get_internal_type (int type)
  63. {
  64. return (type & TYPE_MASK_INTERNAL_TYPE);
  65. }
  66. static int get_depth (int type)
  67. {
  68. return (type >> TYPE_SHIFT_DEPTH);
  69. }
  70. static int bump_depth (int *type_ptr, int elem_depth)
  71. {
  72. if (get_depth(*type_ptr) < elem_depth + 1) {
  73. if (elem_depth + 1 > NCDVAL_MAX_DEPTH) {
  74. return 0;
  75. }
  76. *type_ptr = make_type(get_internal_type(*type_ptr), elem_depth + 1);
  77. }
  78. return 1;
  79. }
  80. static void * NCDValMem__BufAt (NCDValMem *o, NCDVal__idx idx)
  81. {
  82. ASSERT(idx >= 0)
  83. ASSERT(idx < o->used)
  84. return (o->buf ? o->buf : o->fastbuf) + idx;
  85. }
  86. static NCDVal__idx NCDValMem__Alloc (NCDValMem *o, bsize_t alloc_size, NCDVal__idx align)
  87. {
  88. if (alloc_size.is_overflow) {
  89. return -1;
  90. }
  91. NCDVal__idx mod = o->used % align;
  92. NCDVal__idx align_extra = mod ? (align - mod) : 0;
  93. if (alloc_size.value > NCDVAL_MAXIDX - align_extra) {
  94. return -1;
  95. }
  96. NCDVal__idx aligned_alloc_size = align_extra + alloc_size.value;
  97. if (aligned_alloc_size > o->size - o->used) {
  98. NCDVal__idx newsize = (o->buf ? o->size : NCDVAL_FIRST_SIZE);
  99. while (aligned_alloc_size > newsize - o->used) {
  100. if (newsize > NCDVAL_MAXIDX / 2) {
  101. return -1;
  102. }
  103. newsize *= 2;
  104. }
  105. char *newbuf;
  106. if (!o->buf) {
  107. newbuf = malloc(newsize);
  108. if (!newbuf) {
  109. return -1;
  110. }
  111. memcpy(newbuf, o->fastbuf, o->used);
  112. } else {
  113. newbuf = realloc(o->buf, newsize);
  114. if (!newbuf) {
  115. return -1;
  116. }
  117. }
  118. o->buf = newbuf;
  119. o->size = newsize;
  120. }
  121. NCDVal__idx idx = o->used + align_extra;
  122. o->used += aligned_alloc_size;
  123. return idx;
  124. }
  125. static NCDValRef NCDVal__Ref (NCDValMem *mem, NCDVal__idx idx)
  126. {
  127. ASSERT(idx == -1 || mem)
  128. NCDValRef ref = {mem, idx};
  129. return ref;
  130. }
  131. static void NCDVal__AssertMem (NCDValMem *mem)
  132. {
  133. ASSERT(mem)
  134. ASSERT(mem->size >= 0)
  135. ASSERT(mem->used >= 0)
  136. ASSERT(mem->used <= mem->size)
  137. ASSERT(mem->buf || mem->size == NCDVAL_FASTBUF_SIZE)
  138. ASSERT(!mem->buf || mem->size >= NCDVAL_FIRST_SIZE)
  139. }
  140. static void NCDVal_AssertExternal (NCDValMem *mem, const void *e_buf, size_t e_len)
  141. {
  142. #ifndef NDEBUG
  143. const char *e_cbuf = e_buf;
  144. char *buf = (mem->buf ? mem->buf : mem->fastbuf);
  145. ASSERT(e_cbuf >= buf + mem->size || e_cbuf + e_len <= buf)
  146. #endif
  147. }
  148. static void NCDVal__AssertValOnly (NCDValMem *mem, NCDVal__idx idx)
  149. {
  150. // placeholders
  151. if (idx < -1) {
  152. return;
  153. }
  154. ASSERT(idx >= 0)
  155. ASSERT(idx + sizeof(int) <= mem->used)
  156. #ifndef NDEBUG
  157. int *type_ptr = NCDValMem__BufAt(mem, idx);
  158. ASSERT(get_depth(*type_ptr) >= 0)
  159. ASSERT(get_depth(*type_ptr) <= NCDVAL_MAX_DEPTH)
  160. switch (get_internal_type(*type_ptr)) {
  161. case NCDVAL_STRING: {
  162. ASSERT(idx + sizeof(struct NCDVal__string) <= mem->used)
  163. struct NCDVal__string *str_e = NCDValMem__BufAt(mem, idx);
  164. ASSERT(str_e->length >= 0)
  165. ASSERT(idx + sizeof(struct NCDVal__string) + str_e->length + 1 <= mem->used)
  166. } break;
  167. case NCDVAL_LIST: {
  168. ASSERT(idx + sizeof(struct NCDVal__list) <= mem->used)
  169. struct NCDVal__list *list_e = NCDValMem__BufAt(mem, idx);
  170. ASSERT(list_e->maxcount >= 0)
  171. ASSERT(list_e->count >= 0)
  172. ASSERT(list_e->count <= list_e->maxcount)
  173. ASSERT(idx + sizeof(struct NCDVal__list) + list_e->maxcount * sizeof(NCDVal__idx) <= mem->used)
  174. } break;
  175. case NCDVAL_MAP: {
  176. ASSERT(idx + sizeof(struct NCDVal__map) <= mem->used)
  177. struct NCDVal__map *map_e = NCDValMem__BufAt(mem, idx);
  178. ASSERT(map_e->maxcount >= 0)
  179. ASSERT(map_e->count >= 0)
  180. ASSERT(map_e->count <= map_e->maxcount)
  181. ASSERT(idx + sizeof(struct NCDVal__map) + map_e->maxcount * sizeof(struct NCDVal__mapelem) <= mem->used)
  182. } break;
  183. case IDSTRING_TYPE: {
  184. ASSERT(idx + sizeof(struct NCDVal__idstring) <= mem->used)
  185. struct NCDVal__idstring *ids_e = NCDValMem__BufAt(mem, idx);
  186. ASSERT(ids_e->string_id >= 0)
  187. ASSERT(ids_e->string_index)
  188. } break;
  189. case EXTERNALSTRING_TYPE: {
  190. ASSERT(idx + sizeof(struct NCDVal__externalstring) <= mem->used)
  191. struct NCDVal__externalstring *exs_e = NCDValMem__BufAt(mem, idx);
  192. ASSERT(exs_e->data)
  193. ASSERT(!exs_e->ref.target || exs_e->ref.next >= -1)
  194. ASSERT(!exs_e->ref.target || exs_e->ref.next < mem->used)
  195. } break;
  196. default: ASSERT(0);
  197. }
  198. #endif
  199. }
  200. static void NCDVal__AssertVal (NCDValRef val)
  201. {
  202. NCDVal__AssertMem(val.mem);
  203. NCDVal__AssertValOnly(val.mem, val.idx);
  204. }
  205. static NCDValMapElem NCDVal__MapElem (NCDVal__idx elemidx)
  206. {
  207. ASSERT(elemidx >= 0 || elemidx == -1)
  208. NCDValMapElem me = {elemidx};
  209. return me;
  210. }
  211. static void NCDVal__MapAssertElemOnly (NCDValRef map, NCDVal__idx elemidx)
  212. {
  213. #ifndef NDEBUG
  214. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  215. ASSERT(elemidx >= map.idx + offsetof(struct NCDVal__map, elems))
  216. ASSERT(elemidx < map.idx + offsetof(struct NCDVal__map, elems) + map_e->count * sizeof(struct NCDVal__mapelem))
  217. struct NCDVal__mapelem *me_e = NCDValMem__BufAt(map.mem, elemidx);
  218. NCDVal__AssertValOnly(map.mem, me_e->key_idx);
  219. NCDVal__AssertValOnly(map.mem, me_e->val_idx);
  220. #endif
  221. }
  222. static void NCDVal__MapAssertElem (NCDValRef map, NCDValMapElem me)
  223. {
  224. ASSERT(NCDVal_IsMap(map))
  225. NCDVal__MapAssertElemOnly(map, me.elemidx);
  226. }
  227. static NCDVal__idx NCDVal__MapElemIdx (NCDVal__idx mapidx, NCDVal__idx pos)
  228. {
  229. return mapidx + offsetof(struct NCDVal__map, elems) + pos * sizeof(struct NCDVal__mapelem);
  230. }
  231. static int NCDVal__Depth (NCDValRef val)
  232. {
  233. ASSERT(val.idx != -1)
  234. // handle placeholders
  235. if (val.idx < 0) {
  236. return 0;
  237. }
  238. int *elem_type_ptr = NCDValMem__BufAt(val.mem, val.idx);
  239. int depth = get_depth(*elem_type_ptr);
  240. ASSERT(depth >= 0)
  241. ASSERT(depth <= NCDVAL_MAX_DEPTH)
  242. return depth;
  243. }
  244. #include "NCDVal_maptree.h"
  245. #include <structure/CAvl_impl.h>
  246. void NCDValMem_Init (NCDValMem *o)
  247. {
  248. o->buf = NULL;
  249. o->size = NCDVAL_FASTBUF_SIZE;
  250. o->used = 0;
  251. o->first_ref = -1;
  252. }
  253. void NCDValMem_Free (NCDValMem *o)
  254. {
  255. NCDVal__AssertMem(o);
  256. NCDVal__idx refidx = o->first_ref;
  257. while (refidx != -1) {
  258. struct NCDVal__ref *ref = NCDValMem__BufAt(o, refidx);
  259. ASSERT(ref->target)
  260. NCDRefTarget_Deref(ref->target);
  261. refidx = ref->next;
  262. }
  263. if (o->buf) {
  264. BFree(o->buf);
  265. }
  266. }
  267. int NCDValMem_InitCopy (NCDValMem *o, NCDValMem *other)
  268. {
  269. NCDVal__AssertMem(other);
  270. o->size = other->size;
  271. o->used = other->used;
  272. o->first_ref = other->first_ref;
  273. if (!other->buf) {
  274. o->buf = NULL;
  275. memcpy(o->fastbuf, other->fastbuf, other->used);
  276. } else {
  277. o->buf = BAlloc(other->size);
  278. if (!o->buf) {
  279. goto fail0;
  280. }
  281. memcpy(o->buf, other->buf, other->used);
  282. }
  283. NCDVal__idx refidx = o->first_ref;
  284. while (refidx != -1) {
  285. struct NCDVal__ref *ref = NCDValMem__BufAt(o, refidx);
  286. ASSERT(ref->target)
  287. if (!NCDRefTarget_Ref(ref->target)) {
  288. goto fail1;
  289. }
  290. refidx = ref->next;
  291. }
  292. return 1;
  293. fail1:;
  294. NCDVal__idx undo_refidx = o->first_ref;
  295. while (undo_refidx != refidx) {
  296. struct NCDVal__ref *ref = NCDValMem__BufAt(o, undo_refidx);
  297. NCDRefTarget_Deref(ref->target);
  298. undo_refidx = ref->next;
  299. }
  300. if (o->buf) {
  301. BFree(o->buf);
  302. }
  303. fail0:
  304. return 0;
  305. }
  306. void NCDVal_Assert (NCDValRef val)
  307. {
  308. ASSERT(val.idx == -1 || (NCDVal__AssertVal(val), 1))
  309. }
  310. int NCDVal_IsInvalid (NCDValRef val)
  311. {
  312. NCDVal_Assert(val);
  313. return (val.idx == -1);
  314. }
  315. int NCDVal_IsPlaceholder (NCDValRef val)
  316. {
  317. NCDVal_Assert(val);
  318. return (val.idx < -1);
  319. }
  320. int NCDVal_Type (NCDValRef val)
  321. {
  322. NCDVal__AssertVal(val);
  323. if (val.idx < -1) {
  324. return NCDVAL_PLACEHOLDER;
  325. }
  326. int *type_ptr = NCDValMem__BufAt(val.mem, val.idx);
  327. return get_external_type(*type_ptr);
  328. }
  329. NCDValRef NCDVal_NewInvalid (void)
  330. {
  331. NCDValRef ref = {NULL, -1};
  332. return ref;
  333. }
  334. NCDValRef NCDVal_NewPlaceholder (NCDValMem *mem, int plid)
  335. {
  336. NCDVal__AssertMem(mem);
  337. ASSERT(plid >= 0)
  338. ASSERT(NCDVAL_MINIDX + plid < -1)
  339. NCDValRef ref = {mem, NCDVAL_MINIDX + plid};
  340. return ref;
  341. }
  342. int NCDVal_PlaceholderId (NCDValRef val)
  343. {
  344. ASSERT(NCDVal_IsPlaceholder(val))
  345. return (val.idx - NCDVAL_MINIDX);
  346. }
  347. NCDValRef NCDVal_NewCopy (NCDValMem *mem, NCDValRef val)
  348. {
  349. NCDVal__AssertMem(mem);
  350. NCDVal__AssertVal(val);
  351. if (val.idx < -1) {
  352. return NCDVal_NewPlaceholder(mem, NCDVal_PlaceholderId(val));
  353. }
  354. void *ptr = NCDValMem__BufAt(val.mem, val.idx);
  355. switch (get_internal_type(*(int *)ptr)) {
  356. case NCDVAL_STRING: {
  357. size_t len = NCDVal_StringLength(val);
  358. NCDValRef copy = NCDVal_NewStringUninitialized(mem, len);
  359. if (NCDVal_IsInvalid(copy)) {
  360. goto fail;
  361. }
  362. memcpy((char *)NCDVal_StringData(copy), NCDVal_StringData(val), len);
  363. return copy;
  364. } break;
  365. case NCDVAL_LIST: {
  366. size_t count = NCDVal_ListCount(val);
  367. NCDValRef copy = NCDVal_NewList(mem, count);
  368. if (NCDVal_IsInvalid(copy)) {
  369. goto fail;
  370. }
  371. for (size_t i = 0; i < count; i++) {
  372. NCDValRef elem_copy = NCDVal_NewCopy(mem, NCDVal_ListGet(val, i));
  373. if (NCDVal_IsInvalid(elem_copy)) {
  374. goto fail;
  375. }
  376. if (!NCDVal_ListAppend(copy, elem_copy)) {
  377. goto fail;
  378. }
  379. }
  380. return copy;
  381. } break;
  382. case NCDVAL_MAP: {
  383. size_t count = NCDVal_MapCount(val);
  384. NCDValRef copy = NCDVal_NewMap(mem, count);
  385. if (NCDVal_IsInvalid(copy)) {
  386. goto fail;
  387. }
  388. for (NCDValMapElem e = NCDVal_MapFirst(val); !NCDVal_MapElemInvalid(e); e = NCDVal_MapNext(val, e)) {
  389. NCDValRef key_copy = NCDVal_NewCopy(mem, NCDVal_MapElemKey(val, e));
  390. NCDValRef val_copy = NCDVal_NewCopy(mem, NCDVal_MapElemVal(val, e));
  391. if (NCDVal_IsInvalid(key_copy) || NCDVal_IsInvalid(val_copy)) {
  392. goto fail;
  393. }
  394. int inserted;
  395. if (!NCDVal_MapInsert(copy, key_copy, val_copy, &inserted)) {
  396. goto fail;
  397. }
  398. ASSERT_EXECUTE(inserted)
  399. }
  400. return copy;
  401. } break;
  402. case IDSTRING_TYPE: {
  403. struct NCDVal__idstring *ids_e = ptr;
  404. return NCDVal_NewIdString(mem, ids_e->string_id, ids_e->string_index);
  405. } break;
  406. case EXTERNALSTRING_TYPE: {
  407. struct NCDVal__externalstring *exs_e = ptr;
  408. return NCDVal_NewExternalString(mem, exs_e->data, exs_e->length, exs_e->ref.target);
  409. } break;
  410. default: ASSERT(0);
  411. }
  412. ASSERT(0);
  413. fail:
  414. return NCDVal_NewInvalid();
  415. }
  416. int NCDVal_Compare (NCDValRef val1, NCDValRef val2)
  417. {
  418. NCDVal__AssertVal(val1);
  419. NCDVal__AssertVal(val2);
  420. int type1 = NCDVal_Type(val1);
  421. int type2 = NCDVal_Type(val2);
  422. if (type1 != type2) {
  423. return (type1 > type2) - (type1 < type2);
  424. }
  425. switch (type1) {
  426. case NCDVAL_STRING: {
  427. size_t len1 = NCDVal_StringLength(val1);
  428. size_t len2 = NCDVal_StringLength(val2);
  429. size_t min_len = len1 < len2 ? len1 : len2;
  430. int cmp = memcmp(NCDVal_StringData(val1), NCDVal_StringData(val2), min_len);
  431. if (cmp) {
  432. return (cmp > 0) - (cmp < 0);
  433. }
  434. return (len1 > len2) - (len1 < len2);
  435. } break;
  436. case NCDVAL_LIST: {
  437. size_t count1 = NCDVal_ListCount(val1);
  438. size_t count2 = NCDVal_ListCount(val2);
  439. size_t min_count = count1 < count2 ? count1 : count2;
  440. for (size_t i = 0; i < min_count; i++) {
  441. NCDValRef ev1 = NCDVal_ListGet(val1, i);
  442. NCDValRef ev2 = NCDVal_ListGet(val2, i);
  443. int cmp = NCDVal_Compare(ev1, ev2);
  444. if (cmp) {
  445. return cmp;
  446. }
  447. }
  448. return (count1 > count2) - (count1 < count2);
  449. } break;
  450. case NCDVAL_MAP: {
  451. NCDValMapElem e1 = NCDVal_MapOrderedFirst(val1);
  452. NCDValMapElem e2 = NCDVal_MapOrderedFirst(val2);
  453. while (1) {
  454. int inv1 = NCDVal_MapElemInvalid(e1);
  455. int inv2 = NCDVal_MapElemInvalid(e2);
  456. if (inv1 || inv2) {
  457. return inv2 - inv1;
  458. }
  459. NCDValRef key1 = NCDVal_MapElemKey(val1, e1);
  460. NCDValRef key2 = NCDVal_MapElemKey(val2, e2);
  461. int cmp = NCDVal_Compare(key1, key2);
  462. if (cmp) {
  463. return cmp;
  464. }
  465. NCDValRef value1 = NCDVal_MapElemVal(val1, e1);
  466. NCDValRef value2 = NCDVal_MapElemVal(val2, e2);
  467. cmp = NCDVal_Compare(value1, value2);
  468. if (cmp) {
  469. return cmp;
  470. }
  471. e1 = NCDVal_MapOrderedNext(val1, e1);
  472. e2 = NCDVal_MapOrderedNext(val2, e2);
  473. }
  474. } break;
  475. case NCDVAL_PLACEHOLDER: {
  476. int plid1 = NCDVal_PlaceholderId(val1);
  477. int plid2 = NCDVal_PlaceholderId(val2);
  478. return (plid1 > plid2) - (plid1 < plid2);
  479. } break;
  480. default:
  481. ASSERT(0);
  482. return 0;
  483. }
  484. }
  485. NCDValSafeRef NCDVal_ToSafe (NCDValRef val)
  486. {
  487. NCDVal_Assert(val);
  488. NCDValSafeRef sval = {val.idx};
  489. return sval;
  490. }
  491. NCDValRef NCDVal_FromSafe (NCDValMem *mem, NCDValSafeRef sval)
  492. {
  493. NCDVal__AssertMem(mem);
  494. ASSERT(sval.idx == -1 || (NCDVal__AssertValOnly(mem, sval.idx), 1))
  495. NCDValRef val = {mem, sval.idx};
  496. return val;
  497. }
  498. NCDValRef NCDVal_Moved (NCDValMem *mem, NCDValRef val)
  499. {
  500. NCDVal__AssertMem(mem);
  501. ASSERT(val.idx == -1 || (NCDVal__AssertValOnly(mem, val.idx), 1))
  502. NCDValRef val2 = {mem, val.idx};
  503. return val2;
  504. }
  505. int NCDVal_IsString (NCDValRef val)
  506. {
  507. NCDVal__AssertVal(val);
  508. return NCDVal_Type(val) == NCDVAL_STRING;
  509. }
  510. int NCDVal_IsIdString (NCDValRef val)
  511. {
  512. NCDVal__AssertVal(val);
  513. return !(val.idx < -1) && get_internal_type(*(int *)NCDValMem__BufAt(val.mem, val.idx)) == IDSTRING_TYPE;
  514. }
  515. int NCDVal_IsExternalString (NCDValRef val)
  516. {
  517. NCDVal__AssertVal(val);
  518. return !(val.idx < -1) && get_internal_type(*(int *)NCDValMem__BufAt(val.mem, val.idx)) == EXTERNALSTRING_TYPE;
  519. }
  520. int NCDVal_IsStringNoNulls (NCDValRef val)
  521. {
  522. NCDVal__AssertVal(val);
  523. return NCDVal_Type(val) == NCDVAL_STRING && !NCDVal_StringHasNulls(val);
  524. }
  525. NCDValRef NCDVal_NewString (NCDValMem *mem, const char *data)
  526. {
  527. NCDVal__AssertMem(mem);
  528. ASSERT(data)
  529. NCDVal_AssertExternal(mem, data, strlen(data));
  530. return NCDVal_NewStringBin(mem, (const uint8_t *)data, strlen(data));
  531. }
  532. #ifdef NCDVAL_TEST_EXTERNAL_STRINGS
  533. struct test_ext_str {
  534. NCDRefTarget ref_target;
  535. char *data;
  536. };
  537. static void test_ext_str_ref_target_func_dealloc (NCDRefTarget *ref_target)
  538. {
  539. struct test_ext_str *tes = UPPER_OBJECT(ref_target, struct test_ext_str, ref_target);
  540. BFree(tes->data);
  541. BFree(tes);
  542. }
  543. NCDValRef NCDVal_NewStringBin (NCDValMem *mem, const uint8_t *data, size_t len)
  544. {
  545. NCDVal__AssertMem(mem);
  546. ASSERT(len == 0 || data)
  547. NCDVal_AssertExternal(mem, data, len);
  548. struct test_ext_str *tes = BAlloc(sizeof(*tes));
  549. if (!tes) {
  550. goto fail0;
  551. }
  552. tes->data = BAlloc(len);
  553. if (!tes->data) {
  554. goto fail1;
  555. }
  556. if (len > 0) {
  557. memcpy(tes->data, data, len);
  558. }
  559. NCDRefTarget_Init(&tes->ref_target, test_ext_str_ref_target_func_dealloc);
  560. NCDValRef res = NCDVal_NewExternalString(mem, tes->data, len, &tes->ref_target);
  561. NCDRefTarget_Deref(&tes->ref_target);
  562. return res;
  563. fail1:
  564. BFree(tes);
  565. fail0:
  566. return NCDVal_NewInvalid();
  567. }
  568. #endif
  569. #ifndef NCDVAL_TEST_EXTERNAL_STRINGS
  570. NCDValRef NCDVal_NewStringBin (NCDValMem *mem, const uint8_t *data, size_t len)
  571. {
  572. NCDVal__AssertMem(mem);
  573. ASSERT(len == 0 || data)
  574. NCDVal_AssertExternal(mem, data, len);
  575. if (len == SIZE_MAX) {
  576. goto fail;
  577. }
  578. bsize_t size = bsize_add(bsize_fromsize(sizeof(struct NCDVal__string)), bsize_fromsize(len + 1));
  579. NCDVal__idx idx = NCDValMem__Alloc(mem, size, __alignof(struct NCDVal__string));
  580. if (idx < 0) {
  581. goto fail;
  582. }
  583. struct NCDVal__string *str_e = NCDValMem__BufAt(mem, idx);
  584. str_e->type = make_type(NCDVAL_STRING, 0);
  585. str_e->length = len;
  586. if (len > 0) {
  587. memcpy(str_e->data, data, len);
  588. }
  589. str_e->data[len] = '\0';
  590. return NCDVal__Ref(mem, idx);
  591. fail:
  592. return NCDVal_NewInvalid();
  593. }
  594. #endif
  595. NCDValRef NCDVal_NewStringUninitialized (NCDValMem *mem, size_t len)
  596. {
  597. NCDVal__AssertMem(mem);
  598. if (len == SIZE_MAX) {
  599. goto fail;
  600. }
  601. bsize_t size = bsize_add(bsize_fromsize(sizeof(struct NCDVal__string)), bsize_fromsize(len + 1));
  602. NCDVal__idx idx = NCDValMem__Alloc(mem, size, __alignof(struct NCDVal__string));
  603. if (idx < 0) {
  604. goto fail;
  605. }
  606. struct NCDVal__string *str_e = NCDValMem__BufAt(mem, idx);
  607. str_e->type = make_type(NCDVAL_STRING, 0);
  608. str_e->length = len;
  609. str_e->data[len] = '\0';
  610. return NCDVal__Ref(mem, idx);
  611. fail:
  612. return NCDVal_NewInvalid();
  613. }
  614. NCDValRef NCDVal_NewIdString (NCDValMem *mem, NCD_string_id_t string_id, NCDStringIndex *string_index)
  615. {
  616. NCDVal__AssertMem(mem);
  617. ASSERT(string_id >= 0)
  618. ASSERT(string_index)
  619. bsize_t size = bsize_fromsize(sizeof(struct NCDVal__idstring));
  620. NCDVal__idx idx = NCDValMem__Alloc(mem, size, __alignof(struct NCDVal__idstring));
  621. if (idx < 0) {
  622. goto fail;
  623. }
  624. struct NCDVal__idstring *ids_e = NCDValMem__BufAt(mem, idx);
  625. ids_e->type = make_type(IDSTRING_TYPE, 0);
  626. ids_e->string_id = string_id;
  627. ids_e->string_index = string_index;
  628. return NCDVal__Ref(mem, idx);
  629. fail:
  630. return NCDVal_NewInvalid();
  631. }
  632. NCDValRef NCDVal_NewExternalString (NCDValMem *mem, const char *data, size_t len,
  633. NCDRefTarget *ref_target)
  634. {
  635. NCDVal__AssertMem(mem);
  636. ASSERT(data)
  637. NCDVal_AssertExternal(mem, data, len);
  638. bsize_t size = bsize_fromsize(sizeof(struct NCDVal__externalstring));
  639. NCDVal__idx idx = NCDValMem__Alloc(mem, size, __alignof(struct NCDVal__externalstring));
  640. if (idx < 0) {
  641. goto fail;
  642. }
  643. if (ref_target) {
  644. if (!NCDRefTarget_Ref(ref_target)) {
  645. goto fail;
  646. }
  647. }
  648. struct NCDVal__externalstring *exs_e = NCDValMem__BufAt(mem, idx);
  649. exs_e->type = make_type(EXTERNALSTRING_TYPE, 0);
  650. exs_e->data = data;
  651. exs_e->length = len;
  652. exs_e->ref.target = ref_target;
  653. if (ref_target) {
  654. exs_e->ref.next = mem->first_ref;
  655. mem->first_ref = idx + offsetof(struct NCDVal__externalstring, ref);
  656. }
  657. return NCDVal__Ref(mem, idx);
  658. fail:
  659. return NCDVal_NewInvalid();
  660. }
  661. const char * NCDVal_StringData (NCDValRef string)
  662. {
  663. ASSERT(NCDVal_IsString(string))
  664. void *ptr = NCDValMem__BufAt(string.mem, string.idx);
  665. switch (get_internal_type(*(int *)ptr)) {
  666. case IDSTRING_TYPE: {
  667. struct NCDVal__idstring *ids_e = ptr;
  668. const char *value = NCDStringIndex_Value(ids_e->string_index, ids_e->string_id);
  669. return value;
  670. } break;
  671. case EXTERNALSTRING_TYPE: {
  672. struct NCDVal__externalstring *exs_e = ptr;
  673. return exs_e->data;
  674. } break;
  675. }
  676. struct NCDVal__string *str_e = ptr;
  677. return str_e->data;
  678. }
  679. size_t NCDVal_StringLength (NCDValRef string)
  680. {
  681. ASSERT(NCDVal_IsString(string))
  682. void *ptr = NCDValMem__BufAt(string.mem, string.idx);
  683. switch (get_internal_type(*(int *)ptr)) {
  684. case IDSTRING_TYPE: {
  685. struct NCDVal__idstring *ids_e = ptr;
  686. return NCDStringIndex_Length(ids_e->string_index, ids_e->string_id);
  687. } break;
  688. case EXTERNALSTRING_TYPE: {
  689. struct NCDVal__externalstring *exs_e = ptr;
  690. return exs_e->length;
  691. } break;
  692. }
  693. struct NCDVal__string *str_e = ptr;;
  694. return str_e->length;
  695. }
  696. int NCDVal_StringNullTerminate (NCDValRef string, NCDValNullTermString *out)
  697. {
  698. ASSERT(NCDVal_IsString(string))
  699. ASSERT(out)
  700. void *ptr = NCDValMem__BufAt(string.mem, string.idx);
  701. switch (get_internal_type(*(int *)ptr)) {
  702. case IDSTRING_TYPE: {
  703. struct NCDVal__idstring *ids_e = ptr;
  704. out->data = (char *)NCDStringIndex_Value(ids_e->string_index, ids_e->string_id);
  705. out->is_allocated = 0;
  706. return 1;
  707. } break;
  708. case EXTERNALSTRING_TYPE: {
  709. struct NCDVal__externalstring *exs_e = ptr;
  710. char *copy = b_strdup_bin(exs_e->data, exs_e->length);
  711. if (!copy) {
  712. return 0;
  713. }
  714. out->data = copy;
  715. out->is_allocated = 1;
  716. return 1;
  717. } break;
  718. }
  719. struct NCDVal__string *str_e = ptr;
  720. out->data = str_e->data;
  721. out->is_allocated = 0;
  722. return 1;
  723. }
  724. NCDValNullTermString NCDValNullTermString_NewDummy (void)
  725. {
  726. NCDValNullTermString nts;
  727. nts.data = NULL;
  728. nts.is_allocated = 0;
  729. return nts;
  730. }
  731. void NCDValNullTermString_Free (NCDValNullTermString *o)
  732. {
  733. if (o->is_allocated) {
  734. BFree(o->data);
  735. }
  736. }
  737. void NCDVal_IdStringGet (NCDValRef idstring, NCD_string_id_t *out_string_id,
  738. NCDStringIndex **out_string_index)
  739. {
  740. ASSERT(NCDVal_IsIdString(idstring))
  741. ASSERT(out_string_id)
  742. ASSERT(out_string_index)
  743. struct NCDVal__idstring *ids_e = NCDValMem__BufAt(idstring.mem, idstring.idx);
  744. *out_string_id = ids_e->string_id;
  745. *out_string_index = ids_e->string_index;
  746. }
  747. NCD_string_id_t NCDVal_IdStringId (NCDValRef idstring)
  748. {
  749. ASSERT(NCDVal_IsIdString(idstring))
  750. struct NCDVal__idstring *ids_e = NCDValMem__BufAt(idstring.mem, idstring.idx);
  751. return ids_e->string_id;
  752. }
  753. NCDStringIndex * NCDVal_IdStringStringIndex (NCDValRef idstring)
  754. {
  755. ASSERT(NCDVal_IsIdString(idstring))
  756. struct NCDVal__idstring *ids_e = NCDValMem__BufAt(idstring.mem, idstring.idx);
  757. return ids_e->string_index;
  758. }
  759. NCDRefTarget * NCDVal_ExternalStringTarget (NCDValRef externalstring)
  760. {
  761. ASSERT(NCDVal_IsExternalString(externalstring))
  762. struct NCDVal__externalstring *exs_e = NCDValMem__BufAt(externalstring.mem, externalstring.idx);
  763. return exs_e->ref.target;
  764. }
  765. int NCDVal_StringHasNulls (NCDValRef string)
  766. {
  767. ASSERT(NCDVal_IsString(string))
  768. void *ptr = NCDValMem__BufAt(string.mem, string.idx);
  769. switch (get_internal_type(*(int *)ptr)) {
  770. case IDSTRING_TYPE: {
  771. struct NCDVal__idstring *ids_e = ptr;
  772. return NCDStringIndex_HasNulls(ids_e->string_index, ids_e->string_id);
  773. } break;
  774. default: {
  775. const char *data = NCDVal_StringData(string);
  776. size_t length = NCDVal_StringLength(string);
  777. return !!memchr(data, '\0', length);
  778. } break;
  779. }
  780. }
  781. int NCDVal_StringEquals (NCDValRef string, const char *data)
  782. {
  783. ASSERT(NCDVal_IsString(string))
  784. ASSERT(data)
  785. size_t len = strlen(data);
  786. return NCDVal_StringLength(string) == len && !memcmp(NCDVal_StringData(string), data, len);
  787. }
  788. int NCDVal_StringEqualsId (NCDValRef string, NCD_string_id_t string_id,
  789. NCDStringIndex *string_index)
  790. {
  791. ASSERT(NCDVal_IsString(string))
  792. ASSERT(string_id >= 0)
  793. ASSERT(string_index)
  794. void *ptr = NCDValMem__BufAt(string.mem, string.idx);
  795. switch (get_internal_type(*(int *)ptr)) {
  796. case IDSTRING_TYPE: {
  797. struct NCDVal__idstring *ids_e = ptr;
  798. ASSERT(ids_e->string_index == string_index)
  799. return ids_e->string_id == string_id;
  800. } break;
  801. case EXTERNALSTRING_TYPE: {
  802. struct NCDVal__externalstring *exs_e = ptr;
  803. const char *string_data = NCDStringIndex_Value(string_index, string_id);
  804. size_t string_length = NCDStringIndex_Length(string_index, string_id);
  805. return (string_length == exs_e->length) && !memcmp(string_data, exs_e->data, string_length);
  806. } break;
  807. }
  808. struct NCDVal__string *str_e = ptr;
  809. const char *string_data = NCDStringIndex_Value(string_index, string_id);
  810. size_t string_length = NCDStringIndex_Length(string_index, string_id);
  811. return (string_length == str_e->length) && !memcmp(string_data, str_e->data, string_length);
  812. }
  813. int NCDVal_IsList (NCDValRef val)
  814. {
  815. NCDVal__AssertVal(val);
  816. return NCDVal_Type(val) == NCDVAL_LIST;
  817. }
  818. NCDValRef NCDVal_NewList (NCDValMem *mem, size_t maxcount)
  819. {
  820. NCDVal__AssertMem(mem);
  821. bsize_t size = bsize_add(bsize_fromsize(sizeof(struct NCDVal__list)), bsize_mul(bsize_fromsize(maxcount), bsize_fromsize(sizeof(NCDVal__idx))));
  822. NCDVal__idx idx = NCDValMem__Alloc(mem, size, __alignof(struct NCDVal__list));
  823. if (idx < 0) {
  824. goto fail;
  825. }
  826. struct NCDVal__list *list_e = NCDValMem__BufAt(mem, idx);
  827. list_e->type = make_type(NCDVAL_LIST, 0);
  828. list_e->maxcount = maxcount;
  829. list_e->count = 0;
  830. return NCDVal__Ref(mem, idx);
  831. fail:
  832. return NCDVal_NewInvalid();
  833. }
  834. int NCDVal_ListAppend (NCDValRef list, NCDValRef elem)
  835. {
  836. ASSERT(NCDVal_IsList(list))
  837. ASSERT(NCDVal_ListCount(list) < NCDVal_ListMaxCount(list))
  838. ASSERT(elem.mem == list.mem)
  839. NCDVal__AssertValOnly(list.mem, elem.idx);
  840. struct NCDVal__list *list_e = NCDValMem__BufAt(list.mem, list.idx);
  841. if (!bump_depth(&list_e->type, NCDVal__Depth(elem))) {
  842. return 0;
  843. }
  844. list_e->elem_indices[list_e->count++] = elem.idx;
  845. return 1;
  846. }
  847. size_t NCDVal_ListCount (NCDValRef list)
  848. {
  849. ASSERT(NCDVal_IsList(list))
  850. struct NCDVal__list *list_e = NCDValMem__BufAt(list.mem, list.idx);
  851. return list_e->count;
  852. }
  853. size_t NCDVal_ListMaxCount (NCDValRef list)
  854. {
  855. ASSERT(NCDVal_IsList(list))
  856. struct NCDVal__list *list_e = NCDValMem__BufAt(list.mem, list.idx);
  857. return list_e->maxcount;
  858. }
  859. NCDValRef NCDVal_ListGet (NCDValRef list, size_t pos)
  860. {
  861. ASSERT(NCDVal_IsList(list))
  862. ASSERT(pos < NCDVal_ListCount(list))
  863. struct NCDVal__list *list_e = NCDValMem__BufAt(list.mem, list.idx);
  864. ASSERT(pos < list_e->count)
  865. NCDVal__AssertValOnly(list.mem, list_e->elem_indices[pos]);
  866. return NCDVal__Ref(list.mem, list_e->elem_indices[pos]);
  867. }
  868. int NCDVal_ListRead (NCDValRef list, int num, ...)
  869. {
  870. ASSERT(NCDVal_IsList(list))
  871. ASSERT(num >= 0)
  872. size_t count = NCDVal_ListCount(list);
  873. if (num != count) {
  874. return 0;
  875. }
  876. va_list ap;
  877. va_start(ap, num);
  878. for (int i = 0; i < num; i++) {
  879. NCDValRef *dest = va_arg(ap, NCDValRef *);
  880. *dest = NCDVal_ListGet(list, i);
  881. }
  882. va_end(ap);
  883. return 1;
  884. }
  885. int NCDVal_ListReadHead (NCDValRef list, int num, ...)
  886. {
  887. ASSERT(NCDVal_IsList(list))
  888. ASSERT(num >= 0)
  889. size_t count = NCDVal_ListCount(list);
  890. if (num > count) {
  891. return 0;
  892. }
  893. va_list ap;
  894. va_start(ap, num);
  895. for (int i = 0; i < num; i++) {
  896. NCDValRef *dest = va_arg(ap, NCDValRef *);
  897. *dest = NCDVal_ListGet(list, i);
  898. }
  899. va_end(ap);
  900. return 1;
  901. }
  902. int NCDVal_IsMap (NCDValRef val)
  903. {
  904. NCDVal__AssertVal(val);
  905. return NCDVal_Type(val) == NCDVAL_MAP;
  906. }
  907. NCDValRef NCDVal_NewMap (NCDValMem *mem, size_t maxcount)
  908. {
  909. NCDVal__AssertMem(mem);
  910. bsize_t size = bsize_add(bsize_fromsize(sizeof(struct NCDVal__map)), bsize_mul(bsize_fromsize(maxcount), bsize_fromsize(sizeof(struct NCDVal__mapelem))));
  911. NCDVal__idx idx = NCDValMem__Alloc(mem, size, __alignof(struct NCDVal__map));
  912. if (idx < 0) {
  913. goto fail;
  914. }
  915. struct NCDVal__map *map_e = NCDValMem__BufAt(mem, idx);
  916. map_e->type = make_type(NCDVAL_MAP, 0);
  917. map_e->maxcount = maxcount;
  918. map_e->count = 0;
  919. NCDVal__MapTree_Init(&map_e->tree);
  920. return NCDVal__Ref(mem, idx);
  921. fail:
  922. return NCDVal_NewInvalid();
  923. }
  924. int NCDVal_MapInsert (NCDValRef map, NCDValRef key, NCDValRef val, int *out_inserted)
  925. {
  926. ASSERT(NCDVal_IsMap(map))
  927. ASSERT(NCDVal_MapCount(map) < NCDVal_MapMaxCount(map))
  928. ASSERT(key.mem == map.mem)
  929. ASSERT(val.mem == map.mem)
  930. NCDVal__AssertValOnly(map.mem, key.idx);
  931. NCDVal__AssertValOnly(map.mem, val.idx);
  932. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  933. int new_type = map_e->type;
  934. if (!bump_depth(&new_type, NCDVal__Depth(key)) || !bump_depth(&new_type, NCDVal__Depth(val))) {
  935. return 0;
  936. }
  937. NCDVal__idx elemidx = NCDVal__MapElemIdx(map.idx, map_e->count);
  938. struct NCDVal__mapelem *me_e = NCDValMem__BufAt(map.mem, elemidx);
  939. ASSERT(me_e == &map_e->elems[map_e->count])
  940. me_e->key_idx = key.idx;
  941. me_e->val_idx = val.idx;
  942. int res = NCDVal__MapTree_Insert(&map_e->tree, map.mem, NCDVal__MapTreeDeref(map.mem, elemidx), NULL);
  943. if (!res) {
  944. if (out_inserted) {
  945. *out_inserted = 0;
  946. }
  947. return 1;
  948. }
  949. map_e->type = new_type;
  950. map_e->count++;
  951. if (out_inserted) {
  952. *out_inserted = 1;
  953. }
  954. return 1;
  955. }
  956. size_t NCDVal_MapCount (NCDValRef map)
  957. {
  958. ASSERT(NCDVal_IsMap(map))
  959. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  960. return map_e->count;
  961. }
  962. size_t NCDVal_MapMaxCount (NCDValRef map)
  963. {
  964. ASSERT(NCDVal_IsMap(map))
  965. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  966. return map_e->maxcount;
  967. }
  968. int NCDVal_MapElemInvalid (NCDValMapElem me)
  969. {
  970. ASSERT(me.elemidx >= 0 || me.elemidx == -1)
  971. return me.elemidx < 0;
  972. }
  973. NCDValMapElem NCDVal_MapFirst (NCDValRef map)
  974. {
  975. ASSERT(NCDVal_IsMap(map))
  976. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  977. if (map_e->count == 0) {
  978. return NCDVal__MapElem(-1);
  979. }
  980. NCDVal__idx elemidx = NCDVal__MapElemIdx(map.idx, 0);
  981. NCDVal__MapAssertElemOnly(map, elemidx);
  982. return NCDVal__MapElem(elemidx);
  983. }
  984. NCDValMapElem NCDVal_MapNext (NCDValRef map, NCDValMapElem me)
  985. {
  986. NCDVal__MapAssertElem(map, me);
  987. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  988. ASSERT(map_e->count > 0)
  989. NCDVal__idx last_elemidx = NCDVal__MapElemIdx(map.idx, map_e->count - 1);
  990. ASSERT(me.elemidx <= last_elemidx)
  991. if (me.elemidx == last_elemidx) {
  992. return NCDVal__MapElem(-1);
  993. }
  994. NCDVal__idx elemidx = me.elemidx + sizeof(struct NCDVal__mapelem);
  995. NCDVal__MapAssertElemOnly(map, elemidx);
  996. return NCDVal__MapElem(elemidx);
  997. }
  998. NCDValMapElem NCDVal_MapOrderedFirst (NCDValRef map)
  999. {
  1000. ASSERT(NCDVal_IsMap(map))
  1001. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  1002. NCDVal__MapTreeRef ref = NCDVal__MapTree_GetFirst(&map_e->tree, map.mem);
  1003. ASSERT(ref.link == -1 || (NCDVal__MapAssertElemOnly(map, ref.link), 1))
  1004. return NCDVal__MapElem(ref.link);
  1005. }
  1006. NCDValMapElem NCDVal_MapOrderedNext (NCDValRef map, NCDValMapElem me)
  1007. {
  1008. NCDVal__MapAssertElem(map, me);
  1009. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  1010. NCDVal__MapTreeRef ref = NCDVal__MapTree_GetNext(&map_e->tree, map.mem, NCDVal__MapTreeDeref(map.mem, me.elemidx));
  1011. ASSERT(ref.link == -1 || (NCDVal__MapAssertElemOnly(map, ref.link), 1))
  1012. return NCDVal__MapElem(ref.link);
  1013. }
  1014. NCDValRef NCDVal_MapElemKey (NCDValRef map, NCDValMapElem me)
  1015. {
  1016. NCDVal__MapAssertElem(map, me);
  1017. struct NCDVal__mapelem *me_e = NCDValMem__BufAt(map.mem, me.elemidx);
  1018. return NCDVal__Ref(map.mem, me_e->key_idx);
  1019. }
  1020. NCDValRef NCDVal_MapElemVal (NCDValRef map, NCDValMapElem me)
  1021. {
  1022. NCDVal__MapAssertElem(map, me);
  1023. struct NCDVal__mapelem *me_e = NCDValMem__BufAt(map.mem, me.elemidx);
  1024. return NCDVal__Ref(map.mem, me_e->val_idx);
  1025. }
  1026. NCDValMapElem NCDVal_MapFindKey (NCDValRef map, NCDValRef key)
  1027. {
  1028. ASSERT(NCDVal_IsMap(map))
  1029. NCDVal__AssertVal(key);
  1030. struct NCDVal__map *map_e = NCDValMem__BufAt(map.mem, map.idx);
  1031. NCDVal__MapTreeRef ref = NCDVal__MapTree_LookupExact(&map_e->tree, map.mem, key);
  1032. ASSERT(ref.link == -1 || (NCDVal__MapAssertElemOnly(map, ref.link), 1))
  1033. return NCDVal__MapElem(ref.link);
  1034. }
  1035. NCDValRef NCDVal_MapGetValue (NCDValRef map, const char *key_str)
  1036. {
  1037. ASSERT(NCDVal_IsMap(map))
  1038. ASSERT(key_str)
  1039. NCDValMem mem;
  1040. mem.buf = NULL;
  1041. mem.size = NCDVAL_FASTBUF_SIZE;
  1042. mem.used = sizeof(struct NCDVal__externalstring);
  1043. mem.first_ref = -1;
  1044. struct NCDVal__externalstring *exs_e = (void *)mem.fastbuf;
  1045. exs_e->type = make_type(EXTERNALSTRING_TYPE, 0);
  1046. exs_e->data = key_str;
  1047. exs_e->length = strlen(key_str);
  1048. exs_e->ref.target = NULL;
  1049. NCDValRef key = NCDVal__Ref(&mem, 0);
  1050. NCDValMapElem elem = NCDVal_MapFindKey(map, key);
  1051. if (NCDVal_MapElemInvalid(elem)) {
  1052. return NCDVal_NewInvalid();
  1053. }
  1054. return NCDVal_MapElemVal(map, elem);
  1055. }
  1056. static void replaceprog_build_recurser (NCDValMem *mem, NCDVal__idx idx, size_t *out_num_instr, NCDValReplaceProg *prog)
  1057. {
  1058. ASSERT(idx >= 0)
  1059. NCDVal__AssertValOnly(mem, idx);
  1060. ASSERT(out_num_instr)
  1061. *out_num_instr = 0;
  1062. void *ptr = NCDValMem__BufAt(mem, idx);
  1063. struct NCDVal__instr instr;
  1064. switch (get_internal_type(*((int *)(ptr)))) {
  1065. case NCDVAL_STRING:
  1066. case IDSTRING_TYPE:
  1067. case EXTERNALSTRING_TYPE: {
  1068. } break;
  1069. case NCDVAL_LIST: {
  1070. struct NCDVal__list *list_e = ptr;
  1071. for (NCDVal__idx i = 0; i < list_e->count; i++) {
  1072. int elem_changed = 0;
  1073. if (list_e->elem_indices[i] < -1) {
  1074. if (prog) {
  1075. instr.type = NCDVAL_INSTR_PLACEHOLDER;
  1076. instr.placeholder.plid = list_e->elem_indices[i] - NCDVAL_MINIDX;
  1077. instr.placeholder.plidx = idx + offsetof(struct NCDVal__list, elem_indices) + i * sizeof(NCDVal__idx);
  1078. prog->instrs[prog->num_instrs++] = instr;
  1079. }
  1080. (*out_num_instr)++;
  1081. elem_changed = 1;
  1082. } else {
  1083. size_t elem_num_instr;
  1084. replaceprog_build_recurser(mem, list_e->elem_indices[i], &elem_num_instr, prog);
  1085. (*out_num_instr) += elem_num_instr;
  1086. if (elem_num_instr > 0) {
  1087. elem_changed = 1;
  1088. }
  1089. }
  1090. if (elem_changed) {
  1091. if (prog) {
  1092. instr.type = NCDVAL_INSTR_BUMPDEPTH;
  1093. instr.bumpdepth.parent_idx = idx;
  1094. instr.bumpdepth.child_idx_idx = idx + offsetof(struct NCDVal__list, elem_indices) + i * sizeof(NCDVal__idx);
  1095. prog->instrs[prog->num_instrs++] = instr;
  1096. }
  1097. (*out_num_instr)++;
  1098. }
  1099. }
  1100. } break;
  1101. case NCDVAL_MAP: {
  1102. struct NCDVal__map *map_e = ptr;
  1103. for (NCDVal__idx i = 0; i < map_e->count; i++) {
  1104. int key_changed = 0;
  1105. int val_changed = 0;
  1106. if (map_e->elems[i].key_idx < -1) {
  1107. if (prog) {
  1108. instr.type = NCDVAL_INSTR_PLACEHOLDER;
  1109. instr.placeholder.plid = map_e->elems[i].key_idx - NCDVAL_MINIDX;
  1110. instr.placeholder.plidx = idx + offsetof(struct NCDVal__map, elems) + i * sizeof(struct NCDVal__mapelem) + offsetof(struct NCDVal__mapelem, key_idx);
  1111. prog->instrs[prog->num_instrs++] = instr;
  1112. }
  1113. (*out_num_instr)++;
  1114. key_changed = 1;
  1115. } else {
  1116. size_t key_num_instr;
  1117. replaceprog_build_recurser(mem, map_e->elems[i].key_idx, &key_num_instr, prog);
  1118. (*out_num_instr) += key_num_instr;
  1119. if (key_num_instr > 0) {
  1120. key_changed = 1;
  1121. }
  1122. }
  1123. if (map_e->elems[i].val_idx < -1) {
  1124. if (prog) {
  1125. instr.type = NCDVAL_INSTR_PLACEHOLDER;
  1126. instr.placeholder.plid = map_e->elems[i].val_idx - NCDVAL_MINIDX;
  1127. instr.placeholder.plidx = idx + offsetof(struct NCDVal__map, elems) + i * sizeof(struct NCDVal__mapelem) + offsetof(struct NCDVal__mapelem, val_idx);
  1128. prog->instrs[prog->num_instrs++] = instr;
  1129. }
  1130. (*out_num_instr)++;
  1131. val_changed = 1;
  1132. } else {
  1133. size_t val_num_instr;
  1134. replaceprog_build_recurser(mem, map_e->elems[i].val_idx, &val_num_instr, prog);
  1135. (*out_num_instr) += val_num_instr;
  1136. if (val_num_instr > 0) {
  1137. val_changed = 1;
  1138. }
  1139. }
  1140. if (key_changed) {
  1141. if (prog) {
  1142. instr.type = NCDVAL_INSTR_REINSERT;
  1143. instr.reinsert.mapidx = idx;
  1144. instr.reinsert.elempos = i;
  1145. prog->instrs[prog->num_instrs++] = instr;
  1146. }
  1147. (*out_num_instr)++;
  1148. if (prog) {
  1149. instr.type = NCDVAL_INSTR_BUMPDEPTH;
  1150. instr.bumpdepth.parent_idx = idx;
  1151. instr.bumpdepth.child_idx_idx = idx + offsetof(struct NCDVal__map, elems) + i * sizeof(struct NCDVal__mapelem) + offsetof(struct NCDVal__mapelem, key_idx);
  1152. prog->instrs[prog->num_instrs++] = instr;
  1153. }
  1154. (*out_num_instr)++;
  1155. }
  1156. if (val_changed) {
  1157. if (prog) {
  1158. instr.type = NCDVAL_INSTR_BUMPDEPTH;
  1159. instr.bumpdepth.parent_idx = idx;
  1160. instr.bumpdepth.child_idx_idx = idx + offsetof(struct NCDVal__map, elems) + i * sizeof(struct NCDVal__mapelem) + offsetof(struct NCDVal__mapelem, val_idx);
  1161. prog->instrs[prog->num_instrs++] = instr;
  1162. }
  1163. (*out_num_instr)++;
  1164. }
  1165. }
  1166. } break;
  1167. default: ASSERT(0);
  1168. }
  1169. }
  1170. int NCDValReplaceProg_Init (NCDValReplaceProg *o, NCDValRef val)
  1171. {
  1172. NCDVal__AssertVal(val);
  1173. ASSERT(!NCDVal_IsPlaceholder(val))
  1174. size_t num_instrs;
  1175. replaceprog_build_recurser(val.mem, val.idx, &num_instrs, NULL);
  1176. if (!(o->instrs = BAllocArray(num_instrs, sizeof(o->instrs[0])))) {
  1177. BLog(BLOG_ERROR, "BAllocArray failed");
  1178. return 0;
  1179. }
  1180. o->num_instrs = 0;
  1181. size_t num_instrs2;
  1182. replaceprog_build_recurser(val.mem, val.idx, &num_instrs2, o);
  1183. ASSERT(num_instrs2 == num_instrs)
  1184. ASSERT(o->num_instrs == num_instrs)
  1185. return 1;
  1186. }
  1187. void NCDValReplaceProg_Free (NCDValReplaceProg *o)
  1188. {
  1189. BFree(o->instrs);
  1190. }
  1191. int NCDValReplaceProg_Execute (NCDValReplaceProg prog, NCDValMem *mem, NCDVal_replace_func replace, void *arg)
  1192. {
  1193. NCDVal__AssertMem(mem);
  1194. ASSERT(replace)
  1195. for (size_t i = 0; i < prog.num_instrs; i++) {
  1196. struct NCDVal__instr instr = prog.instrs[i];
  1197. switch (instr.type) {
  1198. case NCDVAL_INSTR_PLACEHOLDER: {
  1199. #ifndef NDEBUG
  1200. NCDVal__idx *check_plptr = NCDValMem__BufAt(mem, instr.placeholder.plidx);
  1201. ASSERT(*check_plptr < -1)
  1202. ASSERT(*check_plptr - NCDVAL_MINIDX == instr.placeholder.plid)
  1203. #endif
  1204. NCDValRef repval;
  1205. if (!replace(arg, instr.placeholder.plid, mem, &repval) || NCDVal_IsInvalid(repval)) {
  1206. return 0;
  1207. }
  1208. ASSERT(repval.mem == mem)
  1209. NCDVal__idx *plptr = NCDValMem__BufAt(mem, instr.placeholder.plidx);
  1210. *plptr = repval.idx;
  1211. } break;
  1212. case NCDVAL_INSTR_REINSERT: {
  1213. NCDVal__AssertValOnly(mem, instr.reinsert.mapidx);
  1214. struct NCDVal__map *map_e = NCDValMem__BufAt(mem, instr.reinsert.mapidx);
  1215. ASSERT(map_e->type == NCDVAL_MAP)
  1216. ASSERT(instr.reinsert.elempos >= 0)
  1217. ASSERT(instr.reinsert.elempos < map_e->count)
  1218. NCDVal__MapTreeRef ref = {&map_e->elems[instr.reinsert.elempos], NCDVal__MapElemIdx(instr.reinsert.mapidx, instr.reinsert.elempos)};
  1219. NCDVal__MapTree_Remove(&map_e->tree, mem, ref);
  1220. if (!NCDVal__MapTree_Insert(&map_e->tree, mem, ref, NULL)) {
  1221. BLog(BLOG_ERROR, "duplicate key in map");
  1222. return 0;
  1223. }
  1224. } break;
  1225. case NCDVAL_INSTR_BUMPDEPTH: {
  1226. NCDVal__AssertValOnly(mem, instr.bumpdepth.parent_idx);
  1227. int *parent_type_ptr = NCDValMem__BufAt(mem, instr.bumpdepth.parent_idx);
  1228. NCDVal__idx *child_type_idx_ptr = NCDValMem__BufAt(mem, instr.bumpdepth.child_idx_idx);
  1229. NCDVal__AssertValOnly(mem, *child_type_idx_ptr);
  1230. int *child_type_ptr = NCDValMem__BufAt(mem, *child_type_idx_ptr);
  1231. if (!bump_depth(parent_type_ptr, get_depth(*child_type_ptr))) {
  1232. BLog(BLOG_ERROR, "depth limit exceeded");
  1233. return 0;
  1234. }
  1235. } break;
  1236. default: ASSERT(0);
  1237. }
  1238. }
  1239. return 1;
  1240. }