value.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396
  1. /**
  2. * @file value.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. * @section DESCRIPTION
  30. *
  31. * Synopsis:
  32. * value(value)
  33. * value value::get(where)
  34. * value value::try_get(where)
  35. * value value::getpath(list path)
  36. * value value::insert(where, what)
  37. * value value::insert_undo(where, what)
  38. *
  39. * Description:
  40. * Value objects allow examining and manipulating values.
  41. *
  42. * value(value) constructs a new value object from the given value.
  43. *
  44. * value::get(where) constructs a value object for the element at position 'where'
  45. * (for a list), or the value corresponding to key 'where' (for a map). It is an
  46. * error if the base value is not a list or a map, the index is out of bounds of
  47. * the list, or the key does not exist in the map.
  48. * The resulting value object is NOT a copy, and shares (part of) the same
  49. * underlying value structure as the base value object. Deleting it will remove
  50. * it from the list or map it is part of.
  51. *
  52. * value::try_get(where) is like get(), except that if any restriction on 'where'
  53. * is violated, no error is triggered; instead, the value object is constructed
  54. * as being deleted; this state is exposed via the 'exists' variable.
  55. * This can be used to check for the presence of a key in a map, and in case it
  56. * exists, allow access to the corresponding value without another get() statement.
  57. *
  58. * value::getpath(path) is like get(), except that it performs multiple
  59. * consecutive resolutions. Also, if the path is an empty list, it performs
  60. * no resulution at all.
  61. *
  62. * value::insert(where, what) constructs a value object by inserting into an
  63. * existing value object.
  64. * For lists, 'where' is the index of the element to insert before, or the length
  65. * of the list to append to it.
  66. * For maps, 'where' is the key to insert under. If the key already exists in the
  67. * map, its value is replaced; any references to the old value however remain valid.
  68. *
  69. * value::insert_undo(where, what) is like insert(), except that, on
  70. * deinitialization, it attempts to revert the value to the original state.
  71. * It does this by taking a reference to the old value at 'where' (if any) and
  72. * before inserting the new value 'what' to that location. On deinitialization,
  73. * it removes the value that it inserted from its parent and inserts the stored
  74. * referenced value in its place, assuming this is possible (the inserted value
  75. * has not been deleted and has a parent at deinitialization time).
  76. *
  77. * Variables:
  78. * (empty) - the value stored in the value object
  79. * type - type of the value; "string", "list" or "map"
  80. * length - number of elements in the list or map, or the number of bytes in a
  81. * string
  82. * keys - a list of keys in the map (only if the value is a map)
  83. * exists - "true" or "false", reflecting whether the value object holds a value
  84. * (is not in deleted state)
  85. *
  86. * Synopsis:
  87. * value::remove(where)
  88. * value::delete()
  89. *
  90. * Description:
  91. * value::remove(where) removes from an existing value object.
  92. * For lists, 'where' is the index of the element to remove, and must be in range.
  93. * For maps, 'where' is the key to remove, and must be an existing key.
  94. * In any case, any references to the removed value remain valid.
  95. *
  96. * value::delete() deletes the underlying value data of this value object.
  97. * After delection, the value object enters a deleted state, which will cause any
  98. * operation on it to fail. Any other value objects which referred to the same value
  99. * or parts of it will too enter deleted state. If the value was an element
  100. * in a list or map, is is removed from it.
  101. *
  102. * Synopsis:
  103. * value value::substr(string start [, string length])
  104. *
  105. * Description:
  106. * Constructs a string value by extracting a part of a string.
  107. * 'start' specifies the index of the character (from zero) where the substring to
  108. * extract starts, and must be <= the length of the string.
  109. * 'length' specifies the maximum number of characters to extract, if given.
  110. * The newly constructed value is a copy of the extracted substring.
  111. * The value must be a string value.
  112. */
  113. #include <stdlib.h>
  114. #include <string.h>
  115. #include <stddef.h>
  116. #include <limits.h>
  117. #include <inttypes.h>
  118. #include <misc/offset.h>
  119. #include <misc/debug.h>
  120. #include <misc/parse_number.h>
  121. #include <misc/balloc.h>
  122. #include <structure/LinkedList0.h>
  123. #include <structure/IndexedList.h>
  124. #include <structure/BCountAVL.h>
  125. #include <ncd/NCDModule.h>
  126. #include <generated/blog_channel_ncd_value.h>
  127. #define ModuleLog(i, ...) NCDModuleInst_Backend_Log((i), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
  128. struct value;
  129. struct valref {
  130. struct value *v;
  131. LinkedList0Node refs_list_node;
  132. };
  133. typedef void (*value_deinit_func) (void *deinit_data, NCDModuleInst *i);
  134. struct instance {
  135. NCDModuleInst *i;
  136. struct valref ref;
  137. value_deinit_func deinit_func;
  138. void *deinit_data;
  139. };
  140. struct value {
  141. LinkedList0 refs_list;
  142. struct value *parent;
  143. union {
  144. struct {
  145. IndexedListNode list_contents_il_node;
  146. } list_parent;
  147. struct {
  148. NCDValMem key_mem;
  149. NCDValRef key;
  150. BCountAVLNode map_contents_tree_node;
  151. } map_parent;
  152. };
  153. int type;
  154. union {
  155. struct {
  156. uint8_t *string;
  157. size_t length;
  158. } string;
  159. struct {
  160. IndexedList list_contents_il;
  161. } list;
  162. struct {
  163. BCountAVL map_contents_tree;
  164. } map;
  165. };
  166. };
  167. static int ncdval_comparator (void *unused, void *vv1, void *vv2);
  168. static const char * get_type_str (int type);
  169. static void value_cleanup (struct value *v);
  170. static void value_delete (struct value *v);
  171. static struct value * value_init_string (NCDModuleInst *i, const uint8_t *str, size_t len);
  172. static struct value * value_init_list (NCDModuleInst *i);
  173. static size_t value_list_len (struct value *v);
  174. static struct value * value_list_at (struct value *v, size_t index);
  175. static size_t value_list_indexof (struct value *v, struct value *ev);
  176. static int value_list_insert (NCDModuleInst *i, struct value *list, struct value *v, size_t index);
  177. static void value_list_remove (struct value *list, struct value *v);
  178. static struct value * value_init_map (NCDModuleInst *i);
  179. static size_t value_map_len (struct value *map);
  180. static struct value * value_map_at (struct value *map, size_t index);
  181. static struct value * value_map_find (struct value *map, NCDValRef key);
  182. static int value_map_insert (struct value *map, struct value *v, NCDValMem mem, NCDValSafeRef key, NCDModuleInst *i);
  183. static void value_map_remove (struct value *map, struct value *v);
  184. static void value_map_remove2 (struct value *map, struct value *v, NCDValMem *out_mem, NCDValSafeRef *out_key);
  185. static struct value * value_init_fromvalue (NCDModuleInst *i, NCDValRef value);
  186. static int value_to_value (NCDModuleInst *i, struct value *v, NCDValMem *mem, NCDValRef *out_value);
  187. static struct value * value_get (NCDModuleInst *i, struct value *v, NCDValRef where, int no_error);
  188. static struct value * value_get_path (NCDModuleInst *i, struct value *v, NCDValRef path);
  189. static struct value * value_insert (NCDModuleInst *i, struct value *v, NCDValRef where, NCDValRef what, struct value **out_oldv);
  190. static int value_remove (NCDModuleInst *i, struct value *v, NCDValRef where);
  191. static void valref_init (struct valref *r, struct value *v);
  192. static void valref_free (struct valref *r);
  193. static struct value * valref_val (struct valref *r);
  194. static void valref_break (struct valref *r);
  195. static int ncdval_comparator (void *unused, void *vv1, void *vv2)
  196. {
  197. NCDValRef *v1 = vv1;
  198. NCDValRef *v2 = vv2;
  199. return NCDVal_Compare(*v1, *v2);
  200. }
  201. static const char * get_type_str (int type)
  202. {
  203. switch (type) {
  204. case NCDVAL_STRING: return "string";
  205. case NCDVAL_LIST: return "list";
  206. case NCDVAL_MAP: return "map";
  207. }
  208. ASSERT(0)
  209. return NULL;
  210. }
  211. static void value_cleanup (struct value *v)
  212. {
  213. if (v->parent || !LinkedList0_IsEmpty(&v->refs_list)) {
  214. return;
  215. }
  216. switch (v->type) {
  217. case NCDVAL_STRING: {
  218. BFree(v->string.string);
  219. } break;
  220. case NCDVAL_LIST: {
  221. while (value_list_len(v) > 0) {
  222. struct value *ev = value_list_at(v, 0);
  223. value_list_remove(v, ev);
  224. value_cleanup(ev);
  225. }
  226. } break;
  227. case NCDVAL_MAP: {
  228. while (value_map_len(v) > 0) {
  229. struct value *ev = value_map_at(v, 0);
  230. value_map_remove(v, ev);
  231. value_cleanup(ev);
  232. }
  233. } break;
  234. default: ASSERT(0);
  235. }
  236. free(v);
  237. }
  238. static void value_delete (struct value *v)
  239. {
  240. if (v->parent) {
  241. switch (v->parent->type) {
  242. case NCDVAL_LIST: {
  243. value_list_remove(v->parent, v);
  244. } break;
  245. case NCDVAL_MAP: {
  246. value_map_remove(v->parent, v);
  247. } break;
  248. default: ASSERT(0);
  249. }
  250. }
  251. LinkedList0Node *ln;
  252. while (ln = LinkedList0_GetFirst(&v->refs_list)) {
  253. struct valref *r = UPPER_OBJECT(ln, struct valref, refs_list_node);
  254. ASSERT(r->v == v)
  255. valref_break(r);
  256. }
  257. switch (v->type) {
  258. case NCDVAL_STRING: {
  259. BFree(v->string.string);
  260. } break;
  261. case NCDVAL_LIST: {
  262. while (value_list_len(v) > 0) {
  263. struct value *ev = value_list_at(v, 0);
  264. value_delete(ev);
  265. }
  266. } break;
  267. case NCDVAL_MAP: {
  268. while (value_map_len(v) > 0) {
  269. struct value *ev = value_map_at(v, 0);
  270. value_delete(ev);
  271. }
  272. } break;
  273. default: ASSERT(0);
  274. }
  275. free(v);
  276. }
  277. static struct value * value_init_string (NCDModuleInst *i, const uint8_t *str, size_t len)
  278. {
  279. struct value *v = malloc(sizeof(*v));
  280. if (!v) {
  281. ModuleLog(i, BLOG_ERROR, "malloc failed");
  282. goto fail0;
  283. }
  284. LinkedList0_Init(&v->refs_list);
  285. v->parent = NULL;
  286. v->type = NCDVAL_STRING;
  287. if (!(v->string.string = BAlloc(len))) {
  288. ModuleLog(i, BLOG_ERROR, "BAlloc failed");
  289. goto fail1;
  290. }
  291. memcpy(v->string.string, str, len);
  292. v->string.length = len;
  293. return v;
  294. fail1:
  295. free(v);
  296. fail0:
  297. return NULL;
  298. }
  299. static struct value * value_init_list (NCDModuleInst *i)
  300. {
  301. struct value *v = malloc(sizeof(*v));
  302. if (!v) {
  303. ModuleLog(i, BLOG_ERROR, "malloc failed");
  304. return NULL;
  305. }
  306. LinkedList0_Init(&v->refs_list);
  307. v->parent = NULL;
  308. v->type = NCDVAL_LIST;
  309. IndexedList_Init(&v->list.list_contents_il);
  310. return v;
  311. }
  312. static size_t value_list_len (struct value *v)
  313. {
  314. ASSERT(v->type == NCDVAL_LIST)
  315. return IndexedList_Count(&v->list.list_contents_il);
  316. }
  317. static struct value * value_list_at (struct value *v, size_t index)
  318. {
  319. ASSERT(v->type == NCDVAL_LIST)
  320. ASSERT(index < value_list_len(v))
  321. IndexedListNode *iln = IndexedList_GetAt(&v->list.list_contents_il, index);
  322. ASSERT(iln)
  323. struct value *e = UPPER_OBJECT(iln, struct value, list_parent.list_contents_il_node);
  324. ASSERT(e->parent == v)
  325. return e;
  326. }
  327. static size_t value_list_indexof (struct value *v, struct value *ev)
  328. {
  329. ASSERT(v->type == NCDVAL_LIST)
  330. ASSERT(ev->parent == v)
  331. uint64_t index = IndexedList_IndexOf(&v->list.list_contents_il, &ev->list_parent.list_contents_il_node);
  332. ASSERT(index < value_list_len(v))
  333. return index;
  334. }
  335. static int value_list_insert (NCDModuleInst *i, struct value *list, struct value *v, size_t index)
  336. {
  337. ASSERT(list->type == NCDVAL_LIST)
  338. ASSERT(!v->parent)
  339. ASSERT(index <= value_list_len(list))
  340. if (value_list_len(list) == SIZE_MAX) {
  341. ModuleLog(i, BLOG_ERROR, "list has too many elements");
  342. return 0;
  343. }
  344. IndexedList_InsertAt(&list->list.list_contents_il, &v->list_parent.list_contents_il_node, index);
  345. v->parent = list;
  346. return 1;
  347. }
  348. static void value_list_remove (struct value *list, struct value *v)
  349. {
  350. ASSERT(list->type == NCDVAL_LIST)
  351. ASSERT(v->parent == list)
  352. IndexedList_Remove(&list->list.list_contents_il, &v->list_parent.list_contents_il_node);
  353. v->parent = NULL;
  354. }
  355. static struct value * value_init_map (NCDModuleInst *i)
  356. {
  357. struct value *v = malloc(sizeof(*v));
  358. if (!v) {
  359. ModuleLog(i, BLOG_ERROR, "malloc failed");
  360. return NULL;
  361. }
  362. LinkedList0_Init(&v->refs_list);
  363. v->parent = NULL;
  364. v->type = NCDVAL_MAP;
  365. BCountAVL_Init(&v->map.map_contents_tree, OFFSET_DIFF(struct value, map_parent.key, map_parent.map_contents_tree_node), ncdval_comparator, NULL);
  366. return v;
  367. }
  368. static size_t value_map_len (struct value *map)
  369. {
  370. ASSERT(map->type == NCDVAL_MAP)
  371. return BCountAVL_Count(&map->map.map_contents_tree);
  372. }
  373. static struct value * value_map_at (struct value *map, size_t index)
  374. {
  375. ASSERT(map->type == NCDVAL_MAP)
  376. ASSERT(index < value_map_len(map))
  377. BCountAVLNode *tn = BCountAVL_GetAt(&map->map.map_contents_tree, index);
  378. ASSERT(tn)
  379. struct value *e = UPPER_OBJECT(tn, struct value, map_parent.map_contents_tree_node);
  380. ASSERT(e->parent == map)
  381. return e;
  382. }
  383. static struct value * value_map_find (struct value *map, NCDValRef key)
  384. {
  385. ASSERT(map->type == NCDVAL_MAP)
  386. ASSERT(NCDVal_Type(key))
  387. BCountAVLNode *tn = BCountAVL_LookupExact(&map->map.map_contents_tree, &key);
  388. if (!tn) {
  389. return NULL;
  390. }
  391. struct value *e = UPPER_OBJECT(tn, struct value, map_parent.map_contents_tree_node);
  392. ASSERT(e->parent == map)
  393. return e;
  394. }
  395. static int value_map_insert (struct value *map, struct value *v, NCDValMem mem, NCDValSafeRef key, NCDModuleInst *i)
  396. {
  397. ASSERT(map->type == NCDVAL_MAP)
  398. ASSERT(!v->parent)
  399. ASSERT((NCDVal_Type(NCDVal_FromSafe(&mem, key)), 1))
  400. ASSERT(!value_map_find(map, NCDVal_FromSafe(&mem, key)))
  401. if (value_map_len(map) == SIZE_MAX) {
  402. ModuleLog(i, BLOG_ERROR, "map has too many elements");
  403. return 0;
  404. }
  405. v->map_parent.key_mem = mem;
  406. v->map_parent.key = NCDVal_FromSafe(&v->map_parent.key_mem, key);
  407. int res = BCountAVL_Insert(&map->map.map_contents_tree, &v->map_parent.map_contents_tree_node, NULL);
  408. ASSERT(res)
  409. v->parent = map;
  410. return 1;
  411. }
  412. static void value_map_remove (struct value *map, struct value *v)
  413. {
  414. ASSERT(map->type == NCDVAL_MAP)
  415. ASSERT(v->parent == map)
  416. BCountAVL_Remove(&map->map.map_contents_tree, &v->map_parent.map_contents_tree_node);
  417. NCDValMem_Free(&v->map_parent.key_mem);
  418. v->parent = NULL;
  419. }
  420. static void value_map_remove2 (struct value *map, struct value *v, NCDValMem *out_mem, NCDValSafeRef *out_key)
  421. {
  422. ASSERT(map->type == NCDVAL_MAP)
  423. ASSERT(v->parent == map)
  424. ASSERT(out_mem)
  425. ASSERT(out_key)
  426. BCountAVL_Remove(&map->map.map_contents_tree, &v->map_parent.map_contents_tree_node);
  427. *out_mem = v->map_parent.key_mem;
  428. *out_key = NCDVal_ToSafe(v->map_parent.key);
  429. v->parent = NULL;
  430. }
  431. static struct value * value_init_fromvalue (NCDModuleInst *i, NCDValRef value)
  432. {
  433. ASSERT((NCDVal_Type(value), 1))
  434. struct value *v;
  435. switch (NCDVal_Type(value)) {
  436. case NCDVAL_STRING: {
  437. if (!(v = value_init_string(i, (const uint8_t *)NCDVal_StringValue(value), NCDVal_StringLength(value)))) {
  438. goto fail0;
  439. }
  440. } break;
  441. case NCDVAL_LIST: {
  442. if (!(v = value_init_list(i))) {
  443. goto fail0;
  444. }
  445. size_t count = NCDVal_ListCount(value);
  446. for (size_t j = 0; j < count; j++) {
  447. struct value *ev = value_init_fromvalue(i, NCDVal_ListGet(value, j));
  448. if (!ev) {
  449. goto fail1;
  450. }
  451. if (!value_list_insert(i, v, ev, value_list_len(v))) {
  452. value_cleanup(ev);
  453. goto fail1;
  454. }
  455. }
  456. } break;
  457. case NCDVAL_MAP: {
  458. if (!(v = value_init_map(i))) {
  459. goto fail0;
  460. }
  461. for (NCDValMapElem e = NCDVal_MapFirst(value); !NCDVal_MapElemInvalid(e); e = NCDVal_MapNext(value, e)) {
  462. NCDValRef ekey = NCDVal_MapElemKey(value, e);
  463. NCDValRef eval = NCDVal_MapElemVal(value, e);
  464. NCDValMem key_mem;
  465. NCDValMem_Init(&key_mem);
  466. NCDValRef key = NCDVal_NewCopy(&key_mem, ekey);
  467. if (NCDVal_IsInvalid(key)) {
  468. BLog(BLOG_ERROR, "NCDVal_NewCopy failed");
  469. NCDValMem_Free(&key_mem);
  470. goto fail1;
  471. }
  472. struct value *ev = value_init_fromvalue(i, eval);
  473. if (!ev) {
  474. NCDValMem_Free(&key_mem);
  475. goto fail1;
  476. }
  477. if (!value_map_insert(v, ev, key_mem, NCDVal_ToSafe(key), i)) {
  478. NCDValMem_Free(&key_mem);
  479. value_cleanup(ev);
  480. goto fail1;
  481. }
  482. }
  483. } break;
  484. default: ASSERT(0);
  485. }
  486. return v;
  487. fail1:
  488. value_cleanup(v);
  489. fail0:
  490. return NULL;
  491. }
  492. static int value_to_value (NCDModuleInst *i, struct value *v, NCDValMem *mem, NCDValRef *out_value)
  493. {
  494. ASSERT(mem)
  495. ASSERT(out_value)
  496. switch (v->type) {
  497. case NCDVAL_STRING: {
  498. *out_value = NCDVal_NewStringBin(mem, v->string.string, v->string.length);
  499. if (NCDVal_IsInvalid(*out_value)) {
  500. ModuleLog(i, BLOG_ERROR, "NCDVal_NewStringBin failed");
  501. goto fail;
  502. }
  503. } break;
  504. case NCDVAL_LIST: {
  505. *out_value = NCDVal_NewList(mem, value_list_len(v));
  506. if (NCDVal_IsInvalid(*out_value)) {
  507. ModuleLog(i, BLOG_ERROR, "NCDVal_NewList failed");
  508. goto fail;
  509. }
  510. for (size_t index = 0; index < value_list_len(v); index++) {
  511. NCDValRef eval;
  512. if (!value_to_value(i, value_list_at(v, index), mem, &eval)) {
  513. goto fail;
  514. }
  515. NCDVal_ListAppend(*out_value, eval);
  516. }
  517. } break;
  518. case NCDVAL_MAP: {
  519. *out_value = NCDVal_NewMap(mem, value_map_len(v));
  520. if (NCDVal_IsInvalid(*out_value)) {
  521. ModuleLog(i, BLOG_ERROR, "NCDVal_NewMap failed");
  522. goto fail;
  523. }
  524. for (size_t index = 0; index < value_map_len(v); index++) {
  525. struct value *ev = value_map_at(v, index);
  526. NCDValRef key = NCDVal_NewCopy(mem, ev->map_parent.key);
  527. if (NCDVal_IsInvalid(key)) {
  528. ModuleLog(i, BLOG_ERROR, "NCDVal_NewCopy failed");
  529. goto fail;
  530. }
  531. NCDValRef val;
  532. if (!value_to_value(i, ev, mem, &val)) {
  533. goto fail;
  534. }
  535. int res = NCDVal_MapInsert(*out_value, key, val);
  536. ASSERT(res)
  537. }
  538. } break;
  539. default: ASSERT(0);
  540. }
  541. return 1;
  542. fail:
  543. return 0;
  544. }
  545. static struct value * value_get (NCDModuleInst *i, struct value *v, NCDValRef where, int no_error)
  546. {
  547. ASSERT((NCDVal_Type(where), 1))
  548. switch (v->type) {
  549. case NCDVAL_STRING: {
  550. if (!no_error) ModuleLog(i, BLOG_ERROR, "cannot resolve into a string");
  551. goto fail;
  552. } break;
  553. case NCDVAL_LIST: {
  554. uintmax_t index;
  555. if (!NCDVal_IsStringNoNulls(where) || !parse_unsigned_integer(NCDVal_StringValue(where), &index)) {
  556. if (!no_error) ModuleLog(i, BLOG_ERROR, "index is not a valid number (resolving into list)");
  557. goto fail;
  558. }
  559. if (index >= value_list_len(v)) {
  560. if (!no_error) ModuleLog(i, BLOG_ERROR, "index is out of bounds (resolving into list)");
  561. goto fail;
  562. }
  563. v = value_list_at(v, index);
  564. } break;
  565. case NCDVAL_MAP: {
  566. v = value_map_find(v, where);
  567. if (!v) {
  568. if (!no_error) ModuleLog(i, BLOG_ERROR, "key does not exist (resolving into map)");
  569. goto fail;
  570. }
  571. } break;
  572. default: ASSERT(0);
  573. }
  574. return v;
  575. fail:
  576. return NULL;
  577. }
  578. static struct value * value_get_path (NCDModuleInst *i, struct value *v, NCDValRef path)
  579. {
  580. ASSERT(NCDVal_IsList(path))
  581. size_t count = NCDVal_ListCount(path);
  582. for (size_t j = 0; j < count; j++) {
  583. if (!(v = value_get(i, v, NCDVal_ListGet(path, j), 0))) {
  584. goto fail;
  585. }
  586. }
  587. return v;
  588. fail:
  589. return NULL;
  590. }
  591. static struct value * value_insert (NCDModuleInst *i, struct value *v, NCDValRef where, NCDValRef what, struct value **out_oldv)
  592. {
  593. ASSERT(v)
  594. ASSERT((NCDVal_Type(where), 1))
  595. ASSERT((NCDVal_Type(what), 1))
  596. struct value *nv = value_init_fromvalue(i, what);
  597. if (!nv) {
  598. goto fail0;
  599. }
  600. struct value *oldv = NULL;
  601. switch (v->type) {
  602. case NCDVAL_STRING: {
  603. ModuleLog(i, BLOG_ERROR, "cannot insert into a string");
  604. goto fail1;
  605. } break;
  606. case NCDVAL_LIST: {
  607. uintmax_t index;
  608. if (!NCDVal_IsStringNoNulls(where) || !parse_unsigned_integer(NCDVal_StringValue(where), &index)) {
  609. ModuleLog(i, BLOG_ERROR, "index is not a valid number (inserting into list)");
  610. goto fail1;
  611. }
  612. if (index > value_list_len(v)) {
  613. ModuleLog(i, BLOG_ERROR, "index is out of bounds (inserting into list)");
  614. goto fail1;
  615. }
  616. if (!value_list_insert(i, v, nv, index)) {
  617. goto fail1;
  618. }
  619. } break;
  620. case NCDVAL_MAP: {
  621. oldv = value_map_find(v, where);
  622. if (!oldv && value_map_len(v) == SIZE_MAX) {
  623. ModuleLog(i, BLOG_ERROR, "map has too many elements");
  624. goto fail1;
  625. }
  626. NCDValMem key_mem;
  627. NCDValMem_Init(&key_mem);
  628. NCDValRef key = NCDVal_NewCopy(&key_mem, where);
  629. if (NCDVal_IsInvalid(key)) {
  630. ModuleLog(i, BLOG_ERROR, "NCDVal_NewCopy failed");
  631. NCDValMem_Free(&key_mem);
  632. goto fail1;
  633. }
  634. if (oldv) {
  635. value_map_remove(v, oldv);
  636. }
  637. int res = value_map_insert(v, nv, key_mem, NCDVal_ToSafe(key), i);
  638. ASSERT(res)
  639. } break;
  640. default: ASSERT(0);
  641. }
  642. if (out_oldv) {
  643. *out_oldv = oldv;
  644. }
  645. else if (oldv) {
  646. value_cleanup(oldv);
  647. }
  648. return nv;
  649. fail1:
  650. value_cleanup(nv);
  651. fail0:
  652. return NULL;
  653. }
  654. static int value_remove (NCDModuleInst *i, struct value *v, NCDValRef where)
  655. {
  656. ASSERT(v)
  657. ASSERT((NCDVal_Type(where), 1))
  658. switch (v->type) {
  659. case NCDVAL_STRING: {
  660. ModuleLog(i, BLOG_ERROR, "cannot remove from a string");
  661. goto fail;
  662. } break;
  663. case NCDVAL_LIST: {
  664. uintmax_t index;
  665. if (!NCDVal_IsStringNoNulls(where) || !parse_unsigned_integer(NCDVal_StringValue(where), &index)) {
  666. ModuleLog(i, BLOG_ERROR, "index is not a valid number (removing from list)");
  667. goto fail;
  668. }
  669. if (index >= value_list_len(v)) {
  670. ModuleLog(i, BLOG_ERROR, "index is out of bounds (removing from list)");
  671. goto fail;
  672. }
  673. struct value *ov = value_list_at(v, index);
  674. value_list_remove(v, ov);
  675. value_cleanup(ov);
  676. } break;
  677. case NCDVAL_MAP: {
  678. struct value *ov = value_map_find(v, where);
  679. if (!ov) {
  680. ModuleLog(i, BLOG_ERROR, "key does not exist (removing from map)");
  681. goto fail;
  682. }
  683. value_map_remove(v, ov);
  684. value_cleanup(ov);
  685. } break;
  686. default: ASSERT(0);
  687. }
  688. return 1;
  689. fail:
  690. return 0;
  691. }
  692. static void valref_init (struct valref *r, struct value *v)
  693. {
  694. r->v = v;
  695. if (v) {
  696. LinkedList0_Prepend(&v->refs_list, &r->refs_list_node);
  697. }
  698. }
  699. static void valref_free (struct valref *r)
  700. {
  701. if (r->v) {
  702. LinkedList0_Remove(&r->v->refs_list, &r->refs_list_node);
  703. value_cleanup(r->v);
  704. }
  705. }
  706. static struct value * valref_val (struct valref *r)
  707. {
  708. return r->v;
  709. }
  710. static void valref_break (struct valref *r)
  711. {
  712. ASSERT(r->v)
  713. LinkedList0_Remove(&r->v->refs_list, &r->refs_list_node);
  714. r->v = NULL;
  715. }
  716. static void func_new_common (void *vo, NCDModuleInst *i, struct value *v, value_deinit_func deinit_func, void *deinit_data)
  717. {
  718. struct instance *o = vo;
  719. o->i = i;
  720. // init value references
  721. valref_init(&o->ref, v);
  722. // remember deinit
  723. o->deinit_func = deinit_func;
  724. o->deinit_data = deinit_data;
  725. NCDModuleInst_Backend_Up(i);
  726. return;
  727. }
  728. static void func_die (void *vo)
  729. {
  730. struct instance *o = vo;
  731. // deinit
  732. if (o->deinit_func) {
  733. o->deinit_func(o->deinit_data, o->i);
  734. }
  735. // free value reference
  736. valref_free(&o->ref);
  737. NCDModuleInst_Backend_Dead(o->i);
  738. }
  739. static int func_getvar (void *vo, const char *name, NCDValMem *mem, NCDValRef *out)
  740. {
  741. struct instance *o = vo;
  742. struct value *v = valref_val(&o->ref);
  743. if (!strcmp(name, "exists")) {
  744. const char *str = v ? "true" : "false";
  745. *out = NCDVal_NewString(mem, str);
  746. if (NCDVal_IsInvalid(*out)) {
  747. ModuleLog(o->i, BLOG_ERROR, "NCDVal_NewString failed");
  748. }
  749. return 1;
  750. }
  751. if (strcmp(name, "type") && strcmp(name, "length") && strcmp(name, "keys") && strcmp(name, "")) {
  752. return 0;
  753. }
  754. if (!v) {
  755. ModuleLog(o->i, BLOG_ERROR, "value was deleted");
  756. return 0;
  757. }
  758. if (!strcmp(name, "type")) {
  759. *out = NCDVal_NewString(mem, get_type_str(v->type));
  760. if (NCDVal_IsInvalid(*out)) {
  761. ModuleLog(o->i, BLOG_ERROR, "NCDVal_NewString failed");
  762. }
  763. }
  764. else if (!strcmp(name, "length")) {
  765. size_t len;
  766. switch (v->type) {
  767. case NCDVAL_LIST:
  768. len = value_list_len(v);
  769. break;
  770. case NCDVAL_MAP:
  771. len = value_map_len(v);
  772. break;
  773. case NCDVAL_STRING:
  774. len = v->string.length;
  775. break;
  776. default:
  777. ASSERT(0);
  778. }
  779. char str[64];
  780. snprintf(str, sizeof(str), "%zu", len);
  781. *out = NCDVal_NewString(mem, str);
  782. if (NCDVal_IsInvalid(*out)) {
  783. ModuleLog(o->i, BLOG_ERROR, "NCDVal_NewString failed");
  784. }
  785. }
  786. else if (!strcmp(name, "keys")) {
  787. if (v->type != NCDVAL_MAP) {
  788. ModuleLog(o->i, BLOG_ERROR, "value is not a map (reading keys variable)");
  789. return 0;
  790. }
  791. *out = NCDVal_NewList(mem, value_map_len(v));
  792. if (NCDVal_IsInvalid(*out)) {
  793. ModuleLog(o->i, BLOG_ERROR, "NCDVal_NewList failed");
  794. goto fail;
  795. }
  796. for (size_t j = 0; j < value_map_len(v); j++) {
  797. struct value *ev = value_map_at(v, j);
  798. NCDValRef key = NCDVal_NewCopy(mem, ev->map_parent.key);
  799. if (NCDVal_IsInvalid(key)) {
  800. ModuleLog(o->i, BLOG_ERROR, "NCDVal_NewCopy failed");
  801. goto fail;
  802. }
  803. NCDVal_ListAppend(*out, key);
  804. }
  805. }
  806. else if (!strcmp(name, "")) {
  807. if (!value_to_value(o->i, v, mem, out)) {
  808. return 0;
  809. }
  810. }
  811. else {
  812. ASSERT(0);
  813. }
  814. return 1;
  815. fail:
  816. *out = NCDVal_NewInvalid();
  817. return 1;
  818. }
  819. static void func_new_value (void *vo, NCDModuleInst *i)
  820. {
  821. NCDValRef value_arg;
  822. if (!NCDVal_ListRead(i->args, 1, &value_arg)) {
  823. ModuleLog(i, BLOG_ERROR, "wrong arity");
  824. goto fail0;
  825. }
  826. struct value *v = value_init_fromvalue(i, value_arg);
  827. if (!v) {
  828. goto fail0;
  829. }
  830. func_new_common(vo, i, v, NULL, NULL);
  831. return;
  832. fail0:
  833. NCDModuleInst_Backend_SetError(i);
  834. NCDModuleInst_Backend_Dead(i);
  835. }
  836. static void func_new_get (void *vo, NCDModuleInst *i)
  837. {
  838. NCDValRef where_arg;
  839. if (!NCDVal_ListRead(i->args, 1, &where_arg)) {
  840. ModuleLog(i, BLOG_ERROR, "wrong arity");
  841. goto fail0;
  842. }
  843. struct instance *mo = NCDModuleInst_Backend_GetUser((NCDModuleInst *)i->method_user);
  844. struct value *mov = valref_val(&mo->ref);
  845. if (!mov) {
  846. ModuleLog(i, BLOG_ERROR, "value was deleted");
  847. goto fail0;
  848. }
  849. struct value *v = value_get(i, mov, where_arg, 0);
  850. if (!v) {
  851. goto fail0;
  852. }
  853. func_new_common(vo, i, v, NULL, NULL);
  854. return;
  855. fail0:
  856. NCDModuleInst_Backend_SetError(i);
  857. NCDModuleInst_Backend_Dead(i);
  858. }
  859. static void func_new_try_get (void *vo, NCDModuleInst *i)
  860. {
  861. NCDValRef where_arg;
  862. if (!NCDVal_ListRead(i->args, 1, &where_arg)) {
  863. ModuleLog(i, BLOG_ERROR, "wrong arity");
  864. goto fail0;
  865. }
  866. struct instance *mo = NCDModuleInst_Backend_GetUser((NCDModuleInst *)i->method_user);
  867. struct value *mov = valref_val(&mo->ref);
  868. if (!mov) {
  869. ModuleLog(i, BLOG_ERROR, "value was deleted");
  870. goto fail0;
  871. }
  872. struct value *v = value_get(i, mov, where_arg, 1);
  873. func_new_common(vo, i, v, NULL, NULL);
  874. return;
  875. fail0:
  876. NCDModuleInst_Backend_SetError(i);
  877. NCDModuleInst_Backend_Dead(i);
  878. }
  879. static void func_new_getpath (void *vo, NCDModuleInst *i)
  880. {
  881. NCDValRef path_arg;
  882. if (!NCDVal_ListRead(i->args, 1, &path_arg)) {
  883. ModuleLog(i, BLOG_ERROR, "wrong arity");
  884. goto fail0;
  885. }
  886. if (!NCDVal_IsList(path_arg)) {
  887. ModuleLog(i, BLOG_ERROR, "wrong type");
  888. goto fail0;
  889. }
  890. struct instance *mo = NCDModuleInst_Backend_GetUser((NCDModuleInst *)i->method_user);
  891. struct value *mov = valref_val(&mo->ref);
  892. if (!mov) {
  893. ModuleLog(i, BLOG_ERROR, "value was deleted");
  894. goto fail0;
  895. }
  896. struct value *v = value_get_path(i, mov, path_arg);
  897. if (!v) {
  898. goto fail0;
  899. }
  900. func_new_common(vo, i, v, NULL, NULL);
  901. return;
  902. fail0:
  903. NCDModuleInst_Backend_SetError(i);
  904. NCDModuleInst_Backend_Dead(i);
  905. }
  906. static void func_new_insert (void *vo, NCDModuleInst *i)
  907. {
  908. NCDValRef where_arg;
  909. NCDValRef what_arg;
  910. if (!NCDVal_ListRead(i->args, 2, &where_arg, &what_arg)) {
  911. ModuleLog(i, BLOG_ERROR, "wrong arity");
  912. goto fail0;
  913. }
  914. struct instance *mo = NCDModuleInst_Backend_GetUser((NCDModuleInst *)i->method_user);
  915. struct value *mov = valref_val(&mo->ref);
  916. if (!mov) {
  917. ModuleLog(i, BLOG_ERROR, "value was deleted");
  918. goto fail0;
  919. }
  920. struct value *v = value_insert(i, mov, where_arg, what_arg, NULL);
  921. if (!v) {
  922. goto fail0;
  923. }
  924. func_new_common(vo, i, v, NULL, NULL);
  925. return;
  926. fail0:
  927. NCDModuleInst_Backend_SetError(i);
  928. NCDModuleInst_Backend_Dead(i);
  929. }
  930. struct insert_undo_deinit_data {
  931. struct valref val_ref;
  932. struct valref oldval_ref;
  933. };
  934. static void insert_undo_deinit_func (struct insert_undo_deinit_data *data, NCDModuleInst *i)
  935. {
  936. struct value *val = valref_val(&data->val_ref);
  937. struct value *oldval = valref_val(&data->oldval_ref);
  938. if (val && val->parent && (!oldval || !oldval->parent)) {
  939. // get parent
  940. struct value *parent = val->parent;
  941. // remove this value from parent and restore saved one (or none)
  942. switch (parent->type) {
  943. case NCDVAL_LIST: {
  944. size_t index = value_list_indexof(parent, val);
  945. value_list_remove(parent, val);
  946. if (oldval) {
  947. int res = value_list_insert(i, parent, oldval, index);
  948. ASSERT(res)
  949. }
  950. } break;
  951. case NCDVAL_MAP: {
  952. NCDValMem key_mem;
  953. NCDValSafeRef key;
  954. value_map_remove2(parent, val, &key_mem, &key);
  955. if (oldval) {
  956. int res = value_map_insert(parent, oldval, key_mem, key, i);
  957. ASSERT(res)
  958. } else {
  959. NCDValMem_Free(&key_mem);
  960. }
  961. } break;
  962. default: ASSERT(0);
  963. }
  964. }
  965. valref_free(&data->oldval_ref);
  966. valref_free(&data->val_ref);
  967. free(data);
  968. }
  969. static void func_new_insert_undo (void *vo, NCDModuleInst *i)
  970. {
  971. NCDValRef where_arg;
  972. NCDValRef what_arg;
  973. if (!NCDVal_ListRead(i->args, 2, &where_arg, &what_arg)) {
  974. ModuleLog(i, BLOG_ERROR, "wrong arity");
  975. goto fail0;
  976. }
  977. struct instance *mo = NCDModuleInst_Backend_GetUser((NCDModuleInst *)i->method_user);
  978. struct value *mov = valref_val(&mo->ref);
  979. if (!mov) {
  980. ModuleLog(i, BLOG_ERROR, "value was deleted");
  981. goto fail0;
  982. }
  983. struct insert_undo_deinit_data *data = malloc(sizeof(*data));
  984. if (!data) {
  985. ModuleLog(i, BLOG_ERROR, "malloc failed");
  986. goto fail0;
  987. }
  988. struct value *oldv;
  989. struct value *v = value_insert(i, mov, where_arg, what_arg, &oldv);
  990. if (!v) {
  991. goto fail1;
  992. }
  993. valref_init(&data->val_ref, v);
  994. valref_init(&data->oldval_ref, oldv);
  995. func_new_common(vo, i, v, (value_deinit_func)insert_undo_deinit_func, data);
  996. return;
  997. fail1:
  998. free(data);
  999. fail0:
  1000. NCDModuleInst_Backend_SetError(i);
  1001. NCDModuleInst_Backend_Dead(i);
  1002. }
  1003. static void func_new_substr (void *vo, NCDModuleInst *i)
  1004. {
  1005. NCDValRef start_arg;
  1006. NCDValRef length_arg = NCDVal_NewInvalid();
  1007. if (!NCDVal_ListRead(i->args, 1, &start_arg) &&
  1008. !NCDVal_ListRead(i->args, 2, &start_arg, &length_arg)) {
  1009. ModuleLog(i, BLOG_ERROR, "wrong arity");
  1010. goto fail0;
  1011. }
  1012. if (!NCDVal_IsStringNoNulls(start_arg) || (!NCDVal_IsInvalid(length_arg) && !NCDVal_IsStringNoNulls(length_arg))) {
  1013. ModuleLog(i, BLOG_ERROR, "wrong type");
  1014. goto fail0;
  1015. }
  1016. uintmax_t start;
  1017. if (!parse_unsigned_integer(NCDVal_StringValue(start_arg), &start)) {
  1018. ModuleLog(i, BLOG_ERROR, "start is not a number");
  1019. goto fail0;
  1020. }
  1021. uintmax_t length = UINTMAX_MAX;
  1022. if (!NCDVal_IsInvalid(length_arg) && !parse_unsigned_integer(NCDVal_StringValue(length_arg), &length)) {
  1023. ModuleLog(i, BLOG_ERROR, "length is not a number");
  1024. goto fail0;
  1025. }
  1026. struct instance *mo = NCDModuleInst_Backend_GetUser((NCDModuleInst *)i->method_user);
  1027. struct value *mov = valref_val(&mo->ref);
  1028. if (!mov) {
  1029. ModuleLog(i, BLOG_ERROR, "value was deleted");
  1030. goto fail0;
  1031. }
  1032. if (mov->type != NCDVAL_STRING) {
  1033. ModuleLog(i, BLOG_ERROR, "value is not a string");
  1034. goto fail0;
  1035. }
  1036. if (start > mov->string.length) {
  1037. ModuleLog(i, BLOG_ERROR, "start is out of range");
  1038. goto fail0;
  1039. }
  1040. size_t remain = mov->string.length - start;
  1041. size_t amount = length < remain ? length : remain;
  1042. struct value *v = value_init_string(i, mov->string.string + start, amount);
  1043. if (!v) {
  1044. goto fail0;
  1045. }
  1046. func_new_common(vo, i, v, NULL, NULL);
  1047. return;
  1048. fail0:
  1049. NCDModuleInst_Backend_SetError(i);
  1050. NCDModuleInst_Backend_Dead(i);
  1051. }
  1052. static void remove_func_new (NCDModuleInst *i)
  1053. {
  1054. NCDValRef where_arg;
  1055. if (!NCDVal_ListRead(i->args, 1, &where_arg)) {
  1056. ModuleLog(i, BLOG_ERROR, "wrong arity");
  1057. goto fail0;
  1058. }
  1059. struct instance *mo = NCDModuleInst_Backend_GetUser((NCDModuleInst *)i->method_user);
  1060. struct value *mov = valref_val(&mo->ref);
  1061. if (!mov) {
  1062. ModuleLog(i, BLOG_ERROR, "value was deleted");
  1063. goto fail0;
  1064. }
  1065. if (!value_remove(i, mov, where_arg)) {
  1066. goto fail0;
  1067. }
  1068. NCDModuleInst_Backend_Up(i);
  1069. return;
  1070. fail0:
  1071. NCDModuleInst_Backend_SetError(i);
  1072. NCDModuleInst_Backend_Dead(i);
  1073. }
  1074. static void delete_func_new (NCDModuleInst *i)
  1075. {
  1076. if (!NCDVal_ListRead(i->args, 0)) {
  1077. ModuleLog(i, BLOG_ERROR, "wrong arity");
  1078. goto fail0;
  1079. }
  1080. struct instance *mo = NCDModuleInst_Backend_GetUser((NCDModuleInst *)i->method_user);
  1081. struct value *mov = valref_val(&mo->ref);
  1082. if (!mov) {
  1083. ModuleLog(i, BLOG_ERROR, "value was deleted");
  1084. goto fail0;
  1085. }
  1086. value_delete(mov);
  1087. NCDModuleInst_Backend_Up(i);
  1088. return;
  1089. fail0:
  1090. NCDModuleInst_Backend_SetError(i);
  1091. NCDModuleInst_Backend_Dead(i);
  1092. }
  1093. static const struct NCDModule modules[] = {
  1094. {
  1095. .type = "value",
  1096. .func_new2 = func_new_value,
  1097. .func_die = func_die,
  1098. .func_getvar = func_getvar,
  1099. .alloc_size = sizeof(struct instance)
  1100. }, {
  1101. .type = "value::get",
  1102. .base_type = "value",
  1103. .func_new2 = func_new_get,
  1104. .func_die = func_die,
  1105. .func_getvar = func_getvar,
  1106. .alloc_size = sizeof(struct instance)
  1107. }, {
  1108. .type = "value::try_get",
  1109. .base_type = "value",
  1110. .func_new2 = func_new_try_get,
  1111. .func_die = func_die,
  1112. .func_getvar = func_getvar,
  1113. .alloc_size = sizeof(struct instance)
  1114. }, {
  1115. .type = "value::getpath",
  1116. .base_type = "value",
  1117. .func_new2 = func_new_getpath,
  1118. .func_die = func_die,
  1119. .func_getvar = func_getvar,
  1120. .alloc_size = sizeof(struct instance)
  1121. }, {
  1122. .type = "value::insert",
  1123. .base_type = "value",
  1124. .func_new2 = func_new_insert,
  1125. .func_die = func_die,
  1126. .func_getvar = func_getvar,
  1127. .alloc_size = sizeof(struct instance)
  1128. }, {
  1129. .type = "value::insert_undo",
  1130. .base_type = "value",
  1131. .func_new2 = func_new_insert_undo,
  1132. .func_die = func_die,
  1133. .func_getvar = func_getvar,
  1134. .alloc_size = sizeof(struct instance)
  1135. }, {
  1136. .type = "value::remove",
  1137. .func_new = remove_func_new
  1138. }, {
  1139. .type = "value::delete",
  1140. .func_new = delete_func_new
  1141. }, {
  1142. .type = "value::substr",
  1143. .base_type = "value",
  1144. .func_new2 = func_new_substr,
  1145. .func_die = func_die,
  1146. .func_getvar = func_getvar,
  1147. .alloc_size = sizeof(struct instance)
  1148. }, {
  1149. .type = NULL
  1150. }
  1151. };
  1152. const struct NCDModuleGroup ncdmodule_value = {
  1153. .modules = modules
  1154. };