mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 10:11:53 +00:00
135 lines
3.9 KiB
C
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
|