/* 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);
+char *cbor_encode_uint64_prefix_bin(char *start, char *stop,
+ uint64_t value, uint8_t prefix);
+char *cbor_encode_uint64_prefix_hex(char *start, char *stop,
+ uint64_t value, uint8_t prefix);
+char *cbor_encode_int64_bin(char *start, char *stop, int64_t value);
+char *cbor_encode_int64_hex(char *start, char *stop, int64_t value);
+char *cbor_encode_bytes_prefix_bin(char *start, char *stop,
+ const char *bytes, size_t len,
+ uint8_t prefix);
+char *cbor_encode_bytes_prefix_hex(char *start, char *stop,
+ const char *bytes, size_t len,
+ uint8_t prefix);
+char *cbor_encode_bytes_bin(char *start, char *stop,
+ const char *bytes, size_t len);
+char *cbor_encode_bytes_hex(char *start, char *stop,
+ const char *bytes, size_t len);
+char *cbor_encode_text_bin(char *start, char *stop,
+ const char *text, size_t len);
+char *cbor_encode_text_hex(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
int options; /* LOG_OPT_* options */
int typecast; /* same as logformat_node->typecast */
int in_text; /* inside variable-length text */
- union {
- struct cbor_encode_ctx cbor; /* cbor-encode specific ctx */
- } encode;
};
static THREAD_LOCAL char lf_buildbuf[256]; /* fixed size buffer for building small strings */
* Returns the address of the byte immediately after the last written byte
* on success, or NULL on error. It will not append terminating NULL byte.
*/
-static char *_encode_byte_hex(char *start, char *stop, unsigned char byte)
+static inline char *_encode_byte_hex(char *start, char *stop, unsigned char byte)
{
/* hex form requires 2 bytes */
if ((stop - start) < 2)
return NULL;
*start++ = hextab[(byte >> 4) & 15];
*start++ = hextab[byte & 15];
- return start;
+
+ return start;
}
-/* lf cbor function ptr used to encode a single byte according to RFC8949
- *
- * The function may only be called under CBOR context (that is when
- * LOG_OPT_ENCODE_CBOR option is set).
- *
- * Returns the address of the byte immediately after the last written byte
- * on success, or NULL on error. It will not append terminating NULL byte.
- */
-static char *_lf_cbor_encode_byte(struct cbor_encode_ctx *cbor_ctx,
- char *start, char *stop, unsigned char byte)
+/* lf_cbor helper to write a single byte according to CBOR options */
+static inline char *_lf_cbor_encode_byte(struct lf_buildctx *ctx,
+ char *start, char *stop, unsigned char byte)
{
- struct lf_buildctx *ctx;
-
- BUG_ON(!cbor_ctx || !cbor_ctx->e_fct_ctx);
- ctx = cbor_ctx->e_fct_ctx;
-
if (ctx->options & LOG_OPT_BIN) {
/* raw output */
if ((stop - start) < 1)
ctx->options = g_options;
ctx->typecast = SMP_T_SAME; /* default */
}
-
- if (ctx->options & LOG_OPT_ENCODE_CBOR) {
- /* prepare cbor-specific encode ctx */
- ctx->encode.cbor.e_fct_byte = _lf_cbor_encode_byte;
- ctx->encode.cbor.e_fct_ctx = ctx;
- }
}
/* helper function for _lf_encode_bytes() to escape a single byte
escaped_byte[1] = hextab[(byte >> 4) & 15];
escaped_byte[2] = hextab[byte & 15];
- start = cbor_encode_bytes_prefix(&ctx->encode.cbor, start, stop,
- escaped_byte, 3,
- cbor_string_prefix);
+ if (ctx->options & LOG_OPT_BIN)
+ start = cbor_encode_bytes_prefix_bin(start, stop,
+ escaped_byte, 3,
+ cbor_string_prefix);
+ else
+ start = cbor_encode_bytes_prefix_hex(start, stop,
+ escaped_byte, 3,
+ cbor_string_prefix);
return start;
}
*/
} else {
/* first, flush pending unescaped bytes */
- start = cbor_encode_bytes_prefix(&ctx->encode.cbor, start, stop,
- *pending, (byte - *pending),
- cbor_string_prefix);
+ if (ctx->options & LOG_OPT_BIN)
+ start = cbor_encode_bytes_prefix_bin(start, stop,
+ *pending, (byte - *pending),
+ cbor_string_prefix);
+ else
+ start = cbor_encode_bytes_prefix_hex(start, stop,
+ *pending, (byte - *pending),
+ cbor_string_prefix);
if (start == NULL)
return NULL;
if ((ctx->options & LOG_OPT_ENCODE_CBOR) && !ctx->in_text) {
/* start indefinite-length cbor byte string or text */
- start = _lf_cbor_encode_byte(&ctx->encode.cbor, start, stop,
+ start = _lf_cbor_encode_byte(ctx, start, stop,
(cbor_string_prefix | 0x1F));
if (start == NULL)
return NULL;
if (ctx->options & LOG_OPT_ENCODE_CBOR) {
if (pending != bytes) {
/* flush pending unescaped bytes */
- start = cbor_encode_bytes_prefix(&ctx->encode.cbor, start, stop,
- pending, (bytes - pending),
- cbor_string_prefix);
+ if (ctx->options & LOG_OPT_BIN)
+ start = cbor_encode_bytes_prefix_bin(start, stop,
+ pending, (bytes - pending),
+ cbor_string_prefix);
+ else
+ start = cbor_encode_bytes_prefix_hex(start, stop,
+ pending, (bytes - pending),
+ cbor_string_prefix);
if (start == NULL)
return NULL;
}
if (!ctx->in_text) {
/* cbor break (to end indefinite-length text or byte string) */
- start = _lf_cbor_encode_byte(&ctx->encode.cbor, start, stop, 0xFF);
+ start = _lf_cbor_encode_byte(ctx, start, stop, 0xFF);
if (start == NULL)
return NULL;
}
/* cbor_encode_text() doesn't append terminating NULL
* byte, we must reserve 1 byte for that.
*/
- ret = cbor_encode_text(&ctx->encode.cbor, dst, dst + size - 1, src, len);
+ if (ctx->options & LOG_OPT_BIN)
+ ret = cbor_encode_text_bin(dst, dst + size - 1, src, len);
+ else
+ ret = cbor_encode_text_hex(dst, dst + size - 1, src, len);
if (ret == NULL)
return NULL;
len = ret - dst;
}
if (ctx->options & LOG_OPT_ENCODE_CBOR) {
if (value)
- return _lf_cbor_encode_byte(&ctx->encode.cbor, dst, dst + size, 0xF5);
- return _lf_cbor_encode_byte(&ctx->encode.cbor, dst, dst + size, 0xF4);
+ return _lf_cbor_encode_byte(ctx, dst, dst + size, 0xF5);
+ return _lf_cbor_encode_byte(ctx, dst, dst + size, 0xF4);
}
return NULL; /* not supported */
/* Always print as a regular int64 number (STR typecast isn't
* supported)
*/
- return cbor_encode_int64(&ctx->encode.cbor, dst, dst + size, value);
+ if (ctx->options & LOG_OPT_BIN)
+ return cbor_encode_int64_bin(dst, dst + size, value);
+ else
+ return cbor_encode_int64_hex(dst, dst + size, value);
}
return NULL; /* not supported */
* try to write a cbor byte if there is enough space, or goto out
*/
#define LOG_CBOR_BYTE(x) do { \
- ret = _lf_cbor_encode_byte(&ctx->encode.cbor, \
+ ret = _lf_cbor_encode_byte(ctx, \
tmplog, \
dst + maxsize - 1, \
(x)); \
* cbor decoder to know how to handle them \
*/ \
_x[0] = (x); \
- ret = cbor_encode_text(&ctx->encode.cbor, \
- tmplog, \
- dst + maxsize - 1, \
- _x, sizeof(_x)); \
+ if (ctx->options & LOG_OPT_BIN) \
+ ret = cbor_encode_text_bin(tmplog, \
+ dst + maxsize - 1,\
+ _x, sizeof(_x)); \
+ else \
+ ret = cbor_encode_text_hex(tmplog, \
+ dst + maxsize - 1,\
+ _x, sizeof(_x)); \
if (ret == NULL) \
goto out; \
tmplog = ret; \
LOGCHAR(' ');
}
else if (ctx->options & LOG_OPT_ENCODE_CBOR) {
- ret = cbor_encode_text(&ctx->encode.cbor, tmplog,
- dst + maxsize - 1, tmp->name,
- strlen(tmp->name));
+ if (ctx->options & LOG_OPT_BIN)
+ ret = cbor_encode_text_bin(tmplog, dst + maxsize -1,
+ tmp->name, strlen(tmp->name));
+ else
+ ret = cbor_encode_text_hex(tmplog, dst + maxsize - 1,
+ tmp->name, strlen(tmp->name));
if (ret == NULL)
goto out;
tmplog = ret;
return 0;
}
-/* CBOR helper to encode an uint64 value with prefix (3bits MAJOR type)
- * according to RFC8949
- *
- * CBOR encode ctx is provided in <ctx>
+/* helper to encode a single byte in hex form
*
* Returns the address of the byte immediately after the last written byte
- * on success, or NULL on error. The function cannot write past <stop>.
- * It will not append terminating NULL byte.
+ * on success, or NULL on error. It will not append terminating NULL byte.
*/
-char *cbor_encode_uint64_prefix(struct cbor_encode_ctx *ctx,
- char *start, char *stop, uint64_t value,
- uint8_t prefix)
+static inline char *_encode_byte_hex(char *start, char *stop, unsigned char byte)
{
- int nb_bytes = 0;
+ /* hex form requires 2 bytes */
+ if ((stop - start) < 2)
+ return NULL;
+ *start++ = hextab[(byte >> 4) & 15];
+ *start++ = hextab[byte & 15];
+ return start;
+}
+static inline int _cbor_encode_uint64_prefix(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;
+ *prefix |= value;
}
else {
if (value <= 0xFFU) {
/* 1-byte */
nb_bytes = 1;
- prefix |= 24; // 0x18
+ *prefix |= 24; // 0x18
}
else if (value <= 0xFFFFU) {
/* 2 bytes */
nb_bytes = 2;
- prefix |= 25; // 0x19
+ *prefix |= 25; // 0x19
}
else if (value <= 0xFFFFFFFFU) {
/* 4 bytes */
nb_bytes = 4;
- prefix |= 26; // 0x1A
+ *prefix |= 26; // 0x1A
}
else {
/* 8 bytes */
nb_bytes = 8;
- prefix |= 27; // 0x1B
+ *prefix |= 27; // 0x1B
}
}
- start = ctx->e_fct_byte(ctx, start, stop, prefix);
- if (start == NULL)
+ return nb_bytes;
+}
+
+
+/* CBOR helper to encode an uint64 value with prefix (3bits MAJOR type)
+ * according to RFC8949 in bin form.
+ *
+ * Returns the address of the byte immediately after the last written byte
+ * on success, or NULL on error. The function cannot write past <stop>.
+ * It will not append terminating NULL byte.
+ */
+char *cbor_encode_uint64_prefix_bin(char *start, char *stop, uint64_t value,
+ uint8_t prefix)
+{
+ int nb_bytes;
+
+
+ nb_bytes = _cbor_encode_uint64_prefix(value, &prefix);
+
+ if (stop - start < 1)
return NULL;
+ *start++ = prefix;
+
+ if (start + nb_bytes >= stop)
+ return NULL;
+
+#if defined(__x86_64__)
+ /* we can actually assume the bits are already in proper order
+ * so let's directly write them as-is on the wire to save CPU
+ * time.
+ */
+ memcpy(start, &value, nb_bytes);
+ start += nb_bytes;
+#else
/* 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_fct_byte(ctx, start, stop, cur_byte);
+ *start++ = cur_byte;
if (start == NULL)
return NULL;
nb_bytes--;
}
+#endif
return start;
}
-/* CBOR helper to encode an int64 value according to RFC8949
+/* CBOR helper to encode an uint64 value with prefix (3bits MAJOR type)
+ * according to RFC8949 in hex form.
*
- * CBOR encode ctx is provided in <ctx>
+ * Returns the address of the byte immediately after the last written byte
+ * on success, or NULL on error. The function cannot write past <stop>.
+ * It will not append terminating NULL byte.
+ */
+char *cbor_encode_uint64_prefix_hex(char *start, char *stop, uint64_t value,
+ uint8_t prefix)
+{
+ int nb_bytes;
+
+
+ nb_bytes = _cbor_encode_uint64_prefix(value, &prefix);
+
+ start = _encode_byte_hex(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 = _encode_byte_hex(start, stop, cur_byte);
+ if (start == NULL)
+ return NULL;
+
+ nb_bytes--;
+ }
+
+ return start;
+}
+
+
+/* CBOR helper to encode an int64 value according to RFC8949 in bin form
*
* Returns the address of the byte immediately after the last written byte
* on success, or NULL on error. The function cannot write past <stop>.
* It will not append terminating NULL byte.
*/
-char *cbor_encode_int64(struct cbor_encode_ctx *ctx,
- char *start, char *stop, int64_t value)
+char *cbor_encode_int64_bin(char *start, char *stop, int64_t value)
{
uint64_t absolute_value = llabs(value);
int cbor_prefix;
/* N-1 for negative int */
absolute_value -= 1;
}
- return cbor_encode_uint64_prefix(ctx, start, stop,
- absolute_value, cbor_prefix);
+ return cbor_encode_uint64_prefix_bin(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>
+/* CBOR helper to encode an int64 value according to RFC8949 in hex form
*
* Returns the address of the byte immediately after the last written byte
* on success, or NULL on error. The function cannot write past <stop>.
* It will not append terminating NULL byte.
*/
-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_int64_hex(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_hex(start, stop,
+ absolute_value, cbor_prefix);
+}
+
+static inline char *_cbor_encode_bytes_prefix_bin(char *start, char *stop,
+ const char *bytes, size_t len,
+ uint8_t prefix)
+{
+ /* write prefix (with text length as argument) */
+ start = cbor_encode_uint64_prefix_bin(start, stop,
+ len, prefix);
+ if (start == NULL)
+ return NULL;
+
+ /* write actual bytes if provided */
+ if (start + len >= stop)
+ return NULL;
+ memcpy(start, bytes, len);
+ start += len;
+
+ return start;
+}
+
+static inline char *_cbor_encode_bytes_prefix_hex(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);
+ start = cbor_encode_uint64_prefix_hex(start, stop,
+ len, prefix);
if (start == NULL)
return NULL;
/* write actual bytes if provided */
while (bytes && it < len) {
- start = ctx->e_fct_byte(ctx, start, stop, bytes[it]);
+ start = _encode_byte_hex(start, stop, bytes[it]);
if (start == NULL)
return NULL;
it++;
return start;
}
-/* CBOR helper to encode a text chunk according to RFC8949
+/* CBOR helper to encode a <prefix> string chunk according to RFC8949 in
+ * bin form.
*
- * if <text> is NULL, then only the text prefix (with length) will be emitted
+ * if <bytes> is NULL, then only the <prefix> (with length) will be
+ * emitted
*
* CBOR encode ctx is provided in <ctx>
*
* on success, or NULL on error. The function cannot write past <stop>.
* It will not append terminating NULL byte.
*/
-char *cbor_encode_text(struct cbor_encode_ctx *ctx,
- char *start, char *stop,
- const char *text, size_t len)
+char *cbor_encode_bytes_prefix_bin(char *start, char *stop,
+ const char *bytes, size_t len,
+ uint8_t prefix)
{
- return cbor_encode_bytes_prefix(ctx, start, stop, text, len, 0x60);
+ return _cbor_encode_bytes_prefix_bin(start, stop, bytes, len, prefix);
}
-/* CBOR helper to encode a byte string chunk according to RFC8949
+/* CBOR helper to encode a <prefix> string chunk according to RFC8949 in
+ * hex form.
*
- * if <bytes> is NULL, then only the byte string prefix (with length) will be
+ * if <bytes> is NULL, then only the <prefix> (with length) will be
* emitted
*
* CBOR encode ctx is provided in <ctx>
* on success, or NULL on error. The function cannot write past <stop>.
* It will not append terminating NULL byte.
*/
-char *cbor_encode_bytes(struct cbor_encode_ctx *ctx,
- char *start, char *stop,
- const char *bytes, size_t len)
+char *cbor_encode_bytes_prefix_hex(char *start, char *stop,
+ const char *bytes, size_t len,
+ uint8_t prefix)
+{
+ return _cbor_encode_bytes_prefix_hex(start, stop, bytes, len, prefix);
+}
+
+/* CBOR helper to encode a text chunk according to RFC8949 in bin form.
+ *
+ * if <text> is NULL, then only the text prefix (with length) will be emitted
+ *
+ * Returns the address of the byte immediately after the last written byte
+ * on success, or NULL on error. The function cannot write past <stop>.
+ * It will not append terminating NULL byte.
+ */
+char *cbor_encode_text_bin(char *start, char *stop,
+ const char *text, size_t len)
+{
+ return _cbor_encode_bytes_prefix_bin(start, stop, text, len, 0x60);
+}
+
+/* CBOR helper to encode a text chunk according to RFC8949 in hex form.
+ *
+ * if <text> is NULL, then only the text prefix (with length) will be emitted
+ *
+ * Returns the address of the byte immediately after the last written byte
+ * on success, or NULL on error. The function cannot write past <stop>.
+ * It will not append terminating NULL byte.
+ */
+char *cbor_encode_text_hex(char *start, char *stop,
+ const char *text, size_t len)
+{
+ return _cbor_encode_bytes_prefix_hex(start, stop, text, len, 0x60);
+}
+
+/* CBOR helper to encode a byte string chunk according to RFC8949 in bin form.
+ *
+ * if <bytes> is NULL, then only the byte string prefix (with length) will be
+ * emitted
+ *
+ * Returns the address of the byte immediately after the last written byte
+ * on success, or NULL on error. The function cannot write past <stop>.
+ * It will not append terminating NULL byte.
+ */
+char *cbor_encode_bytes_bin(char *start, char *stop,
+ const char *bytes, size_t len)
+{
+ return _cbor_encode_bytes_prefix_bin(start, stop, bytes, len, 0x40);
+}
+
+/* CBOR helper to encode a byte string chunk according to RFC8949 in hex form.
+ *
+ * if <bytes> is NULL, then only the byte string prefix (with length) will be
+ * emitted
+ *
+ * Returns the address of the byte immediately after the last written byte
+ * on success, or NULL on error. The function cannot write past <stop>.
+ * It will not append terminating NULL byte.
+ */
+char *cbor_encode_bytes_hex(char *start, char *stop,
+ const char *bytes, size_t len)
{
- return cbor_encode_bytes_prefix(ctx, start, stop, bytes, len, 0x40);
+ return _cbor_encode_bytes_prefix_hex(start, stop, bytes, len, 0x40);
}
/* Check a string for using it in a CSV output format. If the string contains