Initial commit

Initial commit.
This commit is contained in:
kntran1
2026-03-23 14:40:39 -05:00
parent e84b2b4166
commit 4e2a5258a5
872 changed files with 165227 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
#!/bin/bash
if [ "$1" == "--help" ]; then
echo "Add header if the zcbor files are updated."
exit -1
fi
add_copy_notice() {
echo "$(printf '/*
* This file has been %s from the zcbor library.
* Commit %s
*/
' "$2" "$(zcbor --version)"; cat $1;)" > $1
}
add_copy_notice src/zcbor_decode.c "copied"
add_copy_notice src/zcbor_encode.c "copied"
add_copy_notice src/zcbor_common.c "copied"
add_copy_notice include/zcbor_decode.h "copied"
add_copy_notice include/zcbor_encode.h "copied"
add_copy_notice include/zcbor_common.h "copied"
add_copy_notice include/zcbor_print.h "copied"
add_copy_notice include/zcbor_tags.h "copied"

View File

@@ -0,0 +1,514 @@
/*
* This file has been copied from the zcbor library.
* Commit zcbor 0.8.1
*/
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZCBOR_COMMON_H__
#define ZCBOR_COMMON_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "zcbor_tags.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ZCBOR_STRINGIFY_PRE(x) #x
#define ZCBOR_STRINGIFY(s) ZCBOR_STRINGIFY_PRE(s)
#define ZCBOR_VERSION_MAJOR 0
#define ZCBOR_VERSION_MINOR 8
#define ZCBOR_VERSION_BUGFIX 1
/** The version string with dots and not prefix. */
#define ZCBOR_VERSION_STR ZCBOR_STRINGIFY(ZCBOR_VERSION_MAJOR) \
"." ZCBOR_STRINGIFY(ZCBOR_VERSION_MINOR) \
"." ZCBOR_STRINGIFY(ZCBOR_VERSION_BUGFIX)
/** Monotonically increasing integer representing the version. */
#define ZCBOR_VERSION ((ZCBOR_VERSION_MAJOR << 24) \
+ (ZCBOR_VERSION_MINOR << 16) \
+ (ZCBOR_VERSION_BUGFIX << 8))
/** Convenience type that allows pointing to strings directly inside the payload
* without the need to copy out.
*/
struct zcbor_string {
const uint8_t *value;
size_t len;
};
/** Type representing a string fragment.
*
* Don't modify any member variables, or subsequent calls may fail.
**/
struct zcbor_string_fragment {
struct zcbor_string fragment; ///! Location and length of the fragment.
size_t offset; ///! The offset in the full string at which this fragment belongs.
size_t total_len; ///! The total length of the string this fragment is a part of.
};
/** Size to use in struct zcbor_string_fragment when the real size is unknown. */
#define ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH SIZE_MAX
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) (((a) < (b)) ? (b) : (a))
#endif
#ifndef ZCBOR_ARRAY_SIZE
#define ZCBOR_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
/* Endian-dependent offset of smaller integer in a bigger one. */
#ifdef ZCBOR_BIG_ENDIAN
#define ZCBOR_ECPY_OFFS(dst_len, src_len) ((dst_len) - (src_len))
#else
#define ZCBOR_ECPY_OFFS(dst_len, src_len) (0)
#endif /* ZCBOR_BIG_ENDIAN */
#if SIZE_MAX <= UINT64_MAX
/** The ZCBOR_SUPPORTS_SIZE_T will be defined if processing of size_t type variables directly
* with zcbor_size_ functions is supported.
**/
#define ZCBOR_SUPPORTS_SIZE_T
#else
#warning "zcbor: Unsupported size_t encoding size"
#endif
struct zcbor_state_constant;
/** The zcbor_state_t structure is used for both encoding and decoding. */
typedef struct {
union {
uint8_t *payload_mut;
uint8_t const *payload; /**< The current place in the payload. Will be
updated when an element is correctly
processed. */
};
uint8_t const *payload_bak; /**< Temporary backup of payload. */
size_t elem_count; /**< The current element is part of a LIST or a MAP,
and this keeps count of how many elements are
expected. This will be checked before processing
and decremented if the element is correctly
processed. */
uint8_t const *payload_end; /**< The end of the payload. This will be
checked against payload before
processing each element. */
bool payload_moved; /**< Is set to true while the state is stored as a backup
if @ref zcbor_update_state is called, since that function
updates the payload_end of all backed-up states. */
/* This is the "decode state", the part of zcbor_state_t that is only used by zcbor_decode.c. */
struct {
bool indefinite_length_array; /**< Is set to true if the decoder is currently
decoding the contents of an indefinite-
length array. */
bool counting_map_elems; /**< Is set to true while the number of elements of the
current map are being counted. */
#ifdef ZCBOR_MAP_SMART_SEARCH
uint8_t *map_search_elem_state; /**< Optional flags to use when searching unordered
maps. If this is not NULL and map_elem_count
is non-zero, this consists of one flag per element
in the current map. The n-th bit can be set to 0
to indicate that the n-th element in the
map should not be searched. These are manipulated
via zcbor_elem_processed() or
zcbor_unordered_map_search(), and should not be
manipulated directly. */
#else
size_t map_elems_processed; /**< The number of elements of an unordered map
that have been processed. */
#endif
size_t map_elem_count; /**< Number of elements in the current unordered map.
This also serves as the number of bits (not bytes)
in the map_search_elem_state array (when applicable). */
} decode_state;
struct zcbor_state_constant *constant_state; /**< The part of the state that is
not backed up and duplicated. */
} zcbor_state_t;
struct zcbor_state_constant {
zcbor_state_t *backup_list;
size_t current_backup;
size_t num_backups;
int error;
#ifdef ZCBOR_STOP_ON_ERROR
bool stop_on_error;
#endif
bool manually_process_elem; /**< Whether an (unordered map) element should be automatically
marked as processed when found via @ref zcbor_search_map_key. */
#ifdef ZCBOR_MAP_SMART_SEARCH
uint8_t *map_search_elem_state_end; /**< The end of the @ref map_search_elem_state buffer. */
#endif
};
/** Function pointer type used with zcbor_multi_decode.
*
* This type is compatible with all decoding functions here and in the generated
* code, except for zcbor_multi_decode.
*/
typedef bool(zcbor_encoder_t)(zcbor_state_t *, const void *);
typedef bool(zcbor_decoder_t)(zcbor_state_t *, void *);
/** Enumeration representing the major types available in CBOR.
*
* The major type is represented in the 3 first bits of the header byte.
*/
typedef enum
{
ZCBOR_MAJOR_TYPE_PINT = 0, ///! Positive Integer
ZCBOR_MAJOR_TYPE_NINT = 1, ///! Negative Integer
ZCBOR_MAJOR_TYPE_BSTR = 2, ///! Byte String
ZCBOR_MAJOR_TYPE_TSTR = 3, ///! Text String
ZCBOR_MAJOR_TYPE_LIST = 4, ///! List
ZCBOR_MAJOR_TYPE_MAP = 5, ///! Map
ZCBOR_MAJOR_TYPE_TAG = 6, ///! Semantic Tag
ZCBOR_MAJOR_TYPE_SIMPLE = 7, ///! Simple values and floats
} zcbor_major_type_t;
/** Extract the major type, i.e. the first 3 bits of the header byte. */
#define ZCBOR_MAJOR_TYPE(header_byte) ((zcbor_major_type_t)(((header_byte) >> 5) & 0x7))
/** Extract the additional info, i.e. the last 5 bits of the header byte. */
#define ZCBOR_ADDITIONAL(header_byte) ((header_byte) & 0x1F)
/** Convenience macro for failing out of a decoding/encoding function.
*/
#define ZCBOR_FAIL() \
do {\
zcbor_log("ZCBOR_FAIL "); \
zcbor_trace_file(state); \
return false; \
} while(0)
#define ZCBOR_FAIL_IF(expr) \
do {\
if (expr) { \
zcbor_log("ZCBOR_FAIL_IF(" #expr ") "); \
ZCBOR_FAIL(); \
} \
} while(0)
#define ZCBOR_ERR(err) \
do { \
zcbor_log("ZCBOR_ERR(%d) ", err); \
zcbor_error(state, err); \
ZCBOR_FAIL(); \
} while(0)
#define ZCBOR_ERR_IF(expr, err) \
do {\
if (expr) { \
zcbor_log("ZCBOR_ERR_IF(" #expr ", %d) ", err); \
ZCBOR_ERR(err); \
} \
} while(0)
#define ZCBOR_CHECK_PAYLOAD() \
ZCBOR_ERR_IF(state->payload >= state->payload_end, ZCBOR_ERR_NO_PAYLOAD)
#ifdef ZCBOR_STOP_ON_ERROR
#define ZCBOR_CHECK_ERROR() \
do { \
if (!zcbor_check_error(state)) { \
ZCBOR_FAIL(); \
} \
} while(0)
#else
#define ZCBOR_CHECK_ERROR()
#endif
#define ZCBOR_VALUE_IN_HEADER 23 ///! Values below this are encoded directly in the header.
#define ZCBOR_VALUE_IS_1_BYTE 24 ///! The next 1 byte contains the value.
#define ZCBOR_VALUE_IS_2_BYTES 25 ///! The next 2 bytes contain the value.
#define ZCBOR_VALUE_IS_4_BYTES 26 ///! The next 4 bytes contain the value.
#define ZCBOR_VALUE_IS_8_BYTES 27 ///! The next 8 bytes contain the value.
#define ZCBOR_VALUE_IS_INDEFINITE_LENGTH 31 ///! The list or map has indefinite length, and will instead be terminated by a 0xFF token.
#define ZCBOR_BOOL_TO_SIMPLE ((uint8_t)20) ///! In CBOR, false/true have the values 20/21
#define ZCBOR_FLAG_RESTORE 1UL ///! Restore from the backup. Overwrite the current state with the state from the backup.
#define ZCBOR_FLAG_CONSUME 2UL ///! Consume the backup. Remove the backup from the stack of backups.
#define ZCBOR_FLAG_KEEP_PAYLOAD 4UL ///! Keep the pre-restore payload after restoring.
#define ZCBOR_FLAG_KEEP_DECODE_STATE 8UL ///! Keep the pre-restore decode state (everything only used for decoding)
#define ZCBOR_SUCCESS 0
#define ZCBOR_ERR_NO_BACKUP_MEM 1
#define ZCBOR_ERR_NO_BACKUP_ACTIVE 2
#define ZCBOR_ERR_LOW_ELEM_COUNT 3
#define ZCBOR_ERR_HIGH_ELEM_COUNT 4
#define ZCBOR_ERR_INT_SIZE 5
#define ZCBOR_ERR_FLOAT_SIZE 6
#define ZCBOR_ERR_ADDITIONAL_INVAL 7 ///! > 27
#define ZCBOR_ERR_NO_PAYLOAD 8
#define ZCBOR_ERR_PAYLOAD_NOT_CONSUMED 9
#define ZCBOR_ERR_WRONG_TYPE 10
#define ZCBOR_ERR_WRONG_VALUE 11
#define ZCBOR_ERR_WRONG_RANGE 12
#define ZCBOR_ERR_ITERATIONS 13
#define ZCBOR_ERR_ASSERTION 14
#define ZCBOR_ERR_PAYLOAD_OUTDATED 15 ///! Because of a call to @ref zcbor_update_state
#define ZCBOR_ERR_ELEM_NOT_FOUND 16
#define ZCBOR_ERR_MAP_MISALIGNED 17
#define ZCBOR_ERR_ELEMS_NOT_PROCESSED 18
#define ZCBOR_ERR_NOT_AT_END 19
#define ZCBOR_ERR_MAP_FLAGS_NOT_AVAILABLE 20
#define ZCBOR_ERR_INVALID_VALUE_ENCODING 21 ///! When ZCBOR_CANONICAL is defined, and the incoming data is not encoded with minimal length.
#define ZCBOR_ERR_UNKNOWN 31
/** The largest possible elem_count. */
#define ZCBOR_MAX_ELEM_COUNT SIZE_MAX
/** Initial value for elem_count for when it just needs to be large. */
#define ZCBOR_LARGE_ELEM_COUNT (ZCBOR_MAX_ELEM_COUNT - 15)
/** Take a backup of the current state. Overwrite the current elem_count. */
bool zcbor_new_backup(zcbor_state_t *state, size_t new_elem_count);
/** Consult the most recent backup. In doing so, check whether elem_count is
* less than or equal to max_elem_count.
* Also, take action based on the flags (See ZCBOR_FLAG_*).
*/
bool zcbor_process_backup(zcbor_state_t *state, uint32_t flags, size_t max_elem_count);
/** Convenience function for starting encoding/decoding of a union.
*
* That is, for attempting to encode, or especially decode, multiple options.
* Makes a new backup.
*/
bool zcbor_union_start_code(zcbor_state_t *state);
/** Convenience function before encoding/decoding one element of a union.
*
* Call this before attempting each option.
* Restores the backup, without consuming it.
*/
bool zcbor_union_elem_code(zcbor_state_t *state);
/** Convenience function before encoding/decoding one element of a union.
*
* Consumes the backup without restoring it.
*/
bool zcbor_union_end_code(zcbor_state_t *state);
/** Initialize a state with backups.
* As long as n_states is more than 1, one of the states in the array is used
* as a struct zcbor_state_constant object.
* If there is no struct zcbor_state_constant (n_states == 1), error codes are
* not available.
* This means that you get a state with (n_states - 2) backups.
* payload, payload_len, elem_count, and elem_state are used to initialize the first state.
* The elem_state is only needed for unordered maps, when ZCBOR_MAP_SMART_SEARCH is enabled.
* It is ignored otherwise.
*/
void zcbor_new_state(zcbor_state_t *state_array, size_t n_states,
const uint8_t *payload, size_t payload_len, size_t elem_count,
uint8_t *elem_state, size_t elem_state_bytes);
/** Do boilerplate entry function procedure.
* Initialize states, call function, and check the result.
*/
int zcbor_entry_function(const uint8_t *payload, size_t payload_len,
void *result, size_t *payload_len_out, zcbor_state_t *state, zcbor_decoder_t func,
size_t n_states, size_t elem_count);
#ifdef ZCBOR_STOP_ON_ERROR
/** Check stored error and fail if present, but only if stop_on_error is true.
*
* @retval true No error found
* @retval false An error was found
*/
static inline bool zcbor_check_error(const zcbor_state_t *state)
{
struct zcbor_state_constant *cs = state->constant_state;
return !(cs && cs->stop_on_error && cs->error);
}
#endif
/** Return the current error state, replacing it with SUCCESS. */
static inline int zcbor_pop_error(zcbor_state_t *state)
{
if (!state->constant_state) {
return ZCBOR_SUCCESS;
}
int err = state->constant_state->error;
state->constant_state->error = ZCBOR_SUCCESS;
return err;
}
/** Look at current error state without altering it */
static inline int zcbor_peek_error(const zcbor_state_t *state)
{
if (!state->constant_state) {
return ZCBOR_SUCCESS;
} else {
return state->constant_state->error;
}
}
/** Write the provided error to the error state. */
static inline void zcbor_error(zcbor_state_t *state, int err)
{
#ifdef ZCBOR_STOP_ON_ERROR
if (zcbor_check_error(state))
#endif
{
if (state->constant_state) {
state->constant_state->error = err;
}
}
}
/** Whether the current payload is exhausted. */
static inline bool zcbor_payload_at_end(const zcbor_state_t *state)
{
return (state->payload == state->payload_end);
}
/** Update the current payload pointer (and payload_end).
*
* For use when the payload is divided into multiple chunks.
*
* This function also updates all backups to the new payload_end.
* This sets a flag so that @ref zcbor_process_backup fails if a backup is
* processed with the flag @ref ZCBOR_FLAG_RESTORE, but without the flag
* @ref ZCBOR_FLAG_KEEP_PAYLOAD since this would cause an invalid state.
*
* @param[inout] state The current state, will be updated with
* the new payload pointer.
* @param[in] payload The new payload chunk.
* @param[in] payload_len The length of the new payload chunk.
*/
void zcbor_update_state(zcbor_state_t *state,
const uint8_t *payload, size_t payload_len);
/** Check that the provided fragments are complete and in the right order.
*
* If the total length is not known, the total_len can have the value
* @ref ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH. If so, all fragments will be
* updated with the actual total length.
*
* @param[in] fragments An array of string fragments. Cannot be NULL.
* @param[in] num_fragments The number of fragments in @p fragments.
*
* @retval true If the fragments are in the right order, and there are no
* fragments missing.
* @retval false If not all fragments have the same total_len, or gaps are
* found, or if any fragment value is NULL.
*/
bool zcbor_validate_string_fragments(struct zcbor_string_fragment *fragments,
size_t num_fragments);
/** Assemble the fragments into a single string.
*
* The fragments are copied in the order they appear, without regard for
* offset or total_len. To ensure that the fragments are correct, first
* validate with @ref zcbor_validate_string_fragments.
*
* @param[in] fragments An array of string fragments. Cannot be NULL.
* @param[in] num_fragments The number of fragments in @p fragments.
* @param[out] result The buffer to place the assembled string into.
* @param[inout] result_len In: The length of the @p result.
* Out: The length of the assembled string.
*
* @retval true On success.
* @retval false If the assembled string would be larger than the buffer.
* The buffer might still be written to.
*/
bool zcbor_splice_string_fragments(struct zcbor_string_fragment *fragments,
size_t num_fragments, uint8_t *result, size_t *result_len);
/** Compare two struct zcbor_string instances.
*
* @param[in] str1 A string
* @param[in] str2 A string to compare to @p str1
*
* @retval true if the strings are identical
* @retval false if length or contents don't match, or one one or both strings is NULL.
*/
bool zcbor_compare_strings(const struct zcbor_string *str1,
const struct zcbor_string *str2);
/** Calculate the length of a CBOR string, list, or map header.
*
* This can be used to find the start of the CBOR object when you have a
* pointer to the start of the contents. The function assumes that the header
* will be the shortest it can be.
*
* @param[in] num_elems The number of elements in the string, list, or map.
*
* @return The length of the header in bytes (1-9).
*/
size_t zcbor_header_len(uint64_t value);
/** Like @ref zcbor_header_len but for integer of any size <= 8. */
size_t zcbor_header_len_ptr(const void *const value, size_t value_len);
/** Convert a float16 value to float32.
*
* @param[in] input The float16 value stored in a uint16_t.
*
* @return The resulting float32 value.
*/
float zcbor_float16_to_32(uint16_t input);
/** Convert a float32 value to float16.
*
* @param[in] input The float32 value.
*
* @return The resulting float16 value as a uint16_t.
*/
uint16_t zcbor_float32_to_16(float input);
#ifdef ZCBOR_MAP_SMART_SEARCH
static inline size_t zcbor_round_up(size_t x, size_t align)
{
return (((x) + (align) - 1) / (align) * (align));
}
#define ZCBOR_BITS_PER_BYTE 8
/** Calculate the number of bytes needed to hold @p num_flags 1 bit flags
*/
static inline size_t zcbor_flags_to_bytes(size_t num_flags)
{
return zcbor_round_up(num_flags, ZCBOR_BITS_PER_BYTE) / ZCBOR_BITS_PER_BYTE;
}
/** Calculate the number of zcbor_state_t instances needed to hold @p num_flags 1 bit flags
*/
static inline size_t zcbor_flags_to_states(size_t num_flags)
{
return zcbor_round_up(num_flags, sizeof(zcbor_state_t) * ZCBOR_BITS_PER_BYTE)
/ (sizeof(zcbor_state_t) * ZCBOR_BITS_PER_BYTE);
}
#define ZCBOR_FLAG_STATES(n_flags) zcbor_flags_to_states(n_flags)
#else
#define ZCBOR_FLAG_STATES(n_flags) 0
#endif
size_t strnlen(const char *, size_t);
#ifdef __cplusplus
}
#endif
#endif /* ZCBOR_COMMON_H__ */

View File

@@ -0,0 +1,452 @@
/*
* This file has been copied from the zcbor library.
* Commit zcbor 0.8.1
*/
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZCBOR_DECODE_H__
#define ZCBOR_DECODE_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "zcbor_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/** The zcbor_decode library provides functions for decoding CBOR data elements.
*
* See The README for an introduction to CBOR, including the meaning of pint,
* nint, bstr etc.
*/
/** See @ref zcbor_new_state() */
void zcbor_new_decode_state(zcbor_state_t *state_array, size_t n_states,
const uint8_t *payload, size_t payload_len, size_t elem_count,
uint8_t *elem_state, size_t elem_state_bytes);
/** Convenience macro for declaring and initializing a decoding state with backups.
*
* This gives you a state variable named @p name. The variable functions like
* a pointer.
*
* @param[in] name The name of the new state variable.
* @param[in] num_backups The number of backup slots to keep in the state.
* @param[in] payload The payload to work on.
* @param[in] payload_size The size (in bytes) of @p payload.
* @param[in] elem_count The starting elem_count (typically 1).
* @param[in] n_flags For use if ZCBOR_MAP_SMART_SEARCH is enabled, ignored otherwise.
* The total number of unordered map search flags needed.
* I.e. the largest number of elements expected in an unordered map,
* including elements in nested unordered maps.
*/
#define ZCBOR_STATE_D(name, num_backups, payload, payload_size, elem_count, n_flags) \
zcbor_state_t name[((num_backups) + 2 + ZCBOR_FLAG_STATES(n_flags))]; \
do { \
zcbor_new_decode_state(name, ZCBOR_ARRAY_SIZE(name), payload, payload_size, elem_count, \
(uint8_t *)&name[(num_backups) + 1], ZCBOR_FLAG_STATES(n_flags) * sizeof(zcbor_state_t)); \
} while(0)
/** The following applies to all _decode() functions listed directly below.
*
* @param[inout] state The current state of the decoding.
* @param[out] result Where to place the decoded value.
* @param[in] result_size (if present) Size in bytes of the memory at @p result
*
* @retval true If the value was decoded correctly.
* @retval false If the value has the wrong type, the payload overflowed, the
* element count was exhausted, or the value was larger than can
* fit in the result variable.
* Use zcbor_peek_error() to see the error code.
*/
bool zcbor_int32_decode(zcbor_state_t *state, int32_t *result); /* pint/nint */
bool zcbor_int64_decode(zcbor_state_t *state, int64_t *result); /* pint/nint */
bool zcbor_uint32_decode(zcbor_state_t *state, uint32_t *result); /* pint */
bool zcbor_uint64_decode(zcbor_state_t *state, uint64_t *result); /* pint */
bool zcbor_size_decode(zcbor_state_t *state, size_t *result); /* pint */
bool zcbor_int_decode(zcbor_state_t *state, void *result, size_t result_size); /* pint/nint */
bool zcbor_uint_decode(zcbor_state_t *state, void *result, size_t result_size); /* pint */
bool zcbor_bstr_decode(zcbor_state_t *state, struct zcbor_string *result); /* bstr */
bool zcbor_tstr_decode(zcbor_state_t *state, struct zcbor_string *result); /* tstr */
bool zcbor_tag_decode(zcbor_state_t *state, uint32_t *result); /* CBOR tag */
bool zcbor_simple_decode(zcbor_state_t *state, uint8_t *result); /* CBOR simple value */
bool zcbor_bool_decode(zcbor_state_t *state, bool *result); /* boolean CBOR simple value */
bool zcbor_float16_decode(zcbor_state_t *state, float *result); /* IEEE754 float16 */
bool zcbor_float16_bytes_decode(zcbor_state_t *state, uint16_t *result); /* IEEE754 float16 raw bytes */
bool zcbor_float16_32_decode(zcbor_state_t *state, float *result); /* IEEE754 float16 or float32 */
bool zcbor_float32_decode(zcbor_state_t *state, float *result); /* IEEE754 float32 */
bool zcbor_float32_64_decode(zcbor_state_t *state, double *result); /* IEEE754 float32 or float64 */
bool zcbor_float64_decode(zcbor_state_t *state, double *result); /* IEEE754 float64 */
bool zcbor_float_decode(zcbor_state_t *state, double *result); /* IEEE754 float16, float32, or float64 */
/** The following applies to all _expect() and _pexpect() functions listed directly below.
*
* @param[inout] state The current state of the decoding.
* @param[in] expected The expected value.
*
* @retval true If the result was decoded correctly and has the expected value.
* @retval false If the decoding failed or the result doesn't have the
* expected value.
* Use zcbor_peek_error() to see the error code.
*/
bool zcbor_int32_expect(zcbor_state_t *state, int32_t expected); /* pint/nint */
bool zcbor_int64_expect(zcbor_state_t *state, int64_t expected); /* pint/nint */
bool zcbor_uint32_expect(zcbor_state_t *state, uint32_t expected); /* pint */
bool zcbor_uint64_expect(zcbor_state_t *state, uint64_t expected); /* pint */
bool zcbor_size_expect(zcbor_state_t *state, size_t expected); /* pint */
bool zcbor_bstr_expect(zcbor_state_t *state, struct zcbor_string *expected); /* bstr */
bool zcbor_tstr_expect(zcbor_state_t *state, struct zcbor_string *expected); /* tstr */
bool zcbor_tag_expect(zcbor_state_t *state, uint32_t expected); /* CBOR tag */
bool zcbor_simple_expect(zcbor_state_t *state, uint8_t expected); /* CBOR simple value */
bool zcbor_bool_expect(zcbor_state_t *state, bool expected); /* boolean CBOR simple value */
bool zcbor_nil_expect(zcbor_state_t *state, void *unused); /* 'nil' CBOR simple value */
bool zcbor_undefined_expect(zcbor_state_t *state, void *unused); /* 'undefined' CBOR simple value */
bool zcbor_float16_expect(zcbor_state_t *state, float expected); /* IEEE754 float16 */
bool zcbor_float16_bytes_expect(zcbor_state_t *state, uint16_t expected); /* IEEE754 float16 raw bytes */
bool zcbor_float16_32_expect(zcbor_state_t *state, float expected); /* IEEE754 float16 or float32 */
bool zcbor_float32_expect(zcbor_state_t *state, float expected); /* IEEE754 float32 */
bool zcbor_float32_64_expect(zcbor_state_t *state, double expected); /* IEEE754 float32 or float64 */
bool zcbor_float64_expect(zcbor_state_t *state, double expected); /* IEEE754 float64 */
bool zcbor_float_expect(zcbor_state_t *state, double expected); /* IEEE754 float16, float32, or float64 */
/** Like the _expect() functions but the value is passed through a pointer.
* (for use as a zcbor_decoder_t function) */
bool zcbor_int32_pexpect(zcbor_state_t *state, int32_t *expected); /* pint/nint */
bool zcbor_int64_pexpect(zcbor_state_t *state, int64_t *expected); /* pint/nint */
bool zcbor_uint32_pexpect(zcbor_state_t *state, uint32_t *expected); /* pint */
bool zcbor_uint64_pexpect(zcbor_state_t *state, uint64_t *expected); /* pint */
bool zcbor_size_pexpect(zcbor_state_t *state, size_t *expected); /* pint */
bool zcbor_tag_pexpect(zcbor_state_t *state, uint32_t *expected); /* CBOR tag */
bool zcbor_simple_pexpect(zcbor_state_t *state, uint8_t *expected); /* CBOR simple value */
bool zcbor_bool_pexpect(zcbor_state_t *state, bool *expected); /* boolean CBOR simple value */
bool zcbor_float16_pexpect(zcbor_state_t *state, float *expected); /* IEEE754 float16 */
bool zcbor_float16_bytes_pexpect(zcbor_state_t *state, uint16_t *expected); /* IEEE754 float16 raw bytes */
bool zcbor_float16_32_pexpect(zcbor_state_t *state, float *expected); /* IEEE754 float16 or float32 */
bool zcbor_float32_pexpect(zcbor_state_t *state, float *expected); /* IEEE754 float32 */
bool zcbor_float32_64_pexpect(zcbor_state_t *state, double *expected); /* IEEE754 float32 or float64 */
bool zcbor_float64_pexpect(zcbor_state_t *state, double *expected); /* IEEE754 float64 */
bool zcbor_float_pexpect(zcbor_state_t *state, double *expected); /* IEEE754 float16, float32, or float64 */
/** Consume and expect a pint/nint with a certain value, within a union.
*
* Calls @ref zcbor_union_elem_code then @ref zcbor_[u]int[32|64]_expect.
*/
bool zcbor_int32_expect_union(zcbor_state_t *state, int32_t expected);
bool zcbor_int64_expect_union(zcbor_state_t *state, int64_t expected);
bool zcbor_uint32_expect_union(zcbor_state_t *state, uint32_t expected);
bool zcbor_uint64_expect_union(zcbor_state_t *state, uint64_t expected);
/** Decode and consume a list/map header.
*
* The contents of the list can be decoded via subsequent function calls.
* A state backup is created to keep track of the element count.
* Call @ref zcbor_list_end_decode / @ref zcbor_map_end_decode when done
* decoding the contents of the list/map
*
* @retval true Header decoded correctly
* @retval false Header decoded incorrectly, or backup failed.
*/
bool zcbor_list_start_decode(zcbor_state_t *state);
bool zcbor_map_start_decode(zcbor_state_t *state);
bool zcbor_unordered_map_start_decode(zcbor_state_t *state);
/** Search for a key in a map.
*
* The CBOR spec allows elements (key-value pairs) in maps to appear in any order.
* This function should be used when the order of elements is unknown.
*
* This must only be used while inside a map that has been entered via
* @ref zcbor_unordered_map_start_decode. Use @ref zcbor_unordered_map_end_decode
* when leaving the map.
*
* This function searches for keys. When this function returns successfully,
* the @p state is pointing to the value corresponding to the found key.
* Therefore, to be able to call this function again, the value must first be
* decoded or skipped.
*
* When searching unordered maps, the found elements must be kept track of.
* By default, this function automatically keeps track, which means it keeps a
* running count of the number of found elements, which is checked when exiting
* the map. You can do this manually instead, see @ref zcbor_elem_processed and
* @ref manually_process_elem. If ZCBOR_MAP_SMART_SEARCH is defined, a flag is
* kept for each element, instead of a rolling count.
*
* @note Unless ZCBOR_MAP_SMART_SEARCH is defined,
* elements are not individually marked as processed, so they may
* be returned again in a subsequent call to this function, if it is
* matched by the @p key_decoder of that call. Because of this, you should
* only use this function when you know the @p key_decoder matches no more
* than one of the keys. Typically this means all keys are known strings
* or integers, i.e. the @p key_decoder is typically a _pexpect() function.
*
* When searching for strings, there are convenience functions available,
* see the zcbor_search_key_* functions.
*
* @param[in] key_decoder A decoding function that will be tried against all
* keys in the map until it returns true, at which point
* @ref zcbor_unordered_map_search will return true.
* For example, a zcbor_*_pexpect() function.
* @param[inout] state The current state of decoding. Must be currently decoding
* the contents of a map, and pointing to one (any) of the
* keys, not one of the values. If successful, the @p state
* will be pointing to the value corresponding to the
* matched key. If unsuccessful, the @p state will be
* unchanged.
* @param[inout] key_result This will be passed as the second argument to the
* @p key_decoder.
*
* @retval true If the key was found, i.e. @p key_decoder returned true.
* @retval false If the key was not found after searching all map elements.
* Or the map was pointing to a value (not a key).
* Or an unexpected error happened while skipping elements or
* jumping from the end of the map to the start.
*/
bool zcbor_unordered_map_search(zcbor_decoder_t key_decoder, zcbor_state_t *state, void *key_result);
/** Find a specific bstr/tstr key as part of a map with unknown element order.
*
* Uses @ref zcbor_unordered_map_search under the hood. Please refer to those docs
* for the conditions under which this can be called.
* Refer to the docs for zcbor_(t|b)str_expect_* (e.g. @ref zcbor_bstr_expect_ptr)
* for parameter docs.
*/
bool zcbor_search_key_bstr_ptr(zcbor_state_t *state, char const *ptr, size_t len);
bool zcbor_search_key_tstr_ptr(zcbor_state_t *state, char const *ptr, size_t len);
bool zcbor_search_key_bstr_term(zcbor_state_t *state, char const *str, size_t maxlen);
bool zcbor_search_key_tstr_term(zcbor_state_t *state, char const *str, size_t maxlen);
#define zcbor_search_key_bstr_lit(state, str) zcbor_search_key_bstr_ptr(state, str, sizeof(str) - 1)
#define zcbor_search_key_tstr_lit(state, str) zcbor_search_key_tstr_ptr(state, str, sizeof(str) - 1)
#define zcbor_search_key_bstr_arr(state, str) zcbor_search_key_bstr_ptr(state, str, (sizeof(str)))
#define zcbor_search_key_tstr_arr(state, str) zcbor_search_key_tstr_ptr(state, str, (sizeof(str)))
/** (Optional) Call this function to mark an (unordered map) element as processed.
*
* @note This should not be called unless the @ref manually_process_elem flag is set.
* By default, i.e. when @ref manually_process_elem is not set, this function is
* called internally by @ref zcbor_unordered_map_search whenever a key is found.
*
* By default, this function increments the internal count @ref map_elems_processed.
*
* If ZCBOR_MAP_SMART_SEARCH is defined, this function instead clears a flag for the
* element (key-value pair) that is currently being processed, or that has just been
* processed, meaning the element won't be found again via @ref zcbor_unordered_map_search.
*
* @ref zcbor_unordered_map_end_decode will fail if @ref map_elems_processed does not
* match the number of elements in the map, or if any of the map element's flag is set.
*/
bool zcbor_elem_processed(zcbor_state_t *state);
/** Finalize decoding a list/map
*
* Check that the list/map had the correct number of elements, and restore the
* previous element count from the backup.
*
* Use @ref zcbor_list_map_end_force_decode to forcibly consume the backup if
* something has gone wrong.
*
* In all successful cases, the state is returned pointing to the byte/element
* after the list/map in the payload.
*
* @retval true Everything ok.
* @retval false Element count not correct.
*/
bool zcbor_list_end_decode(zcbor_state_t *state);
bool zcbor_map_end_decode(zcbor_state_t *state);
bool zcbor_unordered_map_end_decode(zcbor_state_t *state);
bool zcbor_list_map_end_force_decode(zcbor_state_t *state);
/** Find whether the state is at the end of a list or map.
*/
bool zcbor_array_at_end(zcbor_state_t *state);
/** Skip a single element, regardless of type and value.
*
* This means if the element is a map or list, this function will recursively
* skip all its contents.
* This function will also skip any tags preceeding the element.
*
* @param[inout] state The current state of the decoding.
* @param[in] unused Unused parameter to maintain signature parity with
* @ref zcbor_decoder_t.
*/
bool zcbor_any_skip(zcbor_state_t *state, void *unused);
/** Decode 0 or more elements with the same type and constraints.
*
* The decoded values will appear consecutively in the @p result array.
*
* The following is an example of decoding a list containing 3 INTS followed by
* 0 to 2 bstrs:
*
* @code{c}
* uint32_t ints[3];
* struct zcbor_string bstrs[2];
* uint32_t num_decode;
* bool res;
*
* res = zcbor_list_start_decode(state);
* res = res && zcbor_multi_decode(3, 3, &num_decode, zcbor_uint32_decode,
* state, ints, sizeof(ints[0]));
* res = res && zcbor_multi_decode(0, 2, &num_decode, zcbor_bstr_decode,
* state, bstrs, sizeof(bstrs[0]));
* res = res && zcbor_list_end_decode(state);
* // check res
* @endcode
*
* The @ref zcbor_decoder_t type is designed to be compatible with all single-
* value decoder functions in this library, e.g. @ref zcbor_uint32_decode,
* @ref zcbor_tstr_expect, @ref zcbor_nil_expect, etc. For _expect() functions,
* @p result will be used as a value instead of an array/pointer, so
* @p result_len will determine how much the value changes for each call.
* To decode the same value multiple times, use a @p result_len of 0.
* This function can also be used with custom decoder functions, such as those
* generated by the zcbor.py script, which for example decodes larger chunks of
* the data at once.
*
* @param[in] min_decode The minimum acceptable number of elements.
* @param[in] max_decode The maximum acceptable number of elements.
* @param[out] num_decode The actual number of elements decoded.
* @param[in] decoder The decoder function to call under the hood. This
* function will be called with the provided arguments
* repeatedly until the function fails (returns false)
* or until it has been called @p max_decode times.
* The result pointer is moved @p result_len bytes for
* each call to @p decoder, i.e. @p result refers to
* an array of result variables.
* Should not be an _expect() function, use
* _pexpect() instead.
* @param[out] result Where to place the decoded values. Must be an array
* of at least @p max_decode elements.
* @param[in] result_len The length of each result variable. Must be the
* length of the individual elements of @p result.
*
* @retval true If at least @p min_decode variables were correctly decoded.
* @retval false If @p decoder failed before having decoded @p min_decode
* values.
*/
bool zcbor_multi_decode(size_t min_decode, size_t max_decode, size_t *num_decode,
zcbor_decoder_t decoder, zcbor_state_t *state, void *result,
size_t result_len);
/** Attempt to decode a value that might not be present in the data.
*
* Works like @ref zcbor_multi_decode, with @p present as num_decode.
* Will return true, even if the data is not present.
*
* @param[out] present Whether or not the data was present and successfully decoded.
* @param[in] decoder The decoder to attempt.
* @param[out] result The result, if present.
*
* @return Should always return true.
*/
bool zcbor_present_decode(bool *present,
zcbor_decoder_t decoder,
zcbor_state_t *state,
void *result);
/** Supplementary string (bstr/tstr) decoding functions: */
/** Consume and expect a bstr/tstr with the value of the provided char/uint8_t array.
*
* @param[inout] state The current state of the decoding.
* @param[in] str The value to expect. A pointer to the string/array.
* _term() uses strnlen(), so @p str must be null-terminated.
* _lit() uses sizeof()-1, so @p str must be a (null-terminated) string literal.
* _arr() uses sizeof(), so @p str must be a uint8_t array (not null-terminated).
* @param[in] len (if present) The length of the string pointed to by @p str
* @param[in] maxlen (if present) The maximum length of the string pointed to by @p str.
* This value is passed to strnlen.
*/
bool zcbor_bstr_expect_ptr(zcbor_state_t *state, char const *ptr, size_t len);
bool zcbor_tstr_expect_ptr(zcbor_state_t *state, char const *ptr, size_t len);
bool zcbor_bstr_expect_term(zcbor_state_t *state, char const *str, size_t maxlen);
bool zcbor_tstr_expect_term(zcbor_state_t *state, char const *str, size_t maxlen);
#define zcbor_bstr_expect_lit(state, str) zcbor_bstr_expect_ptr(state, str, sizeof(str) - 1)
#define zcbor_tstr_expect_lit(state, str) zcbor_tstr_expect_ptr(state, str, sizeof(str) - 1)
#define zcbor_bstr_expect_arr(state, str) zcbor_bstr_expect_ptr(state, str, sizeof(str))
#define zcbor_tstr_expect_arr(state, str) zcbor_tstr_expect_ptr(state, str, sizeof(str))
/** Decode and consume a bstr header.
*
* The rest of the string can be decoded as CBOR.
* A state backup is created to keep track of the element count.
* Call @ref zcbor_bstr_end_decode when done decoding the contents of the bstr.
*
* @param[inout] state The current state of the decoding.
* @param[out] result The resulting string, for reference. The string should be decoded via
* functions from this API since state is pointing to the start of the string,
* not the end.
*
* @retval true Header decoded correctly
* @retval false Header decoded incorrectly, or backup failed, or payload is not large enough
* to contain the contents of the string. Use @ref zcbor_bstr_start_decode_fragment
* for decoding fragmented payloads.
*/
bool zcbor_bstr_start_decode(zcbor_state_t *state, struct zcbor_string *result);
/** Finalize decoding a CBOR-encoded bstr.
*
* Restore element count from backup.
*/
bool zcbor_bstr_end_decode(zcbor_state_t *state);
/** Supplementary string (bstr/tstr) decoding functions for fragmented payloads: */
/** Start decoding a bstr/tstr, even if the payload contains only part of it.
*
* This must be followed by a call to @ref zcbor_update_state, which can be
* followed by a call to @ref zcbor_next_fragment. Do not call this function
* again on subsequent fragments of the same string.
*
* This consumes the remaining payload as long as it belongs to the string.
*/
bool zcbor_bstr_decode_fragment(zcbor_state_t *state, struct zcbor_string_fragment *result);
bool zcbor_tstr_decode_fragment(zcbor_state_t *state, struct zcbor_string_fragment *result);
/** Extract the next fragment of a string.
*
* Use this function to extract all but the first fragment.
*/
void zcbor_next_fragment(zcbor_state_t *state,
struct zcbor_string_fragment *prev_fragment,
struct zcbor_string_fragment *result);
/** Decode and consume a bstr header, assuming the payload does not contain the whole bstr.
*
* The rest of the string can be decoded as CBOR.
* A state backup is created to keep track of the element count.
* Call @ref zcbor_update_state followed by @ref zcbor_bstr_next_fragment when
* the current payload has been exhausted.
* Call @ref zcbor_bstr_end_decode when done decoding the contents of the bstr.
*/
bool zcbor_bstr_start_decode_fragment(zcbor_state_t *state,
struct zcbor_string_fragment *result);
/** Start decoding the next fragment of a string.
*
* Use this function to extract all but the first fragment of a CBOR-encoded
* bstr.
*/
void zcbor_bstr_next_fragment(zcbor_state_t *state,
struct zcbor_string_fragment *prev_fragment,
struct zcbor_string_fragment *result);
/** Can be used on any fragment to tell if it is the final fragment of the string. */
bool zcbor_is_last_fragment(const struct zcbor_string_fragment *fragment);
#ifdef __cplusplus
}
#endif
#endif /* ZCBOR_DECODE_H__ */

