MINOR: tools: add cbor encode helpers
Add cbor helpers to encode strings (bytes/text) and integers according to RFC8949, also add cbor_encode_ctx struct to pass encoding options such as how to encode a single byte.
This commit is contained in:
parent
3f7c8387c0
commit
810303e3e6
@ -165,4 +165,20 @@ struct net_addr_type {
|
|||||||
int xprt_type; // transport layer
|
int xprt_type; // transport layer
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* To easily pass context to cbor encode functions
|
||||||
|
*/
|
||||||
|
struct cbor_encode_ctx {
|
||||||
|
/* function pointer that cbor encode functions will use to encode a
|
||||||
|
* single byte.
|
||||||
|
*
|
||||||
|
* The function needs to return the position of the last written byte
|
||||||
|
* on success and NULL on failure. The function cannot write past <stop>
|
||||||
|
*/
|
||||||
|
char *(*e_byte_fct)(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop, uint8_t byte);
|
||||||
|
|
||||||
|
/* to pass some context to the encode_byte fct */
|
||||||
|
void *e_byte_fct_ctx;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* _HAPROXY_TOOLS_T_H */
|
#endif /* _HAPROXY_TOOLS_T_H */
|
||||||
|
@ -432,6 +432,25 @@ char *escape_string(char *start, char *stop,
|
|||||||
const char escape, const long *map,
|
const char escape, const long *map,
|
||||||
const char *string, const char *string_stop);
|
const char *string, const char *string_stop);
|
||||||
|
|
||||||
|
/* Below are RFC8949 compliant cbor encode helper functions, see source
|
||||||
|
* file for functions descriptions
|
||||||
|
*/
|
||||||
|
char *cbor_encode_uint64_prefix(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop,
|
||||||
|
uint64_t value, uint8_t prefix);
|
||||||
|
char *cbor_encode_int64(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop, int64_t value);
|
||||||
|
char *cbor_encode_bytes_prefix(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop,
|
||||||
|
const char *bytes, size_t len,
|
||||||
|
uint8_t prefix);
|
||||||
|
char *cbor_encode_bytes(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop,
|
||||||
|
const char *bytes, size_t len);
|
||||||
|
char *cbor_encode_text(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop,
|
||||||
|
const char *text, size_t len);
|
||||||
|
|
||||||
/* Check a string for using it in a CSV output format. If the string contains
|
/* Check a string for using it in a CSV output format. If the string contains
|
||||||
* one of the following four char <">, <,>, CR or LF, the string is
|
* one of the following four char <">, <,>, CR or LF, the string is
|
||||||
* encapsulated between <"> and the <"> are escaped by a <""> sequence.
|
* encapsulated between <"> and the <"> are escaped by a <""> sequence.
|
||||||
|
158
src/tools.c
158
src/tools.c
@ -2064,6 +2064,164 @@ char *escape_string(char *start, char *stop,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* CBOR helper to encode an uint64 value with prefix (3bits MAJOR type)
|
||||||
|
* according to RFC8949
|
||||||
|
*
|
||||||
|
* CBOR encode ctx is provided in <ctx>
|
||||||
|
*
|
||||||
|
* Returns the position of the last written byte on success and NULL on
|
||||||
|
* error. The function cannot write past <stop>
|
||||||
|
*/
|
||||||
|
char *cbor_encode_uint64_prefix(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop, uint64_t value,
|
||||||
|
uint8_t prefix)
|
||||||
|
{
|
||||||
|
int nb_bytes = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For encoding logic, see:
|
||||||
|
* https://www.rfc-editor.org/rfc/rfc8949.html#name-specification-of-the-cbor-e
|
||||||
|
*/
|
||||||
|
if (value < 24) {
|
||||||
|
/* argument is the value itself */
|
||||||
|
prefix |= value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (value <= 0xFFU) {
|
||||||
|
/* 1-byte */
|
||||||
|
nb_bytes = 1;
|
||||||
|
prefix |= 24; // 0x18
|
||||||
|
}
|
||||||
|
else if (value <= 0xFFFFU) {
|
||||||
|
/* 2 bytes */
|
||||||
|
nb_bytes = 2;
|
||||||
|
prefix |= 25; // 0x19
|
||||||
|
}
|
||||||
|
else if (value <= 0xFFFFFFFFU) {
|
||||||
|
/* 4 bytes */
|
||||||
|
nb_bytes = 4;
|
||||||
|
prefix |= 26; // 0x1A
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* 8 bytes */
|
||||||
|
nb_bytes = 8;
|
||||||
|
prefix |= 27; // 0x1B
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start = ctx->e_byte_fct(ctx, start, stop, prefix);
|
||||||
|
if (start == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* encode 1 byte at a time from higher bits to lower bits */
|
||||||
|
while (nb_bytes) {
|
||||||
|
uint8_t cur_byte = (value >> ((nb_bytes - 1) * 8)) & 0xFFU;
|
||||||
|
|
||||||
|
start = ctx->e_byte_fct(ctx, start, stop, cur_byte);
|
||||||
|
if (start == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
nb_bytes--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CBOR helper to encode an int64 value according to RFC8949
|
||||||
|
*
|
||||||
|
* CBOR encode ctx is provided in <ctx>
|
||||||
|
*
|
||||||
|
* Returns the position of the last written byte on success and NULL on
|
||||||
|
* error. The function cannot write past <stop>
|
||||||
|
*/
|
||||||
|
char *cbor_encode_int64(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop, int64_t value)
|
||||||
|
{
|
||||||
|
uint64_t absolute_value = llabs(value);
|
||||||
|
int cbor_prefix;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For encoding logic, see:
|
||||||
|
* https://www.rfc-editor.org/rfc/rfc8949.html#name-specification-of-the-cbor-e
|
||||||
|
*/
|
||||||
|
if (value >= 0)
|
||||||
|
cbor_prefix = 0x00; // unsigned int
|
||||||
|
else {
|
||||||
|
cbor_prefix = 0x20; // negative int
|
||||||
|
/* N-1 for negative int */
|
||||||
|
absolute_value -= 1;
|
||||||
|
}
|
||||||
|
return cbor_encode_uint64_prefix(ctx, start, stop,
|
||||||
|
absolute_value, cbor_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CBOR helper to encode a <prefix> string chunk according to RFC8949
|
||||||
|
*
|
||||||
|
* if <bytes> is NULL, then only the <prefix> (with length) will be
|
||||||
|
* emitted
|
||||||
|
*
|
||||||
|
* CBOR encode ctx is provided in <ctx>
|
||||||
|
*
|
||||||
|
* Returns the position of the last written byte on success and NULL on
|
||||||
|
* error. The function cannot write past <stop>
|
||||||
|
*/
|
||||||
|
char *cbor_encode_bytes_prefix(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop,
|
||||||
|
const char *bytes, size_t len,
|
||||||
|
uint8_t prefix)
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t it = 0;
|
||||||
|
|
||||||
|
/* write prefix (with text length as argument) */
|
||||||
|
start = cbor_encode_uint64_prefix(ctx, start, stop,
|
||||||
|
len, prefix);
|
||||||
|
if (start == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* write actual bytes if provided */
|
||||||
|
while (bytes && it < len) {
|
||||||
|
start = ctx->e_byte_fct(ctx, start, stop, bytes[it]);
|
||||||
|
if (start == NULL)
|
||||||
|
return NULL;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CBOR helper to encode a text chunk according to RFC8949
|
||||||
|
*
|
||||||
|
* if <text> is NULL, then only the text prefix (with length) will be emitted
|
||||||
|
*
|
||||||
|
* CBOR encode ctx is provided in <ctx>
|
||||||
|
*
|
||||||
|
* Returns the position of the last written byte on success and NULL on
|
||||||
|
* error. The function cannot write past <stop>
|
||||||
|
*/
|
||||||
|
char *cbor_encode_text(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop,
|
||||||
|
const char *text, size_t len)
|
||||||
|
{
|
||||||
|
return cbor_encode_bytes_prefix(ctx, start, stop, text, len, 0x60);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CBOR helper to encode a byte string chunk according to RFC8949
|
||||||
|
*
|
||||||
|
* if <bytes> is NULL, then only the byte string prefix (with length) will be
|
||||||
|
* emitted
|
||||||
|
*
|
||||||
|
* CBOR encode ctx is provided in <ctx>
|
||||||
|
*
|
||||||
|
* Returns the position of the last written byte on success and NULL on
|
||||||
|
* error. The function cannot write past <stop>
|
||||||
|
*/
|
||||||
|
char *cbor_encode_bytes(struct cbor_encode_ctx *ctx,
|
||||||
|
char *start, char *stop,
|
||||||
|
const char *bytes, size_t len)
|
||||||
|
{
|
||||||
|
return cbor_encode_bytes_prefix(ctx, start, stop, bytes, len, 0x40);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check a string for using it in a CSV output format. If the string contains
|
/* Check a string for using it in a CSV output format. If the string contains
|
||||||
* one of the following four char <">, <,>, CR or LF, the string is
|
* one of the following four char <">, <,>, CR or LF, the string is
|
||||||
* encapsulated between <"> and the <"> are escaped by a <""> sequence.
|
* encapsulated between <"> and the <"> are escaped by a <""> sequence.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user