hipack.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  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. * Dictionary Functions
  259. * ====================
  260. */
  261. /*~f uint32_t hipack_dict_size (const hipack_dict_t *dict)
  262. *
  263. * Obtains the number of elements in a dictionary.
  264. */
  265. static inline uint32_t
  266. hipack_dict_size (const hipack_dict_t *dict)
  267. {
  268. assert (dict);
  269. return dict->count;
  270. }
  271. /*~f hipack_dict_t* hipack_dict_new (void)
  272. *
  273. * Creates a new, empty dictionary.
  274. */
  275. extern hipack_dict_t* hipack_dict_new (void);
  276. /*~f void hipack_dict_free (hipack_dict_t *dict)
  277. *
  278. * Frees the memory used by a dictionary.
  279. */
  280. extern void hipack_dict_free (hipack_dict_t *dict);
  281. /*~f bool hipack_dict_equal (const hipack_dict_t *a, const hipack_dict_t *b)
  282. *
  283. * Checks whether two dictinaries contain the same keys, and their associated
  284. * values in each of the dictionaries are equal.
  285. */
  286. extern bool hipack_dict_equal (const hipack_dict_t *a,
  287. const hipack_dict_t *b);
  288. /*~f void hipack_dict_set (hipack_dict_t *dict, const hipack_string_t *key, const hipack_value_t *value)
  289. *
  290. * Adds an association of a `key` to a `value`.
  291. *
  292. * Note that this function will copy the `key`. If you are not planning to
  293. * continue reusing the `key`, it is recommended to use
  294. * :c:func:`hipack_dict_set_adopt_key()` instead.
  295. */
  296. extern void hipack_dict_set (hipack_dict_t *dict,
  297. const hipack_string_t *key,
  298. const hipack_value_t *value);
  299. /*~f void hipack_dict_set_adopt_key (hipack_dict_t *dict, hipack_string_t **key, const hipack_value_t *value)
  300. *
  301. * Adds an association of a `key` to a `value`, passing ownership of the
  302. * memory using by the `key` to the dictionary (i.e. the string used as key
  303. * will be freed by the dictionary).
  304. *
  305. * Use this function instead of :c:func:`hipack_dict_set()` when the `key`
  306. * is not going to be used further afterwards.
  307. */
  308. extern void hipack_dict_set_adopt_key (hipack_dict_t *dict,
  309. hipack_string_t **key,
  310. const hipack_value_t *value);
  311. /*~f void hipack_dict_del (hipack_dict_t *dict, const hipack_string_t *key)
  312. *
  313. * Removes the element from a dictionary associated to a `key`.
  314. */
  315. extern void hipack_dict_del (hipack_dict_t *dict,
  316. const hipack_string_t *key);
  317. /*~f hipack_value_t* hipack_dict_get (const hipack_dict_t *dict, const hipack_string_t *key)
  318. *
  319. * Obtains the value associated to a `key` from a dictionary.
  320. *
  321. * The returned value points to memory owned by the dictionary. The value can
  322. * be modified in-place, but it shall not be freed.
  323. */
  324. extern hipack_value_t* hipack_dict_get (const hipack_dict_t *dict,
  325. const hipack_string_t *key);
  326. /*~f hipack_value_t* hipack_dict_first (const hipack_dict_t *dict, const hipack_string_t **key)
  327. *
  328. * Obtains an a *(key, value)* pair, which is considered the *first* in
  329. * iteration order. This can be used in combination with
  330. * :c:func:`hipack_dict_next()` to enumerate all the *(key, value)* pairs
  331. * stored in the dictionary:
  332. *
  333. * .. code-block:: c
  334. *
  335. * hipack_dict_t *d = get_dictionary ();
  336. * hipack_value_t *v;
  337. * hipack_string_t *k;
  338. *
  339. * for (v = hipack_dict_first (d, &k);
  340. * v != NULL;
  341. * v = hipack_dict_next (v, &k)) {
  342. * // Use "k" and "v" normally.
  343. * }
  344. *
  345. * As a shorthand, consider using :c:macro:`HIPACK_DICT_FOREACH()` instead.
  346. */
  347. extern hipack_value_t* hipack_dict_first (const hipack_dict_t *dict,
  348. const hipack_string_t **key);
  349. /*~f hipack_value_t* hipack_dict_next (hipack_value_t *value, const hipack_string_t **key)
  350. *
  351. * Iterates to the next *(key, value)* pair of a dictionary. For usage
  352. * details, see :c:func:`hipack_dict_first()`.
  353. */
  354. extern hipack_value_t* hipack_dict_next (hipack_value_t *value,
  355. const hipack_string_t **key);
  356. /*~M HIPACK_DICT_FOREACH(dict, key, value)
  357. *
  358. * Convenience macro used to iterate over the *(key, value)* pairs contained
  359. * in a dictionary. Internally this uses :c:func:`hipack_dict_first()` and
  360. * :c:func:`hipack_dict_next()`.
  361. *
  362. * .. code-block:: c
  363. *
  364. * hipack_dict_t *d = get_dictionary ();
  365. * hipack_string_t *k;
  366. * hipack_value_t *v;
  367. * HIPACK_DICT_FOREACH (d, k, v) {
  368. * // Use "k" and "v"
  369. * }
  370. *
  371. * Using this macro is the recommended way of writing a loop to enumerate
  372. * elements from a dictionary.
  373. */
  374. #define HIPACK_DICT_FOREACH(_d, _k, _v) \
  375. for ((_v) = hipack_dict_first ((_d), &(_k)); \
  376. (_v) != NULL; \
  377. (_v) = hipack_dict_next ((_v), &(_k)))
  378. /**
  379. * Value Functions
  380. * ===============
  381. */
  382. /*~f hipack_type_t hipack_value_type (const hipack_value_t *value)
  383. *
  384. * Obtains the type of a value.
  385. */
  386. static inline hipack_type_t
  387. hipack_value_type (const hipack_value_t *value)
  388. {
  389. return value->type;
  390. }
  391. /*~f bool hipack_value_is_integer (const hipack_value_t *value)
  392. * Checks whether a value is an integer.
  393. */
  394. /*~f bool hipack_value_is_float (const hipack_value_t *value)
  395. * Checks whether a value is a floating point number.
  396. */
  397. /*~f bool hipack_value_is_bool (const hipack_value_t *value)
  398. * Checks whether a value is a boolean.
  399. */
  400. /*~f bool hipack_value_is_string (const hipack_value_t *value)
  401. * Checks whether a value is a string.
  402. */
  403. /*~f bool hipack_value_is_list (const hipack_value_t *value)
  404. * Checks whether a value is a list.
  405. */
  406. /*~f bool hipack_value_is_dict (const hipack_value_t *value)
  407. * Checks whether a value is a dictionary.
  408. */
  409. /*~f const int32_t hipack_value_get_integer (const hipack_value_t *value)
  410. * Obtains a numeric value as an ``int32_t``.
  411. */
  412. /*~f const double hipack_value_get_float (const hipack_value_t *value)
  413. * Obtains a floating point value as a ``double``.
  414. */
  415. /*~f const bool hipack_value_get_bool (const hipack_value_t *value)
  416. * Obtains a boolean value as a ``bool``.
  417. */
  418. /*~f const hipack_string_t* hipack_value_get_string (const hipack_value_t *value)
  419. * Obtains a numeric value as a :c:type:`hipack_string_t`.
  420. */
  421. /*~f const hipack_list_t* hipack_value_get_list (const hipack_value_t *value)
  422. * Obtains a numeric value as a :c:type:`hipack_list_t`.
  423. */
  424. /*~f const hipack_dict_t* hipack_value_get_dict (const hipack_value_t *value)
  425. * Obtains a numeric value as a :c:type:`hipack_dict_t`.
  426. */
  427. #define HIPACK_TYPES(F) \
  428. F (int32_t, integer, HIPACK_INTEGER) \
  429. F (double, float, HIPACK_FLOAT ) \
  430. F (bool, bool, HIPACK_BOOL ) \
  431. F (hipack_string_t*, string, HIPACK_STRING ) \
  432. F (hipack_list_t*, list, HIPACK_LIST ) \
  433. F (hipack_dict_t*, dict, HIPACK_DICT )
  434. #define HIPACK_DEFINE_IS_TYPE(_type, name, type_tag) \
  435. static inline bool \
  436. hipack_value_is_ ## name (const hipack_value_t *value) { \
  437. return value->type == type_tag; \
  438. }
  439. #define HIPACK_DEFINE_GET_VALUE(_type, name, type_tag) \
  440. static inline const _type \
  441. hipack_value_get_ ## name (const hipack_value_t *value) { \
  442. assert (value->type == type_tag); \
  443. return value->v_ ## name; \
  444. }
  445. HIPACK_TYPES (HIPACK_DEFINE_IS_TYPE)
  446. HIPACK_TYPES (HIPACK_DEFINE_GET_VALUE)
  447. #undef HIPACK_DEFINE_IS_TYPE
  448. #undef HIPACK_DEFINE_GET_VALUE
  449. /*~f bool hipack_value_equal (const hipack_value_t *a, const hipack_value_t *b)
  450. *
  451. * Checks whether two values are equal.
  452. */
  453. extern bool hipack_value_equal (const hipack_value_t *a,
  454. const hipack_value_t *b);
  455. /*~f void hipack_value_free (hipack_value_t *value)
  456. *
  457. * Frees the memory used by a value.
  458. */
  459. static inline void
  460. hipack_value_free (hipack_value_t *value)
  461. {
  462. assert (value);
  463. if (value->annot)
  464. hipack_dict_free (value->annot);
  465. switch (value->type) {
  466. case HIPACK_INTEGER:
  467. case HIPACK_FLOAT:
  468. case HIPACK_BOOL:
  469. /* Nothing to free. */
  470. break;
  471. case HIPACK_STRING:
  472. hipack_string_free (value->v_string);
  473. break;
  474. case HIPACK_LIST:
  475. hipack_list_free (value->v_list);
  476. break;
  477. case HIPACK_DICT:
  478. hipack_dict_free (value->v_dict);
  479. break;
  480. }
  481. }
  482. /*~f void hipack_value_add_annot (hipack_value_t *value, const char *annot)
  483. *
  484. * Adds an annotation to a value. If the value already had the annotation,
  485. * this function is a no-op.
  486. */
  487. static inline void
  488. hipack_value_add_annot (hipack_value_t *value,
  489. const char *annot)
  490. {
  491. assert (value);
  492. assert (annot);
  493. if (!value->annot) {
  494. value->annot = hipack_dict_new ();
  495. }
  496. static const hipack_value_t bool_true = {
  497. .type = HIPACK_BOOL,
  498. .v_bool = true,
  499. };
  500. hipack_string_t *key = hipack_string_new_from_string (annot);
  501. hipack_dict_set_adopt_key (value->annot, &key, &bool_true);
  502. }
  503. /*~f bool hipack_value_has_annot (const hipack_value_t *value, const char *annot)
  504. *
  505. * Checks whether a value has a given annotation.
  506. */
  507. static inline bool
  508. hipack_value_has_annot (const hipack_value_t *value,
  509. const char *annot)
  510. {
  511. assert (value);
  512. assert (annot);
  513. /* TODO: Try to avoid the string copy. */
  514. hipack_string_t *key = hipack_string_new_from_string (annot);
  515. bool result = (value->annot) && hipack_dict_get (value->annot, key);
  516. hipack_string_free (key);
  517. return result;
  518. }
  519. /*~f void hipack_value_del_annot (hipack_value_t *value, const char *annot)
  520. *
  521. * Removes an annotation from a value. If the annotation was not present, this
  522. * function is a no-op.
  523. */
  524. static inline void
  525. hipack_value_del_annot (hipack_value_t *value,
  526. const char *annot)
  527. {
  528. assert (value);
  529. assert (annot);
  530. if (value->annot) {
  531. hipack_string_t *key = hipack_string_new_from_string (annot);
  532. hipack_dict_del (value->annot, key);
  533. }
  534. }
  535. /**
  536. * Reader Interface
  537. * ================
  538. */
  539. /*~t hipack_reader_t
  540. *
  541. * Allows communicating with the parser, instructing it how to read text
  542. * input data, and provides a way for the parser to report errors back.
  543. *
  544. * The following members of the structure are to be used by client code:
  545. */
  546. typedef struct {
  547. /*~m int (*getchar)(void *data)
  548. * Reader callback function. The function will be called every time the
  549. * next character of input is needed. It must return it as an integer,
  550. * :any:`HIPACK_IO_EOF` when trying to read pas the end of the input,
  551. * or :any:`HIPACK_IO_ERROR` if an input error occurs.
  552. */
  553. int (*getchar) (void*);
  554. /*m void *getchar_data
  555. * Data passed to the reader callback function.
  556. */
  557. void *getchar_data;
  558. /*~m const char *error
  559. * On error, a string describing the issue, suitable to be displayed to
  560. * the user.
  561. */
  562. const char *error;
  563. /*~m unsigned error_line
  564. * On error, the line number where parsing was stopped.
  565. */
  566. unsigned error_line;
  567. /*~m unsigned error_column
  568. * On error, the column where parsing was stopped.
  569. */
  570. unsigned error_column;
  571. } hipack_reader_t;
  572. enum {
  573. /*~M HIPACK_IO_EOF
  574. * Constant returned by reader functions when trying to read past the end of
  575. * the input.
  576. */
  577. HIPACK_IO_EOF = -1,
  578. /*~M HIPACK_IO_ERROR
  579. * Constant returned by reader functions on input errors.
  580. */
  581. HIPACK_IO_ERROR = -2,
  582. };
  583. /*~M HIPACK_READ_ERROR
  584. *
  585. * Constant value used to signal an underlying input error.
  586. *
  587. * The `error` field of :c:type:`hipack_reader_t` is set to this value when
  588. * the reader function returns :any:`HIPACK_IO_ERROR`. This is provided to
  589. * allow client code to detect this condition and further query for the
  590. * nature of the input error.
  591. */
  592. extern const char* HIPACK_READ_ERROR;
  593. /*~f hipack_dict_t* hipack_read (hipack_reader_t *reader)
  594. *
  595. * Reads a HiPack message from a stream `reader` and returns a dictionary.
  596. *
  597. * On error, ``NULL`` is returned, and the members `error`, `error_line`,
  598. * and `error_column` (see :c:type:`hipack_reader_t`) are set accordingly
  599. * in the `reader`.
  600. */
  601. extern hipack_dict_t* hipack_read (hipack_reader_t *reader);
  602. /*~f int hipack_stdio_getchar (void* fp)
  603. *
  604. * Reader function which uses ``FILE*`` objects from the standard C library.
  605. *
  606. * To use this function to read from a ``FILE*``, first open a file, and
  607. * then create a reader using this function and the open file as data to
  608. * be passed to it, and then use :c:func:`hipack_read()`:
  609. *
  610. * .. code-block:: c
  611. *
  612. * FILE* stream = fopen (HIPACK_FILE_PATH, "rb")
  613. * hipack_reader_t reader = {
  614. * .getchar = hipack_stdio_getchar,
  615. * .getchar_data = stream,
  616. * };
  617. * hipack_dict_t *message = hipack_read (&reader);
  618. *
  619. * The user is responsible for closing the ``FILE*`` after using it.
  620. */
  621. extern int hipack_stdio_getchar (void* fp);
  622. /**
  623. * Writer Interface
  624. * ================
  625. */
  626. /*~t hipack_writer_t
  627. *
  628. * Allows specifying how to write text output data, and configuring how
  629. * the produced HiPack output looks like.
  630. *
  631. * The following members of the structure are to be used by client code:
  632. */
  633. typedef struct {
  634. /*~m int (*putchar)(void *data, int ch)
  635. * Writer callback function. The function will be called every time a
  636. * character is produced as output. It must return :any:`HIPACK_IO_ERROR`
  637. * if an output error occurs, and it is invalid for the callback to
  638. * return :any:`HIPACK_IO_EOF`. Any other value is interpreted as
  639. * indication of success.
  640. */
  641. int (*putchar) (void*, int);
  642. /*~m void* putchar_data
  643. * Data passed to the writer callback function.
  644. */
  645. void *putchar_data;
  646. /*~m int32_t indent
  647. * Either :any:`HIPACK_WRITER_COMPACT` or :any:`HIPACK_WRITER_INDENTED`.
  648. */
  649. int32_t indent;
  650. } hipack_writer_t;
  651. enum {
  652. /*~M HIPACK_WRITER_COMPACT
  653. * Flag to generate output HiPack messages in their compact representation.
  654. */
  655. HIPACK_WRITER_COMPACT = -1,
  656. /*~M HIPACK_WRITER_INDENTED
  657. * Flag to generate output HiPack messages in “indented” (pretty-printed)
  658. * representation.
  659. */
  660. HIPACK_WRITER_INDENTED = 0,
  661. };
  662. #define HIPACK_DEFINE_WRITE_VALUE(_type, name, type_tag) \
  663. extern bool hipack_write_ ## name (hipack_writer_t *writer, \
  664. const _type value);
  665. HIPACK_TYPES (HIPACK_DEFINE_WRITE_VALUE)
  666. #undef HIPACK_DEFINE_WRITE_VALUE
  667. extern bool hipack_write_value (hipack_writer_t *writer,
  668. const hipack_value_t *value);
  669. /*~f bool hipack_write (hipack_writer_t *writer, const hipack_dict_t *message)
  670. *
  671. * Writes a HiPack `message` to a stream `writer`, and returns whether writing
  672. * the message was successful.
  673. */
  674. extern bool hipack_write (hipack_writer_t *writer,
  675. const hipack_dict_t *message);
  676. /*~f int hipack_stdio_putchar (void* data, int ch)
  677. *
  678. * Writer function which uses ``FILE*`` objects from the standard C library.
  679. *
  680. * To use this function to write a message to a ``FILE*``, first open a file,
  681. * then create a writer using this function, and then use
  682. * :c:func:`hipack_write()`:
  683. *
  684. * .. code-block:: c
  685. *
  686. * FILE* stream = fopen (HIPACK_FILE_PATH, "wb");
  687. * hipack_writer_t writer = {
  688. * .putchar = hipack_stdio_putchar,
  689. * .putchar_data = stream,
  690. * };
  691. * hipack_write (&writer, message);
  692. *
  693. * The user is responsible for closing the ``FILE*`` after using it.
  694. */
  695. extern int hipack_stdio_putchar (void* fp, int ch);
  696. #endif /* !HIPACK_H */