View File

@@ -0,0 +1,245 @@
/*
* This file has been copied from the zcbor library.
* Commit zcbor 0.8.1
*/
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZCBOR_ENCODE_H__
#define ZCBOR_ENCODE_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "zcbor_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/** The zcbor_encode library provides functions for encoding CBOR data elements.
*
* See The README for an introduction to CBOR, including the meaning of pint,
* nint, bstr etc.
*/
/** See @ref zcbor_new_state() */
void zcbor_new_encode_state(zcbor_state_t *state_array, size_t n_states,
uint8_t *payload, size_t payload_len, size_t elem_count);
/** Convenience macro for declaring and initializing an encoding state with backups.
*
* This gives you a state variable named @p name. The variable functions like
* a pointer.
*
* @param[in] name The name of the new state variable.
* @param[in] num_backups The number of backup slots to keep in the state.
* @param[in] payload The payload to work on.
* @param[in] payload_size The size (in bytes) of @p payload.
* @param[in] elem_count The starting elem_count (typically 1).
*/
#define ZCBOR_STATE_E(name, num_backups, payload, payload_size, elem_count) \
zcbor_state_t name[((num_backups) + 2)]; \
do { \
zcbor_new_encode_state(name, ZCBOR_ARRAY_SIZE(name), payload, payload_size, elem_count); \
} while(0)
/** The following applies to all _put and _encode functions listed directly below.
*
* The difference between _put and _encode is only in the argument type,
* but when a @ref zcbor_encoder_t is needed, such as for @ref zcbor_multi_encode,
* the _encode variant must be used.
*
* @param[inout] state The current state of the encoding.
* @param[in] input The value to encode.
*
* @retval true Everything is ok.
* @retval false If the payload is exhausted. Or an unexpected error happened.
* Use zcbor_peek_error() to see the error code.
*/
bool zcbor_int32_put(zcbor_state_t *state, int32_t input); /* pint/nint */
bool zcbor_int64_put(zcbor_state_t *state, int64_t input); /* pint/nint */
bool zcbor_uint32_put(zcbor_state_t *state, uint32_t input); /* pint */
bool zcbor_uint64_put(zcbor_state_t *state, uint64_t input); /* pint */
bool zcbor_size_put(zcbor_state_t *state, size_t input); /* pint */
bool zcbor_tag_put(zcbor_state_t *state, uint32_t tag); /* CBOR tag */
bool zcbor_simple_put(zcbor_state_t *state, uint8_t input); /* CBOR simple value */
bool zcbor_bool_put(zcbor_state_t *state, bool input); /* boolean CBOR simple value */
bool zcbor_nil_put(zcbor_state_t *state, const void *unused); /* 'nil' CBOR simple value */
bool zcbor_undefined_put(zcbor_state_t *state, const void *unused); /* 'undefined' CBOR simple value */
bool zcbor_float16_put(zcbor_state_t *state, float input); /* IEEE754 float16 */
bool zcbor_float16_bytes_put(zcbor_state_t *state, uint16_t input); /* IEEE754 float16 raw bytes */
bool zcbor_float32_put(zcbor_state_t *state, float input); /* IEEE754 float32 */
bool zcbor_float64_put(zcbor_state_t *state, double input); /* IEEE754 float64 */
bool zcbor_int32_encode(zcbor_state_t *state, const int32_t *input); /* pint/nint */
bool zcbor_int64_encode(zcbor_state_t *state, const int64_t *input); /* pint/nint */
bool zcbor_uint32_encode(zcbor_state_t *state, const uint32_t *input); /* pint */
bool zcbor_uint64_encode(zcbor_state_t *state, const uint64_t *input); /* pint */
bool zcbor_size_encode(zcbor_state_t *state, const size_t *input); /* pint */
bool zcbor_int_encode(zcbor_state_t *state, const void *input_int, size_t int_size);
bool zcbor_uint_encode(zcbor_state_t *state, const void *input_uint, size_t uint_size);
bool zcbor_bstr_encode(zcbor_state_t *state, const struct zcbor_string *input); /* bstr */
bool zcbor_tstr_encode(zcbor_state_t *state, const struct zcbor_string *input); /* tstr */
bool zcbor_tag_encode(zcbor_state_t *state, uint32_t *tag); /* CBOR tag. Note that zcbor_tag_encode()'s argument was changed to be a pointer. See also zcbor_tag_put(). */
bool zcbor_simple_encode(zcbor_state_t *state, uint8_t *input); /* CBOR simple value */
bool zcbor_bool_encode(zcbor_state_t *state, const bool *input); /* boolean CBOR simple value */
bool zcbor_float16_encode(zcbor_state_t *state, const float *input); /* IEEE754 float16 */
bool zcbor_float16_bytes_encode(zcbor_state_t *state, const uint16_t *input); /* IEEE754 float16 raw bytes */
bool zcbor_float32_encode(zcbor_state_t *state, const float *input); /* IEEE754 float32 */
bool zcbor_float64_encode(zcbor_state_t *state, const double *input); /* IEEE754 float64 */
/** Encode a list/map header.
*
* The contents of the list/map can be encoded via subsequent function calls.
* If ZCBOR_CANONICAL is defined, a state backup is created to keep track of the
* element count.
* When all members have been encoded, call @ref zcbor_list_end_encode /
* @ref zcbor_map_end_encode to close the list/map.
*
* @param[inout] state The current state of the encoding.
* @param[in] max_num The maximum number of members in the list/map.
* This serves as a size hint for the header. Must be
* equal to the max_num provided to the corresponding
* @ref zcbor_list_end_encode / @ref zcbor_map_end_encode
* call.
* Only used when ZCBOR_CANONICAL is defined.
*/
bool zcbor_list_start_encode(zcbor_state_t *state, size_t max_num);
bool zcbor_map_start_encode(zcbor_state_t *state, size_t max_num);
/** Encode the end of a list/map. Do some checks and deallocate backup.
*
* - Default: Adds a list terminator (0xFF) to mark the
* end of the list/map.
* - If ZCBOR_CANONICAL is defined: Instead encodes the number of members in
* the list/map header. If the header ends up a different size than expected,
* the list/map contents are moved using memmove().
*
* Use @ref zcbor_list_map_end_force_encode to forcibly consume the backup if
* something has gone wrong.
*
* @param[inout] state The current state of the encoding.
* @param[in] max_num The maximum number of members in the list/map. Must be
* equal to the max_num provided to the corresponding
* @ref zcbor_list_start_encode call.
* Only used when ZCBOR_CANONICAL is defined.
*/
bool zcbor_list_end_encode(zcbor_state_t *state, size_t max_num);
bool zcbor_map_end_encode(zcbor_state_t *state, size_t max_num);
bool zcbor_list_map_end_force_encode(zcbor_state_t *state);
/** Encode 0 or more elements with the same type and constraints.
*
* The encoded values are taken from the @p input array.
*
* The following is an example of encoding a list containing 3 INTS followed by
* 0 to 2 bstrs:
*
* @code{c}
* uint32_t ints[3] = <initialize>;
* struct zcbor_string bstrs[2] = <initialize>;
* bool res;
*
* res = zcbor_list_start_encode(state, 5);
* res = res && zcbor_multi_encode(3, zcbor_uint32_encode, state,
* ints, sizeof(uint32_t));
* res = res && zcbor_multi_encode(2, zcbor_bstr_encode, state,
* bstrs, sizeof(struct zcbor_string));
* res = res && zcbor_list_end_encode(state, 5);
* // check res
* @endcode
*
* The @ref zcbor_encoder_t type is designed to be compatible with all single-
* value encoder functions in this library, e.g. @ref zcbor_uint32_encode,
* @ref zcbor_tstr_put, @ref zcbor_nil_put, etc. For _put() functions,
* @p input will be used as a value instead of an array/pointer, so
* @p input_len will determine how much the value changes for each call.
* To encode the same value multiple times, use a @p input_len of 0.
* This function can also be used with custom decoder functions, such as those
* generated by the zcbor.py script, which for example encodes larger chunks of
* the data at once.
*
* @param[in] num_encode The actual number of elements.
* @param[in] encoder The encoder function to call under the hood. This
* function will be called with the provided arguments
* repeatedly until the function fails (returns false)
* or until it has been called @p max_encode times.
* The input pointer is moved @p input_len bytes for
* each call to @p encoder, i.e. @p input refers to an
* array of input variables.
* @param[in] input Source of the encoded values. Must be an array of
* at least @p max_encode elements.
* @param[in] input_len The length of the input variables. Must be the
* length of the individual elements in input.
*
* @retval true If at least @p min_encode variables were correctly encoded.
* @retval false If @p encoder failed before having encoded @p min_encode
* values.
*/
bool zcbor_multi_encode(size_t num_encode, zcbor_encoder_t encoder,
zcbor_state_t *state, const void *input, size_t result_len);
/** Works like @ref zcbor_multi_encode
*
* But first checks that @p num_encode is between @p min_encode and @p max_encode.
*/
bool zcbor_multi_encode_minmax(size_t min_encode, size_t max_encode,
const size_t *num_encode, zcbor_encoder_t encoder,
zcbor_state_t *state, const void *input, size_t input_len);
/* Supplementary string (bstr/tstr) encoding functions: */
/** Encode a char/uint8_t pointer as a bstr/tstr.
*
* @param[inout] state The current state of the encoding.
* @param[in] str The value to encode. A pointer to the string/array.
* _term() uses strnlen(), so @p str must be null-terminated.
* _lit() uses sizeof()-1, so @p str must be a (null-terminated) string literal.
* _arr() uses sizeof(), so @p str must be a uint8_t array (not null-terminated).
* @param[in] len (if present) The length of the string pointed to by @p str
* @param[in] maxlen (if present) The maximum length of the string pointed to by @p str.
* This value is passed to strnlen.
*/
bool zcbor_bstr_encode_ptr(zcbor_state_t *state, const char *str, size_t len);
bool zcbor_tstr_encode_ptr(zcbor_state_t *state, const char *str, size_t len);
bool zcbor_bstr_put_term(zcbor_state_t *state, char const *str, size_t maxlen);
bool zcbor_tstr_put_term(zcbor_state_t *state, char const *str, size_t maxlen);
#define zcbor_bstr_put_lit(state, str) zcbor_bstr_encode_ptr(state, str, sizeof(str) - 1)
#define zcbor_tstr_put_lit(state, str) zcbor_tstr_encode_ptr(state, str, sizeof(str) - 1)
#define zcbor_bstr_put_arr(state, str) zcbor_bstr_encode_ptr(state, str, sizeof(str))
#define zcbor_tstr_put_arr(state, str) zcbor_tstr_encode_ptr(state, str, sizeof(str))
/** Encode a bstr header.
*
* The rest of the string can be encoded as CBOR.
* A state backup is created to keep track of the element count.
* Call @ref zcbor_bstr_end_encode when done encoding the contents of the bstr.
*
* @param[inout] state The current state of the encoding.
*
* @retval true Header encoded correctly
* @retval false Header encoded incorrectly, or backup failed.
*/
bool zcbor_bstr_start_encode(zcbor_state_t *state);
/** Finalize encoding a CBOR-encoded bstr.
*
* This writes the final size of the bstr to the header.
* Restore element count from backup.
*/
bool zcbor_bstr_end_encode(zcbor_state_t *state, struct zcbor_string *result);
#ifdef __cplusplus
}
#endif
#endif /* ZCBOR_ENCODE_H__ */

