1 /*
2 * Copyright (c) 2014-2019 Pavel Kalvoda <me@pavelkalvoda.com>
3 *
4 * libcbor is free software; you can redistribute it and/or modify
5 * it under the terms of the MIT license. See LICENSE for details.
6 */
7
8 #include "encoding.h"
9 #include "internal/encoders.h"
10
cbor_encode_uint8(uint8_t value,unsigned char * buffer,size_t buffer_size)11 size_t cbor_encode_uint8(uint8_t value, unsigned char *buffer,
12 size_t buffer_size) {
13 return _cbor_encode_uint8(value, buffer, buffer_size, 0x00);
14 }
15
cbor_encode_uint16(uint16_t value,unsigned char * buffer,size_t buffer_size)16 size_t cbor_encode_uint16(uint16_t value, unsigned char *buffer,
17 size_t buffer_size) {
18 return _cbor_encode_uint16(value, buffer, buffer_size, 0x00);
19 }
20
cbor_encode_uint32(uint32_t value,unsigned char * buffer,size_t buffer_size)21 size_t cbor_encode_uint32(uint32_t value, unsigned char *buffer,
22 size_t buffer_size) {
23 return _cbor_encode_uint32(value, buffer, buffer_size, 0x00);
24 }
25
cbor_encode_uint64(uint64_t value,unsigned char * buffer,size_t buffer_size)26 size_t cbor_encode_uint64(uint64_t value, unsigned char *buffer,
27 size_t buffer_size) {
28 return _cbor_encode_uint64(value, buffer, buffer_size, 0x00);
29 }
30
cbor_encode_uint(uint64_t value,unsigned char * buffer,size_t buffer_size)31 size_t cbor_encode_uint(uint64_t value, unsigned char *buffer,
32 size_t buffer_size) {
33 return _cbor_encode_uint(value, buffer, buffer_size, 0x00);
34 }
35
cbor_encode_negint8(uint8_t value,unsigned char * buffer,size_t buffer_size)36 size_t cbor_encode_negint8(uint8_t value, unsigned char *buffer,
37 size_t buffer_size) {
38 return _cbor_encode_uint8(value, buffer, buffer_size, 0x20);
39 }
40
cbor_encode_negint16(uint16_t value,unsigned char * buffer,size_t buffer_size)41 size_t cbor_encode_negint16(uint16_t value, unsigned char *buffer,
42 size_t buffer_size) {
43 return _cbor_encode_uint16(value, buffer, buffer_size, 0x20);
44 }
45
cbor_encode_negint32(uint32_t value,unsigned char * buffer,size_t buffer_size)46 size_t cbor_encode_negint32(uint32_t value, unsigned char *buffer,
47 size_t buffer_size) {
48 return _cbor_encode_uint32(value, buffer, buffer_size, 0x20);
49 }
50
cbor_encode_negint64(uint64_t value,unsigned char * buffer,size_t buffer_size)51 size_t cbor_encode_negint64(uint64_t value, unsigned char *buffer,
52 size_t buffer_size) {
53 return _cbor_encode_uint64(value, buffer, buffer_size, 0x20);
54 }
55
cbor_encode_negint(uint64_t value,unsigned char * buffer,size_t buffer_size)56 size_t cbor_encode_negint(uint64_t value, unsigned char *buffer,
57 size_t buffer_size) {
58 return _cbor_encode_uint(value, buffer, buffer_size, 0x20);
59 }
60
cbor_encode_bytestring_start(size_t length,unsigned char * buffer,size_t buffer_size)61 size_t cbor_encode_bytestring_start(size_t length, unsigned char *buffer,
62 size_t buffer_size) {
63 return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0x40);
64 }
65
_cbor_encode_byte(uint8_t value,unsigned char * buffer,size_t buffer_size)66 size_t _cbor_encode_byte(uint8_t value, unsigned char *buffer,
67 size_t buffer_size) {
68 if (buffer_size >= 1) {
69 buffer[0] = value;
70 return 1;
71 } else
72 return 0;
73 }
74
cbor_encode_indef_bytestring_start(unsigned char * buffer,size_t buffer_size)75 size_t cbor_encode_indef_bytestring_start(unsigned char *buffer,
76 size_t buffer_size) {
77 return _cbor_encode_byte(0x5F, buffer, buffer_size);
78 }
79
cbor_encode_string_start(size_t length,unsigned char * buffer,size_t buffer_size)80 size_t cbor_encode_string_start(size_t length, unsigned char *buffer,
81 size_t buffer_size) {
82 return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0x60);
83 }
84
cbor_encode_indef_string_start(unsigned char * buffer,size_t buffer_size)85 size_t cbor_encode_indef_string_start(unsigned char *buffer,
86 size_t buffer_size) {
87 return _cbor_encode_byte(0x7F, buffer, buffer_size);
88 }
89
cbor_encode_array_start(size_t length,unsigned char * buffer,size_t buffer_size)90 size_t cbor_encode_array_start(size_t length, unsigned char *buffer,
91 size_t buffer_size) {
92 return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0x80);
93 }
94
cbor_encode_indef_array_start(unsigned char * buffer,size_t buffer_size)95 size_t cbor_encode_indef_array_start(unsigned char *buffer,
96 size_t buffer_size) {
97 return _cbor_encode_byte(0x9F, buffer, buffer_size);
98 }
99
cbor_encode_map_start(size_t length,unsigned char * buffer,size_t buffer_size)100 size_t cbor_encode_map_start(size_t length, unsigned char *buffer,
101 size_t buffer_size) {
102 return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0xA0);
103 }
104
cbor_encode_indef_map_start(unsigned char * buffer,size_t buffer_size)105 size_t cbor_encode_indef_map_start(unsigned char *buffer, size_t buffer_size) {
106 return _cbor_encode_byte(0xBF, buffer, buffer_size);
107 }
108
cbor_encode_tag(uint64_t value,unsigned char * buffer,size_t buffer_size)109 size_t cbor_encode_tag(uint64_t value, unsigned char *buffer,
110 size_t buffer_size) {
111 return _cbor_encode_uint(value, buffer, buffer_size, 0xC0);
112 }
113
cbor_encode_bool(bool value,unsigned char * buffer,size_t buffer_size)114 size_t cbor_encode_bool(bool value, unsigned char *buffer, size_t buffer_size) {
115 return value ? _cbor_encode_byte(0xF5, buffer, buffer_size)
116 : _cbor_encode_byte(0xF4, buffer, buffer_size);
117 }
118
cbor_encode_null(unsigned char * buffer,size_t buffer_size)119 size_t cbor_encode_null(unsigned char *buffer, size_t buffer_size) {
120 return _cbor_encode_byte(0xF6, buffer, buffer_size);
121 }
122
cbor_encode_undef(unsigned char * buffer,size_t buffer_size)123 size_t cbor_encode_undef(unsigned char *buffer, size_t buffer_size) {
124 return _cbor_encode_byte(0xF7, buffer, buffer_size);
125 }
126
cbor_encode_half(float value,unsigned char * buffer,size_t buffer_size)127 size_t cbor_encode_half(float value, unsigned char *buffer,
128 size_t buffer_size) {
129 /* Assuming value is normalized */
130 uint32_t val = ((union _cbor_float_helper){.as_float = value}).as_uint;
131 uint16_t res;
132 uint8_t exp = (uint8_t)((val & 0x7F800000) >>
133 23); /* 0b0111_1111_1000_0000_0000_0000_0000_0000 */
134 uint32_t mant =
135 val & 0x7FFFFF; /* 0b0000_0000_0111_1111_1111_1111_1111_1111 */
136 if (exp == 0xFF) { /* Infinity or NaNs */
137 if (value != value) {
138 res = (uint16_t)0x00e700; /* Not IEEE semantics - required by CBOR
139 [s. 3.9] */
140 } else {
141 res =
142 (uint16_t)((val & 0x80000000) >> 16 | 0x7C00 | (mant ? 1 : 0) << 15);
143 }
144 } else if (exp == 0x00) { /* Zeroes or subnorms */
145 res = (uint16_t)((val & 0x80000000) >> 16 | mant >> 13);
146 } else { /* Normal numbers */
147 int8_t logical_exp = (int8_t)(exp - 127);
148 assert(logical_exp == exp - 127);
149
150 // Now we know that 2^exp <= 0 logically
151 if (logical_exp < -24) {
152 /* No unambiguous representation exists, this float is not a half float
153 and is too small to be represented using a half, round off to zero.
154 Consistent with the reference implementation. */
155 res = 0;
156 } else if (logical_exp < -14) {
157 /* Offset the remaining decimal places by shifting the significand, the
158 value is lost. This is an implementation decision that works around the
159 absence of standard half-float in the language. */
160 res = (uint16_t)(val & 0x80000000) >> 16 |
161 (uint16_t)(1 << (24 + logical_exp));
162 } else {
163 res = (uint16_t)((val & 0x80000000) >> 16 |
164 ((((uint8_t)logical_exp) + 15) << 10) |
165 (uint16_t)(mant >> 13));
166 }
167 }
168 return _cbor_encode_uint16(res, buffer, buffer_size, 0xE0);
169 }
170
cbor_encode_single(float value,unsigned char * buffer,size_t buffer_size)171 size_t cbor_encode_single(float value, unsigned char *buffer,
172 size_t buffer_size) {
173 return _cbor_encode_uint32(
174 ((union _cbor_float_helper){.as_float = value}).as_uint, buffer,
175 buffer_size, 0xE0);
176 }
177
cbor_encode_double(double value,unsigned char * buffer,size_t buffer_size)178 size_t cbor_encode_double(double value, unsigned char *buffer,
179 size_t buffer_size) {
180 return _cbor_encode_uint64(
181 ((union _cbor_double_helper){.as_double = value}).as_uint, buffer,
182 buffer_size, 0xE0);
183 }
184
cbor_encode_break(unsigned char * buffer,size_t buffer_size)185 size_t cbor_encode_break(unsigned char *buffer, size_t buffer_size) {
186 return _cbor_encode_byte(0xFF, buffer, buffer_size);
187 }
188
cbor_encode_ctrl(uint8_t value,unsigned char * buffer,size_t buffer_size)189 size_t cbor_encode_ctrl(uint8_t value, unsigned char *buffer,
190 size_t buffer_size) {
191 return _cbor_encode_uint8(value, buffer, buffer_size, 0xE0);
192 }
193