blob: 18a9738103873e95f0e35e0dfe638b1f30acf525 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundblade240ca822024-01-16 11:11:00 -07003 Copyright (c) 2018-2024, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07005 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08006
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07007Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors, nor the name "Laurence Lundblade" may be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080020
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070021THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080032 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070033
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080035#include "qcbor/qcbor_encode.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070036#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070038
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080039/**
40 * @file qcbor_encode.c
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080041 *
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080042 * The entire implementation of the QCBOR encoder.
43 */
44
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070046/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080047 * == Nesting Tracking ==
48 *
49 * The following functions and data type QCBORTrackNesting implement
50 * the nesting management for encoding.
51 *
52 * CBOR's two nesting types, arrays and maps, are tracked here. There
53 * is a limit of QCBOR_MAX_ARRAY_NESTING to the number of arrays and
54 * maps that can be nested in one encoding so the encoding context
55 * stays small enough to fit on the stack.
56 *
57 * When an array/map is opened, pCurrentNesting points to the element
58 * in pArrays that records the type, start position and accumulates a
59 * count of the number of items added. When closed the start position
60 * is used to go back and fill in the type and number of items in the
61 * array/map.
62 *
63 * Encoded output can be a CBOR Sequence (RFC 8742) in which case
64 * there is no top-level array or map. It starts out with a string,
65 * integer or other non-aggregate type. It may have an array or map
66 * other than at the start, in which case that nesting is tracked
67 * here.
68 *
69 * QCBOR has a special feature to allow constructing byte string
70 * wrapped CBOR directly into the output buffer, so no extra buffer is
71 * needed for byte string wrapping. This is implemented as nesting
72 * with the type CBOR_MAJOR_TYPE_BYTE_STRING and is tracked here. Byte
73 * string wrapped CBOR is used by COSE for data that is to be hashed.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070074 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -070075static void
Laurence Lundblade274ddef2022-05-17 09:12:23 -070076Nesting_Init(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070077{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080078 /* Assumes pNesting has been zeroed. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070079 pNesting->pCurrentNesting = &pNesting->pArrays[0];
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080080 /* Implied CBOR array at the top nesting level. This is never
81 * returned, but makes the item count work correctly.
82 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070083 pNesting->pCurrentNesting->uMajorType = CBOR_MAJOR_TYPE_ARRAY;
84}
85
Laurence Lundblade8e36f812024-01-26 10:59:29 -070086static uint8_t
Laurence Lundblade274ddef2022-05-17 09:12:23 -070087Nesting_Increase(QCBORTrackNesting *pNesting,
Laurence Lundblade8e36f812024-01-26 10:59:29 -070088 const uint8_t uMajorType,
89 const uint32_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070090{
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070091 if(pNesting->pCurrentNesting == &pNesting->pArrays[QCBOR_MAX_ARRAY_NESTING]) {
Laurence Lundblade29497c02020-07-11 15:44:03 -070092 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070093 } else {
94 pNesting->pCurrentNesting++;
95 pNesting->pCurrentNesting->uCount = 0;
96 pNesting->pCurrentNesting->uStart = uPos;
97 pNesting->pCurrentNesting->uMajorType = uMajorType;
Laurence Lundblade29497c02020-07-11 15:44:03 -070098 return QCBOR_SUCCESS;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070099 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100}
101
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700102static void
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700103Nesting_Decrease(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700104{
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700105 if(pNesting->pCurrentNesting > &pNesting->pArrays[0]) {
106 pNesting->pCurrentNesting--;
107 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700108}
109
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700110static uint8_t
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700111Nesting_Increment(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700112{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800113#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -0800114 if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700115 return QCBOR_ERR_ARRAY_TOO_LONG;
116 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800117#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800118
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700119 pNesting->pCurrentNesting->uCount++;
Laurence Lundblade2c40ab82018-12-30 14:20:29 -0800120
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700121 return QCBOR_SUCCESS;
122}
123
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700124static void
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700125Nesting_Decrement(QCBORTrackNesting *pNesting)
Laurence Lundblade8d3b8552021-06-10 11:11:54 -0700126{
127 /* No error check for going below 0 here needed because this
128 * is only used by QCBOREncode_CancelBstrWrap() and it checks
129 * the nesting level before calling this. */
130 pNesting->pCurrentNesting->uCount--;
131}
132
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700133static uint16_t
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700134Nesting_GetCount(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700135{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800136 /* The nesting count recorded is always the actual number of
137 * individual data items in the array or map. For arrays CBOR uses
138 * the actual item count. For maps, CBOR uses the number of pairs.
139 * This function returns the number needed for the CBOR encoding,
140 * so it divides the number of items by two for maps to get the
141 * number of pairs.
142 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800143 if(pNesting->pCurrentNesting->uMajorType == CBOR_MAJOR_TYPE_MAP) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800144 /* Cast back to uint16_t after integer promotion from bit shift */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800145 return (uint16_t)(pNesting->pCurrentNesting->uCount >> 1);
146 } else {
147 return pNesting->pCurrentNesting->uCount;
148 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700149}
150
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700151static uint32_t
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700152Nesting_GetStartPos(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153{
154 return pNesting->pCurrentNesting->uStart;
155}
156
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800157#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700158static uint8_t
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700159Nesting_GetMajorType(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700160{
161 return pNesting->pCurrentNesting->uMajorType;
162}
163
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700164static bool
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700165Nesting_IsInNest(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700166{
Laurence Lundbladeee851742020-01-08 08:37:05 -0800167 return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? false : true;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700168}
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800169#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700170
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700171
172
173
174/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800175 * == Major CBOR Types ==
176 *
177 * Encoding of the major CBOR types is by these functions:
178 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800179 * CBOR Major Type Public Function
180 * 0 QCBOREncode_AddUInt64()
181 * 0, 1 QCBOREncode_AddUInt64(), QCBOREncode_AddInt64()
182 * 2, 3 QCBOREncode_AddBuffer()
183 * 4, 5 QCBOREncode_OpenMapOrArray(), QCBOREncode_CloseMapOrArray(),
184 * QCBOREncode_OpenMapOrArrayIndefiniteLength(),
185 * QCBOREncode_CloseMapOrArrayIndefiniteLength()
186 * 6 QCBOREncode_AddTag()
187 * 7 QCBOREncode_AddDouble(), QCBOREncode_AddFloat(),
188 * QCBOREncode_AddDoubleNoPreferred(),
189 * QCBOREncode_AddFloatNoPreferred(), QCBOREncode_AddType7()
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800190 *
191 * Additionally, encoding of decimal fractions and bigfloats is by
192 * QCBOREncode_AddExponentAndMantissa() and byte strings that wrap
193 * encoded CBOR are handled by QCBOREncode_OpenMapOrArray() and
194 * QCBOREncode_CloseBstrWrap2().
195 *
196 *
197 * == Error Tracking Plan ==
198 *
199 * Errors are tracked internally and not returned until
200 * QCBOREncode_Finish() or QCBOREncode_GetErrorState() is called. The
201 * CBOR errors are in me->uError. UsefulOutBuf also tracks whether
202 * the buffer is full or not in its context. Once either of these
203 * errors is set they are never cleared. Only QCBOREncode_Init()
204 * resets them. Or said another way, they must never be cleared or
205 * we'll tell the caller all is good when it is not.
206 *
207 * Only one error code is reported by QCBOREncode_Finish() even if
208 * there are multiple errors. The last one set wins. The caller might
209 * have to fix one error to reveal the next one they have to fix.
210 * This is OK.
211 *
212 * The buffer full error tracked by UsefulBuf is only pulled out of
213 * UsefulBuf in QCBOREncode_Finish() so it is the one that usually
214 * wins. UsefulBuf will never go off the end of the buffer even if it
215 * is called again and again when full.
216 *
217 * QCBOR_DISABLE_ENCODE_USAGE_GUARDS disables about half of the error
218 * checks here to reduce code size by about 150 bytes leaving only the
219 * checks for size to avoid buffer overflow. If the calling code is
220 * completely correct, checks are completely unnecessary. For
221 * example, there is no need to check that all the opens are matched
222 * by a close.
223 *
224 * QCBOR_DISABLE_ENCODE_USAGE_GUARDS also disables the check for more
225 * than QCBOR_MAX_ITEMS_IN_ARRAY in an array. Since
226 * QCBOR_MAX_ITEMS_IN_ARRAY is very large (65,535) it is very unlikely
227 * to be reached. If it is reached, the count will wrap around to zero
228 * and CBOR that is not well formed will be produced, but there will
229 * be no buffers overrun and new security issues in the code.
230 *
231 * The 8 errors returned here fall into three categories:
232 *
233 * Sizes
234 * QCBOR_ERR_BUFFER_TOO_LARGE -- Encoded output exceeded UINT32_MAX
235 * QCBOR_ERR_BUFFER_TOO_SMALL -- Output buffer too small
236 * QCBOR_ERR_ARRAY_NESTING_TOO_DEEP -- Nesting > QCBOR_MAX_ARRAY_NESTING1
237 * QCBOR_ERR_ARRAY_TOO_LONG -- Too many items added to an array/map [1]
238 *
239 * Nesting constructed incorrectly
240 * QCBOR_ERR_TOO_MANY_CLOSES -- More close calls than opens [1]
241 * QCBOR_ERR_CLOSE_MISMATCH -- Type of close does not match open [1]
242 * QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes [1]
243 *
244 * Would generate not-well-formed CBOR
245 * QCBOR_ERR_ENCODE_UNSUPPORTED -- Simple type between 24 and 31 [1]
246 *
247 * [1] indicated disabled by QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700248 */
249
Laurence Lundbladeff8106f2024-02-05 20:02:30 -0700250
251/* Forward declaration for reference in QCBOREncode_Init() */
252static void
253QCBOREncode_Private_CloseMapUnsorted(QCBOREncodeContext *pMe);
254
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700255
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700256/*
Laurence Lundbladeff8106f2024-02-05 20:02:30 -0700257 * Public function for initialization. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700258 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700259void
260QCBOREncode_Init(QCBOREncodeContext *pMe, UsefulBuf Storage)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700261{
Laurence Lundblade240ca822024-01-16 11:11:00 -0700262 memset(pMe, 0, sizeof(QCBOREncodeContext));
263 UsefulOutBuf_Init(&(pMe->OutBuf), Storage);
264 Nesting_Init(&(pMe->nesting));
Laurence Lundbladeff8106f2024-02-05 20:02:30 -0700265 pMe->pfnCloseMap = QCBOREncode_Private_CloseMapUnsorted;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700266}
267
268
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000269/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800270 * Public function to encode a CBOR head. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700271 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700272UsefulBufC
273QCBOREncode_EncodeHead(UsefulBuf Buffer,
274 uint8_t uMajorType,
275 uint8_t uMinLen,
276 uint64_t uArgument)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700277{
Laurence Lundbladee9b00322018-12-30 10:33:26 -0800278 /*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800279 * == Description of the CBOR Head ==
280 *
281 * The head of a CBOR data item
282 * +---+-----+ +--------+ +--------+ +--------+ +--------+
283 * |M T| A R G U M E N T . . . |
284 * +---+-----+ +--------+ +--------+ +--------+ ... +--------+
285 *
286 * Every CBOR data item has a "head". It is made up of the "major
287 * type" and the "argument".
288 *
289 * The major type indicates whether the data item is an integer,
290 * string, array or such. It is encoded in 3 bits giving it a range
291 * from 0 to 7. 0 indicates the major type is a positive integer,
292 * 1 a negative integer, 2 a byte string and so on.
293 *
294 * These 3 bits are the first part of the "initial byte" in a data
295 * item. Every data item has an initial byte, and some only have
296 * the initial byte.
297 *
298 * The argument is essentially a number between 0 and UINT64_MAX
299 * (18446744073709551615). This number is interpreted to mean
300 * different things for the different major types. For major type
301 * 0, a positive integer, it is value of the data item. For major
302 * type 2, a byte string, it is the length in bytes of the byte
303 * string. For major type 4, an array, it is the number of data
304 * items in the array.
305 *
306 * Special encoding is used so that the argument values less than
307 * 24 can be encoded very compactly in the same byte as the major
308 * type is encoded. When the lower 5 bits of the initial byte have
309 * a value less than 24, then that is the value of the argument.
310 *
311 * If the lower 5 bits of the initial byte are less than 24, then
312 * they are the value of the argument. This allows integer values 0
313 * - 23 to be CBOR encoded in just one byte.
314 *
315 * When the value of lower 5 bits are 24, 25, 26, or 27 the
316 * argument is encoded in 1, 2, 4 or 8 bytes following the initial
317 * byte in network byte order (bit endian). The cases when it is
318 * 28, 29 and 30 are reserved for future use. The value 31 is a
319 * special indicator for indefinite length strings, arrays and
320 * maps.
321 *
322 * The lower 5 bits are called the "additional information."
323 *
324 * Thus the CBOR head may be 1, 2, 3, 5 or 9 bytes long.
325 *
326 * It is legal in CBOR to encode the argument using any of these
327 * lengths even if it could be encoded in a shorter length. For
328 * example it is legal to encode a data item representing the
329 * positive integer 0 in 9 bytes even though it could be encoded in
330 * only 0. This is legal to allow for for very simple code or even
331 * hardware-only implementations that just output a register
332 * directly.
333 *
334 * CBOR defines preferred encoding as the encoding of the argument
335 * in the smallest number of bytes needed to encode it.
336 *
337 * This function takes the major type and argument as inputs and
338 * outputs the encoded CBOR head for them. It does conversion to
339 * network byte order. It implements CBOR preferred encoding,
340 * outputting the shortest representation of the argument.
341 *
342 * == Endian Conversion ==
343 *
344 * This code does endian conversion without hton() or knowing the
345 * endianness of the machine by using masks and shifts. This avoids
346 * the dependency on hton() and the mess of figuring out how to
347 * find the machine's endianness.
348 *
349 * This is a good efficient implementation on little-endian
350 * machines. A faster and smaller implementation is possible on
351 * big-endian machines because CBOR/network byte order is
352 * big-endian. However big-endian machines are uncommon.
353 *
354 * On x86, this is about 150 bytes instead of 500 bytes for the
355 * original, more formal unoptimized code.
356 *
357 * This also does the CBOR preferred shortest encoding for integers
358 * and is called to do endian conversion for floats.
359 *
360 * It works backwards from the least significant byte to the most
361 * significant byte.
362 *
363 * == Floating Point ==
364 *
365 * When the major type is 7 and the 5 lower bits have the values
366 * 25, 26 or 27, the argument is a floating-point number that is
367 * half, single or double-precision. Note that it is not the
368 * conversion from a floating-point value to an integer value like
369 * converting 0x00 to 0.00, it is the interpretation of the bits in
370 * the argument as an IEEE 754 float-point number.
371 *
372 * Floating-point numbers must be converted to network byte
373 * order. That is accomplished here by exactly the same code that
374 * converts integer arguments to network byte order.
375 *
376 * There is preferred encoding for floating-point numbers in CBOR,
377 * but it is very different than for integers and it is not
378 * implemented here. Half-precision is preferred to
379 * single-precision which is preferred to double-precision only if
380 * the conversion can be performed without loss of precision. Zero
381 * and infinity can always be converted to half-precision, without
382 * loss but 3.141592653589 cannot.
383 *
384 * The way this function knows to not do preferred encoding on the
385 * argument passed here when it is a floating point number is the
386 * uMinLen parameter. It should be 2, 4 or 8 for half, single and
387 * double precision floating point values. This prevents and the
388 * incorrect removal of leading zeros when encoding arguments that
389 * are floating-point numbers.
390 *
391 * == Use of Type int and Static Analyzers ==
392 *
393 * The type int is used here for several variables because of the
394 * way integer promotion works in C for variables that are uint8_t
395 * or uint16_t. The basic rule is that they will always be promoted
396 * to int if they will fit. These integer variables here need only
397 * hold values less than 255 so they will always fit into an int.
398 *
399 * Most of values stored are never negative, so one might think
400 * that unsigned int would be more correct than int. However the C
401 * integer promotion rules only promote to unsigned int if the
402 * result won't fit into an int even if the promotion is for an
403 * unsigned variable like uint8_t.
404 *
405 * By declaring these int, there are few implicit conversions and
406 * fewer casts needed. Code size is reduced a little. It makes
407 * static analyzers happier.
408 *
409 * Note also that declaring these uint8_t won't stop integer wrap
410 * around if the code is wrong. It won't make the code more
411 * correct.
412 *
413 * https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
414 * https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be
415 *
416 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800417 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800418
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800419 /* The buffer must have room for the largest CBOR HEAD + one
420 * extra. The one extra is needed for this code to work as it does
421 * a pre-decrement.
422 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700423 if(Buffer.len < QCBOR_HEAD_BUFFER_SIZE) {
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000424 return NULLUsefulBufC;
425 }
426
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800427 /* Pointer to last valid byte in the buffer */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700428 uint8_t * const pBufferEnd = &((uint8_t *)Buffer.ptr)[QCBOR_HEAD_BUFFER_SIZE-1];
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000429
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800430 /* Point to the last byte and work backwards */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000431 uint8_t *pByte = pBufferEnd;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800432 /* The 5 bits in the initial byte that are not the major type */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800433 int nAdditionalInfo;
Laurence Lundblade2c40ab82018-12-30 14:20:29 -0800434
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800435 if(uMajorType > QCBOR_INDEFINITE_LEN_TYPE_MODIFIER) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800436 /* Special case for start & end of indefinite length */
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800437 uMajorType = uMajorType - QCBOR_INDEFINITE_LEN_TYPE_MODIFIER;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800438 /* This takes advantage of design of CBOR where additional info
439 * is 31 for both opening and closing indefinite length
440 * maps and arrays.
441 */
442 #if CBOR_SIMPLE_BREAK != LEN_IS_INDEFINITE
443 #error additional info for opening array not the same as for closing
444 #endif
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800445 nAdditionalInfo = CBOR_SIMPLE_BREAK;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800446
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000447 } else if (uArgument < CBOR_TWENTY_FOUR && uMinLen == 0) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800448 /* Simple case where argument is < 24 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000449 nAdditionalInfo = (int)uArgument;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800450
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800451 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800452 /* This encodes the argument in 1,2,4 or 8 bytes. The outer loop
453 * runs once for 1 byte and 4 times for 8 bytes. The inner loop
454 * runs 1, 2 or 4 times depending on outer loop counter. This
455 * works backwards shifting 8 bits off the argument being
456 * encoded at a time until all bits from uArgument have been
457 * encoded and the minimum encoding size is reached. Minimum
458 * encoding size is for floating-point numbers that have some
459 * zero-value bytes that must be output.
Laurence Lundbladee9b00322018-12-30 10:33:26 -0800460 */
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800461 static const uint8_t aIterate[] = {1,1,2,4};
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000462
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800463 /* uMinLen passed in is unsigned, but goes negative in the loop
464 * so it must be converted to a signed value.
465 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000466 int nMinLen = (int)uMinLen;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800467 int i;
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000468 for(i = 0; uArgument || nMinLen > 0; i++) {
469 const int nIterations = (int)aIterate[i];
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800470 for(int j = 0; j < nIterations; j++) {
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000471 *--pByte = (uint8_t)(uArgument & 0xff);
472 uArgument = uArgument >> 8;
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800473 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800474 nMinLen -= nIterations;
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800475 }
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800476
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800477 nAdditionalInfo = LEN_IS_ONE_BYTE-1 + i;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700478 }
Laurence Lundbladef970f1d2018-12-14 01:44:23 -0800479
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800480 /* This expression integer-promotes to type int. The code above in
481 * function guarantees that nAdditionalInfo will never be larger
482 * than 0x1f. The caller may pass in a too-large uMajor type. The
483 * conversion to unint8_t will cause an integer wrap around and
484 * incorrect CBOR will be generated, but no security issue will
485 * occur.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800486 */
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800487 const int nInitialByte = (uMajorType << 5) + nAdditionalInfo;
488 *--pByte = (uint8_t)nInitialByte;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800489
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000490#ifdef EXTRA_ENCODE_HEAD_CHECK
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800491 /* This is a sanity check that can be turned on to verify the
492 * pointer math in this function is not going wrong. Turn it on and
493 * run the whole test suite to perform the check.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800494 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000495 if(pBufferEnd - pByte > 9 || pBufferEnd - pByte < 1 || pByte < (uint8_t *)buffer.ptr) {
496 return NULLUsefulBufC;
497 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800498#endif /* EXTRA_ENCODE_HEAD_CHECK */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800499
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800500 /* Length will not go negative because the loops run for at most 8 decrements
501 * of pByte, only one other decrement is made, and the array is sized
502 * for this.
503 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000504 return (UsefulBufC){pByte, (size_t)(pBufferEnd - pByte)};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700505}
506
507
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000508/**
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800509 * @brief Append the CBOR head, the major type and argument
510 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700511 * @param pMe Encoder context.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800512 * @param uMajorType Major type to insert.
513 * @param uArgument The argument (an integer value or a length).
514 * @param uMinLen The minimum number of bytes for encoding the CBOR argument.
515 *
516 * This formats the CBOR "head" and appends it to the output.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000517 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700518static void
519QCBOREncode_Private_AppendCBORHead(QCBOREncodeContext *pMe,
520 const uint8_t uMajorType,
521 const uint64_t uArgument,
522 const uint8_t uMinLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700523{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800524 /* A stack buffer large enough for a CBOR head */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000525 UsefulBuf_MAKE_STACK_UB (pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
526
527 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
528 uMajorType,
529 uMinLen,
530 uArgument);
531
532 /* No check for EncodedHead == NULLUsefulBufC is performed here to
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800533 * save object code. It is very clear that pBufferForEncodedHead is
534 * the correct size. If EncodedHead == NULLUsefulBufC then
535 * UsefulOutBuf_AppendUsefulBuf() will do nothing so there is no
536 * security hole introduced.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000537 */
538
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700539 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), EncodedHead);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700540}
541
542
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000543/**
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700544 * @brief Check for errors when decreasing nesting.
545 *
546 * @param pMe QCBOR encoding context.
547 * @param uMajorType The major type of the nesting.
548 *
549 * Check that there is no previous error, that there is actually some
550 * nesting and that the major type of the opening of the nesting
551 * matches the major type of the nesting being closed.
552 *
553 * This is called when closing maps, arrays, byte string wrapping and
554 * open/close of byte strings.
555 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700556static bool
557QCBOREncode_Private_CheckDecreaseNesting(QCBOREncodeContext *pMe,
558 const uint8_t uMajorType)
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700559{
560#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
561 if(pMe->uError != QCBOR_SUCCESS) {
562 return true;
563 }
564
565 if(!Nesting_IsInNest(&(pMe->nesting))) {
566 pMe->uError = QCBOR_ERR_TOO_MANY_CLOSES;
567 return true;
568 }
569
570 if(Nesting_GetMajorType(&(pMe->nesting)) != uMajorType) {
571 pMe->uError = QCBOR_ERR_CLOSE_MISMATCH;
572 return true;
573 }
574
575#else
576 /* None of these checks are performed if the encode guards are
577 * turned off as they all relate to correct calling.
578 *
579 * Turning off all these checks does not turn off any checking for
580 * buffer overflows or pointer issues.
581 */
582
583 (void)uMajorType;
584 (void)pMe;
585#endif
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700586
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700587 return false;
588}
589
590
591/**
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800592 * @brief Insert the CBOR head for a map, array or wrapped bstr
593 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700594 * @param pMe QCBOR encoding context.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800595 * @param uMajorType One of CBOR_MAJOR_TYPE_XXXX.
596 * @param uLen The length of the data item.
597 *
598 * When an array, map or bstr was opened, nothing was done but note
599 * the position. This function goes back to that position and inserts
600 * the CBOR Head with the major type and length.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000601 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700602static void
603QCBOREncode_Private_InsertCBORHead(QCBOREncodeContext *pMe,
604 uint8_t uMajorType,
605 size_t uLen)
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000606{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700607 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700608 return;
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000609 }
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700610
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600611 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
612 uMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
613 }
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800614
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700615 /* A stack buffer large enough for a CBOR head (9 bytes) */
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800616 UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800617
618 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
619 uMajorType,
620 0,
621 uLen);
622
623 /* No check for EncodedHead == NULLUsefulBufC is performed here to
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800624 * save object code. It is very clear that pBufferForEncodedHead is
625 * the correct size. If EncodedHead == NULLUsefulBufC then
626 * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is no
Laurence Lundblade9e2f7082021-05-17 02:10:48 -0700627 * security hole introduced.
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800628 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700629 UsefulOutBuf_InsertUsefulBuf(&(pMe->OutBuf),
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800630 EncodedHead,
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700631 Nesting_GetStartPos(&(pMe->nesting)));
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800632
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700633 Nesting_Decrease(&(pMe->nesting));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000634}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635
Laurence Lundblade241705e2018-12-30 18:56:14 -0800636
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800637/**
638 * @brief Increment item counter for maps and arrays.
639 *
640 * @param pMe QCBOR encoding context.
641 *
642 * This is mostly a separate function to make code more readable and
643 * to have fewer occurrences of #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800644 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700645static void
646QCBOREncode_Private_IncrementMapOrArrayCount(QCBOREncodeContext *pMe)
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800647{
648#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
649 if(pMe->uError == QCBOR_SUCCESS) {
650 pMe->uError = Nesting_Increment(&(pMe->nesting));
651 }
652#else
653 (void)Nesting_Increment(&(pMe->nesting));
654#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
655}
656
657
658/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800659 * Public functions for adding unsigned integers. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700660 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700661void
662QCBOREncode_AddUInt64(QCBOREncodeContext *pMe, const uint64_t uValue)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700663{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700664 QCBOREncode_Private_AppendCBORHead(pMe,
665 CBOR_MAJOR_TYPE_POSITIVE_INT,
666 uValue,
667 0);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800668
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700669 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700670}
671
Laurence Lundblade56230d12018-11-01 11:14:51 +0700672
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700673/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800674 * Public functions for adding signed integers. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -0800675 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700676void
677QCBOREncode_AddInt64(QCBOREncodeContext *pMe, const int64_t nNum)
Laurence Lundblade067035b2018-11-28 17:35:25 -0800678{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800679 uint8_t uMajorType;
680 uint64_t uValue;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800681
682 if(nNum < 0) {
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700683 /* In CBOR -1 encodes as 0x00 with major type negative int.
684 * First add one as a signed integer because that will not
685 * overflow. Then change the sign as needed for encoding. (The
686 * opposite order, changing the sign and subtracting, can cause
687 * an overflow when encoding INT64_MIN. */
688 int64_t nTmp = nNum + 1;
689 uValue = (uint64_t)-nTmp;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800690 uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
691 } else {
692 uValue = (uint64_t)nNum;
693 uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
694 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700695 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, uValue, 0);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800696
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700697 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800698}
699
700
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700701/**
702 * @brief Semi-private method to add a buffer full of bytes to encoded output.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800703 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700704 * @param[in] pMe The encoding context to add the integer to.
705 * @param[in] uMajorType The CBOR major type of the bytes.
706 * @param[in] Bytes The bytes to add.
707 *
708 * Use QCBOREncode_AddText() or QCBOREncode_AddBytes() or
709 * QCBOREncode_AddEncoded() instead. They are inline functions that
710 * call this and supply the correct major type. This function is
711 * public to make the inline functions work to keep the overall code
712 * size down and because the C language has no way to make it private.
713 *
714 * If this is called the major type should be @c CBOR_MAJOR_TYPE_TEXT_STRING,
715 * @c CBOR_MAJOR_TYPE_BYTE_STRING or @c CBOR_MAJOR_NONE_TYPE_RAW. The
716 * last one is special for adding already-encoded CBOR.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800717 *
718 * This does the work of adding actual strings bytes to the CBOR
719 * output (as opposed to adding numbers and opening / closing
720 * aggregate types).
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800721
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800722 * There are four use cases:
723 * CBOR_MAJOR_TYPE_BYTE_STRING -- Byte strings
724 * CBOR_MAJOR_TYPE_TEXT_STRING -- Text strings
725 * CBOR_MAJOR_NONE_TYPE_RAW -- Already-encoded CBOR
726 * CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY -- Special case
727 *
728 * The first two add the head plus the actual bytes. The third just
729 * adds the bytes as the heas is presumed to be in the bytes. The
730 * fourth just adds the head for the very special case of
731 * QCBOREncode_AddBytesLenOnly().
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700733void
734QCBOREncode_Private_AddBuffer(QCBOREncodeContext *pMe,
735 const uint8_t uMajorType,
736 const UsefulBufC Bytes)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700737{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800738 /* If it is not Raw CBOR, add the type and the length */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800739 if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
740 uint8_t uRealMajorType = uMajorType;
741 if(uRealMajorType == CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
742 uRealMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
743 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700744 QCBOREncode_Private_AppendCBORHead(pMe, uRealMajorType, Bytes.len, 0);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800745 }
746
747 if(uMajorType != CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800748 /* Actually add the bytes */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700749 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Bytes);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800750 }
751
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700752 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700753}
754
Laurence Lundbladecafcfe12018-10-31 21:59:50 +0700755
Laurence Lundblade55a24832018-10-30 04:35:08 +0700756/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800757 * Public functions for adding a tag. See qcbor/qcbor_encode.h
Laurence Lundblade55a24832018-10-30 04:35:08 +0700758 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700759void
760QCBOREncode_AddTag(QCBOREncodeContext *pMe, const uint64_t uTag)
Laurence Lundblade55a24832018-10-30 04:35:08 +0700761{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700762 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_TAG, uTag, 0);
Laurence Lundblade55a24832018-10-30 04:35:08 +0700763}
764
765
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700766/**
767 * @brief Semi-private method to add simple types.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800768 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700769 * @param[in] pMe The encoding context to add the simple value to.
770 * @param[in] uMinLen Minimum encoding size for uNum. Usually 0.
771 * @param[in] uNum One of CBOR_SIMPLEV_FALSE through _UNDEF or other.
772 *
773 * This is used to add simple types like true and false.
774 *
775 * Call QCBOREncode_AddBool(), QCBOREncode_AddNULL(),
776 * QCBOREncode_AddUndef() instead of this.
777 *
778 * This function can add simple values that are not defined by CBOR
779 * yet. This expansion point in CBOR should not be used unless they are
780 * standardized.
781 *
782 * Error handling is the same as QCBOREncode_AddInt64().
Laurence Lundblade56230d12018-11-01 11:14:51 +0700783 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700784void
785QCBOREncode_Private_AddType7(QCBOREncodeContext *pMe,
786 const uint8_t uMinLen,
787 const uint64_t uNum)
Laurence Lundblade55a24832018-10-30 04:35:08 +0700788{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800789#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700790 if(pMe->uError == QCBOR_SUCCESS) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700791 if(uNum >= CBOR_SIMPLEV_RESERVED_START && uNum <= CBOR_SIMPLEV_RESERVED_END) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700792 pMe->uError = QCBOR_ERR_ENCODE_UNSUPPORTED;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800793 return;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700794 }
Laurence Lundblade487930f2018-11-30 11:01:45 -0800795 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800796#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
797
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800798 /* AppendCBORHead() does endian swapping for the float / double */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700799 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_SIMPLE, uNum, uMinLen);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800800
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700801 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundblade55a24832018-10-30 04:35:08 +0700802}
803
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700804
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200805#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700806/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800807 * Public functions for adding a double. See qcbor/qcbor_encode.h
808 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700809void
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700810QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pMe, double dNum)
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700811{
Laurence Lundblade240ca822024-01-16 11:11:00 -0700812#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
813 if(pMe->uMode >= QCBOR_ENCODE_MODE_PREFERRED) {
814 pMe->uError = QCBOR_ERR_NOT_PREFERRED;
815 return;
816 }
817#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
818
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700819 QCBOREncode_Private_AddType7(pMe,
820 sizeof(uint64_t),
821 UsefulBufUtil_CopyDoubleToUint64(dNum));
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700822}
823
Laurence Lundblade240ca822024-01-16 11:11:00 -0700824#include <math.h> // For NaN. Maybe a better way? TODO:
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700825
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800827 * Public functions for adding a double. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700828 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700829void
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700830QCBOREncode_AddDouble(QCBOREncodeContext *pMe, double dNum)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831{
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700832#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade240ca822024-01-16 11:11:00 -0700833 IEEE754_union FloatResult;
834 bool bNoNaNPayload;
835 struct IEEE754_ToInt IntResult;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700836
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700837 if(pMe->uMode == QCBOR_ENCODE_MODE_DCBOR) {
Laurence Lundblade240ca822024-01-16 11:11:00 -0700838 IntResult = IEEE754_DoubleToInt(dNum);
839 switch(IntResult.type) {
840 case IEEE754_ToInt_IS_INT:
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700841 QCBOREncode_AddInt64(pMe, IntResult.integer.is_signed);
Laurence Lundblade240ca822024-01-16 11:11:00 -0700842 return;
843 case IEEE754_ToInt_IS_UINT:
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700844 QCBOREncode_AddUInt64(pMe, IntResult.integer.un_signed);
Laurence Lundblade240ca822024-01-16 11:11:00 -0700845 return;
846 case IEEE754_To_int_NaN:
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700847 dNum = NAN;
848 bNoNaNPayload = true;
849 break;
Laurence Lundblade240ca822024-01-16 11:11:00 -0700850 case IEEE754_ToInt_NO_CONVERSION:
851 bNoNaNPayload = true;
852 }
853 } else {
854 bNoNaNPayload = false;
855 }
856
857 FloatResult = IEEE754_DoubleToSmaller(dNum, true, bNoNaNPayload);
858
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700859 QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
Laurence Lundblade240ca822024-01-16 11:11:00 -0700860
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800861#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700862 QCBOREncode_AddDoubleNoPreferred(pMe, dNum);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800863#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700864}
Laurence Lundblade9682a532020-06-06 18:33:04 -0700865
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700866
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700867
868
869/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800870 * Public functions for adding a float. See qcbor/qcbor_encode.h
871 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700872void
873QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pMe, const float fNum)
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700874{
Laurence Lundblade240ca822024-01-16 11:11:00 -0700875#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
876 if(pMe->uMode >= QCBOR_ENCODE_MODE_PREFERRED) {
877 pMe->uError = QCBOR_ERR_NOT_PREFERRED;
878 return;
879 }
880#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700881 QCBOREncode_Private_AddType7(pMe,
882 sizeof(uint32_t),
883 UsefulBufUtil_CopyFloatToUint32(fNum));
Laurence Lundblade9682a532020-06-06 18:33:04 -0700884}
885
886
887/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800888 * Public functions for adding a float. See qcbor/qcbor_encode.h
Laurence Lundblade9682a532020-06-06 18:33:04 -0700889 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700890void
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700891QCBOREncode_AddFloat(QCBOREncodeContext *pMe, float fNum)
Laurence Lundblade9682a532020-06-06 18:33:04 -0700892{
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700893#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade240ca822024-01-16 11:11:00 -0700894 IEEE754_union FloatResult;
895 bool bNoNaNPayload;
896 struct IEEE754_ToInt IntResult;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700897
Laurence Lundblade240ca822024-01-16 11:11:00 -0700898 if(pMe->uMode == QCBOR_ENCODE_MODE_DCBOR) {
899 IntResult = IEEE754_SingleToInt(fNum);
900 switch(IntResult.type) {
901 case IEEE754_ToInt_IS_INT:
902 QCBOREncode_AddInt64(pMe, IntResult.integer.is_signed);
903 return;
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700904 case IEEE754_ToInt_IS_UINT:
Laurence Lundblade240ca822024-01-16 11:11:00 -0700905 QCBOREncode_AddUInt64(pMe, IntResult.integer.un_signed);
906 return;
907 case IEEE754_To_int_NaN:
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700908 fNum = NAN;
909 bNoNaNPayload = true;
910 break;
Laurence Lundblade240ca822024-01-16 11:11:00 -0700911 case IEEE754_ToInt_NO_CONVERSION:
912 bNoNaNPayload = true;
913 }
914 } else {
915 bNoNaNPayload = false;
916 }
917
918 FloatResult = IEEE754_SingleToHalf(fNum, bNoNaNPayload);
919
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700920 QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800921#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700922 QCBOREncode_AddFloatNoPreferred(pMe, fNum);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800923#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800924}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200925#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800926
927
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -0700928#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700929/**
930 * @brief Semi-private method to add bigfloats and decimal fractions.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800931 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700932 * @param[in] pMe The encoding context to add the value to.
933 * @param[in] uTag The type 6 tag indicating what this is to be.
934 * @param[in] BigNumMantissa Is @ref NULLUsefulBufC if mantissa is an
935 * @c int64_t or the actual big number mantissa
936 * if not.
937 * @param[in] bBigNumIsNegative This is @c true if the big number is negative.
938 * @param[in] nMantissa The @c int64_t mantissa if it is not a big number.
939 * @param[in] nExponent The exponent.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800940 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700941 * This outputs either the @ref CBOR_TAG_DECIMAL_FRACTION or
942 * @ref CBOR_TAG_BIGFLOAT tag. if @c uTag is @ref CBOR_TAG_INVALID64,
943 * then this outputs the "borrowed" content format.
944 *
945 * The tag content output by this is an array with two members, the
946 * exponent and then the mantissa. The mantissa can be either a big
947 * number or an @c int64_t.
948 *
949 * This implementation cannot output an exponent further from 0 than
950 * @c INT64_MAX.
951 *
952 * To output a mantissa that is between INT64_MAX and UINT64_MAX from 0,
953 * it must be as a big number.
954 *
955 * Typically, QCBOREncode_AddDecimalFraction(), QCBOREncode_AddBigFloat(),
956 * QCBOREncode_AddDecimalFractionBigNum() or QCBOREncode_AddBigFloatBigNum()
957 * is called instead of this.
Laurence Lundblade59289e52019-12-30 13:44:37 -0800958 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700959void
960QCBOREncode_Private_AddExpMantissa(QCBOREncodeContext *pMe,
961 const uint64_t uTag,
962 const UsefulBufC BigNumMantissa,
963 const bool bBigNumIsNegative,
964 const int64_t nMantissa,
965 const int64_t nExponent)
Laurence Lundblade59289e52019-12-30 13:44:37 -0800966{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800967 /* This is for encoding either a big float or a decimal fraction,
968 * both of which are an array of two items, an exponent and a
969 * mantissa. The difference between the two is that the exponent
970 * is base-2 for big floats and base-10 for decimal fractions, but
971 * that has no effect on the code here.
Laurence Lundbladeee851742020-01-08 08:37:05 -0800972 */
Laurence Lundbladeae66d3f2020-09-14 18:12:08 -0700973 if(uTag != CBOR_TAG_INVALID64) {
974 QCBOREncode_AddTag(pMe, uTag);
975 }
Laurence Lundblade59289e52019-12-30 13:44:37 -0800976 QCBOREncode_OpenArray(pMe);
977 QCBOREncode_AddInt64(pMe, nExponent);
978 if(!UsefulBuf_IsNULLC(BigNumMantissa)) {
979 if(bBigNumIsNegative) {
980 QCBOREncode_AddNegativeBignum(pMe, BigNumMantissa);
981 } else {
982 QCBOREncode_AddPositiveBignum(pMe, BigNumMantissa);
983 }
984 } else {
985 QCBOREncode_AddInt64(pMe, nMantissa);
986 }
987 QCBOREncode_CloseArray(pMe);
988}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -0700989#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -0800990
991
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700992/**
993 * @brief Semi-private method to open a map, array or bstr-wrapped CBOR
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800994 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700995 * @param[in] pMe The context to add to.
996 * @param[in] uMajorType The major CBOR type to close
997 *
998 * Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or
999 * QCBOREncode_BstrWrap() instead of this.
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001000 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001001void
1002QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext *pMe,
1003 const uint8_t uMajorType)
Laurence Lundblade067035b2018-11-28 17:35:25 -08001004{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001005 /* Add one item to the nesting level we are in for the new map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001006 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundbladed39cd392019-01-11 18:17:38 -08001007
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001008 /* The offset where the length of an array or map will get written
1009 * is stored in a uint32_t, not a size_t to keep stack usage
1010 * smaller. This checks to be sure there is no wrap around when
1011 * recording the offset. Note that on 64-bit machines CBOR larger
1012 * than 4GB can be encoded as long as no array/map offsets occur
1013 * past the 4GB mark, but the public interface says that the
1014 * maximum is 4GB to keep the discussion simpler.
1015 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001016 size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundbladed39cd392019-01-11 18:17:38 -08001017
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001018 /* QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
1019 * code can run on a 32-bit machine and tests can pass on a 32-bit
1020 * machine. If it was exactly UINT32_MAX, then this code would not
1021 * compile or run on a 32-bit machine and an #ifdef or some machine
1022 * size detection would be needed reducing portability.
1023 */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -08001024 if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001025 pMe->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -08001026
1027 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001028 /* Increase nesting level because this is a map or array. Cast
1029 * from size_t to uin32_t is safe because of check above.
1030 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001031 pMe->uError = Nesting_Increase(&(pMe->nesting), uMajorType, (uint32_t)uEndPosition);
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -08001032 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001033}
1034
Laurence Lundblade59289e52019-12-30 13:44:37 -08001035
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001036/**
1037 * @brief Semi-private method to open a map, array with indefinite length
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001038 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001039 * @param[in] pMe The context to add to.
1040 * @param[in] uMajorType The major CBOR type to close
1041 *
1042 * Call QCBOREncode_OpenArrayIndefiniteLength() or
1043 * QCBOREncode_OpenMapIndefiniteLength() instead of this.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001044 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001045void
1046QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
1047 const uint8_t uMajorType)
Jan Jongboom4a93a662019-07-25 08:44:58 +02001048{
Laurence Lundblade240ca822024-01-16 11:11:00 -07001049#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
1050 if(pMe->uMode >= QCBOR_ENCODE_MODE_PREFERRED) {
1051 pMe->uError = QCBOR_ERR_NOT_PREFERRED;
1052 return;
1053 }
1054#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001055 /* Insert the indefinite length marker (0x9f for arrays, 0xbf for maps) */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001056 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, 0, 0);
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001057
1058 /* Call the definite-length opener just to do the bookkeeping for
1059 * nesting. It will record the position of the opening item in the
1060 * encoded output but this is not used when closing this open.
1061 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001062 QCBOREncode_Private_OpenMapOrArray(pMe, uMajorType);
Jan Jongboom4a93a662019-07-25 08:44:58 +02001063}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001064
Laurence Lundbladeee851742020-01-08 08:37:05 -08001065
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001066/**
Laurence Lundbladeff8106f2024-02-05 20:02:30 -07001067 * @brief Semi-private method to close a map, array or bstr wrapped CBOR.
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001068 *
1069 * @param[in] pMe The context to add to.
1070 * @param[in] uMajorType The major CBOR type to close.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001071 */
Laurence Lundblade240ca822024-01-16 11:11:00 -07001072void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001073QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext *pMe,
1074 const uint8_t uMajorType)
Laurence Lundblade240ca822024-01-16 11:11:00 -07001075{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001076 QCBOREncode_Private_InsertCBORHead(pMe, uMajorType, Nesting_GetCount(&(pMe->nesting)));
Laurence Lundblade240ca822024-01-16 11:11:00 -07001077}
1078
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001079
Laurence Lundbladeff8106f2024-02-05 20:02:30 -07001080/**
1081 * @brief Private method to close a map without sorting.
1082 *
1083 * @param[in] pMe The encode context with map to close.
1084 *
1085 * See QCBOREncode_SerializationCDE() implemention for explantion for why this exists in this form.
1086 */
1087static void
1088QCBOREncode_Private_CloseMapUnsorted(QCBOREncodeContext *pMe)
Laurence Lundblade240ca822024-01-16 11:11:00 -07001089{
Laurence Lundbladeff8106f2024-02-05 20:02:30 -07001090 QCBOREncode_Private_CloseMapOrArray(pMe, CBOR_MAJOR_TYPE_MAP);
Laurence Lundblade240ca822024-01-16 11:11:00 -07001091}
1092
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001093
1094/**
1095 * @brief Decode a CBOR item head.
1096 *
1097 * @param[in] pUInBuf UsefulInputBuf to read from.
1098 * @param[out] pnMajorType Major type of decoded head.
1099 * @param[out] puArgument Argument of decoded head.
1100 * @param[out] pnAdditionalInfo Additional info from decoded head.
1101 *
1102 * @return SUCCESS if a head was decoded
1103 * HIT_END if there were not enough bytes to decode a head
1104 * UNSUPPORTED if the decoded item is not one that is supported
1105 *
1106 * This is copied from qcbor_decode.c rather than referenced. This
1107 * makes the core decoder 60 bytes smaller because it gets inlined.
1108 * It would not get inlined if it was referenced. It is important to
1109 * make the core decoder as small as possible. The copy here does make
1110 * map sorting 200 bytes bigger, but map sorting is rarely used in
1111 * environments that need small object code. It would also make
1112 * qcbor_encode.c depend on qcbor_decode.c
1113 *
1114 * This is also super stable and tested. It implements the very
1115 * well-defined part of CBOR that will never change. So this won't
1116 * change.
1117 */
1118static QCBORError
1119QCBOREncodePriv_DecodeHead(UsefulInputBuf *pUInBuf,
1120 int *pnMajorType,
1121 uint64_t *puArgument,
1122 int *pnAdditionalInfo)
1123{
1124 QCBORError uReturn;
1125
1126 /* Get the initial byte that every CBOR data item has and break it
1127 * down. */
1128 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
1129 const int nTmpMajorType = nInitialByte >> 5;
1130 const int nAdditionalInfo = nInitialByte & 0x1f;
1131
1132 /* Where the argument accumulates */
1133 uint64_t uArgument;
1134
1135 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
1136 /* Need to get 1,2,4 or 8 additional argument bytes. Map
1137 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
1138 */
1139 static const uint8_t aIterate[] = {1,2,4,8};
1140
1141 /* Loop getting all the bytes in the argument */
1142 uArgument = 0;
1143 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
1144 /* This shift and add gives the endian conversion. */
1145 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
1146 }
1147 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
1148 /* The reserved and thus-far unused additional info values */
1149 uReturn = QCBOR_ERR_UNSUPPORTED;
1150 goto Done;
1151 } else {
1152 /* Less than 24, additional info is argument or 31, an
1153 * indefinite-length. No more bytes to get.
1154 */
1155 uArgument = (uint64_t)nAdditionalInfo;
1156 }
1157
1158 if(UsefulInputBuf_GetError(pUInBuf)) {
1159 uReturn = QCBOR_ERR_HIT_END;
1160 goto Done;
1161 }
1162
1163 /* All successful if arrived here. */
1164 uReturn = QCBOR_SUCCESS;
1165 *pnMajorType = nTmpMajorType;
1166 *puArgument = uArgument;
1167 *pnAdditionalInfo = nAdditionalInfo;
1168
1169Done:
1170 return uReturn;
1171}
1172
1173
1174/**
1175 * @brief Consume the next item from a UsefulInputBuf.
1176 *
1177 * @param[in] pInBuf UsefulInputBuf from which to consume item.
1178 *
1179 * Recursive, but stack usage is light and encoding depth limit
1180 */
1181static QCBORError
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001182QCBOR_Private_ConsumeNext(UsefulInputBuf *pInBuf)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001183{
1184 int nMajor;
1185 uint64_t uArgument;
1186 int nAdditional;
1187 uint16_t uItemCount;
1188 uint16_t uMul;
1189 uint16_t i;
1190 QCBORError uCBORError;
1191
1192 uCBORError = QCBOREncodePriv_DecodeHead(pInBuf, &nMajor, &uArgument, &nAdditional);
1193 if(uCBORError != QCBOR_SUCCESS) {
1194 return uCBORError;
1195 }
1196
1197 uMul = 1;
1198
1199 switch(nMajor) {
1200 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1201 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1202 break;
1203
1204 case CBOR_MAJOR_TYPE_SIMPLE:
1205 return uArgument == CBOR_SIMPLE_BREAK ? 1 : 0;
1206 break;
1207
1208 case CBOR_MAJOR_TYPE_BYTE_STRING:
1209 case CBOR_MAJOR_TYPE_TEXT_STRING:
1210 if(nAdditional == LEN_IS_INDEFINITE) {
1211 /* Segments of indefinite length */
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001212 while(QCBOR_Private_ConsumeNext(pInBuf) == 0);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001213 }
1214 (void)UsefulInputBuf_GetBytes(pInBuf, uArgument);
1215 break;
1216
1217 case CBOR_MAJOR_TYPE_TAG:
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001218 QCBOR_Private_ConsumeNext(pInBuf);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001219 break;
1220
1221 case CBOR_MAJOR_TYPE_MAP:
1222 uMul = 2;
1223 /* Fallthrough */
1224 case CBOR_MAJOR_TYPE_ARRAY:
1225 uItemCount = (uint16_t)uArgument * uMul;
1226 if(nAdditional == LEN_IS_INDEFINITE) {
1227 uItemCount = UINT16_MAX;
1228 }
1229 for(i = uItemCount; i > 0; i--) {
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001230 if(QCBOR_Private_ConsumeNext(pInBuf)) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001231 /* End of indefinite length */
1232 break;
1233 }
1234 }
1235 break;
1236 }
1237
1238 return QCBOR_SUCCESS;
1239}
1240
1241
1242/**
1243 * @brief Decoded next item to get its length.
1244 *
1245 * Decode the next item in map no matter what type it is. It works
1246 * recursively when an item is a map or array It returns offset just
1247 * past the item decoded or zero there are no more items in the output
1248 * buffer.
1249 *
1250 * This doesn't distinguish between end of the input and an error
1251 * because it is used to decode stuff we encoded into a buffer, not
1252 * stuff that came in from outside. We still want a check for safety
1253 * in case of bugs here, but it is OK to report end of input on error.
1254 */
1255static uint32_t
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001256QCBOREncode_Private_DecodeNextInMap(QCBOREncodeContext *pMe, uint32_t uStart)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001257{
1258 UsefulInputBuf InBuf;
1259 UsefulBufC EncodedMapBytes;
1260 QCBORError uCBORError;
1261
1262 EncodedMapBytes = UsefulOutBuf_OutUBufOffset(&(pMe->OutBuf), uStart);
1263 if(UsefulBuf_IsNULLC(EncodedMapBytes)) {
1264 return 0;
1265 }
1266
1267 UsefulInputBuf_Init(&InBuf, EncodedMapBytes);
1268
1269 /* This is always used on maps, so consume two, the label and the value */
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001270 uCBORError = QCBOR_Private_ConsumeNext(&InBuf);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001271 if(uCBORError) {
1272 return 0;
1273 }
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001274 uCBORError = QCBOR_Private_ConsumeNext(&InBuf);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001275 if(uCBORError) {
1276 return 0;
1277 }
1278
1279 /* Cast is safe because this is QCBOR which limits sizes to UINT32_MAX */
1280 return (uint32_t)UsefulInputBuf_Tell(&InBuf);
1281}
1282
1283
1284/**
1285 * @brief Sort items lexographically by encoded labels.
1286 *
1287 * @param[in] pMe Encoding context.
1288 * @param[in] uStart Offset in outbuf of first item for sorting.
1289 *
1290 * This reaches into the UsefulOutBuf in the encoding context and
1291 * sorts encoded CBOR items. The byte offset start of the items is at
1292 * @c uStart and it goes to the end of valid bytes in the
1293 * UsefulOutBuf.
1294 */
1295static void
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001296QCBOREncode_Private_SortMap(QCBOREncodeContext *pMe, uint32_t uStart)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001297{
1298 bool bSwapped;
1299 int nComparison;
1300 uint32_t uLen2;
1301 uint32_t uLen1;
1302 uint32_t uStart1;
1303 uint32_t uStart2;
1304
1305 if(pMe->uError != QCBOR_SUCCESS) {
1306 return;
1307 }
1308
1309 /* Bubble sort because the sizes of all the items are not the
1310 * same. It works with adjacent pairs so the swap is not too
1311 * difficult even though sizes are different.
1312 *
1313 * While bubble sort is n-squared, it seems OK here because n will
1314 * usually be small and the comparison and swap functions aren't
1315 * too CPU intensive.
1316 *
1317 * Another approach would be to have an array of offsets to the
1318 * items. However this requires memory allocation and the swap
1319 * operation for quick sort or such is complicated because the item
1320 * sizes are not the same and overlap may occur in the bytes being
1321 * swapped.
1322 */
1323 do {
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001324 uLen1 = QCBOREncode_Private_DecodeNextInMap(pMe, uStart);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001325 if(uLen1 == 0) {
1326 /* It's an empty map. Nothing to do. */
1327 break;
1328 }
1329 uStart1 = uStart;
1330 uStart2 = uStart1 + uLen1;
1331 bSwapped = false;
1332
1333 while(1) {
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001334 uLen2 = QCBOREncode_Private_DecodeNextInMap(pMe, uStart2);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001335 if(uLen2 == 0) {
1336 break;
1337 }
1338
1339 nComparison = UsefulOutBuf_Compare(&(pMe->OutBuf), uStart1, uStart2);
1340 if(nComparison < 0) {
1341 UsefulOutBuf_Swap(&(pMe->OutBuf), uStart1, uStart2, uStart2 + uLen2);
1342 uStart1 = uStart1 + uLen2;
1343 bSwapped = true;
1344 } else {
1345 uStart1 = uStart2;
1346 }
1347 uStart2 = uStart2 + uLen2;
1348 }
1349 } while(bSwapped);
1350}
1351
1352
1353/*
1354 * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
1355 */
1356void QCBOREncode_CloseAndSortMap(QCBOREncodeContext *pMe)
1357{
1358 uint32_t uStart;
1359
1360 /* The Header for the map we are about to sort hasn't been
1361 * inserted yet, so uStart is the position of the first item
1362 * and the end out the UsefulOutBuf data is the end of the
1363 * items we are about to sort.
1364 */
1365 uStart = Nesting_GetStartPos(&(pMe->nesting));
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001366 QCBOREncode_Private_SortMap(pMe, uStart);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001367
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001368 QCBOREncode_Private_InsertCBORHead(pMe, CBOR_MAJOR_TYPE_MAP, Nesting_GetCount(&(pMe->nesting)));
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001369}
1370
1371
1372/*
1373 * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
1374 */
1375void QCBOREncode_CloseAndSortMapIndef(QCBOREncodeContext *pMe)
1376{
1377 uint32_t uStart;
1378
1379 uStart = Nesting_GetStartPos(&(pMe->nesting));
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001380 QCBOREncode_Private_SortMap(pMe, uStart);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001381
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001382 QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001383}
1384
1385
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001386/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001387 * Public functions for closing bstr wrapping. See qcbor/qcbor_encode.h
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001388 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001389void
1390QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pMe,
1391 const bool bIncludeCBORHead,
1392 UsefulBufC *pWrappedCBOR)
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001393{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001394 const size_t uInsertPosition = Nesting_GetStartPos(&(pMe->nesting));
1395 const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001396
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001397 /* This subtraction can't go negative because the UsefulOutBuf
1398 * always only grows and never shrinks. UsefulOutBut itself also
1399 * has defenses such that it won't write where it should not even
1400 * if given incorrect input lengths.
1401 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001402 const size_t uBstrLen = uEndPosition - uInsertPosition;
1403
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001404 /* Actually insert */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001405 QCBOREncode_Private_InsertCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uBstrLen);
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001406
1407 if(pWrappedCBOR) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001408 /* Return pointer and length to the enclosed encoded CBOR. The
1409 * intended use is for it to be hashed (e.g., SHA-256) in a COSE
1410 * implementation. This must be used right away, as the pointer
1411 * and length go invalid on any subsequent calls to this
1412 * function because there might be calls to
1413 * InsertEncodedTypeAndNumber() that slides data to the right.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001414 */
1415 size_t uStartOfNew = uInsertPosition;
1416 if(!bIncludeCBORHead) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001417 /* Skip over the CBOR head to just get the inserted bstr */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001418 const size_t uNewEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001419 uStartOfNew += uNewEndPosition - uEndPosition;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001420 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001421 const UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001422 *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uStartOfNew);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001423 }
1424}
1425
Laurence Lundbladeee851742020-01-08 08:37:05 -08001426
Jan Jongboom4a93a662019-07-25 08:44:58 +02001427/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001428 * Public function for canceling a bstr wrap. See qcbor/qcbor_encode.h
1429 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001430void
1431QCBOREncode_CancelBstrWrap(QCBOREncodeContext *pMe)
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001432{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001433 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, CBOR_MAJOR_TYPE_BYTE_STRING)) {
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001434 return;
1435 }
1436
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001437#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001438 const size_t uCurrent = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
1439 if(pMe->nesting.pCurrentNesting->uStart != uCurrent) {
1440 pMe->uError = QCBOR_ERR_CANNOT_CANCEL;
1441 return;
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001442 }
1443 /* QCBOREncode_CancelBstrWrap() can't correctly undo
1444 * QCBOREncode_BstrWrapInMap() or QCBOREncode_BstrWrapInMapN(). It
1445 * can't undo the labels they add. It also doesn't catch the error
1446 * of using it this way. QCBOREncode_CancelBstrWrap() is used
1447 * infrequently and the the result is incorrect CBOR, not a
1448 * security hole, so no extra code or state is added to handle this
1449 * condition.
1450 */
1451#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
1452
1453 Nesting_Decrease(&(pMe->nesting));
1454 Nesting_Decrement(&(pMe->nesting));
1455}
1456
1457
1458/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001459 * Public function for opening a byte string. See qcbor/qcbor_encode.h
1460 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001461void
1462QCBOREncode_OpenBytes(QCBOREncodeContext *pMe, UsefulBuf *pPlace)
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001463{
1464 *pPlace = UsefulOutBuf_GetOutPlace(&(pMe->OutBuf));
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001465#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Paul Liétar79789772022-07-26 20:33:18 +01001466 // TODO: is this right?
1467 uint8_t uMajorType = Nesting_GetMajorType(&(pMe->nesting));
1468 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
1469 pMe->uError = QCBOR_ERR_OPEN_BYTE_STRING;
1470 return;
1471 }
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001472#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
1473
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001474 QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR);
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001475}
1476
1477
1478/*
1479 * Public function for closing a byte string. See qcbor/qcbor_encode.h
1480 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001481void
1482QCBOREncode_CloseBytes(QCBOREncodeContext *pMe, const size_t uAmount)
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001483{
1484 UsefulOutBuf_Advance(&(pMe->OutBuf), uAmount);
1485 if(UsefulOutBuf_GetError(&(pMe->OutBuf))) {
1486 /* Advance too far. Normal off-end error handling in effect here. */
1487 return;
1488 }
1489
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001490 QCBOREncode_Private_InsertCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR, uAmount);
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001491}
1492
1493
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001494/**
1495 * @brief Semi-private method to close a map, array with indefinite length
1496 *
1497 * @param[in] pMe The context to add to.
1498 * @param[in] uMajorType The major CBOR type to close.
1499 *
1500 * Call QCBOREncode_CloseArrayIndefiniteLength() or
1501 * QCBOREncode_CloseMapIndefiniteLength() instead of this.
Jan Jongboom4a93a662019-07-25 08:44:58 +02001502 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001503void
1504QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
1505 const uint8_t uMajorType)
Jan Jongboom4a93a662019-07-25 08:44:58 +02001506{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001507 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001508 return;
Jan Jongboom4a93a662019-07-25 08:44:58 +02001509 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -08001510
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001511 /* Append the break marker (0xff for both arrays and maps) */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001512 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001513 Nesting_Decrease(&(pMe->nesting));
Jan Jongboom4a93a662019-07-25 08:44:58 +02001514}
1515
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001516
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001517/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001518 * Public function to finish and get the encoded result. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001519 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001520QCBORError
1521QCBOREncode_Finish(QCBOREncodeContext *pMe, UsefulBufC *pEncodedCBOR)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001522{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001523 QCBORError uReturn = QCBOREncode_GetErrorState(pMe);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001524
Laurence Lundblade067035b2018-11-28 17:35:25 -08001525 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001526 goto Done;
Laurence Lundblade067035b2018-11-28 17:35:25 -08001527 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001528
Laurence Lundbladedaefdec2020-11-02 20:22:03 -08001529#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001530 if(Nesting_IsInNest(&(pMe->nesting))) {
Laurence Lundblade067035b2018-11-28 17:35:25 -08001531 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001532 goto Done;
1533 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001534#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001535
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001536 *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001537
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001538Done:
Laurence Lundblade067035b2018-11-28 17:35:25 -08001539 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001540}
1541
Laurence Lundblade0595e932018-11-02 22:22:47 +07001542
Laurence Lundblade067035b2018-11-28 17:35:25 -08001543/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001544 * Public functions to get size of the encoded result. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -08001545 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001546QCBORError
1547QCBOREncode_FinishGetSize(QCBOREncodeContext *pMe, size_t *puEncodedLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001548{
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001549 UsefulBufC Enc;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001550
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001551 QCBORError nReturn = QCBOREncode_Finish(pMe, &Enc);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001552
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001553 if(nReturn == QCBOR_SUCCESS) {
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001554 *puEncodedLen = Enc.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001555 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001556
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001557 return nReturn;
1558}