View File

@@ -0,0 +1,170 @@
/*
* This file has been copied from the zcbor library.
* Commit zcbor 0.8.1
*/
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZCBOR_PRINT_H__
#define ZCBOR_PRINT_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ZCBOR_PRINT_FUNC
#include <stdio.h>
#define zcbor_do_print(...) printf(__VA_ARGS__)
#else
#define zcbor_do_print(...) ZCBOR_PRINT_FUNC(__VA_ARGS__)
#endif
#ifdef ZCBOR_VERBOSE
#define zcbor_trace_raw(state) (zcbor_do_print("rem: %zu, cur: 0x%x, ec: 0x%zx, err: %d",\
(size_t)state->payload_end - (size_t)state->payload, *state->payload, state->elem_count, \
state->constant_state ? state->constant_state->error : 0))
#define zcbor_trace(state, appendix) do { \
zcbor_trace_raw(state); \
zcbor_do_print(", %s\n", appendix); \
} while(0)
#define zcbor_trace_file(state) do { \
zcbor_trace_raw(state); \
zcbor_do_print(", %s:%d\n", __FILE__, __LINE__); \
} while(0)
#define zcbor_log_assert(expr, ...) \
do { \
zcbor_do_print("ASSERTION \n \"" #expr \
"\"\nfailed at %s:%d with message:\n ", \
__FILE__, __LINE__); \
zcbor_do_print(__VA_ARGS__);\
} while(0)
#define zcbor_log(...) zcbor_do_print(__VA_ARGS__)
#else
#define zcbor_trace(state, appendix)
#define zcbor_trace_file(state) ((void)state)
#define zcbor_log_assert(...)
#define zcbor_log(...)
#endif
#ifdef ZCBOR_ASSERTS
#define zcbor_assert(expr, ...) \
do { \
if (!(expr)) { \
zcbor_log_assert(expr, __VA_ARGS__); \
ZCBOR_FAIL(); \
} \
} while(0)
#define zcbor_assert_state(expr, ...) \
do { \
if (!(expr)) { \
zcbor_log_assert(expr, __VA_ARGS__); \
ZCBOR_ERR(ZCBOR_ERR_ASSERTION); \
} \
} while(0)
#else
#define zcbor_assert(expr, ...)
#define zcbor_assert_state(expr, ...)
#endif
__attribute__((used))
static void zcbor_print_compare_lines(const uint8_t *str1, const uint8_t *str2, size_t size)
{
for (size_t j = 0; j < size; j++) {
zcbor_do_print("%x ", str1[j]);
}
zcbor_do_print("\r\n");
for (size_t j = 0; j < size; j++) {
zcbor_do_print("%x ", str2[j]);
}
zcbor_do_print("\r\n");
for (size_t j = 0; j < size; j++) {
zcbor_do_print("%x ", str1[j] != str2[j]);
}
zcbor_do_print("\r\n");
zcbor_do_print("\r\n");
}
__attribute__((used))
static void zcbor_print_compare_strings(const uint8_t *str1, const uint8_t *str2, size_t size)
{
const size_t col_width = 16;
for (size_t i = 0; i <= size / col_width; i++) {
zcbor_do_print("line %zu (char %zu)\r\n", i, i*col_width);
zcbor_print_compare_lines(&str1[i*col_width], &str2[i*col_width],
MIN(col_width, (size - i*col_width)));
}
zcbor_do_print("\r\n");
}
__attribute__((used))
static void zcbor_print_compare_strings_diff(const uint8_t *str1, const uint8_t *str2, size_t size)
{
const size_t col_width = 16;
bool printed = false;
for (size_t i = 0; i <= size / col_width; i++) {
if (memcmp(&str1[i*col_width], &str2[i*col_width], MIN(col_width, (size - i*col_width))) != 0) {
zcbor_do_print("line %zu (char %zu)\r\n", i, i*col_width);
zcbor_print_compare_lines(&str1[i*col_width], &str2[i*col_width],
MIN(col_width, (size - i*col_width)));
printed = true;
}
}
if (printed) {
zcbor_do_print("\r\n");
}
}
__attribute__((used))
static const char *zcbor_error_str(int error)
{
#define ZCBOR_ERR_CASE(err) case err: \
return #err; /* The literal is static per C99 6.4.5 paragraph 5. */\
switch(error) {
ZCBOR_ERR_CASE(ZCBOR_SUCCESS)
ZCBOR_ERR_CASE(ZCBOR_ERR_NO_BACKUP_MEM)
ZCBOR_ERR_CASE(ZCBOR_ERR_NO_BACKUP_ACTIVE)
ZCBOR_ERR_CASE(ZCBOR_ERR_LOW_ELEM_COUNT)
ZCBOR_ERR_CASE(ZCBOR_ERR_HIGH_ELEM_COUNT)
ZCBOR_ERR_CASE(ZCBOR_ERR_INT_SIZE)
ZCBOR_ERR_CASE(ZCBOR_ERR_FLOAT_SIZE)
ZCBOR_ERR_CASE(ZCBOR_ERR_ADDITIONAL_INVAL)
ZCBOR_ERR_CASE(ZCBOR_ERR_NO_PAYLOAD)
ZCBOR_ERR_CASE(ZCBOR_ERR_PAYLOAD_NOT_CONSUMED)
ZCBOR_ERR_CASE(ZCBOR_ERR_WRONG_TYPE)
ZCBOR_ERR_CASE(ZCBOR_ERR_WRONG_VALUE)
ZCBOR_ERR_CASE(ZCBOR_ERR_WRONG_RANGE)
ZCBOR_ERR_CASE(ZCBOR_ERR_ITERATIONS)
ZCBOR_ERR_CASE(ZCBOR_ERR_ASSERTION)
ZCBOR_ERR_CASE(ZCBOR_ERR_PAYLOAD_OUTDATED)
ZCBOR_ERR_CASE(ZCBOR_ERR_ELEM_NOT_FOUND)
ZCBOR_ERR_CASE(ZCBOR_ERR_MAP_MISALIGNED)
ZCBOR_ERR_CASE(ZCBOR_ERR_ELEMS_NOT_PROCESSED)
ZCBOR_ERR_CASE(ZCBOR_ERR_NOT_AT_END)
ZCBOR_ERR_CASE(ZCBOR_ERR_MAP_FLAGS_NOT_AVAILABLE)
ZCBOR_ERR_CASE(ZCBOR_ERR_INVALID_VALUE_ENCODING)
}
#undef ZCBOR_ERR_CASE
return "ZCBOR_ERR_UNKNOWN";
}
__attribute__((used))
static void zcbor_print_error(int error)
{
zcbor_do_print("%s\r\n", zcbor_error_str(error));
}
#ifdef __cplusplus
}
#endif
#endif /* ZCBOR_PRINT_H__ */

