1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZCBOR_PRINT_H__
8 #define ZCBOR_PRINT_H__
9 
10 
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14 
15 #ifndef ZCBOR_PRINT_FUNC
16 #include <stdio.h>
17 #define zcbor_do_print(...) printf(__VA_ARGS__)
18 #else
19 #define zcbor_do_print(...) ZCBOR_PRINT_FUNC(__VA_ARGS__)
20 #endif
21 
22 #ifdef ZCBOR_VERBOSE
23 #define zcbor_trace_raw(state) (zcbor_do_print("rem: %zu, cur: 0x%x, ec: 0x%zx, err: %d",\
24 	(size_t)state->payload_end - (size_t)state->payload, *state->payload, state->elem_count, \
25 	state->constant_state ? state->constant_state->error : 0))
26 #define zcbor_trace(state, appendix) do { \
27 	zcbor_trace_raw(state); \
28 	zcbor_do_print(", %s\n", appendix); \
29 } while(0)
30 #define zcbor_trace_file(state) do { \
31 	zcbor_trace_raw(state); \
32 	zcbor_do_print(", %s:%d\n", __FILE__, __LINE__); \
33 } while(0)
34 
35 #define zcbor_log_assert(expr, ...) \
36 do { \
37 	zcbor_do_print("ASSERTION \n  \"" #expr \
38 		"\"\nfailed at %s:%d with message:\n  ", \
39 		__FILE__, __LINE__); \
40 	zcbor_do_print(__VA_ARGS__);\
41 } while(0)
42 #define zcbor_log(...) zcbor_do_print(__VA_ARGS__)
43 #else
44 #define zcbor_trace(state, appendix)
45 #define zcbor_trace_file(state) ((void)state)
46 #define zcbor_log_assert(...)
47 #define zcbor_log(...)
48 #endif
49 
50 #ifdef ZCBOR_ASSERTS
51 #define zcbor_assert(expr, ...) \
52 do { \
53 	if (!(expr)) { \
54 		zcbor_log_assert(expr, __VA_ARGS__); \
55 		ZCBOR_FAIL(); \
56 	} \
57 } while(0)
58 #define zcbor_assert_state(expr, ...) \
59 do { \
60 	if (!(expr)) { \
61 		zcbor_log_assert(expr, __VA_ARGS__); \
62 		ZCBOR_ERR(ZCBOR_ERR_ASSERTION); \
63 	} \
64 } while(0)
65 #else
66 #define zcbor_assert(expr, ...)
67 #define zcbor_assert_state(expr, ...)
68 #endif
69 
70 __attribute__((used))
zcbor_print_compare_lines(const uint8_t * str1,const uint8_t * str2,size_t size)71 static void zcbor_print_compare_lines(const uint8_t *str1, const uint8_t *str2, size_t size)
72 {
73 	for (size_t j = 0; j < size; j++) {
74 		zcbor_do_print("%x ", str1[j]);
75 	}
76 	zcbor_do_print("\r\n");
77 	for (size_t j = 0; j < size; j++) {
78 		zcbor_do_print("%x ", str2[j]);
79 	}
80 	zcbor_do_print("\r\n");
81 	for (size_t j = 0; j < size; j++) {
82 		zcbor_do_print("%x ", str1[j] != str2[j]);
83 	}
84 	zcbor_do_print("\r\n");
85 	zcbor_do_print("\r\n");
86 }
87 
88 __attribute__((used))
zcbor_print_compare_strings(const uint8_t * str1,const uint8_t * str2,size_t size)89 static void zcbor_print_compare_strings(const uint8_t *str1, const uint8_t *str2, size_t size)
90 {
91 	const size_t col_width = 16;
92 
93 	for (size_t i = 0; i <= size / col_width; i++) {
94 		zcbor_do_print("line %zu (char %zu)\r\n", i, i*col_width);
95 		zcbor_print_compare_lines(&str1[i*col_width], &str2[i*col_width],
96 			MIN(col_width, (size - i*col_width)));
97 	}
98 	zcbor_do_print("\r\n");
99 }
100 
101 __attribute__((used))
zcbor_print_compare_strings_diff(const uint8_t * str1,const uint8_t * str2,size_t size)102 static void zcbor_print_compare_strings_diff(const uint8_t *str1, const uint8_t *str2, size_t size)
103 {
104 	const size_t col_width = 16;
105 	bool printed = false;
106 
107 	for (size_t i = 0; i <= size / col_width; i++) {
108 		if (memcmp(&str1[i*col_width], &str2[i*col_width], MIN(col_width, (size - i*col_width))) != 0) {
109 			zcbor_do_print("line %zu (char %zu)\r\n", i, i*col_width);
110 			zcbor_print_compare_lines(&str1[i*col_width], &str2[i*col_width],
111 				MIN(col_width, (size - i*col_width)));
112 			printed = true;
113 		}
114 	}
115 	if (printed) {
116 		zcbor_do_print("\r\n");
117 	}
118 }
119 
120 __attribute__((used))
zcbor_error_str(int error)121 static const char *zcbor_error_str(int error)
122 {
123 	#define ZCBOR_ERR_CASE(err) case err: \
124 		return #err; /* The literal is static per C99 6.4.5 paragraph 5. */\
125 
126 	switch(error) {
127 		ZCBOR_ERR_CASE(ZCBOR_SUCCESS)
128 		ZCBOR_ERR_CASE(ZCBOR_ERR_NO_BACKUP_MEM)
129 		ZCBOR_ERR_CASE(ZCBOR_ERR_NO_BACKUP_ACTIVE)
130 		ZCBOR_ERR_CASE(ZCBOR_ERR_LOW_ELEM_COUNT)
131 		ZCBOR_ERR_CASE(ZCBOR_ERR_HIGH_ELEM_COUNT)
132 		ZCBOR_ERR_CASE(ZCBOR_ERR_INT_SIZE)
133 		ZCBOR_ERR_CASE(ZCBOR_ERR_FLOAT_SIZE)
134 		ZCBOR_ERR_CASE(ZCBOR_ERR_ADDITIONAL_INVAL)
135 		ZCBOR_ERR_CASE(ZCBOR_ERR_NO_PAYLOAD)
136 		ZCBOR_ERR_CASE(ZCBOR_ERR_PAYLOAD_NOT_CONSUMED)
137 		ZCBOR_ERR_CASE(ZCBOR_ERR_WRONG_TYPE)
138 		ZCBOR_ERR_CASE(ZCBOR_ERR_WRONG_VALUE)
139 		ZCBOR_ERR_CASE(ZCBOR_ERR_WRONG_RANGE)
140 		ZCBOR_ERR_CASE(ZCBOR_ERR_ITERATIONS)
141 		ZCBOR_ERR_CASE(ZCBOR_ERR_ASSERTION)
142 		ZCBOR_ERR_CASE(ZCBOR_ERR_PAYLOAD_OUTDATED)
143 		ZCBOR_ERR_CASE(ZCBOR_ERR_ELEM_NOT_FOUND)
144 		ZCBOR_ERR_CASE(ZCBOR_ERR_MAP_MISALIGNED)
145 		ZCBOR_ERR_CASE(ZCBOR_ERR_ELEMS_NOT_PROCESSED)
146 		ZCBOR_ERR_CASE(ZCBOR_ERR_NOT_AT_END)
147 		ZCBOR_ERR_CASE(ZCBOR_ERR_MAP_FLAGS_NOT_AVAILABLE)
148 		ZCBOR_ERR_CASE(ZCBOR_ERR_INVALID_VALUE_ENCODING)
149 	}
150 	#undef ZCBOR_ERR_CASE
151 
152 	return "ZCBOR_ERR_UNKNOWN";
153 }
154 
155 __attribute__((used))
zcbor_print_error(int error)156 static void zcbor_print_error(int error)
157 {
158 	zcbor_do_print("%s\r\n", zcbor_error_str(error));
159 }
160 
161 #ifdef __cplusplus
162 }
163 #endif
164 
165 #endif /* ZCBOR_PRINT_H__ */
166