NCDVal.c 46 KB

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