View File

@@ -0,0 +1,99 @@
/*
* This file has been copied from the zcbor library.
* Commit zcbor 0.8.1
*/
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZCBOR_TAGS_H__
#define ZCBOR_TAGS_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Values defined by RFCs via www.iana.org/assignments/cbor-tags/cbor-tags.xhtml */
enum zcbor_tag {
ZCBOR_TAG_TIME_TSTR = 0, ///! text string [RFC8949] Standard date/time string
ZCBOR_TAG_TIME_NUM = 1, ///! integer or float [RFC8949] Epoch-based date/time
ZCBOR_TAG_UBIGNUM_BSTR = 2, ///! byte string [RFC8949] Unsigned bignum
ZCBOR_TAG_BIGNUM_BSTR = 3, ///! byte string [RFC8949] Negative bignum
ZCBOR_TAG_DECFRAC_ARR = 4, ///! array [RFC8949] Decimal fraction
ZCBOR_TAG_BIGFLOAT_ARR = 5, ///! array [RFC8949] Bigfloat
ZCBOR_TAG_COSE_ENCRYPT0 = 16, ///! COSE_Encrypt0 [RFC9052] COSE Single Recipient Encrypted Data Object
ZCBOR_TAG_COSE_MAC0 = 17, ///! COSE_Mac0 [RFC9052] COSE MAC w/o Recipients Object
ZCBOR_TAG_COSE_SIGN1 = 18, ///! COSE_Sign1 [RFC9052] COSE Single Signer Data Object
ZCBOR_TAG_2BASE64URL = 21, ///! (any) [RFC8949] Expected conversion to base64url encoding
ZCBOR_TAG_2BASE64 = 22, ///! (any) [RFC8949] Expected conversion to base64 encoding
ZCBOR_TAG_2BASE16 = 23, ///! (any) [RFC8949] Expected conversion to base16 encoding
ZCBOR_TAG_BSTR = 24, ///! byte string [RFC8949] Encoded CBOR data item
ZCBOR_TAG_URI_TSTR = 32, ///! text string [RFC8949] URI
ZCBOR_TAG_BASE64URL_TSTR = 33, ///! text string [RFC8949] base64url
ZCBOR_TAG_BASE64_TSTR = 34, ///! text string [RFC8949] base64
ZCBOR_TAG_REGEX = 35, ///! text string [RFC7049] Regular expression (UTF-8)
ZCBOR_TAG_MIME_TSTR = 36, ///! text string [RFC8949] MIME message
ZCBOR_TAG_LANG_TSTR = 38, ///! array [RFC9290] Text string with language tag
ZCBOR_TAG_MULTI_DIM_ARR_R = 40, ///! array of arrays [RFC8746] Multi-dimensional array, row-major order
ZCBOR_TAG_HOMOG_ARR = 41, ///! array [RFC8746] Homogeneous array
ZCBOR_TAG_YANG_BITS = 42, ///! text string [RFC9254] YANG bits datatype; see Section 6.7.
ZCBOR_TAG_YANG_ENUM = 43, ///! text string [RFC9254] YANG enumeration datatype; see Section 6.6.
ZCBOR_TAG_YANG_IDENTITYREF = 44, ///! uint/tstr [RFC9254] YANG identityref datatype; see Section 6.10.
ZCBOR_TAG_YANK_INSTANCE_ID = 45, ///! uint/tstr/array [RFC9254] YANG instance-identifier datatype; see Section 6.13.
ZCBOR_TAG_SID = 46, ///! uint [RFC9254] YANG Schema Item iDentifier (sid); see Section 3.2.
ZCBOR_TAG_IPV4 = 52, ///! bstr or array [RFC9164] IPv4
ZCBOR_TAG_IPV6 = 54, ///! bstr or array [RFC9164] IPv6
ZCBOR_TAG_CWT = 61, ///! CWT [RFC8392] CBOR Web Token
ZCBOR_TAG_TYPED_ARR_U8 = 64, ///! byte string [RFC8746] uint8 Typed Array
ZCBOR_TAG_TYPED_ARR_U16_BE = 65, ///! byte string [RFC8746] uint16, big endian, Typed Array
ZCBOR_TAG_TYPED_ARR_U32_BE = 66, ///! byte string [RFC8746] uint32, big endian, Typed Array
ZCBOR_TAG_TYPED_ARR_U64_BE = 67, ///! byte string [RFC8746] uint64, big endian, Typed Array
ZCBOR_TAG_TYPED_ARR_U8_CA = 68, ///! byte string [RFC8746] uint8 Typed Array, clamped arithmetic
ZCBOR_TAG_TYPED_ARR_U16_LE = 69, ///! byte string [RFC8746] uint16, little endian, Typed Array
ZCBOR_TAG_TYPED_ARR_U32_LE = 70, ///! byte string [RFC8746] uint32, little endian, Typed Array
ZCBOR_TAG_TYPED_ARR_U64_LE = 71, ///! byte string [RFC8746] uint64, little endian, Typed Array
ZCBOR_TAG_TYPED_ARR_S8 = 72, ///! byte string [RFC8746] sint8 Typed Array
ZCBOR_TAG_TYPED_ARR_S16_BE = 73, ///! byte string [RFC8746] sint16, big endian, Typed Array
ZCBOR_TAG_TYPED_ARR_S32_BE = 74, ///! byte string [RFC8746] sint32, big endian, Typed Array
ZCBOR_TAG_TYPED_ARR_S64_BE = 75, ///! byte string [RFC8746] sint64, big endian, Typed Array
ZCBOR_TAG_TYPED_ARR_S16_LE = 77, ///! byte string [RFC8746] sint16, little endian, Typed Array
ZCBOR_TAG_TYPED_ARR_S32_LE = 78, ///! byte string [RFC8746] sint32, little endian, Typed Array
ZCBOR_TAG_TYPED_ARR_S64_LE = 79, ///! byte string [RFC8746] sint64, little endian, Typed Array
ZCBOR_TAG_TYPED_ARR_F16_BE = 80, ///! byte string [RFC8746] IEEE 754 binary16, big endian, Typed Array
ZCBOR_TAG_TYPED_ARR_F32_BE = 81, ///! byte string [RFC8746] IEEE 754 binary32, big endian, Typed Array
ZCBOR_TAG_TYPED_ARR_F64_BE = 82, ///! byte string [RFC8746] IEEE 754 binary64, big endian, Typed Array
ZCBOR_TAG_TYPED_ARR_F128_BE = 83, ///! byte string [RFC8746] IEEE 754 binary128, big endian, Typed Array
ZCBOR_TAG_TYPED_ARR_F16_LE = 84, ///! byte string [RFC8746] IEEE 754 binary16, little endian, Typed Array
ZCBOR_TAG_TYPED_ARR_F32_LE = 85, ///! byte string [RFC8746] IEEE 754 binary32, little endian, Typed Array
ZCBOR_TAG_TYPED_ARR_F64_LE = 86, ///! byte string [RFC8746] IEEE 754 binary64, little endian, Typed Array
ZCBOR_TAG_TYPED_ARR_F128_LE = 87, ///! byte string [RFC8746] IEEE 754 binary128, little endian, Typed Array
ZCBOR_TAG_COSE_ENCRYPT = 96, ///! COSE_Encrypt [RFC9052] COSE Encrypted Data Object
ZCBOR_TAG_COSE_MAC = 97, ///! COSE_Mac [RFC9052] COSE MACed Data Object
ZCBOR_TAG_COSE_SIGN = 98, ///! COSE_Sign [RFC9052] COSE Signed Data Object
ZCBOR_TAG_EPOCH_DAYS = 100, ///! integer [RFC8943] Number of days since the epoch date 1970-01-01
ZCBOR_TAG_REL_OID_BER_SDNV = 110, ///! bstr/array/map [RFC9090] relative object identifier (BER encoding); SDNV [RFC6256] sequence
ZCBOR_TAG_OID_BER = 111, ///! bstr/array/map [RFC9090] object identifier (BER encoding)
ZCBOR_TAG_PEN_REL_OID_BER = 112, ///! bstr/array/map [RFC9090] object identifier (BER encoding), relative to 1.3.6.1.4.1
ZCBOR_TAG_DOTS_SIG_CHAN_OBJ = 271, ///! DOTS sig chan obj [RFC9132] DDoS Open Threat Signaling (DOTS) signal channel object
ZCBOR_TAG_FULL_DATE_STR = 1004, ///! tstr (UTF-8) [RFC8943] Full-date string
ZCBOR_TAG_MULTI_DIM_ARR_C = 1040, ///! array of arrays [RFC8746] Multi-dimensional array, column-major order
ZCBOR_TAG_CBOR = 55799, ///! (any) [RFC8949] Self-described CBOR
ZCBOR_TAG_CBOR_SEQ_FILE = 55800, ///! tagged bstr [RFC9277] indicates that the file contains CBOR Sequences
ZCBOR_TAG_CBOR_FILE_LABEL = 55801, ///! tagged bstr [RFC9277] indicates that the file starts with a CBOR-Labeled Non-CBOR Data label.
ZCBOR_TAG_COAP_CT = 1668546817, ///! bstr or (any) [RFC9277] Start of range: the representation of content-format ct < 65025 is indicated by tag number TN(ct) = 0x63740101 + (ct / 255) * 256 + ct % 255
ZCBOR_TAG_COAP_CT_END = 1668612095, ///! bstr or (any) [RFC9277] End of range: the representation of content-format ct < 65025 is indicated by tag number TN(ct) = 0x63740101 + (ct / 255) * 256 + ct % 255
};
#ifdef __cplusplus
}
#endif
#endif /* ZCBOR_TAGS_H__ */

