NCDValue.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. /**
  2. * @file NCDValue.c
  3. * @author Ambroz Bizjak <[email protected]>
  4. *
  5. * @section LICENSE
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <stdarg.h>
  32. #include <inttypes.h>
  33. #include <misc/debug.h>
  34. #include <misc/offset.h>
  35. #include <ncd/NCDValue.h>
  36. static int ncdvalue_comparator (void *unused, void *vv1, void *vv2)
  37. {
  38. NCDValue *v1 = vv1;
  39. NCDValue *v2 = vv2;
  40. return NCDValue_Compare(v1, v2);
  41. }
  42. static void value_assert (NCDValue *o)
  43. {
  44. switch (o->type) {
  45. case NCDVALUE_STRING:
  46. case NCDVALUE_LIST:
  47. case NCDVALUE_MAP:
  48. case NCDVALUE_VAR:
  49. return;
  50. default:
  51. ASSERT(0);
  52. }
  53. }
  54. int NCDValue_InitCopy (NCDValue *o, NCDValue *v)
  55. {
  56. value_assert(v);
  57. switch (v->type) {
  58. case NCDVALUE_STRING: {
  59. return NCDValue_InitStringBin(o, v->string, v->string_len);
  60. } break;
  61. case NCDVALUE_LIST: {
  62. NCDValue_InitList(o);
  63. for (LinkedList1Node *n = LinkedList1_GetFirst(&v->list); n; n = LinkedList1Node_Next(n)) {
  64. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  65. NCDValue tmp;
  66. if (!NCDValue_InitCopy(&tmp, &e->v)) {
  67. goto fail;
  68. }
  69. if (!NCDValue_ListAppend(o, tmp)) {
  70. NCDValue_Free(&tmp);
  71. goto fail;
  72. }
  73. }
  74. return 1;
  75. fail:
  76. NCDValue_Free(o);
  77. return 0;
  78. } break;
  79. case NCDVALUE_MAP: {
  80. NCDValue_InitMap(o);
  81. for (NCDValue *ekey = NCDValue_MapFirstKey(v); ekey; ekey = NCDValue_MapNextKey(v, ekey)) {
  82. NCDValue *eval = NCDValue_MapKeyValue(v, ekey);
  83. NCDValue tmp_key;
  84. NCDValue tmp_val;
  85. if (!NCDValue_InitCopy(&tmp_key, ekey)) {
  86. goto mapfail;
  87. }
  88. if (!NCDValue_InitCopy(&tmp_val, eval)) {
  89. NCDValue_Free(&tmp_key);
  90. goto mapfail;
  91. }
  92. if (!NCDValue_MapInsert(o, tmp_key, tmp_val)) {
  93. NCDValue_Free(&tmp_key);
  94. NCDValue_Free(&tmp_val);
  95. goto mapfail;
  96. }
  97. }
  98. return 1;
  99. mapfail:
  100. NCDValue_Free(o);
  101. return 0;
  102. } break;
  103. case NCDVALUE_VAR: {
  104. return NCDValue_InitVar(o, v->var_name);
  105. } break;
  106. default:
  107. ASSERT(0);
  108. }
  109. return 0;
  110. }
  111. void NCDValue_Free (NCDValue *o)
  112. {
  113. switch (o->type) {
  114. case NCDVALUE_STRING: {
  115. free(o->string);
  116. } break;
  117. case NCDVALUE_LIST: {
  118. LinkedList1Node *n;
  119. while (n = LinkedList1_GetFirst(&o->list)) {
  120. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  121. NCDValue_Free(&e->v);
  122. LinkedList1_Remove(&o->list, &e->list_node);
  123. free(e);
  124. }
  125. } break;
  126. case NCDVALUE_MAP: {
  127. BAVLNode *tn;
  128. while (tn = BAVL_GetFirst(&o->map_tree)) {
  129. NCDMapElement *e = UPPER_OBJECT(tn, NCDMapElement, map_tree_node);
  130. BAVL_Remove(&o->map_tree, &e->map_tree_node);
  131. NCDValue_Free(&e->key);
  132. NCDValue_Free(&e->val);
  133. free(e);
  134. }
  135. } break;
  136. case NCDVALUE_VAR: {
  137. free(o->var_name);
  138. } break;
  139. default:
  140. ASSERT(0);
  141. }
  142. }
  143. int NCDValue_Type (NCDValue *o)
  144. {
  145. value_assert(o);
  146. return o->type;
  147. }
  148. int NCDValue_IsString (NCDValue *o)
  149. {
  150. value_assert(o);
  151. return o->type == NCDVALUE_STRING;
  152. }
  153. int NCDValue_IsStringNoNulls (NCDValue *o)
  154. {
  155. return NCDValue_IsString(o) && NCDValue_StringHasNoNulls(o);
  156. }
  157. int NCDValue_InitString (NCDValue *o, const char *str)
  158. {
  159. return NCDValue_InitStringBin(o, (const uint8_t *)str, strlen(str));
  160. }
  161. int NCDValue_InitStringBin (NCDValue *o, const uint8_t *str, size_t len)
  162. {
  163. if (len == SIZE_MAX) {
  164. return 0;
  165. }
  166. if (!(o->string = malloc(len + 1))) {
  167. return 0;
  168. }
  169. memcpy(o->string, str, len);
  170. o->string[len] = '\0';
  171. o->string_len = len;
  172. o->type = NCDVALUE_STRING;
  173. return 1;
  174. }
  175. char * NCDValue_StringValue (NCDValue *o)
  176. {
  177. ASSERT(o->type == NCDVALUE_STRING)
  178. return (char *)o->string;
  179. }
  180. size_t NCDValue_StringLength (NCDValue *o)
  181. {
  182. ASSERT(o->type == NCDVALUE_STRING)
  183. return o->string_len;
  184. }
  185. int NCDValue_StringHasNoNulls (NCDValue *o)
  186. {
  187. ASSERT(o->type == NCDVALUE_STRING)
  188. return strlen((char *)o->string) == o->string_len;
  189. }
  190. int NCDValue_StringHasNulls (NCDValue *o)
  191. {
  192. ASSERT(o->type == NCDVALUE_STRING)
  193. return !NCDValue_StringHasNoNulls(o);
  194. }
  195. int NCDValue_StringEquals (NCDValue *o, const char *str)
  196. {
  197. ASSERT(o->type == NCDVALUE_STRING)
  198. return NCDValue_StringHasNoNulls(o) && !strcmp((const char *)o->string, str);
  199. }
  200. int NCDValue_IsList (NCDValue *o)
  201. {
  202. value_assert(o);
  203. return o->type == NCDVALUE_LIST;
  204. }
  205. void NCDValue_InitList (NCDValue *o)
  206. {
  207. LinkedList1_Init(&o->list);
  208. o->list_count = 0;
  209. o->type = NCDVALUE_LIST;
  210. }
  211. int NCDValue_ListAppend (NCDValue *o, NCDValue v)
  212. {
  213. value_assert(o);
  214. value_assert(&v);
  215. ASSERT(o->type == NCDVALUE_LIST)
  216. if (o->list_count == SIZE_MAX) {
  217. return 0;
  218. }
  219. NCDListElement *e = malloc(sizeof(*e));
  220. if (!e) {
  221. return 0;
  222. }
  223. LinkedList1_Append(&o->list, &e->list_node);
  224. o->list_count++;
  225. e->v = v;
  226. return 1;
  227. }
  228. int NCDValue_ListPrepend (NCDValue *o, NCDValue v)
  229. {
  230. value_assert(o);
  231. value_assert(&v);
  232. ASSERT(o->type == NCDVALUE_LIST)
  233. if (o->list_count == SIZE_MAX) {
  234. return 0;
  235. }
  236. NCDListElement *e = malloc(sizeof(*e));
  237. if (!e) {
  238. return 0;
  239. }
  240. LinkedList1_Prepend(&o->list, &e->list_node);
  241. o->list_count++;
  242. e->v = v;
  243. return 1;
  244. }
  245. int NCDValue_ListAppendList (NCDValue *o, NCDValue l)
  246. {
  247. value_assert(o);
  248. value_assert(&l);
  249. ASSERT(o->type == NCDVALUE_LIST)
  250. ASSERT(l.type == NCDVALUE_LIST)
  251. if (l.list_count > SIZE_MAX - o->list_count) {
  252. return 0;
  253. }
  254. LinkedList1Node *n;
  255. while (n = LinkedList1_GetFirst(&l.list)) {
  256. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  257. LinkedList1_Remove(&l.list, &e->list_node);
  258. LinkedList1_Append(&o->list, &e->list_node);
  259. }
  260. o->list_count += l.list_count;
  261. return 1;
  262. }
  263. size_t NCDValue_ListCount (NCDValue *o)
  264. {
  265. value_assert(o);
  266. ASSERT(o->type == NCDVALUE_LIST)
  267. return o->list_count;
  268. }
  269. NCDValue * NCDValue_ListFirst (NCDValue *o)
  270. {
  271. value_assert(o);
  272. ASSERT(o->type == NCDVALUE_LIST)
  273. LinkedList1Node *ln = LinkedList1_GetFirst(&o->list);
  274. if (!ln) {
  275. return NULL;
  276. }
  277. NCDListElement *e = UPPER_OBJECT(ln, NCDListElement, list_node);
  278. return &e->v;
  279. }
  280. NCDValue * NCDValue_ListNext (NCDValue *o, NCDValue *ev)
  281. {
  282. value_assert(o);
  283. ASSERT(o->type == NCDVALUE_LIST)
  284. NCDListElement *cur_e = UPPER_OBJECT(ev, NCDListElement, v);
  285. LinkedList1Node *ln = LinkedList1Node_Next(&cur_e->list_node);
  286. if (!ln) {
  287. return NULL;
  288. }
  289. NCDListElement *e = UPPER_OBJECT(ln, NCDListElement, list_node);
  290. return &e->v;
  291. }
  292. int NCDValue_ListRead (NCDValue *o, int num, ...)
  293. {
  294. value_assert(o);
  295. ASSERT(o->type == NCDVALUE_LIST)
  296. ASSERT(num >= 0)
  297. if (num != NCDValue_ListCount(o)) {
  298. return 0;
  299. }
  300. va_list ap;
  301. va_start(ap, num);
  302. for (LinkedList1Node *n = LinkedList1_GetFirst(&o->list); n; n = LinkedList1Node_Next(n)) {
  303. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  304. NCDValue **dest = va_arg(ap, NCDValue **);
  305. *dest = &e->v;
  306. }
  307. va_end(ap);
  308. return 1;
  309. }
  310. int NCDValue_ListReadHead (NCDValue *o, int num, ...)
  311. {
  312. value_assert(o);
  313. ASSERT(o->type == NCDVALUE_LIST)
  314. ASSERT(num >= 0)
  315. if (num > NCDValue_ListCount(o)) {
  316. return 0;
  317. }
  318. va_list ap;
  319. va_start(ap, num);
  320. LinkedList1Node *n = LinkedList1_GetFirst(&o->list);
  321. while (num > 0) {
  322. ASSERT(n)
  323. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  324. NCDValue **dest = va_arg(ap, NCDValue **);
  325. *dest = &e->v;
  326. n = LinkedList1Node_Next(n);
  327. num--;
  328. }
  329. va_end(ap);
  330. return 1;
  331. }
  332. NCDValue * NCDValue_ListGet (NCDValue *o, size_t pos)
  333. {
  334. value_assert(o);
  335. ASSERT(o->type == NCDVALUE_LIST)
  336. ASSERT(pos < o->list_count)
  337. NCDValue *e = NCDValue_ListFirst(o);
  338. while (e) {
  339. if (pos == 0) {
  340. break;
  341. }
  342. pos--;
  343. e = NCDValue_ListNext(o, e);
  344. }
  345. ASSERT(e)
  346. return e;
  347. }
  348. NCDValue NCDValue_ListShift (NCDValue *o)
  349. {
  350. value_assert(o);
  351. ASSERT(o->type == NCDVALUE_LIST)
  352. ASSERT(o->list_count > 0)
  353. NCDListElement *e = UPPER_OBJECT(LinkedList1_GetFirst(&o->list), NCDListElement, list_node);
  354. NCDValue v = e->v;
  355. LinkedList1_Remove(&o->list, &e->list_node);
  356. o->list_count--;
  357. free(e);
  358. return v;
  359. }
  360. NCDValue NCDValue_ListRemove (NCDValue *o, NCDValue *ev)
  361. {
  362. value_assert(o);
  363. ASSERT(o->type == NCDVALUE_LIST)
  364. ASSERT(o->list_count > 0)
  365. NCDListElement *e = UPPER_OBJECT(ev, NCDListElement, v);
  366. NCDValue v = e->v;
  367. LinkedList1_Remove(&o->list, &e->list_node);
  368. o->list_count--;
  369. free(e);
  370. return v;
  371. }
  372. int NCDValue_IsMap (NCDValue *o)
  373. {
  374. value_assert(o);
  375. return o->type == NCDVALUE_MAP;
  376. }
  377. void NCDValue_InitMap (NCDValue *o)
  378. {
  379. o->type = NCDVALUE_MAP;
  380. BAVL_Init(&o->map_tree, OFFSET_DIFF(NCDMapElement, key, map_tree_node), ncdvalue_comparator, NULL);
  381. o->map_count = 0;
  382. }
  383. size_t NCDValue_MapCount (NCDValue *o)
  384. {
  385. value_assert(o);
  386. ASSERT(o->type == NCDVALUE_MAP)
  387. return o->map_count;
  388. }
  389. NCDValue * NCDValue_MapFirstKey (NCDValue *o)
  390. {
  391. value_assert(o);
  392. ASSERT(o->type == NCDVALUE_MAP)
  393. BAVLNode *tn = BAVL_GetFirst(&o->map_tree);
  394. if (!tn) {
  395. return NULL;
  396. }
  397. NCDMapElement *e = UPPER_OBJECT(tn, NCDMapElement, map_tree_node);
  398. value_assert(&e->key);
  399. value_assert(&e->val);
  400. return &e->key;
  401. }
  402. NCDValue * NCDValue_MapNextKey (NCDValue *o, NCDValue *ekey)
  403. {
  404. value_assert(o);
  405. ASSERT(o->type == NCDVALUE_MAP)
  406. NCDMapElement *e = UPPER_OBJECT(ekey, NCDMapElement, key);
  407. value_assert(&e->key);
  408. value_assert(&e->val);
  409. BAVLNode *tn = BAVL_GetNext(&o->map_tree, &e->map_tree_node);
  410. if (!tn) {
  411. return NULL;
  412. }
  413. NCDMapElement *ne = UPPER_OBJECT(tn, NCDMapElement, map_tree_node);
  414. value_assert(&ne->key);
  415. value_assert(&ne->val);
  416. return &ne->key;
  417. }
  418. NCDValue * NCDValue_MapKeyValue (NCDValue *o, NCDValue *ekey)
  419. {
  420. value_assert(o);
  421. ASSERT(o->type == NCDVALUE_MAP)
  422. NCDMapElement *e = UPPER_OBJECT(ekey, NCDMapElement, key);
  423. value_assert(&e->key);
  424. value_assert(&e->val);
  425. return &e->val;
  426. }
  427. NCDValue * NCDValue_MapFindKey (NCDValue *o, NCDValue *key)
  428. {
  429. value_assert(o);
  430. ASSERT(o->type == NCDVALUE_MAP)
  431. value_assert(key);
  432. BAVLNode *tn = BAVL_LookupExact(&o->map_tree, key);
  433. if (!tn) {
  434. return NULL;
  435. }
  436. NCDMapElement *e = UPPER_OBJECT(tn, NCDMapElement, map_tree_node);
  437. value_assert(&e->key);
  438. value_assert(&e->val);
  439. ASSERT(!NCDValue_Compare(&e->key, key))
  440. return &e->key;
  441. }
  442. NCDValue * NCDValue_MapInsert (NCDValue *o, NCDValue key, NCDValue val)
  443. {
  444. value_assert(o);
  445. ASSERT(o->type == NCDVALUE_MAP)
  446. value_assert(&key);
  447. value_assert(&val);
  448. ASSERT(!NCDValue_MapFindKey(o, &key))
  449. if (o->map_count == SIZE_MAX) {
  450. return NULL;
  451. }
  452. NCDMapElement *e = malloc(sizeof(*e));
  453. if (!e) {
  454. return NULL;
  455. }
  456. e->key = key;
  457. e->val = val;
  458. int res = BAVL_Insert(&o->map_tree, &e->map_tree_node, NULL);
  459. ASSERT(res)
  460. o->map_count++;
  461. return &e->key;
  462. }
  463. void NCDValue_MapRemove (NCDValue *o, NCDValue *ekey, NCDValue *out_key, NCDValue *out_val)
  464. {
  465. value_assert(o);
  466. ASSERT(o->type == NCDVALUE_MAP)
  467. ASSERT(out_key)
  468. ASSERT(out_val)
  469. ASSERT(o->map_count > 0)
  470. NCDMapElement *e = UPPER_OBJECT(ekey, NCDMapElement, key);
  471. value_assert(&e->key);
  472. value_assert(&e->val);
  473. BAVL_Remove(&o->map_tree, &e->map_tree_node);
  474. *out_key = e->key;
  475. *out_val = e->val;
  476. o->map_count--;
  477. free(e);
  478. }
  479. NCDValue * NCDValue_MapFindValueByString (NCDValue *o, const char *key_str)
  480. {
  481. value_assert(o);
  482. ASSERT(o->type == NCDVALUE_MAP)
  483. ASSERT(key_str)
  484. NCDValue key;
  485. key.type = NCDVALUE_STRING;
  486. key.string = (uint8_t *)key_str;
  487. key.string_len = strlen(key_str);
  488. NCDValue *ekey = NCDValue_MapFindKey(o, &key);
  489. if (!ekey) {
  490. return NULL;
  491. }
  492. return NCDValue_MapKeyValue(o, ekey);
  493. }
  494. int NCDValue_IsVar (NCDValue *o)
  495. {
  496. value_assert(o);
  497. return o->type == NCDVALUE_VAR;
  498. }
  499. int NCDValue_InitVar (NCDValue *o, const char *var_name)
  500. {
  501. ASSERT(var_name)
  502. if (!(o->var_name = strdup(var_name))) {
  503. return 0;
  504. }
  505. o->type = NCDVALUE_VAR;
  506. return 1;
  507. }
  508. const char * NCDValue_VarName (NCDValue *o)
  509. {
  510. value_assert(o);
  511. ASSERT(o->type == NCDVALUE_VAR)
  512. return o->var_name;
  513. }
  514. int NCDValue_Compare (NCDValue *o, NCDValue *v)
  515. {
  516. value_assert(o);
  517. value_assert(v);
  518. int cmp = (o->type > v->type) - (o->type < v->type);
  519. if (cmp) {
  520. return cmp;
  521. }
  522. ASSERT(o->type == v->type)
  523. if (o->type == NCDVALUE_STRING) {
  524. size_t min_len = o->string_len < v->string_len ? o->string_len : v->string_len;
  525. int cmp = memcmp(o->string, v->string, min_len);
  526. if (cmp) {
  527. return (cmp > 0) - (cmp < 0);
  528. }
  529. return (o->string_len > v->string_len) - (o->string_len < v->string_len);
  530. }
  531. if (o->type == NCDVALUE_LIST) {
  532. NCDValue *x = NCDValue_ListFirst(o);
  533. NCDValue *y = NCDValue_ListFirst(v);
  534. while (1) {
  535. if (!x && y) {
  536. return -1;
  537. }
  538. if (x && !y) {
  539. return 1;
  540. }
  541. if (!x && !y) {
  542. return 0;
  543. }
  544. int res = NCDValue_Compare(x, y);
  545. if (res) {
  546. return res;
  547. }
  548. x = NCDValue_ListNext(o, x);
  549. y = NCDValue_ListNext(v, y);
  550. }
  551. }
  552. if (o->type == NCDVALUE_MAP) {
  553. NCDValue *key1 = NCDValue_MapFirstKey(o);
  554. NCDValue *key2 = NCDValue_MapFirstKey(v);
  555. while (1) {
  556. if (!key1 && key2) {
  557. return -1;
  558. }
  559. if (key1 && !key2) {
  560. return 1;
  561. }
  562. if (!key1 && !key2) {
  563. return 0;
  564. }
  565. int res = NCDValue_Compare(key1, key2);
  566. if (res) {
  567. return res;
  568. }
  569. NCDValue *val1 = NCDValue_MapKeyValue(o, key1);
  570. NCDValue *val2 = NCDValue_MapKeyValue(v, key2);
  571. res = NCDValue_Compare(val1, val2);
  572. if (res) {
  573. return res;
  574. }
  575. key1 = NCDValue_MapNextKey(o, key1);
  576. key2 = NCDValue_MapNextKey(v, key2);
  577. }
  578. }
  579. if (o->type == NCDVALUE_VAR) {
  580. int res = strcmp(o->var_name, v->var_name);
  581. return (res > 0) - (res < 0);
  582. }
  583. ASSERT(0)
  584. return 0;
  585. }