summaryrefslogtreecommitdiffstats
path: root/src/internal.h
blob: 57487c253075bb4fa701ad35083dc5973fdb4e66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
 * @file internal.h
 * @brief Helpers shared between the translation units of this library.
 *
 * Nothing here is part of the public ABI.
 */
#ifndef CEPIS_INTERNAL_H
#define CEPIS_INTERNAL_H

#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>

#include "cepis.h"
#include "csv.h"
#include "json.h"

/** A growable, always NUL-terminated byte buffer. */
typedef struct cepis_buf {
        char *data;
        size_t len;
        size_t cap;
} cepis_buf_t;

/** @brief Put @p buf into the empty state. Allocates nothing. */
void cepis_buf_init(cepis_buf_t *buf);

/** @brief Append @p len bytes. @return `false` on allocation failure. */
bool cepis_buf_append(cepis_buf_t *buf, const char *data, size_t len);

/** @brief Append a NUL-terminated string. */
bool cepis_buf_append_str(cepis_buf_t *buf, const char *text);

/** @brief Release the buffer and return it to the empty state. */
void cepis_buf_free(cepis_buf_t *buf);

/** @brief `strdup`, tolerating a `NULL` argument by copying `""`. */
char *cepis_strdup(const char *text);

/**
 * @brief Fill @p err, tolerating `NULL`.
 * @return @p status, so callers can `return cepis_set_error(...)`.
 */
cepis_status_t cepis_set_error(cepis_error_t *err, cepis_status_t status,
                               long http_status, double retry_after,
                               const char *fmt, ...);

/**
 * @brief Build an address from a parsed JSON object.
 * @param object  The decoded body.
 * @param raw     The body as it arrived, copied into
 *                ::cepis_address_t::raw. May be `NULL`.
 * @param raw_len Length of @p raw.
 * @return An owned address, or `NULL` on allocation failure.
 *
 * Unknown members are ignored but preserved in `raw`, so a field the API grows
 * cannot break this client. A malformed `geo` block yields `geo == NULL` rather
 * than failing the whole address: the rest of the response is still useful.
 */
cepis_address_t *cepis_address_from_json(const json_value_t *object,
                                         const char *raw, size_t raw_len);

/**
 * @brief Build an address from one CSV record and the header record.
 * @return An owned address, or `NULL` on allocation failure. The result never
 *         carries a coordinate: the CSV has no `geo` column.
 */
cepis_address_t *cepis_address_from_csv(const csv_row_t *header,
                                        const csv_row_t *record);

/** @brief Build a health report from a parsed JSON object. */
cepis_health_t *cepis_health_from_json(const json_value_t *object);

#endif