View File

@@ -0,0 +1,27 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
pkg.name: boot/zcbor
pkg.description: Library for encoding and decoding data to/from cbor.
pkg.author: "Nordic Semiconductor"
pkg.homepage: "https://github.com/NordicSemiconductor/zcbor"
pkg.keywords:
- zcbor
#pkg.src_dirs: src

View File

@@ -0,0 +1,442 @@
/*
* This file has been copied from the zcbor library.
* Commit zcbor 0.8.1
*/
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "zcbor_common.h"
#include "zcbor_print.h"
_Static_assert((sizeof(size_t) == sizeof(void *)),
"This code needs size_t to be the same length as pointers.");
_Static_assert((sizeof(zcbor_state_t) >= sizeof(struct zcbor_state_constant)),
"This code needs zcbor_state_t to be at least as large as zcbor_backups_t.");
bool zcbor_new_backup(zcbor_state_t *state, size_t new_elem_count)
{
ZCBOR_CHECK_ERROR();
if ((state->constant_state->current_backup)
>= state->constant_state->num_backups) {
ZCBOR_ERR(ZCBOR_ERR_NO_BACKUP_MEM);
}
state->payload_moved = false;
(state->constant_state->current_backup)++;
/* use the backup at current_backup - 1, since otherwise, the 0th
* backup would be unused. */
size_t i = (state->constant_state->current_backup) - 1;
memcpy(&state->constant_state->backup_list[i], state,
sizeof(zcbor_state_t));
state->elem_count = new_elem_count;
zcbor_log("New backup (level %zu)\n", i);
return true;
}
bool zcbor_process_backup(zcbor_state_t *state, uint32_t flags,
size_t max_elem_count)
{
ZCBOR_CHECK_ERROR();
zcbor_state_t local_copy = *state;
if (state->constant_state->current_backup == 0) {
zcbor_log("No backups available.\r\n");
ZCBOR_ERR(ZCBOR_ERR_NO_BACKUP_ACTIVE);
}
/* use the backup at current_backup - 1, since otherwise, the
* 0th backup would be unused. */
size_t i = state->constant_state->current_backup - 1;
zcbor_log("Process backup (level %zu, flags 0x%x)\n", i, flags);
if (flags & ZCBOR_FLAG_RESTORE) {
if (!(flags & ZCBOR_FLAG_KEEP_PAYLOAD)) {
if (state->constant_state->backup_list[i].payload_moved) {
zcbor_log("Payload pointer out of date.\r\n");
ZCBOR_ERR(ZCBOR_ERR_PAYLOAD_OUTDATED);
}
}
memcpy(state, &state->constant_state->backup_list[i],
sizeof(zcbor_state_t));
}
if (flags & ZCBOR_FLAG_CONSUME) {
state->constant_state->current_backup--;
}
if (local_copy.elem_count > max_elem_count) {
zcbor_log("elem_count: %zu (expected max %zu)\r\n",
local_copy.elem_count, max_elem_count);
ZCBOR_ERR(ZCBOR_ERR_HIGH_ELEM_COUNT);
}
if (flags & ZCBOR_FLAG_KEEP_PAYLOAD) {
state->payload = local_copy.payload;
}
if (flags & ZCBOR_FLAG_KEEP_DECODE_STATE) {
/* Copy decode state */
state->decode_state = local_copy.decode_state;
}
return true;
}
static void update_backups(zcbor_state_t *state, uint8_t const *new_payload_end)
{
if (state->constant_state) {
for (unsigned int i = 0; i < state->constant_state->current_backup; i++) {
state->constant_state->backup_list[i].payload_end = new_payload_end;
state->constant_state->backup_list[i].payload_moved = true;
}
}
}
bool zcbor_union_start_code(zcbor_state_t *state)
{
if (!zcbor_new_backup(state, state->elem_count)) {
ZCBOR_FAIL();
}
return true;
}
bool zcbor_union_elem_code(zcbor_state_t *state)
{
if (!zcbor_process_backup(state, ZCBOR_FLAG_RESTORE, state->elem_count)) {
ZCBOR_FAIL();
}
return true;
}
bool zcbor_union_end_code(zcbor_state_t *state)
{
if (!zcbor_process_backup(state, ZCBOR_FLAG_CONSUME, state->elem_count)) {
ZCBOR_FAIL();
}
return true;
}
void zcbor_new_state(zcbor_state_t *state_array, size_t n_states,
const uint8_t *payload, size_t payload_len, size_t elem_count,
uint8_t *flags, size_t flags_bytes)
{
state_array[0].payload = payload;
state_array[0].payload_end = payload + payload_len;
state_array[0].elem_count = elem_count;
state_array[0].payload_moved = false;
state_array[0].decode_state.indefinite_length_array = false;
#ifdef ZCBOR_MAP_SMART_SEARCH
state_array[0].decode_state.map_search_elem_state = flags;
state_array[0].decode_state.map_elem_count = 0;
#else
state_array[0].decode_state.map_elems_processed = 0;
(void)flags;
(void)flags_bytes;
#endif
state_array[0].constant_state = NULL;
if (n_states < 2) {
return;
}
/* Use the last state as a struct zcbor_state_constant object. */
state_array[0].constant_state = (struct zcbor_state_constant *)&state_array[n_states - 1];
state_array[0].constant_state->backup_list = NULL;
state_array[0].constant_state->num_backups = n_states - 2;
state_array[0].constant_state->current_backup = 0;
state_array[0].constant_state->error = ZCBOR_SUCCESS;
#ifdef ZCBOR_STOP_ON_ERROR
state_array[0].constant_state->stop_on_error = false;
#endif
state_array[0].constant_state->manually_process_elem = false;
#ifdef ZCBOR_MAP_SMART_SEARCH
state_array[0].constant_state->map_search_elem_state_end = flags + flags_bytes;
#endif
if (n_states > 2) {
state_array[0].constant_state->backup_list = &state_array[1];
}
}
void zcbor_update_state(zcbor_state_t *state,
const uint8_t *payload, size_t payload_len)
{
state->payload = payload;
state->payload_end = payload + payload_len;
update_backups(state, state->payload_end);
}
bool zcbor_validate_string_fragments(struct zcbor_string_fragment *fragments,
size_t num_fragments)
{
size_t total_len = 0;
if (fragments == NULL) {
return false;
}
for (size_t i = 0; i < num_fragments; i++) {
if (fragments[i].offset != total_len) {
return false;
}
if (fragments[i].fragment.value == NULL) {
return false;
}
if (fragments[i].total_len != fragments[0].total_len) {
return false;
}
total_len += fragments[i].fragment.len;
if (total_len > fragments[0].total_len) {
return false;
}
}
if (num_fragments && total_len != fragments[0].total_len) {
return false;
}
if (num_fragments && (fragments[0].total_len == ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH)) {
for (size_t i = 0; i < num_fragments; i++) {
fragments[i].total_len = total_len;
}
}
return true;
}
bool zcbor_splice_string_fragments(struct zcbor_string_fragment *fragments,
size_t num_fragments, uint8_t *result, size_t *result_len)
{
size_t total_len = 0;
if (!fragments) {
return false;
}
for (size_t i = 0; i < num_fragments; i++) {
if ((total_len > *result_len)
|| (fragments[i].fragment.len > (*result_len - total_len))) {
return false;
}
memcpy(&result[total_len],
fragments[i].fragment.value, fragments[i].fragment.len);
total_len += fragments[i].fragment.len;
}
*result_len = total_len;
return true;
}
bool zcbor_compare_strings(const struct zcbor_string *str1,
const struct zcbor_string *str2)
{
return (str1 != NULL) && (str2 != NULL)
&& (str1->value != NULL) && (str2->value != NULL) && (str1->len == str2->len)
&& (memcmp(str1->value, str2->value, str1->len) == 0);
}
size_t zcbor_header_len(uint64_t value)
{
if (value <= ZCBOR_VALUE_IN_HEADER) {
return 1;
} else if (value <= 0xFF) {
return 2;
} else if (value <= 0xFFFF) {
return 3;
} else if (value <= 0xFFFFFFFF) {
return 5;
} else {
return 9;
}
}
size_t zcbor_header_len_ptr(const void *const value, size_t value_len)
{
uint64_t val64 = 0;
if (value_len > sizeof(val64)) {
return 0;
}
memcpy(((uint8_t*)&val64) + ZCBOR_ECPY_OFFS(sizeof(val64), value_len), value, value_len);
return zcbor_header_len(val64);
}
int zcbor_entry_function(const uint8_t *payload, size_t payload_len,
void *result, size_t *payload_len_out, zcbor_state_t *state, zcbor_decoder_t func,
size_t n_states, size_t elem_count)
{
zcbor_new_state(state, n_states, payload, payload_len, elem_count, NULL, 0);
bool ret = func(state, result);
if (!ret) {
int err = zcbor_pop_error(state);
err = (err == ZCBOR_SUCCESS) ? ZCBOR_ERR_UNKNOWN : err;
return err;
}
if (payload_len_out != NULL) {
*payload_len_out = MIN(payload_len,
(size_t)state[0].payload - (size_t)payload);
}
return ZCBOR_SUCCESS;
}
/* Float16: */
#define F16_SIGN_OFFS 15 /* Bit offset of the sign bit. */
#define F16_EXPO_OFFS 10 /* Bit offset of the exponent. */
#define F16_EXPO_MSK 0x1F /* Bitmask for the exponent (right shifted by F16_EXPO_OFFS). */
#define F16_MANTISSA_MSK 0x3FF /* Bitmask for the mantissa. */
#define F16_MAX 65520 /* Lowest float32 value that rounds up to float16 infinity.
* (65519.996 rounds to 65504) */
#define F16_MIN_EXPO 24 /* Negative exponent of the non-zero float16 value closest to 0 (2^-24) */
#define F16_MIN (1.0f / (1 << F16_MIN_EXPO)) /* The non-zero float16 value closest to 0 (2^-24) */
#define F16_MIN_NORM (1.0f / (1 << 14)) /* The normalized float16 value closest to 0 (2^-14) */
#define F16_BIAS 15 /* The exponent bias of normalized float16 values. */
/* Float32: */
#define F32_SIGN_OFFS 31 /* Bit offset of the sign bit. */
#define F32_EXPO_OFFS 23 /* Bit offset of the exponent. */
#define F32_EXPO_MSK 0xFF /* Bitmask for the exponent (right shifted by F32_EXPO_OFFS). */
#define F32_MANTISSA_MSK 0x7FFFFF /* Bitmask for the mantissa. */
#define F32_BIAS 127 /* The exponent bias of normalized float32 values. */
/* Rounding: */
#define SUBNORM_ROUND_MSK (F32_MANTISSA_MSK | (1 << F32_EXPO_OFFS)) /* mantissa + lsb of expo for
* tiebreak. */
#define SUBNORM_ROUND_BIT_MSK (1 << (F32_EXPO_OFFS - 1)) /* msb of mantissa (0x400000) */
#define NORM_ROUND_MSK (F32_MANTISSA_MSK >> (F16_EXPO_OFFS - 1)) /* excess mantissa when going from
* float32 to float16 + 1 extra bit
* for tiebreak. */
#define NORM_ROUND_BIT_MSK (1 << (F32_EXPO_OFFS - F16_EXPO_OFFS - 1)) /* bit 12 (0x1000) */
float zcbor_float16_to_32(uint16_t input)
{
uint32_t sign = input >> F16_SIGN_OFFS;
uint32_t expo = (input >> F16_EXPO_OFFS) & F16_EXPO_MSK;
uint32_t mantissa = input & F16_MANTISSA_MSK;
if ((expo == 0) && (mantissa != 0)) {
/* Subnormal float16 - convert to normalized float32 */
return ((float)mantissa * F16_MIN) * (sign ? -1 : 1);
} else {
/* Normalized / zero / Infinity / NaN */
uint32_t new_expo = (expo == 0 /* zero */) ? 0
: (expo == F16_EXPO_MSK /* inf/NaN */) ? F32_EXPO_MSK
: (expo + (F32_BIAS - F16_BIAS));
uint32_t value32 = (sign << F32_SIGN_OFFS) | (new_expo << F32_EXPO_OFFS)
| (mantissa << (F32_EXPO_OFFS - F16_EXPO_OFFS));
float result;
memcpy(&result, &value32, sizeof(result));
return result;
}
}
uint16_t zcbor_float32_to_16(float input)
{
uint32_t value32;
memcpy(&value32, &input, sizeof(value32));
uint32_t sign = value32 >> F32_SIGN_OFFS;
uint32_t expo = (value32 >> F32_EXPO_OFFS) & F32_EXPO_MSK;
uint32_t mantissa = value32 & F32_MANTISSA_MSK;
uint16_t value16 = (uint16_t)(sign << F16_SIGN_OFFS);
uint32_t abs_value32 = value32 & ~(1 << F32_SIGN_OFFS);
float abs_input;
memcpy(&abs_input, &abs_value32, sizeof(abs_input));
if (abs_input <= (F16_MIN / 2)) {
/* 0 or too small for float16. Round down to 0. value16 is already correct. */
} else if (abs_input < F16_MIN) {
/* Round up to 2^(-24) (F16_MIN), has other rounding rules than larger values. */
value16 |= 0x0001;
} else if (abs_input < F16_MIN_NORM) {
/* Subnormal float16 (normal float32) */
uint32_t adjusted_mantissa =
/* Adjust for the purposes of checking rounding. */
/* The lsb of expo is needed for the cases where expo is 103 (minimum). */
((value32 << (expo - (F32_BIAS - F16_MIN_EXPO))) & SUBNORM_ROUND_MSK);
uint16_t rounding_bit =
/* "Round to nearest, ties to even". */
/* 0x400000 means ties go down towards even. (0xC00000 means ties go up.) */
(adjusted_mantissa & SUBNORM_ROUND_BIT_MSK)
&& (adjusted_mantissa != SUBNORM_ROUND_BIT_MSK);
value16 |= ((uint16_t)(abs_input * (1 << 24)) + rounding_bit); /* expo is 0 */
} else if (abs_input < F16_MAX) {
/* Normal float16 (normal float32) */
uint16_t rounding_bit =
/* Bit 13 of the mantissa represents which way to round, except for the */
/* special case where bits 0-12 and 14 are 0. */
/* This is because of "Round to nearest, ties to even". */
/* 0x1000 means ties go down towards even. (0x3000 means ties go up.) */
((mantissa & NORM_ROUND_BIT_MSK)
&& ((mantissa & NORM_ROUND_MSK) != NORM_ROUND_BIT_MSK));
value16 |= (uint16_t)((expo - (F32_BIAS - F16_BIAS)) << F16_EXPO_OFFS);
value16 |= (uint16_t)(mantissa >> (F32_EXPO_OFFS - F16_EXPO_OFFS));
value16 += rounding_bit; /* Might propagate to exponent. */
} else if (expo != F32_EXPO_MSK || !mantissa) {
/* Infinite, or finite normal float32 too large for float16. Round up to inf. */
value16 |= (F16_EXPO_MSK << F16_EXPO_OFFS);
} else {
/* NaN */
/* Preserve msbit of mantissa. */
uint16_t new_mantissa = (uint16_t)(mantissa >> (F32_EXPO_OFFS - F16_EXPO_OFFS));
value16 |= (F16_EXPO_MSK << F16_EXPO_OFFS) | (new_mantissa ? new_mantissa : 1);
}
return value16;
}
/** Weak strnlen() implementation in case it is not available.
*
* This function is in the public domain, according to:
* https://github.com/arm-embedded/gcc-arm-none-eabi.debian/blob/master/src/libiberty/strnlen.c
*/
__attribute__((__weak__))
size_t strnlen (const char *s, size_t maxlen)
{
size_t i;
for (i = 0; i < maxlen; ++i) {
if (s[i] == '\0') {
break;
}
}
return i;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,614 @@
/*
* This file has been copied from the zcbor library.
* Commit zcbor 0.8.1
*/
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "zcbor_encode.h"
#include "zcbor_common.h"
#include "zcbor_print.h"
_Static_assert((sizeof(size_t) == sizeof(void *)),
"This code needs size_t to be the same length as pointers.");
static uint8_t log2ceil(size_t val)
{
switch(val) {
case 1: return 0;
case 2: return 1;
case 3: return 2;
case 4: return 2;
case 5: return 3;
case 6: return 3;
case 7: return 3;
case 8: return 3;
}
zcbor_log("Should not come here.\r\n");
return 0;
}
static uint8_t get_additional(size_t len, uint8_t value0)
{
return len == 0 ? value0 : (uint8_t)(24 + log2ceil(len));
}
static bool encode_header_byte(zcbor_state_t *state,
zcbor_major_type_t major_type, uint8_t additional)
{
ZCBOR_CHECK_ERROR();
ZCBOR_CHECK_PAYLOAD();
zcbor_assert_state(additional < 32, "Unsupported additional value: %d\r\n", additional);
*(state->payload_mut++) = (uint8_t)((major_type << 5) | (additional & 0x1F));
return true;
}
/** Encode a single value.
*/
static bool value_encode_len(zcbor_state_t *state, zcbor_major_type_t major_type,
const void *const result, size_t result_len)
{
uint8_t *u8_result = (uint8_t *)result;
if ((state->payload + 1 + result_len) > state->payload_end) {
ZCBOR_ERR(ZCBOR_ERR_NO_PAYLOAD);
}
if (!encode_header_byte(state, major_type,
get_additional(result_len, u8_result[0]))) {
ZCBOR_FAIL();
}
state->payload_mut--;
zcbor_trace(state, "value_encode_len");
state->payload_mut++;
#ifdef ZCBOR_BIG_ENDIAN
memcpy(state->payload_mut, u8_result, result_len);
state->payload_mut += result_len;
#else
for (; result_len > 0; result_len--) {
*(state->payload_mut++) = u8_result[result_len - 1];
}
#endif /* ZCBOR_BIG_ENDIAN */
state->elem_count++;
return true;
}
static bool value_encode(zcbor_state_t *state, zcbor_major_type_t major_type,
const void *const input, size_t max_result_len)
{
zcbor_assert_state(max_result_len != 0, "0-length result not supported.\r\n");
size_t result_len = zcbor_header_len_ptr(input, max_result_len) - 1;
const void *result = input;
#ifdef ZCBOR_BIG_ENDIAN
result = (uint8_t *)input + max_result_len - (result_len ? result_len : 1);
#endif
return value_encode_len(state, major_type, result, result_len);
}
bool zcbor_int_encode(zcbor_state_t *state, const void *input_int, size_t int_size)
{
zcbor_major_type_t major_type;
uint8_t input_buf[8];
const uint8_t *input_uint8 = input_int;
const int8_t *input_int8 = input_int;
const uint8_t *input = input_int;
if (int_size > sizeof(int64_t)) {
ZCBOR_ERR(ZCBOR_ERR_INT_SIZE);
}
#ifdef ZCBOR_BIG_ENDIAN
if (input_int8[0] < 0) {
#else
if (input_int8[int_size - 1] < 0) {
#endif
major_type = ZCBOR_MAJOR_TYPE_NINT;
/* Convert to CBOR's representation by flipping all bits. */
for (unsigned int i = 0; i < int_size; i++) {
input_buf[i] = (uint8_t)~input_uint8[i];
}
input = input_buf;
} else {
major_type = ZCBOR_MAJOR_TYPE_PINT;
}
if (!value_encode(state, major_type, input, int_size)) {
ZCBOR_FAIL();
}
return true;
}
bool zcbor_uint_encode(zcbor_state_t *state, const void *input_uint, size_t uint_size)
{
if (!value_encode(state, ZCBOR_MAJOR_TYPE_PINT, input_uint, uint_size)) {
zcbor_log("uint with size %zu failed.\r\n", uint_size);
ZCBOR_FAIL();
}
return true;
}
bool zcbor_int32_encode(zcbor_state_t *state, const int32_t *input)
{
return zcbor_int_encode(state, input, sizeof(*input));
}
bool zcbor_int64_encode(zcbor_state_t *state, const int64_t *input)
{
return zcbor_int_encode(state, input, sizeof(*input));
}
bool zcbor_uint32_encode(zcbor_state_t *state, const uint32_t *input)
{
return zcbor_uint_encode(state, input, sizeof(*input));
}
bool zcbor_uint64_encode(zcbor_state_t *state, const uint64_t *input)
{
return zcbor_uint_encode(state, input, sizeof(*input));
}
bool zcbor_int32_put(zcbor_state_t *state, int32_t input)
{
return zcbor_int_encode(state, &input, sizeof(input));
}
bool zcbor_int64_put(zcbor_state_t *state, int64_t input)
{
return zcbor_int_encode(state, &input, sizeof(input));
}
bool zcbor_uint32_put(zcbor_state_t *state, uint32_t input)
{
return zcbor_uint_encode(state, &input, sizeof(input));
}
bool zcbor_uint64_put(zcbor_state_t *state, uint64_t input)
{
return zcbor_uint_encode(state, &input, sizeof(input));
}
#ifdef ZCBOR_SUPPORTS_SIZE_T
bool zcbor_size_put(zcbor_state_t *state, size_t input)
{
return zcbor_uint_encode(state, &input, sizeof(input));
}
bool zcbor_size_encode(zcbor_state_t *state, const size_t *input)
{
return zcbor_uint_encode(state, input, sizeof(*input));
}
#endif
static bool str_start_encode(zcbor_state_t *state,
const struct zcbor_string *input, zcbor_major_type_t major_type)
{
if (input->value && ((zcbor_header_len_ptr(&input->len, sizeof(input->len))
+ input->len + (size_t)state->payload)
> (size_t)state->payload_end)) {
ZCBOR_ERR(ZCBOR_ERR_NO_PAYLOAD);
}
if (!value_encode(state, major_type, &input->len, sizeof(input->len))) {
ZCBOR_FAIL();
}
return true;
}
static size_t remaining_str_len(zcbor_state_t *state)
{
size_t max_len = (size_t)state->payload_end - (size_t)state->payload;
size_t result_len = zcbor_header_len_ptr(&max_len, sizeof(max_len)) - 1;
return max_len - result_len - 1;
}
bool zcbor_bstr_start_encode(zcbor_state_t *state)
{
if (!zcbor_new_backup(state, 0)) {
ZCBOR_FAIL();
}
uint64_t max_len = remaining_str_len(state);
/* Encode a dummy header */
if (!value_encode(state, ZCBOR_MAJOR_TYPE_BSTR, &max_len, sizeof(max_len))) {
ZCBOR_FAIL();
}
return true;
}
bool zcbor_bstr_end_encode(zcbor_state_t *state, struct zcbor_string *result)
{
const uint8_t *payload = state->payload;
struct zcbor_string dummy_value;
if (result == NULL) {
/* Use a dummy value for the sake of the length calculation below.
* Will not be returned.
*/
result = &dummy_value;
}
if (!zcbor_process_backup(state, ZCBOR_FLAG_RESTORE | ZCBOR_FLAG_CONSUME, 0xFFFFFFFF)) {
ZCBOR_FAIL();
}
result->value = state->payload_end - remaining_str_len(state);
result->len = (size_t)payload - (size_t)result->value;
/* Reencode header of list now that we know the number of elements. */
if (!zcbor_bstr_encode(state, result)) {
ZCBOR_FAIL();
}
return true;
}
static bool str_encode(zcbor_state_t *state,
const struct zcbor_string *input, zcbor_major_type_t major_type)
{
ZCBOR_CHECK_PAYLOAD(); /* To make the size_t cast below safe. */
if (input->len > (size_t)(state->payload_end - state->payload)) {
ZCBOR_ERR(ZCBOR_ERR_NO_PAYLOAD);
}
if (!str_start_encode(state, input, major_type)) {
ZCBOR_FAIL();
}
if (state->payload_mut != input->value) {
/* Use memmove since string might be encoded into the same space
* because of bstrx_cbor_start_encode/bstrx_cbor_end_encode. */
memmove(state->payload_mut, input->value, input->len);
}
state->payload += input->len;
return true;
}
bool zcbor_bstr_encode(zcbor_state_t *state, const struct zcbor_string *input)
{
return str_encode(state, input, ZCBOR_MAJOR_TYPE_BSTR);
}
bool zcbor_tstr_encode(zcbor_state_t *state, const struct zcbor_string *input)
{
return str_encode(state, input, ZCBOR_MAJOR_TYPE_TSTR);
}
bool zcbor_bstr_encode_ptr(zcbor_state_t *state, const char *str, size_t len)
{
const struct zcbor_string zs = { .value = (const uint8_t *)str, .len = len };
return zcbor_bstr_encode(state, &zs);
}
bool zcbor_tstr_encode_ptr(zcbor_state_t *state, const char *str, size_t len)
{
const struct zcbor_string zs = { .value = (const uint8_t *)str, .len = len };
return zcbor_tstr_encode(state, &zs);
}
bool zcbor_bstr_put_term(zcbor_state_t *state, char const *str, size_t maxlen)
{
return zcbor_bstr_encode_ptr(state, str, strnlen(str, maxlen));
}
bool zcbor_tstr_put_term(zcbor_state_t *state, char const *str, size_t maxlen)
{
return zcbor_tstr_encode_ptr(state, str, strnlen(str, maxlen));
}
static bool list_map_start_encode(zcbor_state_t *state, size_t max_num,
zcbor_major_type_t major_type)
{
#ifdef ZCBOR_CANONICAL
if (!zcbor_new_backup(state, 0)) {
ZCBOR_FAIL();
}
/* Encode dummy header with max number of elements. */
if (!value_encode(state, major_type, &max_num, sizeof(max_num))) {
ZCBOR_FAIL();
}
state->elem_count--; /* Because of dummy header. */
#else
(void)max_num;
if (!encode_header_byte(state, major_type, ZCBOR_VALUE_IS_INDEFINITE_LENGTH)) {
ZCBOR_FAIL();
}
#endif
return true;
}
bool zcbor_list_start_encode(zcbor_state_t *state, size_t max_num)
{
return list_map_start_encode(state, max_num, ZCBOR_MAJOR_TYPE_LIST);
}
bool zcbor_map_start_encode(zcbor_state_t *state, size_t max_num)
{
return list_map_start_encode(state, max_num, ZCBOR_MAJOR_TYPE_MAP);
}
static bool list_map_end_encode(zcbor_state_t *state, size_t max_num,
zcbor_major_type_t major_type)
{
#ifdef ZCBOR_CANONICAL
size_t list_count = ((major_type == ZCBOR_MAJOR_TYPE_LIST) ?
state->elem_count
: (state->elem_count / 2));
const uint8_t *payload = state->payload;
size_t max_header_len = zcbor_header_len_ptr(&max_num, 4) - 1;
size_t header_len = zcbor_header_len_ptr(&list_count, 4) - 1;
if (!zcbor_process_backup(state, ZCBOR_FLAG_RESTORE | ZCBOR_FLAG_CONSUME, 0xFFFFFFFF)) {
ZCBOR_FAIL();
}
zcbor_log("list_count: %zu\r\n", list_count);
/** If max_num is smaller than the actual number of encoded elements,
* the value_encode() below will corrupt the data if the encoded
* header is larger than the previously encoded header. */
if (header_len > max_header_len) {
zcbor_log("max_num too small.\r\n");
ZCBOR_ERR(ZCBOR_ERR_HIGH_ELEM_COUNT);
}
/* Reencode header of list now that we know the number of elements. */
if (!(value_encode(state, major_type, &list_count, sizeof(list_count)))) {
ZCBOR_FAIL();
}
if (max_header_len != header_len) {
const uint8_t *start = state->payload + max_header_len - header_len;
size_t body_size = (size_t)payload - (size_t)start;
memmove(state->payload_mut, start, body_size);
/* Reset payload pointer to end of list */
state->payload += body_size;
} else {
/* Reset payload pointer to end of list */
state->payload = payload;
}
#else
(void)max_num;
(void)major_type;
if (!encode_header_byte(state, ZCBOR_MAJOR_TYPE_SIMPLE, ZCBOR_VALUE_IS_INDEFINITE_LENGTH)) {
ZCBOR_FAIL();
}
#endif
return true;
}
bool zcbor_list_end_encode(zcbor_state_t *state, size_t max_num)
{
return list_map_end_encode(state, max_num, ZCBOR_MAJOR_TYPE_LIST);
}
bool zcbor_map_end_encode(zcbor_state_t *state, size_t max_num)
{
return list_map_end_encode(state, max_num, ZCBOR_MAJOR_TYPE_MAP);
}
bool zcbor_list_map_end_force_encode(zcbor_state_t *state)
{
#ifdef ZCBOR_CANONICAL
if (!zcbor_process_backup(state, ZCBOR_FLAG_RESTORE | ZCBOR_FLAG_CONSUME,
ZCBOR_MAX_ELEM_COUNT)) {
ZCBOR_FAIL();
}
#endif
(void)state;
return true;
}
bool zcbor_simple_encode(zcbor_state_t *state, uint8_t *input)
{
if (!value_encode(state, ZCBOR_MAJOR_TYPE_SIMPLE, input, sizeof(*input))) {
zcbor_log("Error encoding %u (0x%p)\r\n", *input, input);
ZCBOR_FAIL();
}
return true;
}
bool zcbor_simple_put(zcbor_state_t *state, uint8_t input)
{
return value_encode(state, ZCBOR_MAJOR_TYPE_SIMPLE, &input, sizeof(input));
}
bool zcbor_nil_put(zcbor_state_t *state, const void *unused)
{
(void)unused;
return zcbor_simple_put(state, 22);
}
bool zcbor_undefined_put(zcbor_state_t *state, const void *unused)
{
(void)unused;
return zcbor_simple_put(state, 23);
}
bool zcbor_bool_encode(zcbor_state_t *state, const bool *input)
{
return zcbor_bool_put(state, *input);
}
bool zcbor_bool_put(zcbor_state_t *state, bool input)
{
return zcbor_simple_put(state, (!!input + ZCBOR_BOOL_TO_SIMPLE));
}
bool zcbor_float64_encode(zcbor_state_t *state, const double *input)
{
if (!value_encode_len(state, ZCBOR_MAJOR_TYPE_SIMPLE, input,
sizeof(*input))) {
ZCBOR_FAIL();
}
return true;
}
bool zcbor_float64_put(zcbor_state_t *state, double input)
{
return zcbor_float64_encode(state, &input);
}
bool zcbor_float32_encode(zcbor_state_t *state, const float *input)
{
if (!value_encode_len(state, ZCBOR_MAJOR_TYPE_SIMPLE, input,
sizeof(*input))) {
ZCBOR_FAIL();
}
return true;
}
bool zcbor_float32_put(zcbor_state_t *state, float input)
{
return zcbor_float32_encode(state, &input);
}
bool zcbor_float16_encode(zcbor_state_t *state, const float *input)
{
return zcbor_float16_put(state, *input);
}
bool zcbor_float16_put(zcbor_state_t *state, float input)
{
return zcbor_float16_bytes_put(state, zcbor_float32_to_16(input));
}
bool zcbor_float16_bytes_encode(zcbor_state_t *state, const uint16_t *input)
{
if (!value_encode_len(state, ZCBOR_MAJOR_TYPE_SIMPLE, input,
sizeof(*input))) {
ZCBOR_FAIL();
}
return true;
}
bool zcbor_float16_bytes_put(zcbor_state_t *state, uint16_t input)
{
return zcbor_float16_bytes_encode(state, &input);
}
bool zcbor_tag_put(zcbor_state_t *state, uint32_t tag)
{
if (!value_encode(state, ZCBOR_MAJOR_TYPE_TAG, &tag, sizeof(tag))) {
ZCBOR_FAIL();
}
state->elem_count--;
return true;
}
bool zcbor_tag_encode(zcbor_state_t *state, uint32_t *tag)
{
return zcbor_tag_put(state, *tag);
}
bool zcbor_multi_encode_minmax(size_t min_encode, size_t max_encode,
const size_t *num_encode, zcbor_encoder_t encoder,
zcbor_state_t *state, const void *input, size_t result_len)
{
if ((*num_encode >= min_encode) && (*num_encode <= max_encode)) {
return zcbor_multi_encode(*num_encode, encoder, state, input, result_len);
} else {
ZCBOR_ERR(ZCBOR_ERR_ITERATIONS);
}
}
bool zcbor_multi_encode(const size_t num_encode, zcbor_encoder_t encoder,
zcbor_state_t *state, const void *input, size_t result_len)
{
ZCBOR_CHECK_ERROR();
for (size_t i = 0; i < num_encode; i++) {
if (!encoder(state, (const uint8_t *)input + i*result_len)) {
ZCBOR_FAIL();
}
}
zcbor_log("Encoded %zu elements.\n", num_encode);
return true;
}
void zcbor_new_encode_state(zcbor_state_t *state_array, size_t n_states,
uint8_t *payload, size_t payload_len, size_t elem_count)
{
zcbor_new_state(state_array, n_states, payload, payload_len, elem_count, NULL, 0);
}