mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-03 10:42:07 +00:00
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
|
||||
};
|
||||
|
||||
/* 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 */
|
||||
|
@ -432,6 +432,25 @@ char *escape_string(char *start, char *stop,
|
||||
const char escape, const long *map,
|
||||
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
|
||||
* one of the following four char <">, <,>, CR or LF, the string is
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* one of the following four char <">, <,>, CR or LF, the string is
|
||||
* encapsulated between <"> and the <"> are escaped by a <""> sequence.
|
||||
|
Loading…
Reference in New Issue
Block a user