libcbor 0.12.0
libcbor is a C library for parsing and generating CBOR, the general-purpose schema-less binary data format.
Loading...
Searching...
No Matches
encoding.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014-2020 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
10#include <math.h>
11
12#include "internal/encoders.h"
13
14size_t cbor_encode_uint8(uint8_t value, unsigned char* buffer,
15 size_t buffer_size) {
16 return _cbor_encode_uint8(value, buffer, buffer_size, 0x00);
17}
18
19size_t cbor_encode_uint16(uint16_t value, unsigned char* buffer,
20 size_t buffer_size) {
21 return _cbor_encode_uint16(value, buffer, buffer_size, 0x00);
22}
23
24size_t cbor_encode_uint32(uint32_t value, unsigned char* buffer,
25 size_t buffer_size) {
26 return _cbor_encode_uint32(value, buffer, buffer_size, 0x00);
27}
28
29size_t cbor_encode_uint64(uint64_t value, unsigned char* buffer,
30 size_t buffer_size) {
31 return _cbor_encode_uint64(value, buffer, buffer_size, 0x00);
32}
33
34size_t cbor_encode_uint(uint64_t value, unsigned char* buffer,
35 size_t buffer_size) {
36 return _cbor_encode_uint(value, buffer, buffer_size, 0x00);
37}
38
39size_t cbor_encode_negint8(uint8_t value, unsigned char* buffer,
40 size_t buffer_size) {
41 return _cbor_encode_uint8(value, buffer, buffer_size, 0x20);
42}
43
44size_t cbor_encode_negint16(uint16_t value, unsigned char* buffer,
45 size_t buffer_size) {
46 return _cbor_encode_uint16(value, buffer, buffer_size, 0x20);
47}
48
49size_t cbor_encode_negint32(uint32_t value, unsigned char* buffer,
50 size_t buffer_size) {
51 return _cbor_encode_uint32(value, buffer, buffer_size, 0x20);
52}
53
54size_t cbor_encode_negint64(uint64_t value, unsigned char* buffer,
55 size_t buffer_size) {
56 return _cbor_encode_uint64(value, buffer, buffer_size, 0x20);
57}
58
59size_t cbor_encode_negint(uint64_t value, unsigned char* buffer,
60 size_t buffer_size) {
61 return _cbor_encode_uint(value, buffer, buffer_size, 0x20);
62}
63
64size_t cbor_encode_bytestring_start(size_t length, unsigned char* buffer,
65 size_t buffer_size) {
66 return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0x40);
67}
68
69size_t _cbor_encode_byte(uint8_t value, unsigned char* buffer,
70 size_t buffer_size) {
71 if (buffer_size >= 1) {
72 buffer[0] = value;
73 return 1;
74 } else
75 return 0;
76}
77
78size_t cbor_encode_indef_bytestring_start(unsigned char* buffer,
79 size_t buffer_size) {
80 return _cbor_encode_byte(0x5F, buffer, buffer_size);
81}
82
83size_t cbor_encode_string_start(size_t length, unsigned char* buffer,
84 size_t buffer_size) {
85 return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0x60);
86}
87
88size_t cbor_encode_indef_string_start(unsigned char* buffer,
89 size_t buffer_size) {
90 return _cbor_encode_byte(0x7F, buffer, buffer_size);
91}
92
93size_t cbor_encode_array_start(size_t length, unsigned char* buffer,
94 size_t buffer_size) {
95 return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0x80);
96}
97
98size_t cbor_encode_indef_array_start(unsigned char* buffer,
99 size_t buffer_size) {
100 return _cbor_encode_byte(0x9F, buffer, buffer_size);
101}
102
103size_t cbor_encode_map_start(size_t length, unsigned char* buffer,
104 size_t buffer_size) {
105 return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0xA0);
106}
107
108size_t cbor_encode_indef_map_start(unsigned char* buffer, size_t buffer_size) {
109 return _cbor_encode_byte(0xBF, buffer, buffer_size);
110}
111
112size_t cbor_encode_tag(uint64_t value, unsigned char* buffer,
113 size_t buffer_size) {
114 return _cbor_encode_uint(value, buffer, buffer_size, 0xC0);
115}
116
117size_t cbor_encode_bool(bool value, unsigned char* buffer, size_t buffer_size) {
118 return value ? _cbor_encode_byte(0xF5, buffer, buffer_size)
119 : _cbor_encode_byte(0xF4, buffer, buffer_size);
120}
121
122size_t cbor_encode_null(unsigned char* buffer, size_t buffer_size) {
123 return _cbor_encode_byte(0xF6, buffer, buffer_size);
124}
125
126size_t cbor_encode_undef(unsigned char* buffer, size_t buffer_size) {
127 return _cbor_encode_byte(0xF7, buffer, buffer_size);
128}
129
130size_t cbor_encode_half(float value, unsigned char* buffer,
131 size_t buffer_size) {
132 // TODO: Broken on systems that do not use IEEE 754
133 /* Assuming value is normalized */
134 uint32_t val = ((union _cbor_float_helper){.as_float = value}).as_uint;
135 uint16_t res;
136 uint8_t exp = (uint8_t)((val & 0x7F800000u) >>
137 23u); /* 0b0111_1111_1000_0000_0000_0000_0000_0000 */
138 uint32_t mant =
139 val & 0x7FFFFFu; /* 0b0000_0000_0111_1111_1111_1111_1111_1111 */
140 if (exp == 0xFF) { /* Infinity or NaNs */
141 if (isnan(value)) {
142 // Note: Values of signaling NaNs are discarded. See `cbor_encode_single`.
143 res = (uint16_t)0x007e00;
144 } else {
145 // If the mantissa is non-zero, we have a NaN, but those are handled
146 // above. See
147 // https://en.wikipedia.org/wiki/Half-precision_floating-point_format
148 CBOR_ASSERT(mant == 0u);
149 res = (uint16_t)((val & 0x80000000u) >> 16u | 0x7C00u);
150 }
151 } else if (exp == 0x00) { /* Zeroes or subnorms */
152 res = (uint16_t)((val & 0x80000000u) >> 16u | mant >> 13u);
153 } else { /* Normal numbers */
154 int8_t logical_exp = (int8_t)(exp - 127);
155 CBOR_ASSERT(logical_exp == exp - 127);
156
157 // Now we know that 2^exp <= 0 logically
158 if (logical_exp < -24) {
159 /* No unambiguous representation exists, this float is not a half float
160 and is too small to be represented using a half, round off to zero.
161 Consistent with the reference implementation. */
162 res = 0;
163 } else if (logical_exp < -14) {
164 /* Offset the remaining decimal places by shifting the significand, the
165 value is lost. This is an implementation decision that works around the
166 absence of standard half-float in the language. */
167 res = (uint16_t)((val & 0x80000000u) >> 16u) | // Extract sign bit
168 ((uint16_t)(1u << (24u + logical_exp)) +
169 (uint16_t)(((mant >> (-logical_exp - 2)) + 1) >>
170 1)); // Round half away from zero for simplicity
171 } else {
172 res = (uint16_t)((val & 0x80000000u) >> 16u |
173 ((((uint8_t)logical_exp) + 15u) << 10u) |
174 (uint16_t)(mant >> 13u));
175 }
176 }
177 return _cbor_encode_uint16(res, buffer, buffer_size, 0xE0);
178}
179
180size_t cbor_encode_single(float value, unsigned char* buffer,
181 size_t buffer_size) {
182 // Note: Values of signaling NaNs are discarded. There is no standard
183 // way to extract it without assumptions about the internal float
184 // representation.
185 if (isnan(value)) {
186 return _cbor_encode_uint32(0x7FC0 << 16, buffer, buffer_size, 0xE0);
187 }
188 // TODO: Broken on systems that do not use IEEE 754
189 return _cbor_encode_uint32(
190 ((union _cbor_float_helper){.as_float = value}).as_uint, buffer,
191 buffer_size, 0xE0);
192}
193
194size_t cbor_encode_double(double value, unsigned char* buffer,
195 size_t buffer_size) {
196 // Note: Values of signaling NaNs are discarded. See `cbor_encode_single`.
197 if (isnan(value)) {
198 return _cbor_encode_uint64((uint64_t)0x7FF8 << 48, buffer, buffer_size,
199 0xE0);
200 }
201 // TODO: Broken on systems that do not use IEEE 754
202 return _cbor_encode_uint64(
203 ((union _cbor_double_helper){.as_double = value}).as_uint, buffer,
204 buffer_size, 0xE0);
205}
206
207size_t cbor_encode_break(unsigned char* buffer, size_t buffer_size) {
208 return _cbor_encode_byte(0xFF, buffer, buffer_size);
209}
210
211size_t cbor_encode_ctrl(uint8_t value, unsigned char* buffer,
212 size_t buffer_size) {
213 return _cbor_encode_uint8(value, buffer, buffer_size, 0xE0);
214}
#define CBOR_ASSERT(e)
Definition common.h:73
size_t _cbor_encode_uint16(uint16_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
Definition encoders.c:29
size_t _cbor_encode_uint8(uint8_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
Definition encoders.c:12
size_t _cbor_encode_uint32(uint32_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
Definition encoders.c:46
size_t _cbor_encode_uint64(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
Definition encoders.c:65
size_t _cbor_encode_uint(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
Definition encoders.c:88
size_t cbor_encode_negint16(uint16_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:44
size_t cbor_encode_ctrl(uint8_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:211
size_t cbor_encode_map_start(size_t length, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:103
size_t cbor_encode_tag(uint64_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:112
size_t _cbor_encode_byte(uint8_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:69
size_t cbor_encode_negint64(uint64_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:54
size_t cbor_encode_indef_map_start(unsigned char *buffer, size_t buffer_size)
Definition encoding.c:108
size_t cbor_encode_negint(uint64_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:59
size_t cbor_encode_array_start(size_t length, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:93
size_t cbor_encode_uint8(uint8_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:14
size_t cbor_encode_half(float value, unsigned char *buffer, size_t buffer_size)
Encodes a half-precision float.
Definition encoding.c:130
size_t cbor_encode_indef_bytestring_start(unsigned char *buffer, size_t buffer_size)
Definition encoding.c:78
size_t cbor_encode_undef(unsigned char *buffer, size_t buffer_size)
Definition encoding.c:126
size_t cbor_encode_double(double value, unsigned char *buffer, size_t buffer_size)
Encodes a double precision float.
Definition encoding.c:194
size_t cbor_encode_indef_array_start(unsigned char *buffer, size_t buffer_size)
Definition encoding.c:98
size_t cbor_encode_uint16(uint16_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:19
size_t cbor_encode_uint64(uint64_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:29
size_t cbor_encode_uint(uint64_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:34
size_t cbor_encode_negint32(uint32_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:49
size_t cbor_encode_string_start(size_t length, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:83
size_t cbor_encode_uint32(uint32_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:24
size_t cbor_encode_negint8(uint8_t value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:39
size_t cbor_encode_bytestring_start(size_t length, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:64
size_t cbor_encode_null(unsigned char *buffer, size_t buffer_size)
Definition encoding.c:122
size_t cbor_encode_break(unsigned char *buffer, size_t buffer_size)
Definition encoding.c:207
size_t cbor_encode_single(float value, unsigned char *buffer, size_t buffer_size)
Encodes a single precision float.
Definition encoding.c:180
size_t cbor_encode_indef_string_start(unsigned char *buffer, size_t buffer_size)
Definition encoding.c:88
size_t cbor_encode_bool(bool value, unsigned char *buffer, size_t buffer_size)
Definition encoding.c:117
Raw memory casts helper.
Definition data.h:153
Raw memory casts helper.
Definition data.h:147