hipack.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. /*
  2. * hipack.h
  3. * Copyright (C) 2015 Adrian Perez <aperez@igalia.com>
  4. *
  5. * Distributed under terms of the MIT license.
  6. */
  7. #ifndef HIPACK_H
  8. #define HIPACK_H
  9. #include <stdio.h>
  10. #include <assert.h>
  11. #include <stdint.h>
  12. #include <string.h>
  13. #include <stdbool.h>
  14. /**
  15. * =============
  16. * API Reference
  17. * =============
  18. *
  19. * Types
  20. * =====
  21. */
  22. /*~t hipack_type_t
  23. *
  24. * Type of a value. This enumeration takes one of the following values:
  25. *
  26. * - ``HIPACK_INTEGER``: Integer value.
  27. * - ``HIPACK_FLOAT``: Floating point value.
  28. * - ``HIPACK_BOOL``: Boolean value.
  29. * - ``HIPACK_STRING``: String value.
  30. * - ``HIPACK_LIST``: List value.
  31. * - ``HIPACK_DICT``: Dictionary value.
  32. */
  33. typedef enum {
  34. HIPACK_INTEGER,
  35. HIPACK_FLOAT,
  36. HIPACK_BOOL,
  37. HIPACK_STRING,
  38. HIPACK_LIST,
  39. HIPACK_DICT,
  40. } hipack_type_t;
  41. /* Forward declarations. */
  42. typedef struct hipack_value hipack_value_t;
  43. typedef struct hipack_string hipack_string_t;
  44. typedef struct hipack_dict hipack_dict_t;
  45. typedef struct hipack_dict_node hipack_dict_node_t;
  46. typedef struct hipack_list hipack_list_t;
  47. /*~t hipack_value_t
  48. *
  49. * Represent any valid HiPack value.
  50. *
  51. * - :func:`hipack_value_type()` obtains the type of a value.
  52. */
  53. struct hipack_value {
  54. hipack_type_t type;
  55. hipack_dict_t *annot;
  56. union {
  57. int32_t v_integer;
  58. double v_float;
  59. bool v_bool;
  60. hipack_string_t *v_string;
  61. hipack_list_t *v_list;
  62. hipack_dict_t *v_dict;
  63. };
  64. };
  65. /*~t hipack_string_t
  66. *
  67. * String value.
  68. */
  69. struct hipack_string {
  70. uint32_t size;
  71. uint8_t data[]; /* C99 flexible array. */
  72. };
  73. /*~t hipack_list_t
  74. *
  75. * List value.
  76. */
  77. struct hipack_list {
  78. uint32_t size;
  79. hipack_value_t data[]; /* C99 flexible array. */
  80. };
  81. /*~t hipack_dict_t
  82. *
  83. * Dictionary value.
  84. */
  85. struct hipack_dict {
  86. hipack_dict_node_t **nodes;
  87. hipack_dict_node_t *first;
  88. uint32_t count;
  89. uint32_t size;
  90. };
  91. /**
  92. * Memory Allocation
  93. * =================
  94. *
  95. * How ``hipack-c`` allocates memory can be customized by setting
  96. * :c:data:`hipack_alloc` to a custom allocation function.
  97. */
  98. /*~v hipack_alloc
  99. *
  100. * Allocation function. By default it is set to :func:`hipack_alloc_stdlib()`,
  101. * which uses the implementations of ``malloc()``, ``realloc()``, and
  102. * ``free()`` provided by the C library.
  103. *
  104. * Allocation functions always have the following prototype:
  105. *
  106. * .. code-block:: c
  107. *
  108. * void* func (void *oldptr, size_t size);
  109. *
  110. * The behavior must be as follows:
  111. *
  112. * - When invoked with ``oldptr`` set to ``NULL``, and a non-zero ``size``,
  113. * the function behaves like ``malloc()``: a memory block of at least
  114. * ``size`` bytes is allocated and a pointer to it returned.
  115. * - When ``oldptr`` is non-``NULL``, and a non-zero ``size``, the function
  116. * behaves like ``realloc()``: the memory area pointed to by ``oldptr``
  117. * is resized to be at least ``size`` bytes, or its contents moved to a
  118. * new memory area of at least ``size`` bytes. The returned pointer may
  119. * either be ``oldptr``, or a pointer to the new memory area if the data
  120. * was relocated.
  121. * - When ``oldptr`` is non-``NULL``, and ``size`` is zero, the function
  122. * behaves like ``free()``.
  123. */
  124. extern void* (*hipack_alloc) (void*, size_t);
  125. /*~f void* hipack_alloc_stdlib(void*, size_t)
  126. *
  127. * Default allocation function. It uses ``malloc()``, ``realloc()``, and
  128. * ``free()`` from the C library. By default :any:`hipack_alloc` is set
  129. * to use this function.
  130. */
  131. extern void* hipack_alloc_stdlib (void*, size_t);
  132. /*~f void* hipack_alloc_array_extra (void *oldptr, size_t nmemb, size_t size, size_t extra)
  133. *
  134. * Allocates (if `oldptr` is ``NULL``) or reallocates (if `oldptr` is
  135. * non-``NULL``) memory for an array which contains `nmemb` elements, each one
  136. * of `size` bytes, plus an arbitrary amount of `extra` bytes.
  137. *
  138. * This function is used internally by the HiPack parser, and it is not likely
  139. * to be needed by client code.
  140. */
  141. extern void* hipack_alloc_array_extra (void*, size_t nmemb, size_t size, size_t extra);
  142. /*~f void* hipack_alloc_array (void *optr, size_t nmemb, size_t size)
  143. *
  144. * Same as :c:func:`hipack_alloc_array_extra()`, without allowing to specify
  145. * the amount of extra bytes. The following calls are both equivalent:
  146. *
  147. * .. code-block:: c
  148. *
  149. * void *a = hipack_alloc_array_extra (NULL, 10, 4, 0);
  150. * void *b = hipack_alloc_array (NULL, 10, 4);
  151. *
  152. * See :c:func:`hipack_alloc_array_extra()` for details.
  153. */
  154. static inline void*
  155. hipack_alloc_array (void *optr, size_t nmemb, size_t size)
  156. {
  157. return hipack_alloc_array_extra (optr, nmemb, size, 0);
  158. }
  159. /*~f void* hipack_alloc_bzero (size_t size)
  160. *
  161. * Allocates an area of memory of `size` bytes, and initializes it to zeroes.
  162. */
  163. static inline void*
  164. hipack_alloc_bzero (size_t size)
  165. {
  166. assert (size > 0);
  167. return memset ((*hipack_alloc) (NULL, size), 0, size);
  168. }
  169. /*~f void hipack_alloc_free (void *pointer)
  170. *
  171. * Frees the memory area referenced by the given `pointer`.
  172. */
  173. static inline void
  174. hipack_alloc_free (void *optr)
  175. {
  176. (*hipack_alloc) (optr, 0);
  177. }
  178. /**
  179. * String Functions
  180. * ================
  181. *
  182. * The following functions are provided as a convenience to operate on values
  183. * of type :c:type:`hipack_string_t`.
  184. *
  185. * .. note:: The hash function used by :c:func:`hipack_string_hash()` is
  186. * *not* guaranteed to be cryptographically safe. Please do avoid exposing
  187. * values returned by this function to the attack surface of your
  188. * applications, in particular *do not expose them to the network*.
  189. */
  190. /*~f hipack_string_t* hipack_string_copy (const hipack_string_t *hstr)
  191. *
  192. * Returns a new copy of a string.
  193. *
  194. * The returned value must be freed using :c:func:`hipack_string_free()`.
  195. */
  196. extern hipack_string_t* hipack_string_copy (const hipack_string_t *hstr);
  197. /*~f hipack_string_t* hipack_string_new_from_string (const char *str)
  198. *
  199. * Creates a new string from a C-style zero terminated string.
  200. *
  201. * The returned value must be freed using :c:func:`hipack_string_free()`.
  202. */
  203. extern hipack_string_t* hipack_string_new_from_string (const char *str);
  204. /*~f hipack_string_t* hipack_string_new_from_lstring (const char *str, uint32_t len)
  205. *
  206. * Creates a new string from a memory area and its length.
  207. *
  208. * The returned value must be freed using :c:func:`hipack_string_free()`.
  209. */
  210. extern hipack_string_t* hipack_string_new_from_lstring (const char *str, uint32_t len);
  211. /*~f uint32_t hipack_string_hash (const hipack_string_t *hstr)
  212. *
  213. * Calculates a hash value for a string.
  214. */
  215. extern uint32_t hipack_string_hash (const hipack_string_t *hstr);
  216. /*~f bool hipack_string_equal (const hipack_string_t *hstr1, const hipack_string_t *hstr2)
  217. * Compares two strings to check whether their contents are the same.
  218. */
  219. extern bool hipack_string_equal (const hipack_string_t *hstr1,
  220. const hipack_string_t *hstr2);
  221. /*~f void hipack_string_free (hipack_string_t *hstr)
  222. * Frees the memory used by a string.
  223. */
  224. extern void hipack_string_free (hipack_string_t *hstr);
  225. /**
  226. * List Functions
  227. * ==============
  228. */
  229. /*~f hipack_list_t* hipack_list_new (uint32_t size)
  230. * Creates a new list for ``size`` elements.
  231. */
  232. extern hipack_list_t* hipack_list_new (uint32_t size);
  233. /*~f void hipack_list_free (hipack_list_t *list)
  234. * Frees the memory used by a list.
  235. */
  236. extern void hipack_list_free (hipack_list_t *list);
  237. /*~f bool hipack_list_equal (const hipack_list_t *a, const hipack_list_t *b)
  238. * Checks whether two lists contains the same values.
  239. */
  240. extern bool hipack_list_equal (const hipack_list_t *a,
  241. const hipack_list_t *b);
  242. /*~f uint32_t hipack_list_size (const hipack_list_t *list)
  243. * Obtains the number of elements in a list.
  244. */
  245. static inline uint32_t
  246. hipack_list_size (const hipack_list_t *list)
  247. {
  248. assert (list);
  249. return list->size;
  250. }
  251. /*~M HIPACK_LIST_AT(list, index)
  252. *
  253. * Obtains a pointer to the element at a given `index` of a `list`.
  254. */
  255. #define HIPACK_LIST_AT(_list, _index) \
  256. (assert ((_index) < (_list)->size), &((_list)->data[_index]))
  257. /**
  258. * .. _dict_funcs:
  259. *
  260. * Dictionary Functions
  261. * ====================
  262. */
  263. /*~f uint32_t hipack_dict_size (const hipack_dict_t *dict)
  264. *
  265. * Obtains the number of elements in a dictionary.
  266. */
  267. static inline uint32_t
  268. hipack_dict_size (const hipack_dict_t *dict)
  269. {
  270. assert (dict);
  271. return dict->count;
  272. }
  273. /*~f hipack_dict_t* hipack_dict_new (void)
  274. *
  275. * Creates a new, empty dictionary.
  276. */
  277. extern hipack_dict_t* hipack_dict_new (void);
  278. /*~f void hipack_dict_free (hipack_dict_t *dict)
  279. *
  280. * Frees the memory used by a dictionary.
  281. */
  282. extern void hipack_dict_free (hipack_dict_t *dict);
  283. /*~f bool hipack_dict_equal (const hipack_dict_t *a, const hipack_dict_t *b)
  284. *
  285. * Checks whether two dictinaries contain the same keys, and their associated
  286. * values in each of the dictionaries are equal.
  287. */
  288. extern bool hipack_dict_equal (const hipack_dict_t *a,
  289. const hipack_dict_t *b);
  290. /*~f void hipack_dict_set (hipack_dict_t *dict, const hipack_string_t *key, const hipack_value_t *value)
  291. *
  292. * Adds an association of a `key` to a `value`.
  293. *
  294. * Note that this function will copy the `key`. If you are not planning to
  295. * continue reusing the `key`, it is recommended to use
  296. * :c:func:`hipack_dict_set_adopt_key()` instead.
  297. */
  298. extern void hipack_dict_set (hipack_dict_t *dict,
  299. const hipack_string_t *key,
  300. const hipack_value_t *value);
  301. /*~f void hipack_dict_set_adopt_key (hipack_dict_t *dict, hipack_string_t **key, const hipack_value_t *value)
  302. *
  303. * Adds an association of a `key` to a `value`, passing ownership of the
  304. * memory using by the `key` to the dictionary (i.e. the string used as key
  305. * will be freed by the dictionary).
  306. *
  307. * Use this function instead of :c:func:`hipack_dict_set()` when the `key`
  308. * is not going to be used further afterwards.
  309. */
  310. extern void hipack_dict_set_adopt_key (hipack_dict_t *dict,
  311. hipack_string_t **key,
  312. const hipack_value_t *value);
  313. /*~f void hipack_dict_del (hipack_dict_t *dict, const hipack_string_t *key)
  314. *
  315. * Removes the element from a dictionary associated to a `key`.
  316. */
  317. extern void hipack_dict_del (hipack_dict_t *dict,
  318. const hipack_string_t *key);
  319. /*~f hipack_value_t* hipack_dict_get (const hipack_dict_t *dict, const hipack_string_t *key)
  320. *
  321. * Obtains the value associated to a `key` from a dictionary.
  322. *
  323. * The returned value points to memory owned by the dictionary. The value can
  324. * be modified in-place, but it shall not be freed.
  325. */
  326. extern hipack_value_t* hipack_dict_get (const hipack_dict_t *dict,
  327. const hipack_string_t *key);
  328. /*~f hipack_value_t* hipack_dict_first (const hipack_dict_t *dict, const hipack_string_t **key)
  329. *
  330. * Obtains an a *(key, value)* pair, which is considered the *first* in
  331. * iteration order. This can be used in combination with
  332. * :c:func:`hipack_dict_next()` to enumerate all the *(key, value)* pairs
  333. * stored in the dictionary:
  334. *
  335. * .. code-block:: c
  336. *
  337. * hipack_dict_t *d = get_dictionary ();
  338. * hipack_value_t *v;
  339. * hipack_string_t *k;
  340. *
  341. * for (v = hipack_dict_first (d, &k);
  342. * v != NULL;
  343. * v = hipack_dict_next (v, &k)) {
  344. * // Use "k" and "v" normally.
  345. * }
  346. *
  347. * As a shorthand, consider using :c:macro:`HIPACK_DICT_FOREACH()` instead.
  348. */
  349. extern hipack_value_t* hipack_dict_first (const hipack_dict_t *dict,
  350. const hipack_string_t **key);
  351. /*~f hipack_value_t* hipack_dict_next (hipack_value_t *value, const hipack_string_t **key)
  352. *
  353. * Iterates to the next *(key, value)* pair of a dictionary. For usage
  354. * details, see :c:func:`hipack_dict_first()`.
  355. */
  356. extern hipack_value_t* hipack_dict_next (hipack_value_t *value,
  357. const hipack_string_t **key);
  358. /*~M HIPACK_DICT_FOREACH(dict, key, value)
  359. *
  360. * Convenience macro used to iterate over the *(key, value)* pairs contained
  361. * in a dictionary. Internally this uses :c:func:`hipack_dict_first()` and
  362. * :c:func:`hipack_dict_next()`.
  363. *
  364. * .. code-block:: c
  365. *
  366. * hipack_dict_t *d = get_dictionary ();
  367. * hipack_string_t *k;
  368. * hipack_value_t *v;
  369. * HIPACK_DICT_FOREACH (d, k, v) {
  370. * // Use "k" and "v"
  371. * }
  372. *
  373. * Using this macro is the recommended way of writing a loop to enumerate
  374. * elements from a dictionary.
  375. */
  376. #define HIPACK_DICT_FOREACH(_d, _k, _v) \
  377. for ((_v) = hipack_dict_first ((_d), &(_k)); \
  378. (_v) != NULL; \
  379. (_v) = hipack_dict_next ((_v), &(_k)))
  380. /**
  381. * Value Functions
  382. * ===============
  383. */
  384. /*~f hipack_type_t hipack_value_type (const hipack_value_t *value)
  385. *
  386. * Obtains the type of a value.
  387. */
  388. static inline hipack_type_t
  389. hipack_value_type (const hipack_value_t *value)
  390. {
  391. return value->type;
  392. }
  393. /*~f hipack_value_t hipack_integer (int32_t value)
  394. * Creates a new integer value.
  395. */
  396. /*~f hipack_value_t hipack_float (double value)
  397. * Creates a new floating point value.
  398. */
  399. /*~f hipack_value_t hipack_bool (bool value)
  400. * Creates a new boolean value.
  401. */
  402. /*~f hipack_value_t hipack_string (hipack_string_t *value)
  403. * Creates a new string value.
  404. */
  405. /*~f hipack_value_t hipack_list (hipack_list_t *value)
  406. * Creates a new list value.
  407. */
  408. /*~f hipack_value_t hipack_dict (hipack_dict_t *value)
  409. * Creates a new dictionary value.
  410. */
  411. /*~f bool hipack_value_is_integer (const hipack_value_t *value)
  412. * Checks whether a value is an integer.
  413. */
  414. /*~f bool hipack_value_is_float (const hipack_value_t *value)
  415. * Checks whether a value is a floating point number.
  416. */
  417. /*~f bool hipack_value_is_bool (const hipack_value_t *value)
  418. * Checks whether a value is a boolean.
  419. */
  420. /*~f bool hipack_value_is_string (const hipack_value_t *value)
  421. * Checks whether a value is a string.
  422. */
  423. /*~f bool hipack_value_is_list (const hipack_value_t *value)
  424. * Checks whether a value is a list.
  425. */
  426. /*~f bool hipack_value_is_dict (const hipack_value_t *value)
  427. * Checks whether a value is a dictionary.
  428. */
  429. /*~f const int32_t hipack_value_get_integer (const hipack_value_t *value)
  430. * Obtains a numeric value as an ``int32_t``.
  431. */
  432. /*~f const double hipack_value_get_float (const hipack_value_t *value)
  433. * Obtains a floating point value as a ``double``.
  434. */
  435. /*~f const bool hipack_value_get_bool (const hipack_value_t *value)
  436. * Obtains a boolean value as a ``bool``.
  437. */
  438. /*~f const hipack_string_t* hipack_value_get_string (const hipack_value_t *value)
  439. * Obtains a numeric value as a :c:type:`hipack_string_t`.
  440. */
  441. /*~f const hipack_list_t* hipack_value_get_list (const hipack_value_t *value)
  442. * Obtains a numeric value as a :c:type:`hipack_list_t`.
  443. */
  444. /*~f const hipack_dict_t* hipack_value_get_dict (const hipack_value_t *value)
  445. * Obtains a numeric value as a :c:type:`hipack_dict_t`.
  446. */
  447. #define HIPACK_TYPES(F) \
  448. F (int32_t, integer, HIPACK_INTEGER) \
  449. F (double, float, HIPACK_FLOAT ) \
  450. F (bool, bool, HIPACK_BOOL ) \
  451. F (hipack_string_t*, string, HIPACK_STRING ) \
  452. F (hipack_list_t*, list, HIPACK_LIST ) \
  453. F (hipack_dict_t*, dict, HIPACK_DICT )
  454. #define HIPACK_DEFINE_IS_TYPE(_type, name, type_tag) \
  455. static inline bool \
  456. hipack_value_is_ ## name (const hipack_value_t *value) { \
  457. return value->type == type_tag; \
  458. }
  459. #define HIPACK_DEFINE_GET_VALUE(_type, name, type_tag) \
  460. static inline const _type \
  461. hipack_value_get_ ## name (const hipack_value_t *value) { \
  462. assert (value->type == type_tag); \
  463. return value->v_ ## name; \
  464. }
  465. #define HIPACK_DEFINE_MAKE_VALUE(_type, name, type_tag) \
  466. static inline hipack_value_t \
  467. hipack_ ## name (_type value) { \
  468. hipack_value_t v = { type_tag, NULL, { value } }; \
  469. return v; \
  470. }
  471. HIPACK_TYPES (HIPACK_DEFINE_IS_TYPE)
  472. HIPACK_TYPES (HIPACK_DEFINE_GET_VALUE)
  473. #undef HIPACK_DEFINE_IS_TYPE
  474. #undef HIPACK_DEFINE_GET_VALUE
  475. #undef HIPACK_DEFINE_MAKE_VALUE
  476. /*~f bool hipack_value_equal (const hipack_value_t *a, const hipack_value_t *b)
  477. *
  478. * Checks whether two values are equal.
  479. */
  480. extern bool hipack_value_equal (const hipack_value_t *a,
  481. const hipack_value_t *b);
  482. /*~f void hipack_value_free (hipack_value_t *value)
  483. *
  484. * Frees the memory used by a value.
  485. */
  486. static inline void
  487. hipack_value_free (hipack_value_t *value)
  488. {
  489. assert (value);
  490. if (value->annot)
  491. hipack_dict_free (value->annot);
  492. switch (value->type) {
  493. case HIPACK_INTEGER:
  494. case HIPACK_FLOAT:
  495. case HIPACK_BOOL:
  496. /* Nothing to free. */
  497. break;
  498. case HIPACK_STRING:
  499. hipack_string_free (value->v_string);
  500. break;
  501. case HIPACK_LIST:
  502. hipack_list_free (value->v_list);
  503. break;
  504. case HIPACK_DICT:
  505. hipack_dict_free (value->v_dict);
  506. break;
  507. }
  508. }
  509. /*~f void hipack_value_add_annot (hipack_value_t *value, const char *annot)
  510. *
  511. * Adds an annotation to a value. If the value already had the annotation,
  512. * this function is a no-op.
  513. */
  514. static inline void
  515. hipack_value_add_annot (hipack_value_t *value,
  516. const char *annot)
  517. {
  518. assert (value);
  519. assert (annot);
  520. if (!value->annot) {
  521. value->annot = hipack_dict_new ();
  522. }
  523. static const hipack_value_t bool_true = {
  524. .type = HIPACK_BOOL,
  525. .v_bool = true,
  526. };
  527. hipack_string_t *key = hipack_string_new_from_string (annot);
  528. hipack_dict_set_adopt_key (value->annot, &key, &bool_true);
  529. }
  530. /*~f bool hipack_value_has_annot (const hipack_value_t *value, const char *annot)
  531. *
  532. * Checks whether a value has a given annotation.
  533. */
  534. static inline bool
  535. hipack_value_has_annot (const hipack_value_t *value,
  536. const char *annot)
  537. {
  538. assert (value);
  539. assert (annot);
  540. /* TODO: Try to avoid the string copy. */
  541. hipack_string_t *key = hipack_string_new_from_string (annot);
  542. bool result = (value->annot) && hipack_dict_get (value->annot, key);
  543. hipack_string_free (key);
  544. return result;
  545. }
  546. /*~f void hipack_value_del_annot (hipack_value_t *value, const char *annot)
  547. *
  548. * Removes an annotation from a value. If the annotation was not present, this
  549. * function is a no-op.
  550. */
  551. static inline void
  552. hipack_value_del_annot (hipack_value_t *value,
  553. const char *annot)
  554. {
  555. assert (value);
  556. assert (annot);
  557. if (value->annot) {
  558. hipack_string_t *key = hipack_string_new_from_string (annot);
  559. hipack_dict_del (value->annot, key);
  560. }
  561. }
  562. /**
  563. * Reader Interface
  564. * ================
  565. */
  566. /*~t hipack_reader_t
  567. *
  568. * Allows communicating with the parser, instructing it how to read text
  569. * input data, and provides a way for the parser to report errors back.
  570. *
  571. * The following members of the structure are to be used by client code:
  572. */
  573. typedef struct {
  574. /*~m int (*getchar)(void *data)
  575. * Reader callback function. The function will be called every time the
  576. * next character of input is needed. It must return it as an integer,
  577. * :any:`HIPACK_IO_EOF` when trying to read pas the end of the input,
  578. * or :any:`HIPACK_IO_ERROR` if an input error occurs.
  579. */
  580. int (*getchar) (void*);
  581. /*m void *getchar_data
  582. * Data passed to the reader callback function.
  583. */
  584. void *getchar_data;
  585. /*~m const char *error
  586. * On error, a string describing the issue, suitable to be displayed to
  587. * the user.
  588. */
  589. const char *error;
  590. /*~m unsigned error_line
  591. * On error, the line number where parsing was stopped.
  592. */
  593. unsigned error_line;
  594. /*~m unsigned error_column
  595. * On error, the column where parsing was stopped.
  596. */
  597. unsigned error_column;
  598. } hipack_reader_t;
  599. enum {
  600. /*~M HIPACK_IO_EOF
  601. * Constant returned by reader functions when trying to read past the end of
  602. * the input.
  603. */
  604. HIPACK_IO_EOF = -1,
  605. /*~M HIPACK_IO_ERROR
  606. * Constant returned by reader functions on input errors.
  607. */
  608. HIPACK_IO_ERROR = -2,
  609. };
  610. /*~M HIPACK_READ_ERROR
  611. *
  612. * Constant value used to signal an underlying input error.
  613. *
  614. * The `error` field of :c:type:`hipack_reader_t` is set to this value when
  615. * the reader function returns :any:`HIPACK_IO_ERROR`. This is provided to
  616. * allow client code to detect this condition and further query for the
  617. * nature of the input error.
  618. */
  619. extern const char* HIPACK_READ_ERROR;
  620. /*~f hipack_dict_t* hipack_read (hipack_reader_t *reader)
  621. *
  622. * Reads a HiPack message from a stream `reader` and returns a dictionary.
  623. *
  624. * On error, ``NULL`` is returned, and the members `error`, `error_line`,
  625. * and `error_column` (see :c:type:`hipack_reader_t`) are set accordingly
  626. * in the `reader`.
  627. */
  628. extern hipack_dict_t* hipack_read (hipack_reader_t *reader);
  629. /*~f int hipack_stdio_getchar (void* fp)
  630. *
  631. * Reader function which uses ``FILE*`` objects from the standard C library.
  632. *
  633. * To use this function to read from a ``FILE*``, first open a file, and
  634. * then create a reader using this function and the open file as data to
  635. * be passed to it, and then use :c:func:`hipack_read()`:
  636. *
  637. * .. code-block:: c
  638. *
  639. * FILE* stream = fopen (HIPACK_FILE_PATH, "rb")
  640. * hipack_reader_t reader = {
  641. * .getchar = hipack_stdio_getchar,
  642. * .getchar_data = stream,
  643. * };
  644. * hipack_dict_t *message = hipack_read (&reader);
  645. *
  646. * The user is responsible for closing the ``FILE*`` after using it.
  647. */
  648. extern int hipack_stdio_getchar (void* fp);
  649. /**
  650. * Writer Interface
  651. * ================
  652. */
  653. /*~t hipack_writer_t
  654. *
  655. * Allows specifying how to write text output data, and configuring how
  656. * the produced HiPack output looks like.
  657. *
  658. * The following members of the structure are to be used by client code:
  659. */
  660. typedef struct {
  661. /*~m int (*putchar)(void *data, int ch)
  662. * Writer callback function. The function will be called every time a
  663. * character is produced as output. It must return :any:`HIPACK_IO_ERROR`
  664. * if an output error occurs, and it is invalid for the callback to
  665. * return :any:`HIPACK_IO_EOF`. Any other value is interpreted as
  666. * indication of success.
  667. */
  668. int (*putchar) (void*, int);
  669. /*~m void* putchar_data
  670. * Data passed to the writer callback function.
  671. */
  672. void *putchar_data;
  673. /*~m int32_t indent
  674. * Either :any:`HIPACK_WRITER_COMPACT` or :any:`HIPACK_WRITER_INDENTED`.
  675. */
  676. int32_t indent;
  677. } hipack_writer_t;
  678. enum {
  679. /*~M HIPACK_WRITER_COMPACT
  680. * Flag to generate output HiPack messages in their compact representation.
  681. */
  682. HIPACK_WRITER_COMPACT = -1,
  683. /*~M HIPACK_WRITER_INDENTED
  684. * Flag to generate output HiPack messages in “indented” (pretty-printed)
  685. * representation.
  686. */
  687. HIPACK_WRITER_INDENTED = 0,
  688. };
  689. #define HIPACK_DEFINE_WRITE_VALUE(_type, name, type_tag) \
  690. extern bool hipack_write_ ## name (hipack_writer_t *writer, \
  691. const _type value);
  692. HIPACK_TYPES (HIPACK_DEFINE_WRITE_VALUE)
  693. #undef HIPACK_DEFINE_WRITE_VALUE
  694. extern bool hipack_write_value (hipack_writer_t *writer,
  695. const hipack_value_t *value);
  696. /*~f bool hipack_write (hipack_writer_t *writer, const hipack_dict_t *message)
  697. *
  698. * Writes a HiPack `message` to a stream `writer`, and returns whether writing
  699. * the message was successful.
  700. */
  701. extern bool hipack_write (hipack_writer_t *writer,
  702. const hipack_dict_t *message);
  703. /*~f int hipack_stdio_putchar (void* data, int ch)
  704. *
  705. * Writer function which uses ``FILE*`` objects from the standard C library.
  706. *
  707. * To use this function to write a message to a ``FILE*``, first open a file,
  708. * then create a writer using this function, and then use
  709. * :c:func:`hipack_write()`:
  710. *
  711. * .. code-block:: c
  712. *
  713. * FILE* stream = fopen (HIPACK_FILE_PATH, "wb");
  714. * hipack_writer_t writer = {
  715. * .putchar = hipack_stdio_putchar,
  716. * .putchar_data = stream,
  717. * };
  718. * hipack_write (&writer, message);
  719. *
  720. * The user is responsible for closing the ``FILE*`` after using it.
  721. */
  722. extern int hipack_stdio_putchar (void* fp, int ch);
  723. #endif /* !HIPACK_H */