value.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  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_remove(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_remove(where, what) is like value::insert(), except that it
  70. * also removes the value that was inserted on deinitialization (except if it
  71. * was removed externally, or deleted entirely).
  72. *
  73. * Variables:
  74. * (empty) - the value stored in the value object
  75. * type - type of the value; "string", "list" or "map"
  76. * length - number of elements in the list or map (only if the value if a list
  77. * or a map)
  78. * keys - a list of keys in the map (only if the value is a map)
  79. * exists - "true" or "false", reflecting whether the value object holds a value
  80. * (is not in deleted state)
  81. *
  82. * Synopsis:
  83. * value::remove(where)
  84. * value::delete()
  85. *
  86. * Description:
  87. * value::remove(where) removes from an existing value object.
  88. * For lists, 'where' is the index of the element to remove, and must be in range.
  89. * For maps, 'where' is the key to remove, and must be an existing key.
  90. * In any case, any references to the removed value remain valid.
  91. *
  92. * value::delete() deletes the underlying value data of this value object.
  93. * After delection, the value object enters a deleted state, which will cause any
  94. * operation on it to fail. Any other value objects which referred to the same value
  95. * or parts of it will too enter deleted state. If the value was an element
  96. * in a list or map, is is removed from it.
  97. */
  98. #include <stdlib.h>
  99. #include <string.h>
  100. #include <stddef.h>
  101. #include <limits.h>
  102. #include <misc/offset.h>
  103. #include <misc/debug.h>
  104. #include <misc/parse_number.h>
  105. #include <structure/LinkedList0.h>
  106. #include <structure/IndexedList.h>
  107. #include <structure/BCountAVL.h>
  108. #include <ncd/NCDModule.h>
  109. #include <generated/blog_channel_ncd_value.h>
  110. #define ModuleLog(i, ...) NCDModuleInst_Backend_Log((i), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
  111. struct value;
  112. struct valref {
  113. struct value *v;
  114. LinkedList0Node refs_list_node;
  115. };
  116. struct instance {
  117. NCDModuleInst *i;
  118. struct valref ref;
  119. struct valref restore_ref;
  120. int restore_on_deinit;
  121. };
  122. struct value {
  123. LinkedList0 refs_list;
  124. struct value *parent;
  125. union {
  126. struct {
  127. IndexedListNode list_contents_il_node;
  128. } list_parent;
  129. struct {
  130. NCDValue key;
  131. BCountAVLNode map_contents_tree_node;
  132. } map_parent;
  133. };
  134. int type;
  135. union {
  136. struct {
  137. char *string;
  138. } string;
  139. struct {
  140. IndexedList list_contents_il;
  141. } list;
  142. struct {
  143. BCountAVL map_contents_tree;
  144. } map;
  145. };
  146. };
  147. static int ncdvalue_comparator (void *unused, void *vv1, void *vv2);
  148. static const char * get_type_str (int type);
  149. static void value_cleanup (struct value *v);
  150. static void value_delete (struct value *v);
  151. static struct value * value_init_string (NCDModuleInst *i, const char *str);
  152. static struct value * value_init_list (NCDModuleInst *i);
  153. static size_t value_list_len (struct value *v);
  154. static struct value * value_list_at (struct value *v, size_t index);
  155. static size_t value_list_indexof (struct value *v, struct value *ev);
  156. static int value_list_insert (NCDModuleInst *i, struct value *list, struct value *v, size_t index);
  157. static void value_list_remove (struct value *list, struct value *v);
  158. static struct value * value_init_map (NCDModuleInst *i);
  159. static size_t value_map_len (struct value *map);
  160. static struct value * value_map_at (struct value *map, size_t index);
  161. static struct value * value_map_find (struct value *map, NCDValue *key);
  162. static int value_map_insert (struct value *map, struct value *v, NCDValue key, NCDModuleInst *i);
  163. static void value_map_remove (struct value *map, struct value *v);
  164. static void value_map_remove2 (struct value *map, struct value *v, NCDValue *out_key);
  165. static struct value * value_init_fromvalue (NCDModuleInst *i, NCDValue *value);
  166. static int value_to_value (NCDModuleInst *i, struct value *v, NCDValue *out_value);
  167. static struct value * value_get (NCDModuleInst *i, struct value *v, NCDValue *where, int no_error);
  168. static struct value * value_get_path (NCDModuleInst *i, struct value *v, NCDValue *path);
  169. static struct value * value_insert (NCDModuleInst *i, struct value *v, NCDValue *where, NCDValue *what);
  170. static int value_remove (NCDModuleInst *i, struct value *v, NCDValue *where);
  171. static void valref_init (struct valref *r, struct value *v);
  172. static void valref_free (struct valref *r);
  173. static struct value * valref_val (struct valref *r);
  174. static void valref_break (struct valref *r);
  175. static int ncdvalue_comparator (void *unused, void *vv1, void *vv2)
  176. {
  177. NCDValue *v1 = vv1;
  178. NCDValue *v2 = vv2;
  179. return NCDValue_Compare(v1, v2);
  180. }
  181. static const char * get_type_str (int type)
  182. {
  183. switch (type) {
  184. case NCDVALUE_STRING: return "string";
  185. case NCDVALUE_LIST: return "list";
  186. case NCDVALUE_MAP: return "map";
  187. }
  188. ASSERT(0)
  189. return NULL;
  190. }
  191. static void value_cleanup (struct value *v)
  192. {
  193. if (v->parent || !LinkedList0_IsEmpty(&v->refs_list)) {
  194. return;
  195. }
  196. switch (v->type) {
  197. case NCDVALUE_STRING: {
  198. free(v->string.string);
  199. } break;
  200. case NCDVALUE_LIST: {
  201. while (value_list_len(v) > 0) {
  202. struct value *ev = value_list_at(v, 0);
  203. value_list_remove(v, ev);
  204. value_cleanup(ev);
  205. }
  206. } break;
  207. case NCDVALUE_MAP: {
  208. while (value_map_len(v) > 0) {
  209. struct value *ev = value_map_at(v, 0);
  210. value_map_remove(v, ev);
  211. value_cleanup(ev);
  212. }
  213. } break;
  214. default: ASSERT(0);
  215. }
  216. free(v);
  217. }
  218. static void value_delete (struct value *v)
  219. {
  220. if (v->parent) {
  221. switch (v->parent->type) {
  222. case NCDVALUE_LIST: {
  223. value_list_remove(v->parent, v);
  224. } break;
  225. case NCDVALUE_MAP: {
  226. value_map_remove(v->parent, v);
  227. } break;
  228. default: ASSERT(0);
  229. }
  230. }
  231. LinkedList0Node *ln;
  232. while (ln = LinkedList0_GetFirst(&v->refs_list)) {
  233. struct valref *r = UPPER_OBJECT(ln, struct valref, refs_list_node);
  234. ASSERT(r->v == v)
  235. valref_break(r);
  236. }
  237. switch (v->type) {
  238. case NCDVALUE_STRING: {
  239. free(v->string.string);
  240. } break;
  241. case NCDVALUE_LIST: {
  242. while (value_list_len(v) > 0) {
  243. struct value *ev = value_list_at(v, 0);
  244. value_delete(ev);
  245. }
  246. } break;
  247. case NCDVALUE_MAP: {
  248. while (value_map_len(v) > 0) {
  249. struct value *ev = value_map_at(v, 0);
  250. value_delete(ev);
  251. }
  252. } break;
  253. default: ASSERT(0);
  254. }
  255. free(v);
  256. }
  257. static struct value * value_init_string (NCDModuleInst *i, const char *str)
  258. {
  259. struct value *v = malloc(sizeof(*v));
  260. if (!v) {
  261. ModuleLog(i, BLOG_ERROR, "malloc failed");
  262. goto fail0;
  263. }
  264. LinkedList0_Init(&v->refs_list);
  265. v->parent = NULL;
  266. v->type = NCDVALUE_STRING;
  267. if (!(v->string.string = strdup(str))) {
  268. ModuleLog(i, BLOG_ERROR, "strdup failed");
  269. goto fail1;
  270. }
  271. return v;
  272. fail1:
  273. free(v);
  274. fail0:
  275. return NULL;
  276. }
  277. static struct value * value_init_list (NCDModuleInst *i)
  278. {
  279. struct value *v = malloc(sizeof(*v));
  280. if (!v) {
  281. ModuleLog(i, BLOG_ERROR, "malloc failed");
  282. return NULL;
  283. }
  284. LinkedList0_Init(&v->refs_list);
  285. v->parent = NULL;
  286. v->type = NCDVALUE_LIST;
  287. IndexedList_Init(&v->list.list_contents_il);
  288. return v;
  289. }
  290. static size_t value_list_len (struct value *v)
  291. {
  292. ASSERT(v->type == NCDVALUE_LIST)
  293. return IndexedList_Count(&v->list.list_contents_il);
  294. }
  295. static struct value * value_list_at (struct value *v, size_t index)
  296. {
  297. ASSERT(v->type == NCDVALUE_LIST)
  298. ASSERT(index < value_list_len(v))
  299. IndexedListNode *iln = IndexedList_GetAt(&v->list.list_contents_il, index);
  300. ASSERT(iln)
  301. struct value *e = UPPER_OBJECT(iln, struct value, list_parent.list_contents_il_node);
  302. ASSERT(e->parent == v)
  303. return e;
  304. }
  305. static size_t value_list_indexof (struct value *v, struct value *ev)
  306. {
  307. ASSERT(v->type == NCDVALUE_LIST)
  308. ASSERT(ev->parent == v)
  309. uint64_t index = IndexedList_IndexOf(&v->list.list_contents_il, &ev->list_parent.list_contents_il_node);
  310. ASSERT(index < value_list_len(v))
  311. return index;
  312. }
  313. static int value_list_insert (NCDModuleInst *i, struct value *list, struct value *v, size_t index)
  314. {
  315. ASSERT(list->type == NCDVALUE_LIST)
  316. ASSERT(!v->parent)
  317. ASSERT(index <= value_list_len(list))
  318. if (value_list_len(list) == SIZE_MAX) {
  319. ModuleLog(i, BLOG_ERROR, "list has too many elements");
  320. return 0;
  321. }
  322. IndexedList_InsertAt(&list->list.list_contents_il, &v->list_parent.list_contents_il_node, index);
  323. v->parent = list;
  324. return 1;
  325. }
  326. static void value_list_remove (struct value *list, struct value *v)
  327. {
  328. ASSERT(list->type == NCDVALUE_LIST)
  329. ASSERT(v->parent == list)
  330. IndexedList_Remove(&list->list.list_contents_il, &v->list_parent.list_contents_il_node);
  331. v->parent = NULL;
  332. }
  333. static struct value * value_init_map (NCDModuleInst *i)
  334. {
  335. struct value *v = malloc(sizeof(*v));
  336. if (!v) {
  337. ModuleLog(i, BLOG_ERROR, "malloc failed");
  338. return NULL;
  339. }
  340. LinkedList0_Init(&v->refs_list);
  341. v->parent = NULL;
  342. v->type = NCDVALUE_MAP;
  343. BCountAVL_Init(&v->map.map_contents_tree, OFFSET_DIFF(struct value, map_parent.key, map_parent.map_contents_tree_node), ncdvalue_comparator, NULL);
  344. return v;
  345. }
  346. static size_t value_map_len (struct value *map)
  347. {
  348. ASSERT(map->type == NCDVALUE_MAP)
  349. return BCountAVL_Count(&map->map.map_contents_tree);
  350. }
  351. static struct value * value_map_at (struct value *map, size_t index)
  352. {
  353. ASSERT(map->type == NCDVALUE_MAP)
  354. ASSERT(index < value_map_len(map))
  355. BCountAVLNode *tn = BCountAVL_GetAt(&map->map.map_contents_tree, index);
  356. ASSERT(tn)
  357. struct value *e = UPPER_OBJECT(tn, struct value, map_parent.map_contents_tree_node);
  358. ASSERT(e->parent == map)
  359. return e;
  360. }
  361. static struct value * value_map_find (struct value *map, NCDValue *key)
  362. {
  363. ASSERT(map->type == NCDVALUE_MAP)
  364. ASSERT(key)
  365. BCountAVLNode *tn = BCountAVL_LookupExact(&map->map.map_contents_tree, key);
  366. if (!tn) {
  367. return NULL;
  368. }
  369. struct value *e = UPPER_OBJECT(tn, struct value, map_parent.map_contents_tree_node);
  370. ASSERT(e->parent == map)
  371. return e;
  372. }
  373. static int value_map_insert (struct value *map, struct value *v, NCDValue key, NCDModuleInst *i)
  374. {
  375. ASSERT(map->type == NCDVALUE_MAP)
  376. ASSERT(!v->parent)
  377. ASSERT(!value_map_find(map, &key))
  378. if (value_map_len(map) == SIZE_MAX) {
  379. ModuleLog(i, BLOG_ERROR, "map has too many elements");
  380. return 0;
  381. }
  382. v->map_parent.key = key;
  383. int res = BCountAVL_Insert(&map->map.map_contents_tree, &v->map_parent.map_contents_tree_node, NULL);
  384. ASSERT(res)
  385. v->parent = map;
  386. return 1;
  387. }
  388. static void value_map_remove (struct value *map, struct value *v)
  389. {
  390. ASSERT(map->type == NCDVALUE_MAP)
  391. ASSERT(v->parent == map)
  392. BCountAVL_Remove(&map->map.map_contents_tree, &v->map_parent.map_contents_tree_node);
  393. NCDValue_Free(&v->map_parent.key);
  394. v->parent = NULL;
  395. }
  396. static void value_map_remove2 (struct value *map, struct value *v, NCDValue *out_key)
  397. {
  398. ASSERT(map->type == NCDVALUE_MAP)
  399. ASSERT(v->parent == map)
  400. ASSERT(out_key)
  401. BCountAVL_Remove(&map->map.map_contents_tree, &v->map_parent.map_contents_tree_node);
  402. *out_key = v->map_parent.key;
  403. v->parent = NULL;
  404. }
  405. static struct value * value_init_fromvalue (NCDModuleInst *i, NCDValue *value)
  406. {
  407. struct value *v;
  408. switch (NCDValue_Type(value)) {
  409. case NCDVALUE_STRING: {
  410. if (!(v = value_init_string(i, NCDValue_StringValue(value)))) {
  411. goto fail0;
  412. }
  413. } break;
  414. case NCDVALUE_LIST: {
  415. if (!(v = value_init_list(i))) {
  416. goto fail0;
  417. }
  418. for (NCDValue *eval = NCDValue_ListFirst(value); eval; eval = NCDValue_ListNext(value, eval)) {
  419. struct value *ev = value_init_fromvalue(i, eval);
  420. if (!ev) {
  421. goto fail1;
  422. }
  423. if (!value_list_insert(i, v, ev, value_list_len(v))) {
  424. value_cleanup(ev);
  425. goto fail1;
  426. }
  427. }
  428. } break;
  429. case NCDVALUE_MAP: {
  430. if (!(v = value_init_map(i))) {
  431. goto fail0;
  432. }
  433. for (NCDValue *ekey = NCDValue_MapFirstKey(value); ekey; ekey = NCDValue_MapNextKey(value, ekey)) {
  434. NCDValue *eval = NCDValue_MapKeyValue(value, ekey);
  435. NCDValue key;
  436. if (!NCDValue_InitCopy(&key, ekey)) {
  437. BLog(BLOG_ERROR, "NCDValue_InitCopy failed");
  438. goto fail1;
  439. }
  440. struct value *ev = value_init_fromvalue(i, eval);
  441. if (!ev) {
  442. NCDValue_Free(&key);
  443. goto fail1;
  444. }
  445. if (!value_map_insert(v, ev, key, i)) {
  446. NCDValue_Free(&key);
  447. value_cleanup(ev);
  448. goto fail1;
  449. }
  450. }
  451. } break;
  452. default: ASSERT(0);
  453. }
  454. return v;
  455. fail1:
  456. value_cleanup(v);
  457. fail0:
  458. return NULL;
  459. }
  460. static int value_to_value (NCDModuleInst *i, struct value *v, NCDValue *out_value)
  461. {
  462. switch (v->type) {
  463. case NCDVALUE_STRING: {
  464. if (!(NCDValue_InitString(out_value, v->string.string))) {
  465. ModuleLog(i, BLOG_ERROR, "NCDValue_InitString failed");
  466. goto fail0;
  467. }
  468. } break;
  469. case NCDVALUE_LIST: {
  470. NCDValue_InitList(out_value);
  471. for (size_t index = 0; index < value_list_len(v); index++) {
  472. NCDValue eval;
  473. if (!value_to_value(i, value_list_at(v, index), &eval)) {
  474. goto fail1;
  475. }
  476. if (!NCDValue_ListAppend(out_value, eval)) {
  477. ModuleLog(i, BLOG_ERROR, "NCDValue_ListAppend failed");
  478. NCDValue_Free(&eval);
  479. goto fail1;
  480. }
  481. }
  482. } break;
  483. case NCDVALUE_MAP: {
  484. NCDValue_InitMap(out_value);
  485. for (size_t index = 0; index < value_map_len(v); index++) {
  486. struct value *ev = value_map_at(v, index);
  487. NCDValue key;
  488. NCDValue val;
  489. if (!NCDValue_InitCopy(&key, &ev->map_parent.key)) {
  490. ModuleLog(i, BLOG_ERROR, "NCDValue_InitCopy failed");
  491. goto fail1;
  492. }
  493. if (!value_to_value(i, ev, &val)) {
  494. NCDValue_Free(&key);
  495. goto fail1;
  496. }
  497. if (!NCDValue_MapInsert(out_value, key, val)) {
  498. ModuleLog(i, BLOG_ERROR, "NCDValue_MapInsert failed");
  499. NCDValue_Free(&key);
  500. NCDValue_Free(&val);
  501. goto fail1;
  502. }
  503. }
  504. } break;
  505. default: ASSERT(0);
  506. }
  507. return 1;
  508. fail1:
  509. NCDValue_Free(out_value);
  510. fail0:
  511. return 0;
  512. }
  513. static struct value * value_get (NCDModuleInst *i, struct value *v, NCDValue *where, int no_error)
  514. {
  515. switch (v->type) {
  516. case NCDVALUE_STRING: {
  517. if (!no_error) ModuleLog(i, BLOG_ERROR, "cannot resolve into a string");
  518. goto fail;
  519. } break;
  520. case NCDVALUE_LIST: {
  521. if (NCDValue_Type(where) != NCDVALUE_STRING) {
  522. if (!no_error) ModuleLog(i, BLOG_ERROR, "index is not a string (resolving into list)");
  523. goto fail;
  524. }
  525. uintmax_t index;
  526. if (!parse_unsigned_integer(NCDValue_StringValue(where), &index)) {
  527. if (!no_error) ModuleLog(i, BLOG_ERROR, "index is not a valid number (resolving into list)");
  528. goto fail;
  529. }
  530. if (index >= value_list_len(v)) {
  531. if (!no_error) ModuleLog(i, BLOG_ERROR, "index is out of bounds (resolving into list)");
  532. goto fail;
  533. }
  534. v = value_list_at(v, index);
  535. } break;
  536. case NCDVALUE_MAP: {
  537. v = value_map_find(v, where);
  538. if (!v) {
  539. if (!no_error) ModuleLog(i, BLOG_ERROR, "key does not exist (resolving into map)");
  540. goto fail;
  541. }
  542. } break;
  543. default: ASSERT(0);
  544. }
  545. return v;
  546. fail:
  547. return NULL;
  548. }
  549. static struct value * value_get_path (NCDModuleInst *i, struct value *v, NCDValue *path)
  550. {
  551. ASSERT(NCDValue_Type(path) == NCDVALUE_LIST)
  552. for (NCDValue *ev = NCDValue_ListFirst(path); ev; ev = NCDValue_ListNext(path, ev)) {
  553. if (!(v = value_get(i, v, ev, 0))) {
  554. goto fail;
  555. }
  556. }
  557. return v;
  558. fail:
  559. return NULL;
  560. }
  561. static struct value * value_insert (NCDModuleInst *i, struct value *v, NCDValue *where, NCDValue *what)
  562. {
  563. struct value *nv;
  564. switch (v->type) {
  565. case NCDVALUE_STRING: {
  566. ModuleLog(i, BLOG_ERROR, "cannot insert into a string");
  567. goto fail;
  568. } break;
  569. case NCDVALUE_LIST: {
  570. if (NCDValue_Type(where) != NCDVALUE_STRING) {
  571. ModuleLog(i, BLOG_ERROR, "index is not a string (inserting into list)");
  572. goto fail;
  573. }
  574. uintmax_t index;
  575. if (!parse_unsigned_integer(NCDValue_StringValue(where), &index)) {
  576. ModuleLog(i, BLOG_ERROR, "index is not a valid number (inserting into list)");
  577. goto fail;
  578. }
  579. if (index > value_list_len(v)) {
  580. ModuleLog(i, BLOG_ERROR, "index is out of bounds (inserting into list)");
  581. goto fail;
  582. }
  583. nv = value_init_fromvalue(i, what);
  584. if (!nv) {
  585. goto fail;
  586. }
  587. if (!value_list_insert(i, v, nv, index)) {
  588. value_cleanup(nv);
  589. goto fail;
  590. }
  591. } break;
  592. case NCDVALUE_MAP: {
  593. struct value *ov = value_map_find(v, where);
  594. if (!ov && value_map_len(v) == SIZE_MAX) {
  595. ModuleLog(i, BLOG_ERROR, "map has too many elements");
  596. goto fail;
  597. }
  598. NCDValue key;
  599. if (!NCDValue_InitCopy(&key, where)) {
  600. ModuleLog(i, BLOG_ERROR, "NCDValue_InitCopy failed");
  601. goto fail;
  602. }
  603. nv = value_init_fromvalue(i, what);
  604. if (!nv) {
  605. NCDValue_Free(&key);
  606. goto fail;
  607. }
  608. if (ov) {
  609. value_map_remove(v, ov);
  610. value_cleanup(ov);
  611. }
  612. int res = value_map_insert(v, nv, key, i);
  613. ASSERT(res)
  614. } break;
  615. default: ASSERT(0);
  616. }
  617. return nv;
  618. fail:
  619. return NULL;
  620. }
  621. static int value_remove (NCDModuleInst *i, struct value *v, NCDValue *where)
  622. {
  623. switch (v->type) {
  624. case NCDVALUE_STRING: {
  625. ModuleLog(i, BLOG_ERROR, "cannot remove from a string");
  626. goto fail;
  627. } break;
  628. case NCDVALUE_LIST: {
  629. if (NCDValue_Type(where) != NCDVALUE_STRING) {
  630. ModuleLog(i, BLOG_ERROR, "index is not a string (removing from list)");
  631. goto fail;
  632. }
  633. uintmax_t index;
  634. if (!parse_unsigned_integer(NCDValue_StringValue(where), &index)) {
  635. ModuleLog(i, BLOG_ERROR, "index is not a valid number (removing from list)");
  636. goto fail;
  637. }
  638. if (index >= value_list_len(v)) {
  639. ModuleLog(i, BLOG_ERROR, "index is out of bounds (removing from list)");
  640. goto fail;
  641. }
  642. struct value *ov = value_list_at(v, index);
  643. value_list_remove(v, ov);
  644. value_cleanup(ov);
  645. } break;
  646. case NCDVALUE_MAP: {
  647. struct value *ov = value_map_find(v, where);
  648. if (!ov) {
  649. ModuleLog(i, BLOG_ERROR, "key does not exist (removing from map)");
  650. goto fail;
  651. }
  652. value_map_remove(v, ov);
  653. value_cleanup(ov);
  654. } break;
  655. default: ASSERT(0);
  656. }
  657. return 1;
  658. fail:
  659. return 0;
  660. }
  661. static void valref_init (struct valref *r, struct value *v)
  662. {
  663. r->v = v;
  664. if (v) {
  665. LinkedList0_Prepend(&v->refs_list, &r->refs_list_node);
  666. }
  667. }
  668. static void valref_free (struct valref *r)
  669. {
  670. if (r->v) {
  671. LinkedList0_Remove(&r->v->refs_list, &r->refs_list_node);
  672. value_cleanup(r->v);
  673. }
  674. }
  675. static struct value * valref_val (struct valref *r)
  676. {
  677. return r->v;
  678. }
  679. static void valref_break (struct valref *r)
  680. {
  681. ASSERT(r->v)
  682. LinkedList0_Remove(&r->v->refs_list, &r->refs_list_node);
  683. r->v = NULL;
  684. }
  685. static void func_new_common (NCDModuleInst *i, struct value *v, int restore_on_deinit, struct value *restore_v)
  686. {
  687. ASSERT(!(!restore_on_deinit) || !restore_v)
  688. ASSERT(!(restore_v) || !restore_v->parent)
  689. // allocate instance
  690. struct instance *o = malloc(sizeof(*o));
  691. if (!o) {
  692. ModuleLog(i, BLOG_ERROR, "failed to allocate instance");
  693. goto fail0;
  694. }
  695. o->i = i;
  696. NCDModuleInst_Backend_SetUser(i, o);
  697. // init value references
  698. valref_init(&o->ref, v);
  699. valref_init(&o->restore_ref, restore_v);
  700. // set restore on deinit flag
  701. o->restore_on_deinit = restore_on_deinit;
  702. NCDModuleInst_Backend_Up(i);
  703. return;
  704. fail1:
  705. free(o);
  706. fail0:
  707. value_cleanup(v);
  708. NCDModuleInst_Backend_SetError(i);
  709. NCDModuleInst_Backend_Dead(i);
  710. }
  711. static void func_die (void *vo)
  712. {
  713. struct instance *o = vo;
  714. NCDModuleInst *i = o->i;
  715. struct value *v = valref_val(&o->ref);
  716. if (o->restore_on_deinit && v && v->parent) {
  717. // get restore value
  718. struct value *rv = valref_val(&o->restore_ref);
  719. ASSERT(!rv || !rv->parent)
  720. // remove this value from parent and restore saved one (or none)
  721. switch (v->parent->type) {
  722. case NCDVALUE_LIST: {
  723. size_t index = value_list_indexof(v->parent, v);
  724. value_list_remove(v->parent, v);
  725. if (rv) {
  726. int res = value_list_insert(i, v->parent, rv, index);
  727. ASSERT(res)
  728. }
  729. } break;
  730. case NCDVALUE_MAP: {
  731. NCDValue key;
  732. value_map_remove2(v->parent, v, &key);
  733. if (rv) {
  734. int res = value_map_insert(v->parent, rv, key, i);
  735. ASSERT(res)
  736. } else {
  737. NCDValue_Free(&key);
  738. }
  739. } break;
  740. default: ASSERT(0);
  741. }
  742. }
  743. // free value references
  744. valref_free(&o->ref);
  745. valref_free(&o->restore_ref);
  746. // free instance
  747. free(o);
  748. NCDModuleInst_Backend_Dead(i);
  749. }
  750. static int func_getvar (void *vo, const char *name, NCDValue *out_value)
  751. {
  752. struct instance *o = vo;
  753. struct value *v = valref_val(&o->ref);
  754. if (!strcmp(name, "exists")) {
  755. const char *str = v ? "true" : "false";
  756. if (!NCDValue_InitString(out_value, str)) {
  757. ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitString failed");
  758. return 0;
  759. }
  760. return 1;
  761. }
  762. if (strcmp(name, "type") && strcmp(name, "length") && strcmp(name, "keys") && strcmp(name, "")) {
  763. return 0;
  764. }
  765. if (!v) {
  766. ModuleLog(o->i, BLOG_ERROR, "value was deleted");
  767. return 0;
  768. }
  769. if (!strcmp(name, "type")) {
  770. if (!NCDValue_InitString(out_value, get_type_str(v->type))) {
  771. ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitString failed");
  772. return 0;
  773. }
  774. }
  775. else if (!strcmp(name, "length")) {
  776. size_t len;
  777. switch (v->type) {
  778. case NCDVALUE_LIST:
  779. len = value_list_len(v);
  780. break;
  781. case NCDVALUE_MAP:
  782. len = value_map_len(v);
  783. break;
  784. default:
  785. ModuleLog(o->i, BLOG_ERROR, "value is not a list or map");
  786. return 0;
  787. }
  788. char str[64];
  789. snprintf(str, sizeof(str), "%zu", len);
  790. if (!NCDValue_InitString(out_value, str)) {
  791. ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitString failed");
  792. return 0;
  793. }
  794. }
  795. else if (!strcmp(name, "keys")) {
  796. if (v->type != NCDVALUE_MAP) {
  797. ModuleLog(o->i, BLOG_ERROR, "value is not a map (reading keys variable)");
  798. return 0;
  799. }
  800. NCDValue_InitList(out_value);
  801. for (size_t i = 0; i < value_map_len(v); i++) {
  802. struct value *ev = value_map_at(v, i);
  803. NCDValue key;
  804. if (!NCDValue_InitCopy(&key, &ev->map_parent.key)) {
  805. ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitCopy failed");
  806. goto map_fail1;
  807. }
  808. if (!NCDValue_ListAppend(out_value, key)) {
  809. ModuleLog(o->i, BLOG_ERROR, "NCDValue_ListAppend failed");
  810. NCDValue_Free(&key);
  811. goto map_fail1;
  812. }
  813. }
  814. return 1;
  815. map_fail1:
  816. NCDValue_Free(out_value);
  817. return 0;
  818. }
  819. else if (!strcmp(name, "")) {
  820. if (!value_to_value(o->i, v, out_value)) {
  821. return 0;
  822. }
  823. }
  824. else {
  825. ASSERT(0);
  826. }
  827. return 1;
  828. }
  829. static void func_new_value (NCDModuleInst *i)
  830. {
  831. NCDValue *value_arg;
  832. if (!NCDValue_ListRead(i->args, 1, &value_arg)) {
  833. ModuleLog(i, BLOG_ERROR, "wrong arity");
  834. goto fail0;
  835. }
  836. struct value *v = value_init_fromvalue(i, value_arg);
  837. if (!v) {
  838. goto fail0;
  839. }
  840. func_new_common(i, v, 0, NULL);
  841. return;
  842. fail0:
  843. NCDModuleInst_Backend_SetError(i);
  844. NCDModuleInst_Backend_Dead(i);
  845. }
  846. static void func_new_get (NCDModuleInst *i)
  847. {
  848. NCDValue *where_arg;
  849. if (!NCDValue_ListRead(i->args, 1, &where_arg)) {
  850. ModuleLog(i, BLOG_ERROR, "wrong arity");
  851. goto fail0;
  852. }
  853. struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
  854. struct value *mov = valref_val(&mo->ref);
  855. if (!mov) {
  856. ModuleLog(i, BLOG_ERROR, "value was deleted");
  857. goto fail0;
  858. }
  859. struct value *v = value_get(i, mov, where_arg, 0);
  860. if (!v) {
  861. goto fail0;
  862. }
  863. func_new_common(i, v, 0, NULL);
  864. return;
  865. fail0:
  866. NCDModuleInst_Backend_SetError(i);
  867. NCDModuleInst_Backend_Dead(i);
  868. }
  869. static void func_new_try_get (NCDModuleInst *i)
  870. {
  871. NCDValue *where_arg;
  872. if (!NCDValue_ListRead(i->args, 1, &where_arg)) {
  873. ModuleLog(i, BLOG_ERROR, "wrong arity");
  874. goto fail0;
  875. }
  876. struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
  877. struct value *mov = valref_val(&mo->ref);
  878. if (!mov) {
  879. ModuleLog(i, BLOG_ERROR, "value was deleted");
  880. goto fail0;
  881. }
  882. struct value *v = value_get(i, mov, where_arg, 1);
  883. func_new_common(i, v, 0, NULL);
  884. return;
  885. fail0:
  886. NCDModuleInst_Backend_SetError(i);
  887. NCDModuleInst_Backend_Dead(i);
  888. }
  889. static void func_new_getpath (NCDModuleInst *i)
  890. {
  891. NCDValue *path_arg;
  892. if (!NCDValue_ListRead(i->args, 1, &path_arg)) {
  893. ModuleLog(i, BLOG_ERROR, "wrong arity");
  894. goto fail0;
  895. }
  896. if (NCDValue_Type(path_arg) != NCDVALUE_LIST) {
  897. ModuleLog(i, BLOG_ERROR, "wrong type");
  898. goto fail0;
  899. }
  900. struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
  901. struct value *mov = valref_val(&mo->ref);
  902. if (!mov) {
  903. ModuleLog(i, BLOG_ERROR, "value was deleted");
  904. goto fail0;
  905. }
  906. struct value *v = value_get_path(i, mov, path_arg);
  907. if (!v) {
  908. goto fail0;
  909. }
  910. func_new_common(i, v, 0, NULL);
  911. return;
  912. fail0:
  913. NCDModuleInst_Backend_SetError(i);
  914. NCDModuleInst_Backend_Dead(i);
  915. }
  916. static void func_new_insert (NCDModuleInst *i)
  917. {
  918. NCDValue *where_arg;
  919. NCDValue *what_arg;
  920. if (!NCDValue_ListRead(i->args, 2, &where_arg, &what_arg)) {
  921. ModuleLog(i, BLOG_ERROR, "wrong arity");
  922. goto fail0;
  923. }
  924. struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
  925. struct value *mov = valref_val(&mo->ref);
  926. if (!mov) {
  927. ModuleLog(i, BLOG_ERROR, "value was deleted");
  928. goto fail0;
  929. }
  930. struct value *v = value_insert(i, mov, where_arg, what_arg);
  931. if (!v) {
  932. goto fail0;
  933. }
  934. func_new_common(i, v, 0, NULL);
  935. return;
  936. fail0:
  937. NCDModuleInst_Backend_SetError(i);
  938. NCDModuleInst_Backend_Dead(i);
  939. }
  940. static void func_new_insert_remove (NCDModuleInst *i)
  941. {
  942. NCDValue *where_arg;
  943. NCDValue *what_arg;
  944. if (!NCDValue_ListRead(i->args, 2, &where_arg, &what_arg)) {
  945. ModuleLog(i, BLOG_ERROR, "wrong arity");
  946. goto fail0;
  947. }
  948. struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
  949. struct value *mov = valref_val(&mo->ref);
  950. if (!mov) {
  951. ModuleLog(i, BLOG_ERROR, "value was deleted");
  952. goto fail0;
  953. }
  954. struct value *v = value_insert(i, mov, where_arg, what_arg);
  955. if (!v) {
  956. goto fail0;
  957. }
  958. func_new_common(i, v, 1, NULL);
  959. return;
  960. fail0:
  961. NCDModuleInst_Backend_SetError(i);
  962. NCDModuleInst_Backend_Dead(i);
  963. }
  964. static void remove_func_new (NCDModuleInst *i)
  965. {
  966. NCDValue *where_arg;
  967. if (!NCDValue_ListRead(i->args, 1, &where_arg)) {
  968. ModuleLog(i, BLOG_ERROR, "wrong arity");
  969. goto fail0;
  970. }
  971. struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
  972. struct value *mov = valref_val(&mo->ref);
  973. if (!mov) {
  974. ModuleLog(i, BLOG_ERROR, "value was deleted");
  975. goto fail0;
  976. }
  977. if (!value_remove(i, mov, where_arg)) {
  978. goto fail0;
  979. }
  980. NCDModuleInst_Backend_Up(i);
  981. return;
  982. fail0:
  983. NCDModuleInst_Backend_SetError(i);
  984. NCDModuleInst_Backend_Dead(i);
  985. }
  986. static void delete_func_new (NCDModuleInst *i)
  987. {
  988. if (!NCDValue_ListRead(i->args, 0)) {
  989. ModuleLog(i, BLOG_ERROR, "wrong arity");
  990. goto fail0;
  991. }
  992. struct instance *mo = ((NCDModuleInst *)i->method_user)->inst_user;
  993. struct value *mov = valref_val(&mo->ref);
  994. if (!mov) {
  995. ModuleLog(i, BLOG_ERROR, "value was deleted");
  996. goto fail0;
  997. }
  998. value_delete(mov);
  999. NCDModuleInst_Backend_Up(i);
  1000. return;
  1001. fail0:
  1002. NCDModuleInst_Backend_SetError(i);
  1003. NCDModuleInst_Backend_Dead(i);
  1004. }
  1005. static const struct NCDModule modules[] = {
  1006. {
  1007. .type = "value",
  1008. .func_new = func_new_value,
  1009. .func_die = func_die,
  1010. .func_getvar = func_getvar
  1011. }, {
  1012. .type = "value::get",
  1013. .base_type = "value",
  1014. .func_new = func_new_get,
  1015. .func_die = func_die,
  1016. .func_getvar = func_getvar
  1017. }, {
  1018. .type = "value::try_get",
  1019. .base_type = "value",
  1020. .func_new = func_new_try_get,
  1021. .func_die = func_die,
  1022. .func_getvar = func_getvar
  1023. }, {
  1024. .type = "value::getpath",
  1025. .base_type = "value",
  1026. .func_new = func_new_getpath,
  1027. .func_die = func_die,
  1028. .func_getvar = func_getvar
  1029. }, {
  1030. .type = "value::insert",
  1031. .base_type = "value",
  1032. .func_new = func_new_insert,
  1033. .func_die = func_die,
  1034. .func_getvar = func_getvar
  1035. }, {
  1036. .type = "value::insert_remove",
  1037. .base_type = "value",
  1038. .func_new = func_new_insert_remove,
  1039. .func_die = func_die,
  1040. .func_getvar = func_getvar
  1041. }, {
  1042. .type = "value::remove",
  1043. .func_new = remove_func_new
  1044. }, {
  1045. .type = "value::delete",
  1046. .func_new = delete_func_new
  1047. }, {
  1048. .type = NULL
  1049. }
  1050. };
  1051. const struct NCDModuleGroup ncdmodule_value = {
  1052. .modules = modules
  1053. };