16void cbor_init(CborWriter *w, uint8_t *buf,
size_t cap)
21size_t cbor_len(
const CborWriter *w)
26bool cbor_ok(
const CborWriter *w)
31static void put(CborWriter *w, uint8_t b)
39static void head(CborWriter *w, uint8_t major, uint64_t val)
41 uint8_t m = (uint8_t)(major << 5);
44 put(w, (uint8_t)(m | val));
46 else if (val < 0x100ULL)
48 put(w, (uint8_t)(m | 24));
51 else if (val < 0x10000ULL)
53 put(w, (uint8_t)(m | 25));
56 else if (val < 0x100000000ULL)
58 put(w, (uint8_t)(m | 26));
63 put(w, (uint8_t)(m | 27));
68void cbor_uint(CborWriter *w, uint64_t v)
73void cbor_int(CborWriter *w, int64_t v)
76 head(w, 0, (uint64_t)v);
78 head(w, 1, (uint64_t)(-1 - v));
81void cbor_bytes(CborWriter *w,
const uint8_t *data,
size_t len)
83 head(w, 2, (uint64_t)len);
84 for (
size_t i = 0; i < len; i++)
88void cbor_text_n(CborWriter *w,
const char *s,
size_t len)
90 head(w, 3, (uint64_t)len);
91 for (
size_t i = 0; i < len; i++)
92 put(w, (uint8_t)s[i]);
95void cbor_text(CborWriter *w,
const char *s)
97 cbor_text_n(w, s, s ? strnlen(s, w->cap + 1) : 0);
100void cbor_bool(CborWriter *w,
bool b)
102 put(w, b ? 0xf5 : 0xf4);
105void cbor_null(CborWriter *w)
110void cbor_float(CborWriter *w,
float f)
113 memcpy(&bits, &f,
sizeof(bits));
118void cbor_array(CborWriter *w,
size_t count)
120 head(w, 4, (uint64_t)count);
123void cbor_map(CborWriter *w,
size_t count)
125 head(w, 5, (uint64_t)count);
132void cbor_reader_init(CborReader *r,
const uint8_t *buf,
size_t len)
137bool cbor_reader_ok(
const CborReader *r)
144static bool read_head(CborReader *r, uint8_t *major, uint64_t *val)
146 if (r->err || r->pos >= r->len)
151 uint8_t b = r->buf[r->pos];
152 uint8_t info = (uint8_t)(b & 0x1f);
153 *major = (uint8_t)(b >> 5);
183CborType cbor_peek(CborReader *r)
185 if (r->err || r->pos >= r->len)
186 return CborType::CBOR_TYPE_INVALID;
187 uint8_t b = r->buf[r->pos];
191 return CborType::CBOR_TYPE_UINT;
193 return CborType::CBOR_TYPE_INT;
195 return CborType::CBOR_TYPE_BYTES;
197 return CborType::CBOR_TYPE_TEXT;
199 return CborType::CBOR_TYPE_ARRAY;
201 return CborType::CBOR_TYPE_MAP;
203 uint8_t info = (uint8_t)(b & 0x1f);
204 if (info == 20 || info == 21)
205 return CborType::CBOR_TYPE_BOOL;
207 return CborType::CBOR_TYPE_NULL;
208 if (info == 26 || info == 27)
209 return CborType::CBOR_TYPE_FLOAT;
210 return CborType::CBOR_TYPE_INVALID;
213 return CborType::CBOR_TYPE_INVALID;
217bool cbor_read_uint(CborReader *r, uint64_t *out)
221 if (!read_head(r, &m, &v))
232bool cbor_read_int(CborReader *r, int64_t *out)
236 if (!read_head(r, &m, &v))
241 *out = -1 - (int64_t)v;
250bool cbor_read_bool(CborReader *r,
bool *out)
252 if (r->err || r->pos >= r->len)
257 uint8_t b = r->buf[r->pos];
271bool cbor_read_null(CborReader *r)
273 if (r->err || r->pos >= r->len || r->buf[r->pos] != 0xf6)
282bool cbor_read_float(CborReader *r,
float *out)
284 if (r->err || r->pos >= r->len)
289 uint8_t b = r->buf[r->pos];
295 uint32_t bits = (uint32_t)v;
296 memcpy(out, &bits,
sizeof(*out));
305 memcpy(&d, &bits,
sizeof(d));
314static bool read_str(CborReader *r, uint8_t want_major,
const uint8_t **out,
size_t *len)
318 if (!read_head(r, &m, &v))
320 if (m != want_major || r->pos + v > r->len)
325 *out = &r->buf[r->pos];
331bool cbor_read_text(CborReader *r,
const char **out,
size_t *len)
333 return read_str(r, 3, (
const uint8_t **)out, len);
336bool cbor_read_bytes(CborReader *r,
const uint8_t **out,
size_t *len)
338 return read_str(r, 2, out, len);
341bool cbor_read_array(CborReader *r,
size_t *count)
345 if (!read_head(r, &m, &v))
356bool cbor_read_map(CborReader *r,
size_t *count)
360 if (!read_head(r, &m, &v))
Shared byte-cursor mechanics for the binary codecs (one source of truth).
void det_bw_put_be(W *w, uint64_t val, int nbytes)
Append the low nbytes of val, big-endian (network order).
bool det_br_take_be(R *r, size_t nbytes, uint64_t *out)
Read nbytes big-endian immediately after the tag byte at pos, advancing past the tag and the argument...
void det_br_init(R *r, const uint8_t *buf, size_t len)
Bind a read cursor to buf (length len) at offset 0.
void det_bw_put(W *w, uint8_t b)
Append one byte; on overflow set the flag but keep counting pos.
bool det_br_ok(const R *r)
True while no malformed / out-of-bounds read has occurred.
bool det_bw_ok(const W *w)
True while every write has fit in the buffer.
void det_bw_init(W *w, uint8_t *buf, size_t cap)
Bind a write cursor to buf (capacity cap) and reset it.
size_t det_bw_len(const W *w)
Bytes the payload needs so far (keeps counting past cap on overflow).
Layer 6 (Presentation) - zero-heap CBOR (RFC 8949) encoder.