zcbor
Advanced tools
| /* | ||
| * Copyright (c) 2024 Nordic Semiconductor ASA | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
| #include <stdint.h> | ||
| #include <stdbool.h> | ||
| #include <stddef.h> | ||
| #include <inttypes.h> | ||
| #include <zcbor_common.h> | ||
| #include <zcbor_decode.h> | ||
| #include <zcbor_print.h> | ||
| 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"); | ||
| } | ||
| 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"); | ||
| } | ||
| 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"); | ||
| } | ||
| } | ||
| 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) | ||
| ZCBOR_ERR_CASE(ZCBOR_ERR_CONSTANT_STATE_MISSING) | ||
| } | ||
| #undef ZCBOR_ERR_CASE | ||
| return "ZCBOR_ERR_UNKNOWN"; | ||
| } | ||
| void zcbor_print_error(int error) | ||
| { | ||
| zcbor_do_print("%s\r\n", zcbor_error_str(error)); | ||
| } |
@@ -24,4 +24,4 @@ /* | ||
| #define ZCBOR_VERSION_MAJOR 0 | ||
| #define ZCBOR_VERSION_MINOR 8 | ||
| #define ZCBOR_VERSION_BUGFIX 1 | ||
| #define ZCBOR_VERSION_MINOR 9 | ||
| #define ZCBOR_VERSION_BUGFIX 0 | ||
@@ -149,2 +149,4 @@ /** The version string with dots and not prefix. */ | ||
| #endif | ||
| bool enforce_canonical; /**< Fail when decoding if data is non-canonical. | ||
| The default/initial value follows ZCBOR_CANONICAL */ | ||
| bool manually_process_elem; /**< Whether an (unordered map) element should be automatically | ||
@@ -157,2 +159,16 @@ marked as processed when found via @ref zcbor_search_map_key. */ | ||
| #ifdef ZCBOR_CANONICAL | ||
| #define ZCBOR_ENFORCE_CANONICAL_DEFAULT true | ||
| #else | ||
| #define ZCBOR_ENFORCE_CANONICAL_DEFAULT false | ||
| #endif | ||
| #define ZCBOR_ENFORCE_CANONICAL(state) (state->constant_state \ | ||
| ? state->constant_state->enforce_canonical : ZCBOR_ENFORCE_CANONICAL_DEFAULT) | ||
| #define ZCBOR_MANUALLY_PROCESS_ELEM_DEFAULT false | ||
| #define ZCBOR_MANUALLY_PROCESS_ELEM(state) (state->constant_state \ | ||
| ? state->constant_state->manually_process_elem : ZCBOR_MANUALLY_PROCESS_ELEM_DEFAULT) | ||
| /** Function pointer type used with zcbor_multi_decode. | ||
@@ -242,3 +258,7 @@ * | ||
| #define ZCBOR_BOOL_TO_SIMPLE ((uint8_t)20) ///! In CBOR, false/true have the values 20/21 | ||
| #define ZCBOR_NIL_VAL ((uint8_t)22) | ||
| #define ZCBOR_UNDEF_VAL ((uint8_t)23) | ||
| #define ZCBOR_IS_FLOAT(header_byte) (((header_byte) >= 0xF9) && ((header_byte) <= 0xFB)) | ||
| #define ZCBOR_FLAG_RESTORE 1UL ///! Restore from the backup. Overwrite the current state with the state from the backup. | ||
@@ -270,3 +290,4 @@ #define ZCBOR_FLAG_CONSUME 2UL ///! Consume the backup. Remove the backup from the stack of backups. | ||
| #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_INVALID_VALUE_ENCODING 21 ///! When ZCBOR_CANONICAL is defined, and the incoming data is not encoded with minimal length, or uses indefinite length array. | ||
| #define ZCBOR_ERR_CONSTANT_STATE_MISSING 22 | ||
| #define ZCBOR_ERR_UNKNOWN 31 | ||
@@ -464,2 +485,14 @@ | ||
| /** If a string (header + payload) is encoded into the rest of the payload, how long would it be? | ||
| * | ||
| * Note that a string with this length doesn't necessarily fill the rest of the | ||
| * payload. For some payload lengths, e.g. 25, it's impossible to encode a | ||
| * string of that total length. | ||
| * | ||
| * @param[in] state The current state. | ||
| * | ||
| * @return The length of the string (payload, not including header) in bytes. | ||
| */ | ||
| size_t zcbor_remaining_str_len(zcbor_state_t *state); | ||
| /** Convert a float16 value to float32. | ||
@@ -466,0 +499,0 @@ * |
@@ -76,3 +76,2 @@ /* | ||
| 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 */ | ||
@@ -105,3 +104,2 @@ bool zcbor_float16_decode(zcbor_state_t *state, float *result); /* IEEE754 float16 */ | ||
| 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 */ | ||
@@ -126,3 +124,2 @@ bool zcbor_nil_expect(zcbor_state_t *state, void *unused); /* 'nil' CBOR simple value */ | ||
| 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 */ | ||
@@ -129,0 +126,0 @@ bool zcbor_float16_pexpect(zcbor_state_t *state, float *expected); /* IEEE754 float16 */ |
@@ -68,3 +68,2 @@ /* | ||
| 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 */ | ||
@@ -88,3 +87,2 @@ bool zcbor_nil_put(zcbor_state_t *state, const void *unused); /* 'nil' CBOR simple value */ | ||
| 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 */ | ||
@@ -91,0 +89,0 @@ bool zcbor_float16_encode(zcbor_state_t *state, const float *input); /* IEEE754 float16 */ |
@@ -15,2 +15,6 @@ /* | ||
| #include <stdint.h> | ||
| #include <stdbool.h> | ||
| #include <stddef.h> | ||
| #ifndef ZCBOR_PRINT_FUNC | ||
@@ -71,93 +75,12 @@ #include <stdio.h> | ||
| __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"); | ||
| } | ||
| void zcbor_print_compare_lines(const uint8_t *str1, const uint8_t *str2, size_t size); | ||
| __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; | ||
| void zcbor_print_compare_strings(const uint8_t *str1, const uint8_t *str2, size_t size); | ||
| 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"); | ||
| } | ||
| void zcbor_print_compare_strings_diff(const uint8_t *str1, const uint8_t *str2, size_t size); | ||
| __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; | ||
| const char *zcbor_error_str(int error); | ||
| 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"); | ||
| } | ||
| } | ||
| void zcbor_print_error(int error); | ||
| __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 | ||
@@ -164,0 +87,0 @@ } |
@@ -44,3 +44,3 @@ /* | ||
| 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_YANG_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. | ||
@@ -47,0 +47,0 @@ ZCBOR_TAG_IPV4 = 52, ///! bstr or array [RFC9164] IPv4 |
+10
-3
| Metadata-Version: 2.1 | ||
| Name: zcbor | ||
| Version: 0.8.1 | ||
| Version: 0.9.0 | ||
| Summary: Code generation and validation using CDDL schemas | ||
@@ -99,2 +99,7 @@ Author: Nordic Semiconductor ASA | ||
| `n_flags` is used when decoding maps where the order is unknown. | ||
| It allows using the `zcbor_unordered_map_search()` function to search for elements. | ||
| See the header files for more information. | ||
| ```c | ||
@@ -119,3 +124,3 @@ /** Initialize a decoding state (could include an array of backup states). | ||
| ------------------------- | ----------- | ||
| `ZCBOR_CANONICAL` | Assume canonical encoding (AKA "deterministically encoded CBOR"). When encoding lists and maps, do not use indefinite length encoding. Enabling `ZCBOR_CANONICAL` increases code size and makes the encoding library more often use state backups. When decoding, ensure that the incoming data conforms to canonical encoding, i.e. no indefinite length encoding, and always using minimal length encoding (e.g. not using 16 bits to encode a value < 256). Note: the map ordering constraint in canonical encoding is not checked. | ||
| `ZCBOR_CANONICAL` | Assume canonical encoding (AKA "deterministically encoded CBOR", ch 4.2.1 in RFC8949). When encoding lists and maps, do not use indefinite length encoding. Enabling `ZCBOR_CANONICAL` increases code size and makes the encoding library more often use state backups. When decoding, if `enforce_canonical` is true, ensure that the incoming data conforms to canonical encoding, i.e. no indefinite length encoding, and always using minimal length encoding (e.g. not using 16 bits to encode a value < 256). Enabling `ZCBOR_CANONICAL` changes the default of `enforce_canonical` from `false` to `true` Note: the map ordering constraint in canonical encoding is not checked. | ||
| `ZCBOR_VERBOSE` | Print log messages on encoding/decoding errors (`zcbor_log()`), and also a trace message (`zcbor_trace()`) for each decoded value, and in each generated function (when using code generation). | ||
@@ -545,3 +550,5 @@ `ZCBOR_ASSERTS` | Enable asserts (`zcbor_assert()`). When they fail, the assert statements instruct the current function to return a `ZCBOR_ERR_ASSERTION` error. If `ZCBOR_VERBOSE` is enabled, a message is printed. | ||
| Header to be included in the comment at the top of | ||
| generated C files, e.g. copyright. | ||
| generated files, e.g. copyright. Can be a string or a | ||
| path to a file. If interpreted as a path to an | ||
| existing file, the file's contents will be used. | ||
@@ -548,0 +555,0 @@ ``` |
+9
-2
@@ -76,2 +76,7 @@ zcbor | ||
| `n_flags` is used when decoding maps where the order is unknown. | ||
| It allows using the `zcbor_unordered_map_search()` function to search for elements. | ||
| See the header files for more information. | ||
| ```c | ||
@@ -96,3 +101,3 @@ /** Initialize a decoding state (could include an array of backup states). | ||
| ------------------------- | ----------- | ||
| `ZCBOR_CANONICAL` | Assume canonical encoding (AKA "deterministically encoded CBOR"). When encoding lists and maps, do not use indefinite length encoding. Enabling `ZCBOR_CANONICAL` increases code size and makes the encoding library more often use state backups. When decoding, ensure that the incoming data conforms to canonical encoding, i.e. no indefinite length encoding, and always using minimal length encoding (e.g. not using 16 bits to encode a value < 256). Note: the map ordering constraint in canonical encoding is not checked. | ||
| `ZCBOR_CANONICAL` | Assume canonical encoding (AKA "deterministically encoded CBOR", ch 4.2.1 in RFC8949). When encoding lists and maps, do not use indefinite length encoding. Enabling `ZCBOR_CANONICAL` increases code size and makes the encoding library more often use state backups. When decoding, if `enforce_canonical` is true, ensure that the incoming data conforms to canonical encoding, i.e. no indefinite length encoding, and always using minimal length encoding (e.g. not using 16 bits to encode a value < 256). Enabling `ZCBOR_CANONICAL` changes the default of `enforce_canonical` from `false` to `true` Note: the map ordering constraint in canonical encoding is not checked. | ||
| `ZCBOR_VERBOSE` | Print log messages on encoding/decoding errors (`zcbor_log()`), and also a trace message (`zcbor_trace()`) for each decoded value, and in each generated function (when using code generation). | ||
@@ -522,3 +527,5 @@ `ZCBOR_ASSERTS` | Enable asserts (`zcbor_assert()`). When they fail, the assert statements instruct the current function to return a `ZCBOR_ERR_ASSERTION` error. If `ZCBOR_VERBOSE` is enabled, a message is printed. | ||
| Header to be included in the comment at the top of | ||
| generated C files, e.g. copyright. | ||
| generated files, e.g. copyright. Can be a string or a | ||
| path to a file. If interpreted as a path to an | ||
| existing file, the file's contents will be used. | ||
@@ -525,0 +532,0 @@ ``` |
+18
-1
@@ -166,3 +166,4 @@ /* | ||
| #endif | ||
| state_array[0].constant_state->manually_process_elem = false; | ||
| state_array[0].constant_state->enforce_canonical = ZCBOR_ENFORCE_CANONICAL_DEFAULT; | ||
| state_array[0].constant_state->manually_process_elem = ZCBOR_MANUALLY_PROCESS_ELEM_DEFAULT; | ||
| #ifdef ZCBOR_MAP_SMART_SEARCH | ||
@@ -286,2 +287,18 @@ state_array[0].constant_state->map_search_elem_state_end = flags + flags_bytes; | ||
| size_t zcbor_remaining_str_len(zcbor_state_t *state) | ||
| { | ||
| size_t max_len = (size_t)state->payload_end - (size_t)state->payload; | ||
| if (max_len == 0) { | ||
| return 0; | ||
| } | ||
| size_t max_header_len = zcbor_header_len(max_len); | ||
| size_t min_header_len = zcbor_header_len(max_len - max_header_len); | ||
| size_t header_len = zcbor_header_len(max_len - min_header_len); | ||
| return max_len - header_len; | ||
| } | ||
| int zcbor_entry_function(const uint8_t *payload, size_t payload_len, | ||
@@ -288,0 +305,0 @@ void *result, size_t *payload_len_out, zcbor_state_t *state, zcbor_decoder_t func, |
+142
-98
@@ -106,22 +106,37 @@ /* | ||
| /** Get a single value. | ||
| /** Get a single value. I.e. a number or simple value, or a list/map/string header. | ||
| * | ||
| * @details @p ppayload must point to the header byte. This function will | ||
| * @details @p state->payload must point to the header byte. This function will | ||
| * retrieve the value (either from within the additional info, or from | ||
| * the subsequent bytes) and return it in the result. The result can | ||
| * have arbitrary length. | ||
| * have arbitrary length within 1-8 bytes. | ||
| * | ||
| * The function will also validate | ||
| * - Min/max constraints on the value. | ||
| * - That @p payload doesn't overrun past @p payload_end. | ||
| * - That @p elem_count has not been exhausted. | ||
| * - That @p state->payload doesn't overrun past @p state->payload_end. | ||
| * - That @p state->elem_count has not been exhausted. | ||
| * - That the value is encoded in a canonical way (if enforce_canonical | ||
| * is enabled). | ||
| * | ||
| * @p ppayload and @p elem_count are updated if the function | ||
| * succeeds. If not, they are left unchanged. | ||
| * @p state->payload and @p state->elem_count are updated if the function | ||
| * succeeds. If not, they are left unchanged. @p state->payload is updated | ||
| * to point to the next byte after the value (for a list/map/tstr/bstr | ||
| * this means the first byte of the list/string payload). | ||
| * @p state->elem_count is decremented by one. | ||
| * | ||
| * @p state->payload_bak is updated to point to the start of the value. | ||
| * | ||
| * CBOR values are always big-endian, so this function converts from | ||
| * big to little-endian if necessary (@ref ZCBOR_BIG_ENDIAN). | ||
| * | ||
| * @param state[inout] The current state of the decoding. | ||
| * @param result[out] Pointer to an integer where the result will be stored. | ||
| * @param result_len The size of the result integer. | ||
| * @param indefinite_length_array[inout] | ||
| * As input: NULL if an indefinite length value is not expected. | ||
| * As output: Whether the value signifies an indefinite length array. | ||
| * | ||
| * @return true if the value was successfully extracted, false otherwise. | ||
| */ | ||
| static bool value_extract(zcbor_state_t *state, | ||
| void *const result, size_t result_len) | ||
| void *const result, size_t result_len, bool *indefinite_length_array) | ||
| { | ||
@@ -131,2 +146,3 @@ zcbor_trace(state, "value_extract"); | ||
| zcbor_assert_state(result_len <= 8, "result sizes above 8 bytes not supported.\r\n"); | ||
| zcbor_assert_state(state != NULL, "state cannot be NULL.\r\n"); | ||
| zcbor_assert_state(result != NULL, "result cannot be NULL.\r\n"); | ||
@@ -137,22 +153,35 @@ | ||
| uint8_t additional = ZCBOR_ADDITIONAL(*state->payload); | ||
| size_t len = additional_len(additional); | ||
| uint8_t *result_offs = (uint8_t *)result + ZCBOR_ECPY_OFFS(result_len, MAX(1, len)); | ||
| uint8_t header_byte = *state->payload; | ||
| uint8_t additional = ZCBOR_ADDITIONAL(header_byte); | ||
| size_t len = 0; | ||
| ZCBOR_ERR_IF(additional > ZCBOR_VALUE_IS_8_BYTES, ZCBOR_ERR_ADDITIONAL_INVAL); | ||
| ZCBOR_ERR_IF(len > result_len, ZCBOR_ERR_INT_SIZE); | ||
| ZCBOR_ERR_IF((state->payload + len + 1) > state->payload_end, | ||
| ZCBOR_ERR_NO_PAYLOAD); | ||
| if ((additional == ZCBOR_VALUE_IS_INDEFINITE_LENGTH) && (indefinite_length_array != NULL)) { | ||
| /* Indefinite length is not allowed in canonical CBOR */ | ||
| ZCBOR_ERR_IF(ZCBOR_ENFORCE_CANONICAL(state), | ||
| ZCBOR_ERR_INVALID_VALUE_ENCODING); | ||
| memset(result, 0, result_len); | ||
| if (len == 0) { | ||
| *result_offs = additional; | ||
| *indefinite_length_array = true; | ||
| } else { | ||
| endian_copy(result_offs, state->payload + 1, len); | ||
| len = additional_len(additional); | ||
| uint8_t *result_offs = (uint8_t *)result + ZCBOR_ECPY_OFFS(result_len, MAX(1, len)); | ||
| #ifdef ZCBOR_CANONICAL | ||
| ZCBOR_ERR_IF((zcbor_header_len_ptr(result, result_len) != (len + 1)), | ||
| ZCBOR_ERR_INVALID_VALUE_ENCODING); | ||
| #endif | ||
| ZCBOR_ERR_IF(additional > ZCBOR_VALUE_IS_8_BYTES, ZCBOR_ERR_ADDITIONAL_INVAL); | ||
| ZCBOR_ERR_IF(len > result_len, ZCBOR_ERR_INT_SIZE); | ||
| ZCBOR_ERR_IF((state->payload + len + 1) > state->payload_end, | ||
| ZCBOR_ERR_NO_PAYLOAD); | ||
| memset(result, 0, result_len); | ||
| if (len == 0) { | ||
| *result_offs = additional; | ||
| } else { | ||
| endian_copy(result_offs, state->payload + 1, len); | ||
| /* Check whether value could have been encoded shorter. | ||
| Only check when enforcing canonical CBOR, and never check floats. */ | ||
| if (ZCBOR_ENFORCE_CANONICAL(state) && !ZCBOR_IS_FLOAT(header_byte)) { | ||
| ZCBOR_ERR_IF((zcbor_header_len_ptr(result, result_len) != (len + 1)), | ||
| ZCBOR_ERR_INVALID_VALUE_ENCODING); | ||
| } | ||
| } | ||
| } | ||
@@ -166,3 +195,27 @@ | ||
| static int val_to_int(zcbor_major_type_t major_type, void *result, size_t result_size) | ||
| { | ||
| #ifdef ZCBOR_BIG_ENDIAN | ||
| int8_t msbyte = *(int8_t *)result; | ||
| #else | ||
| int8_t msbyte = ((int8_t *)result)[result_size - 1]; | ||
| #endif | ||
| uint8_t *result_uint8 = (uint8_t *)result; | ||
| if ((result_size == 0) || (msbyte < 0)) { | ||
| /* Value is too large to fit in a signed integer. */ | ||
| return ZCBOR_ERR_INT_SIZE; | ||
| } | ||
| if (major_type == ZCBOR_MAJOR_TYPE_NINT) { | ||
| /* Convert from CBOR's representation by flipping all bits. */ | ||
| for (unsigned int i = 0; i < result_size; i++) { | ||
| result_uint8[i] = (uint8_t)~result_uint8[i]; | ||
| } | ||
| } | ||
| return ZCBOR_SUCCESS; | ||
| } | ||
| bool zcbor_int_decode(zcbor_state_t *state, void *result, size_t result_size) | ||
@@ -173,4 +226,2 @@ { | ||
| zcbor_major_type_t major_type = ZCBOR_MAJOR_TYPE(*state->payload); | ||
| uint8_t *result_uint8 = (uint8_t *)result; | ||
| int8_t *result_int8 = (int8_t *)result; | ||
@@ -183,22 +234,11 @@ if (major_type != ZCBOR_MAJOR_TYPE_PINT | ||
| if (!value_extract(state, result, result_size)) { | ||
| if (!value_extract(state, result, result_size, NULL)) { | ||
| ZCBOR_FAIL(); | ||
| } | ||
| #ifdef ZCBOR_BIG_ENDIAN | ||
| if (result_int8[0] < 0) { | ||
| #else | ||
| if (result_int8[result_size - 1] < 0) { | ||
| #endif | ||
| /* Value is too large to fit in a signed integer. */ | ||
| ERR_RESTORE(ZCBOR_ERR_INT_SIZE); | ||
| int err = val_to_int(major_type, result, result_size); | ||
| if (err != ZCBOR_SUCCESS) { | ||
| ERR_RESTORE(err); | ||
| } | ||
| if (major_type == ZCBOR_MAJOR_TYPE_NINT) { | ||
| /* Convert from CBOR's representation by flipping all bits. */ | ||
| for (unsigned int i = 0; i < result_size; i++) { | ||
| result_uint8[i] = (uint8_t)~result_uint8[i]; | ||
| } | ||
| } | ||
| return true; | ||
@@ -227,3 +267,3 @@ } | ||
| if (!value_extract(state, result, result_size)) { | ||
| if (!value_extract(state, result, result_size, NULL)) { | ||
| zcbor_log("uint with size %zu failed.\r\n", result_size); | ||
@@ -395,3 +435,3 @@ ZCBOR_FAIL(); | ||
| if (!value_extract(state, &result->len, sizeof(result->len))) { | ||
| if (!value_extract(state, &result->len, sizeof(result->len), NULL)) { | ||
| ZCBOR_FAIL(); | ||
@@ -404,2 +444,29 @@ } | ||
| /** | ||
| * @brief Checks if there is a potential overflow when decoding a string. | ||
| * | ||
| * This function is used to check if the payload contains the whole string. | ||
| * The payload in the state must point to the start of the string payload, the | ||
| * length having already been extracted from the header via @ref value_extract or | ||
| * @ref str_start_decode. | ||
| * | ||
| * @param state The current state of the decoding. | ||
| * @param len The decoded length of the string. | ||
| * @return true if ok (no overflow), false otherwise. | ||
| */ | ||
| static bool str_overflow_check(zcbor_state_t *state, size_t len) | ||
| { | ||
| /* Casting to size_t is safe since value_extract() checks that | ||
| * payload_end is bigger that payload. */ | ||
| if (len > (size_t)(state->payload_end - state->payload)) { | ||
| zcbor_log("error: 0x%zu > 0x%zu\r\n", | ||
| len, | ||
| (state->payload_end - state->payload)); | ||
| ERR_RESTORE(ZCBOR_ERR_NO_PAYLOAD); | ||
| } | ||
| return true; | ||
| } | ||
| static bool str_start_decode_with_overflow_check(zcbor_state_t *state, | ||
@@ -410,15 +477,6 @@ struct zcbor_string *result, zcbor_major_type_t exp_major_type) | ||
| if (!res) { | ||
| if (!res || !str_overflow_check(state, result->len)) { | ||
| ZCBOR_FAIL(); | ||
| } | ||
| /* Casting to size_t is safe since str_start_decode() checks that | ||
| * payload_end is bigger that payload. */ | ||
| if (result->len > (size_t)(state->payload_end - state->payload)) { | ||
| zcbor_log("error: 0x%zu > 0x%zu\r\n", | ||
| result->len, | ||
| (state->payload_end - state->payload)); | ||
| ERR_RESTORE(ZCBOR_ERR_NO_PAYLOAD); | ||
| } | ||
| return true; | ||
@@ -660,19 +718,8 @@ } | ||
| #ifndef ZCBOR_CANONICAL | ||
| if (ZCBOR_ADDITIONAL(*state->payload) == ZCBOR_VALUE_IS_INDEFINITE_LENGTH) { | ||
| /* Indefinite length array. */ | ||
| new_elem_count = ZCBOR_LARGE_ELEM_COUNT; | ||
| ZCBOR_ERR_IF(state->elem_count == 0, ZCBOR_ERR_LOW_ELEM_COUNT); | ||
| indefinite_length_array = true; | ||
| state->payload_bak = state->payload++; | ||
| state->elem_count--; | ||
| } else | ||
| #endif | ||
| { | ||
| if (!value_extract(state, &new_elem_count, sizeof(new_elem_count))) { | ||
| ZCBOR_FAIL(); | ||
| } | ||
| if (!value_extract(state, &new_elem_count, sizeof(new_elem_count), &indefinite_length_array)) { | ||
| ZCBOR_FAIL(); | ||
| } | ||
| if (!zcbor_new_backup(state, new_elem_count)) { | ||
| if (!zcbor_new_backup(state, indefinite_length_array | ||
| ? ZCBOR_LARGE_ELEM_COUNT : new_elem_count)) { | ||
| FAIL_RESTORE(); | ||
@@ -712,7 +759,4 @@ } | ||
| { | ||
| #ifdef ZCBOR_CANONICAL | ||
| const bool indefinite_length_array = false; | ||
| #else | ||
| const bool indefinite_length_array = state->decode_state.indefinite_length_array; | ||
| #endif | ||
| return ((!indefinite_length_array && (state->elem_count == 0)) | ||
@@ -835,2 +879,4 @@ || (indefinite_length_array | ||
| size_t extra_bytes = new_bytes - old_bytes; | ||
| ZCBOR_ERR_IF(!state->constant_state, ZCBOR_ERR_CONSTANT_STATE_MISSING); | ||
| const uint8_t *flags_end = state->constant_state->map_search_elem_state_end; | ||
@@ -930,3 +976,3 @@ | ||
| if (should_try_key(state) && try_key(state, key_result, key_decoder)) { | ||
| if (!state->constant_state->manually_process_elem) { | ||
| if (!ZCBOR_MANUALLY_PROCESS_ELEM(state)) { | ||
| ZCBOR_FAIL_IF(!zcbor_elem_processed(state)); | ||
@@ -993,3 +1039,2 @@ } | ||
| #ifndef ZCBOR_CANONICAL | ||
| if (state->decode_state.indefinite_length_array) { | ||
@@ -1002,3 +1047,2 @@ if (!array_end_expect(state)) { | ||
| } | ||
| #endif | ||
| if (!zcbor_process_backup(state, | ||
@@ -1075,9 +1119,17 @@ ZCBOR_FLAG_RESTORE | ZCBOR_FLAG_CONSUME | ZCBOR_FLAG_KEEP_PAYLOAD, | ||
| uint8_t additional = ZCBOR_ADDITIONAL(*state->payload); | ||
| /* Simple values must be 0-23 (additional is 0-23) or 24-255 (additional is 24). | ||
| * Other additional values are not considered simple values. */ | ||
| ZCBOR_ERR_IF(ZCBOR_ADDITIONAL(*state->payload) > 24, ZCBOR_ERR_WRONG_TYPE); | ||
| ZCBOR_ERR_IF(additional > ZCBOR_VALUE_IS_1_BYTE, ZCBOR_ERR_WRONG_TYPE); | ||
| if (!value_extract(state, result, sizeof(*result))) { | ||
| if (!value_extract(state, result, sizeof(*result), NULL)) { | ||
| ZCBOR_FAIL(); | ||
| } | ||
| /* Simple values less than 24 MUST be encoded in the additional information. | ||
| Simple values 24 to 31 inclusive are unused. Ref: RFC8949 sec 3.3 */ | ||
| if ((additional == ZCBOR_VALUE_IS_1_BYTE) && (*result < 32)) { | ||
| ERR_RESTORE(ZCBOR_ERR_INVALID_VALUE_ENCODING); | ||
| } | ||
| return true; | ||
@@ -1116,3 +1168,3 @@ } | ||
| (void)unused; | ||
| return zcbor_simple_expect(state, 22); | ||
| return zcbor_simple_expect(state, ZCBOR_NIL_VAL); | ||
| } | ||
@@ -1125,3 +1177,3 @@ | ||
| (void)unused; | ||
| return zcbor_simple_expect(state, 23); | ||
| return zcbor_simple_expect(state, ZCBOR_UNDEF_VAL); | ||
| } | ||
@@ -1176,3 +1228,3 @@ | ||
| if (!value_extract(state, result, sizeof(*result))) { | ||
| if (!value_extract(state, result, sizeof(*result), NULL)) { | ||
| ZCBOR_FAIL(); | ||
@@ -1248,3 +1300,3 @@ } | ||
| if (!value_extract(state, result, sizeof(*result))) { | ||
| if (!value_extract(state, result, sizeof(*result), NULL)) { | ||
| ZCBOR_FAIL(); | ||
@@ -1317,3 +1369,3 @@ } | ||
| if (!value_extract(state, result, sizeof(*result))) { | ||
| if (!value_extract(state, result, sizeof(*result), NULL)) { | ||
| ZCBOR_FAIL(); | ||
@@ -1448,10 +1500,7 @@ } | ||
| #ifdef ZCBOR_CANONICAL | ||
| const bool indefinite_length_array = false; | ||
| #else | ||
| const bool indefinite_length_array = ((additional == ZCBOR_VALUE_IS_INDEFINITE_LENGTH) | ||
| && ((major_type == ZCBOR_MAJOR_TYPE_LIST) || (major_type == ZCBOR_MAJOR_TYPE_MAP))); | ||
| #endif | ||
| bool indefinite_length_array = false; | ||
| bool *ila_ptr = ((major_type == ZCBOR_MAJOR_TYPE_MAP) | ||
| || (major_type == ZCBOR_MAJOR_TYPE_LIST)) ? &indefinite_length_array : NULL; | ||
| if (!indefinite_length_array && !value_extract(&state_copy, &value, sizeof(value))) { | ||
| if (!value_extract(&state_copy, &value, sizeof(value), ila_ptr)) { | ||
| /* Can happen because of elem_count (or payload_end) */ | ||
@@ -1464,8 +1513,4 @@ ZCBOR_FAIL(); | ||
| case ZCBOR_MAJOR_TYPE_TSTR: | ||
| /* 'value' is the length of the BSTR or TSTR. | ||
| * The subtraction is safe because value_extract() above | ||
| * checks that payload_end is greater than payload. */ | ||
| ZCBOR_ERR_IF( | ||
| value > (uint64_t)(state_copy.payload_end - state_copy.payload), | ||
| ZCBOR_ERR_NO_PAYLOAD); | ||
| /* 'value' is the length of the BSTR or TSTR. */ | ||
| ZCBOR_FAIL_IF(!str_overflow_check(state, (size_t)value)); | ||
| (state_copy.payload) += value; | ||
@@ -1479,3 +1524,2 @@ break; | ||
| if (indefinite_length_array) { | ||
| state_copy.payload++; | ||
| value = ZCBOR_LARGE_ELEM_COUNT; | ||
@@ -1511,3 +1555,3 @@ } | ||
| if (!value_extract(state, result, sizeof(*result))) { | ||
| if (!value_extract(state, result, sizeof(*result), NULL)) { | ||
| ZCBOR_FAIL(); | ||
@@ -1514,0 +1558,0 @@ } |
+10
-16
@@ -51,3 +51,5 @@ /* | ||
| *(state->payload_mut++) = (uint8_t)((major_type << 5) | (additional & 0x1F)); | ||
| *(state->payload_mut) = (uint8_t)((major_type << 5) | (additional & 0x1F)); | ||
| zcbor_trace(state, "value_encode"); | ||
| state->payload_mut++; | ||
| return true; | ||
@@ -72,5 +74,2 @@ } | ||
| } | ||
| state->payload_mut--; | ||
| zcbor_trace(state, "value_encode_len"); | ||
| state->payload_mut++; | ||
@@ -230,11 +229,2 @@ #ifdef ZCBOR_BIG_ENDIAN | ||
| 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) | ||
@@ -246,3 +236,3 @@ { | ||
| uint64_t max_len = remaining_str_len(state); | ||
| uint64_t max_len = zcbor_remaining_str_len(state); | ||
@@ -273,3 +263,3 @@ /* Encode a dummy header */ | ||
| result->value = state->payload_end - remaining_str_len(state); | ||
| result->value = state->payload + zcbor_header_len(zcbor_remaining_str_len(state)); | ||
| result->len = (size_t)payload - (size_t)result->value; | ||
@@ -463,2 +453,6 @@ | ||
| { | ||
| /* Simple values 24 to 31 inclusive are unused. Ref: RFC8949 sec 3.3 */ | ||
| if ((*input > ZCBOR_VALUE_IN_HEADER) && (*input < 32)) { | ||
| ZCBOR_ERR(ZCBOR_ERR_INVALID_VALUE_ENCODING); | ||
| } | ||
| if (!value_encode(state, ZCBOR_MAJOR_TYPE_SIMPLE, input, sizeof(*input))) { | ||
@@ -474,3 +468,3 @@ zcbor_log("Error encoding %u (0x%p)\r\n", *input, input); | ||
| { | ||
| return value_encode(state, ZCBOR_MAJOR_TYPE_SIMPLE, &input, sizeof(input)); | ||
| return zcbor_simple_encode(state, &input); | ||
| } | ||
@@ -477,0 +471,0 @@ |
| Metadata-Version: 2.1 | ||
| Name: zcbor | ||
| Version: 0.8.1 | ||
| Version: 0.9.0 | ||
| Summary: Code generation and validation using CDDL schemas | ||
@@ -99,2 +99,7 @@ Author: Nordic Semiconductor ASA | ||
| `n_flags` is used when decoding maps where the order is unknown. | ||
| It allows using the `zcbor_unordered_map_search()` function to search for elements. | ||
| See the header files for more information. | ||
| ```c | ||
@@ -119,3 +124,3 @@ /** Initialize a decoding state (could include an array of backup states). | ||
| ------------------------- | ----------- | ||
| `ZCBOR_CANONICAL` | Assume canonical encoding (AKA "deterministically encoded CBOR"). When encoding lists and maps, do not use indefinite length encoding. Enabling `ZCBOR_CANONICAL` increases code size and makes the encoding library more often use state backups. When decoding, ensure that the incoming data conforms to canonical encoding, i.e. no indefinite length encoding, and always using minimal length encoding (e.g. not using 16 bits to encode a value < 256). Note: the map ordering constraint in canonical encoding is not checked. | ||
| `ZCBOR_CANONICAL` | Assume canonical encoding (AKA "deterministically encoded CBOR", ch 4.2.1 in RFC8949). When encoding lists and maps, do not use indefinite length encoding. Enabling `ZCBOR_CANONICAL` increases code size and makes the encoding library more often use state backups. When decoding, if `enforce_canonical` is true, ensure that the incoming data conforms to canonical encoding, i.e. no indefinite length encoding, and always using minimal length encoding (e.g. not using 16 bits to encode a value < 256). Enabling `ZCBOR_CANONICAL` changes the default of `enforce_canonical` from `false` to `true` Note: the map ordering constraint in canonical encoding is not checked. | ||
| `ZCBOR_VERBOSE` | Print log messages on encoding/decoding errors (`zcbor_log()`), and also a trace message (`zcbor_trace()`) for each decoded value, and in each generated function (when using code generation). | ||
@@ -545,3 +550,5 @@ `ZCBOR_ASSERTS` | Enable asserts (`zcbor_assert()`). When they fail, the assert statements instruct the current function to return a `ZCBOR_ERR_ASSERTION` error. If `ZCBOR_VERBOSE` is enabled, a message is printed. | ||
| Header to be included in the comment at the top of | ||
| generated C files, e.g. copyright. | ||
| generated files, e.g. copyright. Can be a string or a | ||
| path to a file. If interpreted as a path to an | ||
| existing file, the file's contents will be used. | ||
@@ -548,0 +555,0 @@ ``` |
| LICENSE | ||
| README.md | ||
| __init__.py | ||
| pyproject.toml | ||
@@ -13,7 +14,19 @@ ./__init__.py | ||
| ./src/zcbor_encode.c | ||
| ./src/zcbor_print.c | ||
| ./zcbor/VERSION | ||
| ./zcbor/prelude.cddl | ||
| ./zcbor/zcbor.py | ||
| include/zcbor_common.h | ||
| include/zcbor_decode.h | ||
| include/zcbor_encode.h | ||
| include/zcbor_print.h | ||
| include/zcbor_tags.h | ||
| scripts/requirements-base.txt | ||
| src/zcbor_common.c | ||
| src/zcbor_decode.c | ||
| src/zcbor_encode.c | ||
| src/zcbor_print.c | ||
| zcbor/VERSION | ||
| zcbor/prelude.cddl | ||
| zcbor/zcbor.py | ||
| zcbor.egg-info/PKG-INFO | ||
@@ -20,0 +33,0 @@ zcbor.egg-info/SOURCES.txt |
+1
-1
@@ -1,1 +0,1 @@ | ||
| 0.8.1 | ||
| 0.9.0 |
Sorry, the diff of this file is too big to display
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
405816
3.59%25
4.17%2923
4.84%