0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-10-18 18:08:45 +00:00
bird/lib/cbor.h
2024-10-05 15:54:15 +02:00

135 lines
3.9 KiB
C

#ifndef CBOR_H
#define CBOR_H
#include "nest/bird.h"
enum cbor_basic_type {
CBOR_POSINT = 0,
CBOR_NEGINT = 1,
CBOR_BYTES = 2,
CBOR_TEXT = 3,
CBOR_ARRAY = 4,
CBOR_MAP = 5,
CBOR_TAG = 6,
CBOR_SPECIAL = 7,
};
const char *cbor_type_str(enum cbor_basic_type);
struct cbor_writer {
int pt; // where will next byte go
int capacity;
int8_t *cbor;
struct linpool *lp;
};
struct cbor_writer *cbor_init(uint8_t *buff, uint32_t capacity, struct linpool *lp);
void cbor_open_block(struct cbor_writer *writer);
void cbor_open_list(struct cbor_writer *writer);
void cbor_close_block_or_list(struct cbor_writer *writer);
void cbor_open_block_with_length(struct cbor_writer *writer, uint32_t length);
void cbor_open_list_with_length(struct cbor_writer *writer, uint32_t length);
void cbor_add_int(struct cbor_writer *writer, int64_t item);
void cbor_add_ipv4(struct cbor_writer *writer, ip4_addr);
void cbor_add_ipv6(struct cbor_writer *writer, ip6_addr);
void cbor_epoch_time(struct cbor_writer *writer, int64_t time, int shift);
void cbor_relativ_time(struct cbor_writer *writer, int64_t time, int shift);
void cbor_add_ipv4_prefix(struct cbor_writer *writer, net_addr_ip4 *n);
void cbor_add_ipv6_prefix(struct cbor_writer *writer, net_addr_ip6 *n);
void cbor_add_uint(struct cbor_writer *writer, uint64_t item);
void cbor_add_tag(struct cbor_writer *writer, int item);
void cbor_add_string(struct cbor_writer *writer, const char *string);
void cbor_nonterminated_string(struct cbor_writer *writer, const char *string, uint32_t length);
void write_item(struct cbor_writer *writer, uint8_t major, uint64_t num);
void cbor_write_item_with_constant_val_length_4(struct cbor_writer *writer, uint8_t major, uint64_t num);
void rewrite_4bytes_int(struct cbor_writer *writer, int pt, int num);
/*
* Parser bits
*/
struct cbor_parser_context {
/* Public part */
linpool *lp; /* Linpool for in-parser allocations */
byte type; /* Last parsed type */
enum {
CPT_VARLEN = 1,
} tflags; /* Additional flags for the type / value pair */
u64 value; /* Last parsed (integer) value */
byte *target_buf; /* Target buf for CBOR_BYTES or CBOR_TEXT */
uint target_len; /* Set how many bytes to store */
const char *error; /* Error message */
/* Private part */
lp_state *flush; /* Linpool reset pointer */
enum { /* Multi-byte reader */
CPE_TYPE = 0,
CPE_READ_INT,
CPE_COMPLETE_INT,
CPE_READ_BYTE,
CPE_ITEM_DONE,
CPE_EXIT,
} partial_state;
u64 partial_countdown; /* How many items remaining in CBOR_ARRAY / CBOR_MAP */
uint stack_pos, stack_max; /* Nesting of CBOR_ARRAY / CBOR_MAP */
u64 stack_countdown[0];
};
struct cbor_parser_context *cbor_parser_new(pool *, uint stack_max_depth);
static inline void cbor_parser_free(struct cbor_parser_context *ctx)
{ rfree(ctx->lp); }
void cbor_parser_reset(struct cbor_parser_context *ctx);
enum cbor_parse_result {
CPR_ERROR = 0,
CPR_MORE = 1,
CPR_MAJOR = 2,
CPR_STR_END = 3,
} cbor_parse_byte(struct cbor_parser_context *, const byte);
bool cbor_parse_block_end(struct cbor_parser_context *);
#define CBOR_PARSE_IF(_ctx, _type, _target) if (((_ctx)->type == CBOR_##_type) && CBOR_STORE_##_type((_ctx), _target))
#define CBOR_PARSE_ONLY(_ctx, _type, _target) CBOR_PARSE_IF(_ctx, _type, _target) {} else CBOR_PARSER_ERROR("Expected %s for %s, got %s", #_type, #_target, cbor_type_str((_ctx)->type))
#define CBOR_STORE_POSINT(_ctx, _target) ((_target = (_ctx)->value), 1)
#define CBOR_STORE_NEGINT(_ctx, _target) ((_target = -1LL-(_ctx)->value), 1)
#define CBOR_STORE_BYTES(_ctx, _target) ({ \
if ((_ctx)->tflags & CPT_VARLEN) CBOR_PARSER_ERROR("Variable length string not supported yet"); \
if ((_target)) CBOR_PARSER_ERROR("Duplicate argument %s", #_target); \
ASSERT_DIE(!(_ctx)->target_buf); \
_target = (_ctx)->target_buf = lp_alloc((_ctx)->lp, ((_ctx)->target_len = (_ctx)->value) + 1); \
1; })
#define CBOR_STORE_TEXT CBOR_STORE_BYTES
#endif