NCDValue.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /**
  2. * @file NCDValue.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * This file is part of BadVPN.
  8. *
  9. * BadVPN is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * BadVPN is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. */
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <stdarg.h>
  25. #include <inttypes.h>
  26. #include <misc/debug.h>
  27. #include <misc/offset.h>
  28. #include <ncd/NCDValue.h>
  29. static void value_assert (NCDValue *o)
  30. {
  31. switch (o->type) {
  32. case NCDVALUE_STRING:
  33. case NCDVALUE_LIST:
  34. return;
  35. default:
  36. ASSERT(0);
  37. }
  38. }
  39. int NCDValue_InitCopy (NCDValue *o, NCDValue *v)
  40. {
  41. value_assert(v);
  42. switch (v->type) {
  43. case NCDVALUE_STRING: {
  44. return NCDValue_InitString(o, v->string);
  45. } break;
  46. case NCDVALUE_LIST: {
  47. NCDValue_InitList(o);
  48. LinkedList2Iterator it;
  49. LinkedList2Iterator_InitForward(&it, &v->list);
  50. LinkedList2Node *n;
  51. while (n = LinkedList2Iterator_Next(&it)) {
  52. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  53. NCDValue tmp;
  54. if (!NCDValue_InitCopy(&tmp, &e->v)) {
  55. goto fail;
  56. }
  57. if (!NCDValue_ListAppend(o, tmp)) {
  58. NCDValue_Free(&tmp);
  59. goto fail;
  60. }
  61. }
  62. return 1;
  63. fail:
  64. LinkedList2Iterator_Free(&it);
  65. NCDValue_Free(o);
  66. return 0;
  67. } break;
  68. default:
  69. ASSERT(0);
  70. }
  71. return 0;
  72. }
  73. void NCDValue_Free (NCDValue *o)
  74. {
  75. switch (o->type) {
  76. case NCDVALUE_STRING: {
  77. free(o->string);
  78. } break;
  79. case NCDVALUE_LIST: {
  80. LinkedList2Node *n;
  81. while (n = LinkedList2_GetFirst(&o->list)) {
  82. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  83. NCDValue_Free(&e->v);
  84. LinkedList2_Remove(&o->list, &e->list_node);
  85. free(e);
  86. }
  87. } break;
  88. default:
  89. ASSERT(0);
  90. }
  91. }
  92. int NCDValue_Type (NCDValue *o)
  93. {
  94. value_assert(o);
  95. return o->type;
  96. }
  97. int NCDValue_InitString (NCDValue *o, const char *str)
  98. {
  99. size_t len = strlen(str);
  100. if (!(o->string = malloc(len + 1))) {
  101. return 0;
  102. }
  103. memcpy(o->string, str, len);
  104. o->string[len] = '\0';
  105. o->type = NCDVALUE_STRING;
  106. return 1;
  107. }
  108. char * NCDValue_StringValue (NCDValue *o)
  109. {
  110. ASSERT(o->type == NCDVALUE_STRING)
  111. return o->string;
  112. }
  113. void NCDValue_InitList (NCDValue *o)
  114. {
  115. LinkedList2_Init(&o->list);
  116. o->list_count = 0;
  117. o->type = NCDVALUE_LIST;
  118. }
  119. int NCDValue_ListAppend (NCDValue *o, NCDValue v)
  120. {
  121. value_assert(o);
  122. value_assert(&v);
  123. ASSERT(o->type == NCDVALUE_LIST)
  124. if (o->list_count == SIZE_MAX) {
  125. return 0;
  126. }
  127. NCDListElement *e = malloc(sizeof(*e));
  128. if (!e) {
  129. return 0;
  130. }
  131. LinkedList2_Append(&o->list, &e->list_node);
  132. o->list_count++;
  133. e->v = v;
  134. return 1;
  135. }
  136. int NCDValue_ListAppendList (NCDValue *o, NCDValue l)
  137. {
  138. value_assert(o);
  139. value_assert(&l);
  140. ASSERT(o->type == NCDVALUE_LIST)
  141. ASSERT(l.type == NCDVALUE_LIST)
  142. if (l.list_count > SIZE_MAX - o->list_count) {
  143. return 0;
  144. }
  145. LinkedList2Node *n;
  146. while (n = LinkedList2_GetFirst(&l.list)) {
  147. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  148. LinkedList2_Remove(&l.list, &e->list_node);
  149. LinkedList2_Append(&o->list, &e->list_node);
  150. }
  151. o->list_count += l.list_count;
  152. return 1;
  153. }
  154. size_t NCDValue_ListCount (NCDValue *o)
  155. {
  156. value_assert(o);
  157. ASSERT(o->type == NCDVALUE_LIST)
  158. return o->list_count;
  159. }
  160. NCDValue * NCDValue_ListFirst (NCDValue *o)
  161. {
  162. value_assert(o);
  163. ASSERT(o->type == NCDVALUE_LIST)
  164. if (LinkedList2_IsEmpty(&o->list)) {
  165. return NULL;
  166. }
  167. NCDListElement *e = UPPER_OBJECT(LinkedList2_GetFirst(&o->list), NCDListElement, list_node);
  168. return &e->v;
  169. }
  170. NCDValue * NCDValue_ListNext (NCDValue *o, NCDValue *ev)
  171. {
  172. value_assert(o);
  173. ASSERT(o->type == NCDVALUE_LIST)
  174. NCDListElement *e = UPPER_OBJECT(ev, NCDListElement, v);
  175. LinkedList2Iterator it;
  176. LinkedList2Iterator_Init(&it, &o->list, 1, &e->list_node);
  177. LinkedList2Iterator_Next(&it);
  178. LinkedList2Node *nen = LinkedList2Iterator_Next(&it);
  179. LinkedList2Iterator_Free(&it);
  180. if (!nen) {
  181. return NULL;
  182. }
  183. NCDListElement *ne = UPPER_OBJECT(nen, NCDListElement, list_node);
  184. return &ne->v;
  185. }
  186. int NCDValue_ListRead (NCDValue *o, int num, ...)
  187. {
  188. value_assert(o);
  189. ASSERT(o->type == NCDVALUE_LIST)
  190. ASSERT(num >= 0)
  191. if (num != NCDValue_ListCount(o)) {
  192. return 0;
  193. }
  194. va_list ap;
  195. va_start(ap, num);
  196. LinkedList2Iterator it;
  197. LinkedList2Iterator_InitForward(&it, &o->list);
  198. LinkedList2Node *n;
  199. while (n = LinkedList2Iterator_Next(&it)) {
  200. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  201. NCDValue **dest = va_arg(ap, NCDValue **);
  202. *dest = &e->v;
  203. }
  204. va_end(ap);
  205. return 1;
  206. }
  207. int NCDValue_ListReadHead (NCDValue *o, int num, ...)
  208. {
  209. value_assert(o);
  210. ASSERT(o->type == NCDVALUE_LIST)
  211. ASSERT(num >= 0)
  212. if (num > NCDValue_ListCount(o)) {
  213. return 0;
  214. }
  215. va_list ap;
  216. va_start(ap, num);
  217. LinkedList2Node *n = LinkedList2_GetFirst(&o->list);
  218. while (num > 0) {
  219. ASSERT(n)
  220. NCDListElement *e = UPPER_OBJECT(n, NCDListElement, list_node);
  221. NCDValue **dest = va_arg(ap, NCDValue **);
  222. *dest = &e->v;
  223. n = LinkedList2Node_Next(n);
  224. num--;
  225. }
  226. va_end(ap);
  227. return 1;
  228. }
  229. NCDValue * NCDValue_ListGet (NCDValue *o, size_t pos)
  230. {
  231. value_assert(o);
  232. ASSERT(o->type == NCDVALUE_LIST)
  233. ASSERT(pos < o->list_count)
  234. NCDValue *e = NCDValue_ListFirst(o);
  235. while (e) {
  236. if (pos == 0) {
  237. break;
  238. }
  239. pos--;
  240. e = NCDValue_ListNext(o, e);
  241. }
  242. ASSERT(e)
  243. return e;
  244. }
  245. NCDValue NCDValue_ListShift (NCDValue *o)
  246. {
  247. value_assert(o);
  248. ASSERT(o->type == NCDVALUE_LIST)
  249. ASSERT(o->list_count > 0)
  250. NCDListElement *e = UPPER_OBJECT(LinkedList2_GetFirst(&o->list), NCDListElement, list_node);
  251. NCDValue v = e->v;
  252. LinkedList2_Remove(&o->list, &e->list_node);
  253. o->list_count--;
  254. free(e);
  255. return v;
  256. }
  257. int NCDValue_Compare (NCDValue *o, NCDValue *v)
  258. {
  259. value_assert(o);
  260. value_assert(v);
  261. if (o->type == NCDVALUE_STRING && v->type == NCDVALUE_LIST) {
  262. return -1;
  263. }
  264. if (o->type == NCDVALUE_LIST && v->type == NCDVALUE_STRING) {
  265. return 1;
  266. }
  267. if (o->type == NCDVALUE_STRING && v->type == NCDVALUE_STRING) {
  268. int cmp = strcmp(o->string, v->string);
  269. if (cmp < 0) {
  270. return -1;
  271. }
  272. if (cmp > 0) {
  273. return 1;
  274. }
  275. return 0;
  276. }
  277. NCDValue *x = NCDValue_ListFirst(o);
  278. NCDValue *y = NCDValue_ListFirst(v);
  279. while (1) {
  280. if (!x && y) {
  281. return -1;
  282. }
  283. if (x && !y) {
  284. return 1;
  285. }
  286. if (!x && !y) {
  287. return 0;
  288. }
  289. int res = NCDValue_Compare(x, y);
  290. if (res) {
  291. return res;
  292. }
  293. x = NCDValue_ListNext(o, x);
  294. y = NCDValue_ListNext(v, y);
  295. }
  296. }