blob: 567f463ea14b6d004f507e468eeb5ca109517afa [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.
3 Copyright (c) 2018, Laurence Lundblade.
4 All rights reserved.
Laurence Lundblade624405d2018-09-18 20:10:47 -07005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade624405d2018-09-18 20:10:47 -070019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundblade624405d2018-09-18 20:10:47 -070031 ==============================================================================*/
32
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070033/*===================================================================================
34 FILE: qcbor_encode.c
35
36 DESCRIPTION: This file contains the implementation of QCBOR.
37
38 EDIT HISTORY FOR FILE:
39
40 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
42
43 when who what, where, why
44 -------- ---- ---------------------------------------------------
Laurence Lundblade067035b2018-11-28 17:35:25 -080045 11/29/18 llundblade Rework to simpler handling of tags and labels.
46 11/9/18 llundblade Error codes are now enums.
47 11/1/18 llundblade Floating support.
48 10/31/18 llundblade Switch to one license that is almost BSD-3.
49 09/28/18 llundblade Added bstr wrapping feature for COSE implementation.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070050 02/05/18 llundbla Works on CPUs which require integer alignment.
51 Requires new version of UsefulBuf.
52 07/05/17 llundbla Add bstr wrapping of maps/arrays for COSE
53 03/01/17 llundbla More data types
54 11/13/16 llundbla Integrate most TZ changes back into github version.
55 09/30/16 gkanike Porting to TZ.
56 03/15/16 llundbla Initial Version.
57
58 =====================================================================================*/
59
60#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070061#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070062
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070063
64/*...... This is a ruler that is 80 characters long...........................*/
65
66
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070067/*
68 CBOR's two nesting types, arrays and maps, are tracked here. There is a
69 limit of QCBOR_MAX_ARRAY_NESTING to the number of arrays and maps
70 that can be nested in one encoding so the encoding context stays
71 small enough to fit on the stack.
72
73 When an array / map is opened, pCurrentNesting points to the element
74 in pArrays that records the type, start position and accumluates a
75 count of the number of items added. When closed the start position is
76 used to go back and fill in the type and number of items in the array
77 / map.
78
79 Encoded output be just items like ints and strings that are
80 not part of any array / map. That is, the first thing encoded
81 does not have to be an array or a map.
82 */
83inline static void Nesting_Init(QCBORTrackNesting *pNesting)
84{
85 // assumes pNesting has been zeroed
86 pNesting->pCurrentNesting = &pNesting->pArrays[0];
87 // Implied CBOR array at the top nesting level. This is never returned,
88 // but makes the item count work correctly.
89 pNesting->pCurrentNesting->uMajorType = CBOR_MAJOR_TYPE_ARRAY;
90}
91
Laurence Lundblade30816f22018-11-10 13:40:22 +070092inline static QCBORError Nesting_Increase(QCBORTrackNesting *pNesting, uint8_t uMajorType, uint32_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070093{
Laurence Lundblade30816f22018-11-10 13:40:22 +070094 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070095
96 if(pNesting->pCurrentNesting == &pNesting->pArrays[QCBOR_MAX_ARRAY_NESTING]) {
97 // trying to open one too many
98 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
99 } else {
100 pNesting->pCurrentNesting++;
101 pNesting->pCurrentNesting->uCount = 0;
102 pNesting->pCurrentNesting->uStart = uPos;
103 pNesting->pCurrentNesting->uMajorType = uMajorType;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700104 }
105 return nReturn;
106}
107
108inline static void Nesting_Decrease(QCBORTrackNesting *pNesting)
109{
110 pNesting->pCurrentNesting--;
111}
112
Laurence Lundblade30816f22018-11-10 13:40:22 +0700113inline static QCBORError Nesting_Increment(QCBORTrackNesting *pNesting, uint16_t uAmount)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700114{
115 if(uAmount >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) {
116 return QCBOR_ERR_ARRAY_TOO_LONG;
117 }
118
119 pNesting->pCurrentNesting->uCount += uAmount;
120 return QCBOR_SUCCESS;
121}
122
123inline static uint16_t Nesting_GetCount(QCBORTrackNesting *pNesting)
124{
125 // The nesting count recorded is always the actual number of individiual
126 // data items in the array or map. For arrays CBOR uses the actual item
127 // count. For maps, CBOR uses the number of pairs. This function returns
128 // the number needed for the CBOR encoding, so it divides the number of
129 // items by two for maps to get the number of pairs. This implementation
130 // takes advantage of the map major type being one larger the array major
131 // type, hence the subtraction returns either 1 or 2.
132 return pNesting->pCurrentNesting->uCount / (pNesting->pCurrentNesting->uMajorType - CBOR_MAJOR_TYPE_ARRAY+1);
133}
134
135inline static uint32_t Nesting_GetStartPos(QCBORTrackNesting *pNesting)
136{
137 return pNesting->pCurrentNesting->uStart;
138}
139
140inline static uint8_t Nesting_GetMajorType(QCBORTrackNesting *pNesting)
141{
142 return pNesting->pCurrentNesting->uMajorType;
143}
144
145inline static int Nesting_IsInNest(QCBORTrackNesting *pNesting)
146{
147 return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? 0 : 1;
148}
149
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700150
151
152
153/*
154 Error tracking plan -- Errors are tracked internally and not returned
155 until Finish is called. The CBOR errors are in me->uError.
Laurence Lundblade067035b2018-11-28 17:35:25 -0800156 UsefulOutBuf also tracks whether the buffer is full or not in its
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700157 context. Once either of these errors is set they are never
158 cleared. Only Init() resets them. Or said another way, they must
159 never be cleared or we'll tell the caller all is good when it is not.
160
161 Only one error code is reported by Finish() even if there are
162 multiple errors. The last one set wins. The caller might have to fix
163 one error to reveal the next one they have to fix. This is OK.
164
165 The buffer full error tracked by UsefulBuf is only pulled out of
166 UsefulBuf in Finish() so it is the one that usually wins. UsefulBuf
167 will never go off the end of the buffer even if it is called again
168 and again when full.
169
170 It is really tempting to not check for overflow on the count in the
171 number of items in an array. It would save a lot of code, it is
172 extremely unlikely that any one will every put 65,000 items in an
173 array, and the only bad thing that would happen is the CBOR would be
174 bogus. Once we prove that is the only consequence, then we can make
175 the change.
176
177 Since this does not parse any input, you could in theory remove all
178 error checks in this code if you knew the caller called it
179 correctly. Maybe someday CDDL or some such language will be able to
180 generate the code to call this and the calling code would always be
Laurence Lundblade56230d12018-11-01 11:14:51 +0700181 correct. This could also automatically size some of the data
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700182 structures like array/map nesting resulting in some good memory
183 savings.
Laurence Lundblade067035b2018-11-28 17:35:25 -0800184
185 Errors returned here fall into three categories:
186
187 Sizes
188 QCBOR_ERR_BUFFER_TOO_LARGE -- A buffer passed in > UINT32_MAX
189 QCBOR_ERR_BUFFER_TOO_SMALL -- output buffer too small
190
191 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP -- Too many opens without closes
192 QCBOR_ERR_ARRAY_TOO_LONG -- Too many things added to an array/map
193
194 Nesting constructed incorrectly
195 QCBOR_ERR_TOO_MANY_CLOSES -- more close calls than opens
196 QCBOR_ERR_CLOSE_MISMATCH -- Type of close does not match open
197 QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes
198
199 Bad data
200 QCBOR_ERR_BAD_SIMPLE -- Simple value integer not valid
201
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700202 */
203
204
205
206
207/*
208 Public function for initialization. See header qcbor.h
209 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700210void QCBOREncode_Init(QCBOREncodeContext *me, UsefulBuf Storage)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700211{
212 memset(me, 0, sizeof(QCBOREncodeContext));
Laurence Lundblade2296db52018-09-14 18:08:39 -0700213 if(Storage.len > UINT32_MAX) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700214 me->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
215 } else {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700216 UsefulOutBuf_Init(&(me->OutBuf), Storage);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700217 Nesting_Init(&(me->nesting));
218 }
219}
220
221
222
223
224/*
225 All CBOR data items have a type and a number. The number is either
226 the value of the item for integer types, the length of the content
227 for string, byte, array and map types, a tag for major type 6, and
228 has serveral uses for major type 7.
229
230 This function encodes the type and the number. There are several
231 encodings for the number depending on how large it is and how it is
232 used.
233
234 Every encoding of the type and number has at least one byte, the
235 "initial byte".
236
237 The top three bits of the initial byte are the major type for the
238 CBOR data item. The eight major types defined by the standard are
239 defined as CBOR_MAJOR_TYPE_xxxx in qcbor.h.
240
241 The remaining five bits, known as "additional information", and
242 possibly more bytes encode the number. If the number is less than 24,
243 then it is encoded entirely in the five bits. This is neat because it
244 allows you to encode an entire CBOR data item in 1 byte for many
245 values and types (integers 0-23, true, false, and tags).
246
247 If the number is larger than 24, then it is encoded in 1,2,4 or 8
248 additional bytes, with the number of these bytes indicated by the
249 values of the 5 bits 24, 25, 25 and 27.
250
251 It is possible to encode a particular number in many ways with this
252 representation. This implementation always uses the smallest
253 possible representation. This is also the suggestion made in the RFC
254 for cannonical CBOR.
255
256 This function inserts them into the output buffer at the specified
Laurence Lundblade067035b2018-11-28 17:35:25 -0800257 position. AppendEncodedTypeAndNumber() appends to the end.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700258
259 This function takes care of converting to network byte order.
260
261 This function is also used to insert floats and doubles. Before this
262 function is called the float or double must be copied into a
263 uint64_t. That is how they are passed in. They are then converted to
264 network byte order correctly. The uMinLen param makes sure that even
Laurence Lundblade067035b2018-11-28 17:35:25 -0800265 if all the digits of a halft, float or double are 0 it is still correctly
266 encoded in 2, 4 or 8 bytes.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700267
268 */
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800269#ifndef FORMALLY_CORRECT_INSERTENCODEDTYPEANDNUMBER
270/* This code does endian conversion without hton or knowing the
271 endianness of the machine with masks and shifts. It avoids the
272 dependency on hton and any mess of figuring out how to find
273 the machines's endianness.
274
275 It is a good efficient implementation on little endian machines.
276 A better implementation is possible on big endian machines
277 because CBOR/network byte order is big endian. However big
278 endian machines are uncommon.
279
280 It is about 200 bytes instead of 500 bytes of code on x86.
281
282 This also does the preferred shortest encoding for integers.
283
284 It works backwards from the LSB to the MSB as needed.
285
286 Code Reviewers: THIS FUNCTION DOES POINTER MATH
287 */
288
289static void InsertEncodedTypeAndNumber(QCBOREncodeContext *me, uint8_t uMajorType, int nMinLen, uint64_t uNumber, size_t uPos)
290{
291 uint8_t bytes[sizeof(uint64_t)+2];
292 uint8_t *pByte = &bytes[sizeof(bytes)];
293 uint8_t ib;
294
295 if(uNumber < CBOR_TWENTY_FOUR && nMinLen == 0) {
296 ib = uNumber;
297 } else {
298 static const uint8_t aIterate[] = {1,1,2,4};
299 ib = 0;
300 while(uNumber || nMinLen > 0) {
301 const uint8_t x = aIterate[ib];
302 nMinLen -= x;
303 for (int i = 0; i < x; i++) {
304 *--pByte = uNumber & 0xff;
305 uNumber = uNumber >> 8;
306 }
307 ib++;
308 }
309 ib += LEN_IS_ONE_BYTE-1;
310 }
311 *--pByte = (uMajorType << 5) + ib;
312
313 UsefulOutBuf_InsertData(&(me->OutBuf), pByte, &bytes[sizeof(bytes)] - pByte, uPos);
314}
315
316#else
317
318/* This does the same as the above, but is easier to understand. This also does no pointer math. */
319static void InsertEncodedTypeAndNumber(QCBOREncodeContext *me, uint8_t uMajorType, int nMinLen, uint64_t uNumber, size_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700320{
321 // No need to worry about integer overflow here because a) uMajorType is
322 // always generated internally, not by the caller, b) this is for CBOR
323 // _generation_, not parsing c) a mistake will result in bad CBOR generation,
324 // not a security vulnerability.
Laurence Lundblade56230d12018-11-01 11:14:51 +0700325 uMajorType <<= 5;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700326
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800327 if(uNumber > 0xffffffff || nMinLen >= 8) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700328 UsefulOutBuf_InsertByte(&(me->OutBuf), uMajorType + LEN_IS_EIGHT_BYTES, uPos);
329 UsefulOutBuf_InsertUint64(&(me->OutBuf), (uint64_t)uNumber, uPos+1);
330
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800331 } else if(uNumber > 0xffff || nMinLen >= 4) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700332 UsefulOutBuf_InsertByte(&(me->OutBuf), uMajorType + LEN_IS_FOUR_BYTES, uPos);
333 UsefulOutBuf_InsertUint32(&(me->OutBuf), (uint32_t)uNumber, uPos+1);
334
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800335 } else if (uNumber > 0xff || nMinLen>= 2) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700336 // Between 0 and 65535
337 UsefulOutBuf_InsertByte(&(me->OutBuf), uMajorType + LEN_IS_TWO_BYTES, uPos);
338 UsefulOutBuf_InsertUint16(&(me->OutBuf), (uint16_t)uNumber, uPos+1);
339
340 } else if(uNumber >= 24) {
341 // Between 0 and 255, but only between 24 and 255 is ever encoded here
342 UsefulOutBuf_InsertByte(&(me->OutBuf), uMajorType + LEN_IS_ONE_BYTE, uPos);
343 UsefulOutBuf_InsertByte(&(me->OutBuf), (uint8_t)uNumber, uPos+1);
344
345 } else {
346 // Between 0 and 23
347 UsefulOutBuf_InsertByte(&(me->OutBuf), uMajorType + (uint8_t)uNumber, uPos);
348 }
349}
Laurence Lundblade351bfea2018-12-07 21:34:31 +0900350
Laurence Lundblade351bfea2018-12-07 21:34:31 +0900351#endif
352
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700353
354
355/*
356 Append the type and number info to the end of the buffer.
357
358 See InsertEncodedTypeAndNumber() function above for details
359*/
360inline static void AppendEncodedTypeAndNumber(QCBOREncodeContext *me, uint8_t uMajorType, uint64_t uNumber)
361{
362 // An append is an insert at the end.
363 InsertEncodedTypeAndNumber(me, uMajorType, 0, uNumber, UsefulOutBuf_GetEndPosition(&(me->OutBuf)));
364}
365
366
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700367
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700368/*
Laurence Lundblade067035b2018-11-28 17:35:25 -0800369 Public functions for closing arrays and maps. See header qcbor.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700370 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800371void QCBOREncode_AddUInt64(QCBOREncodeContext *me, uint64_t uValue)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700372{
Laurence Lundblade067035b2018-11-28 17:35:25 -0800373 if(me->uError == QCBOR_SUCCESS) {
374 AppendEncodedTypeAndNumber(me, CBOR_MAJOR_TYPE_POSITIVE_INT, uValue);
375 me->uError = Nesting_Increment(&(me->nesting), 1);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700376 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700377}
378
Laurence Lundblade56230d12018-11-01 11:14:51 +0700379
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700380/*
Laurence Lundblade067035b2018-11-28 17:35:25 -0800381 Public functions for closing arrays and maps. See header qcbor.h
382 */
383void QCBOREncode_AddInt64(QCBOREncodeContext *me, int64_t nNum)
384{
385 if(me->uError == QCBOR_SUCCESS) {
386 uint8_t uMajorType;
387 uint64_t uValue;
388
389 if(nNum < 0) {
390 uValue = (uint64_t)(-nNum - 1); // This is the way negative ints work in CBOR. -1 encodes as 0x00 with major type negative int.
391 uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
392 } else {
393 uValue = (uint64_t)nNum;
394 uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
395 }
396
397 AppendEncodedTypeAndNumber(me, uMajorType, uValue);
398 me->uError = Nesting_Increment(&(me->nesting), 1);
399 }
400}
401
402
403/*
404 Semi-private function. It is exposed to user of the interface,
405 but they will usually call one of the inline wrappers rather than this.
406
407 See header qcbor.h
408
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700409 Does the work of adding some bytes to the CBOR output. Works for a
410 byte and text strings, which are the same in in CBOR though they have
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700411 different major types. This is also used to insert raw
412 pre-encoded CBOR.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700413 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800414void QCBOREncode_AddBuffer(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC Bytes)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700415{
416 if(Bytes.len >= UINT32_MAX) {
Laurence Lundblade56230d12018-11-01 11:14:51 +0700417 // This implementation doesn't allow buffers larger than UINT32_MAX.
418 // This is primarily because QCBORTrackNesting.pArrays[].uStart is
419 // an uint32 rather than size_t to keep the stack usage down. Also
420 // it is entirely impractical to create tokens bigger than 4GB in
421 // contiguous RAM
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700422 me->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
423
424 } else {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700425 if(!me->uError) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700426 // If it is not Raw CBOR, add the type and the length
427 if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
Laurence Lundblade067035b2018-11-28 17:35:25 -0800428 AppendEncodedTypeAndNumber(me, uMajorType, Bytes.len);
Laurence Lundblade56230d12018-11-01 11:14:51 +0700429 // The increment in uPos is to account for bytes added for
430 // type and number so the buffer being added goes to the
431 // right place
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700432 }
433
434 // Actually add the bytes
Laurence Lundblade067035b2018-11-28 17:35:25 -0800435 UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), Bytes);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700436
437 // Update the array counting if there is any nesting at all
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700438 me->uError = Nesting_Increment(&(me->nesting), 1);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700439 }
440 }
441}
442
Laurence Lundbladecafcfe12018-10-31 21:59:50 +0700443
Laurence Lundblade55a24832018-10-30 04:35:08 +0700444/*
Laurence Lundblade067035b2018-11-28 17:35:25 -0800445 Public functions for closing arrays and maps. See header qcbor.h
Laurence Lundblade55a24832018-10-30 04:35:08 +0700446 */
447void QCBOREncode_AddTag(QCBOREncodeContext *me, uint64_t uTag)
448{
Laurence Lundblade55a24832018-10-30 04:35:08 +0700449 AppendEncodedTypeAndNumber(me, CBOR_MAJOR_TYPE_OPTIONAL, uTag);
450}
451
452
Laurence Lundblade487930f2018-11-30 11:01:45 -0800453
454
Laurence Lundblade56230d12018-11-01 11:14:51 +0700455/*
Laurence Lundblade487930f2018-11-30 11:01:45 -0800456 Semi-private function. It is exposed to user of the interface,
457 but they will usually call one of the inline wrappers rather than this.
458
459 See header qcbor.h
Laurence Lundblade56230d12018-11-01 11:14:51 +0700460 */
Laurence Lundblade487930f2018-11-30 11:01:45 -0800461void QCBOREncode_AddType7(QCBOREncodeContext *me, size_t uSize, uint64_t uNum)
Laurence Lundblade55a24832018-10-30 04:35:08 +0700462{
Laurence Lundblade487930f2018-11-30 11:01:45 -0800463 if(me->uError == QCBOR_SUCCESS) {
464 // This function call takes care of endian swapping for the float / double
465 InsertEncodedTypeAndNumber(me,
466 CBOR_MAJOR_TYPE_SIMPLE, // The major type for
467 // floats and doubles
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800468 (int)uSize, // min size / tells
Laurence Lundblade487930f2018-11-30 11:01:45 -0800469 // encoder to do it right
470 uNum, // Bytes of the floating
471 // point number as a uint
472 UsefulOutBuf_GetEndPosition(&(me->OutBuf))); // end position for append
473
474 me->uError = Nesting_Increment(&(me->nesting), 1);
475 }
Laurence Lundblade55a24832018-10-30 04:35:08 +0700476}
477
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700478
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700479/*
Laurence Lundblade067035b2018-11-28 17:35:25 -0800480 Public functions for closing arrays and maps. See header qcbor.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700481 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800482void QCBOREncode_AddDouble(QCBOREncodeContext *me, double dNum)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700483{
Laurence Lundblade067035b2018-11-28 17:35:25 -0800484 const IEEE754_union uNum = IEEE754_DoubleToSmallest(dNum);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700485
Laurence Lundblade487930f2018-11-30 11:01:45 -0800486 QCBOREncode_AddType7(me, uNum.uSize, uNum.uValue);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800487}
488
489
490/*
491 Semi-public function. It is exposed to user of the interface,
492 but they will usually call one of the inline wrappers rather than this.
493
494 See header qcbor.h
495*/
496void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType)
497{
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700498 // Add one item to the nesting level we are in for the new map or array
499 me->uError = Nesting_Increment(&(me->nesting), 1);
500 if(!me->uError) {
501 // Increase nesting level because this is a map or array
502 // Cast from size_t to uin32_t is safe because the UsefulOutBuf
503 // size is limited to UINT32_MAX in QCBOR_Init().
Laurence Lundbladea954db92018-09-28 19:27:31 -0700504 me->uError = Nesting_Increase(&(me->nesting), uMajorType, (uint32_t)UsefulOutBuf_GetEndPosition(&(me->OutBuf)));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700505 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700506}
507
508
509/*
Laurence Lundbladecafcfe12018-10-31 21:59:50 +0700510 Public functions for closing arrays and maps. See header qcbor.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700511 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800512void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC *pWrappedCBOR)
Laurence Lundbladea954db92018-09-28 19:27:31 -0700513{
514 if(!me->uError) {
515 if(!Nesting_IsInNest(&(me->nesting))) {
516 me->uError = QCBOR_ERR_TOO_MANY_CLOSES;
517 } else if( Nesting_GetMajorType(&(me->nesting)) != uMajorType) {
Laurence Lundblade067035b2018-11-28 17:35:25 -0800518 me->uError = QCBOR_ERR_CLOSE_MISMATCH;
Laurence Lundbladea954db92018-09-28 19:27:31 -0700519 } else {
Laurence Lundblade56230d12018-11-01 11:14:51 +0700520 // When the array, map or bstr wrap was started, nothing was done
521 // except note the position of the start of it. This code goes back
522 // and inserts the actual CBOR array, map or bstr and its length.
523 // That means all the data that is in the array, map or wrapped
524 // needs to be slid to the right. This is done by UsefulOutBuf's
525 // insert function that is called from inside
526 // InsertEncodedTypeAndNumber()
527 const size_t uInsertPosition = Nesting_GetStartPos(&(me->nesting));
528 const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
529 // This can't go negative because the UsefulOutBuf always only grows
530 // and never shrinks. UsefulOutBut itself also has defenses such that
531 // it won't write were it should not even if given hostile input lengths
532 const size_t uLenOfEncodedMapOrArray = uEndPosition - uInsertPosition;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700533
Laurence Lundblade56230d12018-11-01 11:14:51 +0700534 // Length is number of bytes for a bstr and number of items a for map & array
535 const size_t uLength = uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING ?
Laurence Lundbladea954db92018-09-28 19:27:31 -0700536 uLenOfEncodedMapOrArray : Nesting_GetCount(&(me->nesting));
537
538 // Actually insert
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700539 InsertEncodedTypeAndNumber(me,
Laurence Lundbladea954db92018-09-28 19:27:31 -0700540 uMajorType, // major type bstr, array or map
541 0, // no minimum length for encoding
542 uLength, // either len of bstr or num items in array or map
543 uInsertPosition); // position in out buffer
544
545 // Return pointer and length to the enclosed encoded CBOR. The intended
546 // use is for it to be hashed (e.g., SHA-256) in a COSE implementation.
547 // This must be used right away, as the pointer and length go invalid
548 // on any subsequent calls to this function because of the
549 // InsertEncodedTypeAndNumber() call that slides data to the right.
550 if(pWrappedCBOR) {
551 UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(me->OutBuf));
Laurence Lundblade56230d12018-11-01 11:14:51 +0700552 size_t uBstrLen = UsefulOutBuf_GetEndPosition(&(me->OutBuf)) - uEndPosition;
Laurence Lundbladea954db92018-09-28 19:27:31 -0700553 *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uInsertPosition+uBstrLen);
554 }
555 Nesting_Decrease(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700557 }
558}
559
560
Laurence Lundblade56230d12018-11-01 11:14:51 +0700561
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700562/*
563 Public functions to finish and get the encoded result. See header qcbor.h
564 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700565QCBORError QCBOREncode_Finish(QCBOREncodeContext *me, UsefulBufC *pEncodedCBOR)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700566{
Laurence Lundblade067035b2018-11-28 17:35:25 -0800567 QCBORError uReturn = me->uError;
568
569 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700570 goto Done;
Laurence Lundblade067035b2018-11-28 17:35:25 -0800571 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700572
573 if (Nesting_IsInNest(&(me->nesting))) {
Laurence Lundblade067035b2018-11-28 17:35:25 -0800574 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700575 goto Done;
576 }
577
578 if(UsefulOutBuf_GetError(&(me->OutBuf))) {
579 // Stuff didn't fit in the buffer.
Laurence Lundblade56230d12018-11-01 11:14:51 +0700580 // This check catches this condition for all the appends and inserts
581 // so checks aren't needed when the appends and inserts are performed.
582 // And of course UsefulBuf will never overrun the input buffer given
583 // to it. No complex analysis of the error handling in this file is
584 // needed to know that is true. Just read the UsefulBuf code.
Laurence Lundblade067035b2018-11-28 17:35:25 -0800585 uReturn = QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700586 goto Done;
587 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700588
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700589 *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(me->OutBuf));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700590
591Done:
Laurence Lundblade067035b2018-11-28 17:35:25 -0800592 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700593}
594
Laurence Lundblade0595e932018-11-02 22:22:47 +0700595
Laurence Lundblade067035b2018-11-28 17:35:25 -0800596/*
597 Public functions to finish and get the encoded result. See header qcbor.h
598 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700599QCBORError QCBOREncode_FinishGetSize(QCBOREncodeContext *me, size_t *puEncodedLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700600{
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700601 UsefulBufC Enc;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700602
Laurence Lundblade30816f22018-11-10 13:40:22 +0700603 QCBORError nReturn = QCBOREncode_Finish(me, &Enc);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700604
605 if(nReturn == QCBOR_SUCCESS) {
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700606 *puEncodedLen = Enc.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700607 }
608
609 return nReturn;
610}
611
612
Laurence Lundblade067035b2018-11-28 17:35:25 -0800613
614
615/*
616 Notes on the code
617
618 CBOR Major Type Public Function
619 0 QCBOREncode_AddUInt64
620 0, 1 QCBOREncode_AddUInt64, QCBOREncode_AddInt64
621 2, 3 QCBOREncode_AddBuffer, Also QCBOREncode_OpenMapOrArray
622 4, 5 QCBOREncode_OpenMapOrArray
623 6 QCBOREncode_AddTag
624 7 QCBOREncode_AddDouble, QCBOREncode_AddSimple
625
626 Object code sizes on X86 with LLVM compiler and -Os (Nov 27, 2018)
627
628 _QCBOREncode_Init 84
629 _QCBOREncode_AddUInt64 76
630 _QCBOREncode_AddInt64 87
631 _QCBOREncode_AddBuffer 131
632 _QCBOREncode_AddSimple 30
633 _AppendType7 83
634 _QCBOREncode_OpenMapOrArray 89
635 _QCBOREncode_CloseMapOrArray 181
636 _InsertEncodedTypeAndNumber 480
637 _QCBOREncode_Finish 72
638
639 Total is about 1.4KB (including FinishGetSize and AddTag and AddDouble)
640
Laurence Lundblade067035b2018-11-28 17:35:25 -0800641 _QCBOREncode_CloseMapOrArray is larger because it has a lot
642 of nesting tracking to do and much of Nesting_ inlines
643 into it. It probably can't be reduced much.
644
645 If the error returned by Nesting_Increment() can be ignored
646 because the limit is so high and the consequence of exceeding
647 is proved to be inconsequential, then a lot of if(me->uError)
648 instance can be removed, saving some code.
649
650 */
651
652
Laurence Lundblade351bfea2018-12-07 21:34:31 +0900653/*
654 _InsertEncodedTypeAndNumber: ## @InsertEncodedTypeAndNumber
655Lfunc_begin10:
656 .loc 7 307 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:307:0
657 .cfi_startproc
658## BB#0:
659 pushq %rbp
660Lcfi30:
661 .cfi_def_cfa_offset 16
662Lcfi31:
663 .cfi_offset %rbp, -16
664 movq %rsp, %rbp
665Lcfi32:
666 subq $80, %rsp
667 movb %sil, %al
668 movl $4294967295, %esi ## imm = 0xFFFFFFFF
669 movl %esi, %r9d
670 movq (%r10), %r10
671 movq %r10, -8(%rbp)
672 movq %rdi, -32(%rbp)
673 movb %al, -33(%rbp)
674 movq %rdx, -48(%rbp)
675 movq %rcx, -56(%rbp)
676 movq %r8, -64(%rbp)
677Ltmp50:
678 .loc 7 314 15 prologue_end ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:314:15
679 movzbl -33(%rbp), %esi
680 shll $5, %esi
681 movb %sil, %al
682 movb %al, -33(%rbp)
683Ltmp51:
684 .loc 7 316 15 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:316:15
685 cmpq %r9, -56(%rbp)
686 .loc 7 316 28 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:316:28
687 ja LBB10_2
688## BB#1:
689 .loc 7 316 39 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:316:39
690 cmpq $8, -48(%rbp)
691Ltmp52:
692 .loc 7 316 7 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:316:7
693 jb LBB10_3
694LBB10_2:
695Ltmp53:
696 .loc 7 317 19 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:317:19
697 movzbl -33(%rbp), %eax
698 .loc 7 317 30 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:317:30
699 addl $27, %eax
700 .loc 7 317 19 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:317:19
701 movb %al, %cl
702 .loc 7 317 16 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:317:16
703 movb %cl, -17(%rbp)
704 .loc 7 318 17 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:318:17
705 movq -56(%rbp), %rdi
706 callq __OSSwapInt64
707 .loc 7 318 15 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:318:15
708 movq %rax, -56(%rbp)
709 .loc 7 319 7 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:319:7
710 movq -56(%rbp), %rax
711 movq %rax, -16(%rbp)
712 .loc 7 320 16 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:320:16
713 movq $9, -72(%rbp)
714 .loc 7 322 4 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:322:4
715 jmp LBB10_15
716Ltmp54:
717LBB10_3:
718 .loc 7 322 22 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:322:22
719 cmpq $65535, -56(%rbp) ## imm = 0xFFFF
720 .loc 7 322 31 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:322:31
721 ja LBB10_5
722## BB#4:
723 .loc 7 322 42 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:322:42
724 cmpq $4, -48(%rbp)
725Ltmp55:
726 .loc 7 322 14 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:322:14
727 jb LBB10_6
728LBB10_5:
729Ltmp56:
730 .loc 7 323 19 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:323:19
731 movzbl -33(%rbp), %eax
732 .loc 7 323 30 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:323:30
733 addl $26, %eax
734 .loc 7 323 19 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:323:19
735 movb %al, %cl
736 .loc 7 323 16 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:323:16
737 movb %cl, -17(%rbp)
738 .loc 7 324 28 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:324:28
739 movq -56(%rbp), %rdx
740 movl %edx, %eax
741 movl %eax, %edi
742 callq __OSSwapInt32
743 .loc 7 324 16 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:324:16
744 movl %eax, -76(%rbp)
745 .loc 7 325 7 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:325:7
746 movl -76(%rbp), %eax
747 movl %eax, -16(%rbp)
748 .loc 7 326 16 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:326:16
749 movq $5, -72(%rbp)
750 .loc 7 328 4 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:328:4
751 jmp LBB10_14
752Ltmp57:
753LBB10_6:
754 .loc 7 328 23 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:328:23
755 cmpq $255, -56(%rbp)
756 .loc 7 328 30 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:328:30
757 ja LBB10_8
758## BB#7:
759 .loc 7 328 40 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:328:40
760 cmpq $2, -48(%rbp)
761Ltmp58:
762 .loc 7 328 15 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:328:15
763 jb LBB10_9
764LBB10_8:
765Ltmp59:
766 .loc 7 330 19 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:330:19
767 movzbl -33(%rbp), %eax
768 .loc 7 330 30 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:330:30
769 addl $25, %eax
770 .loc 7 330 19 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:330:19
771 movb %al, %cl
772 .loc 7 330 16 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:330:16
773 movb %cl, -17(%rbp)
774 .loc 7 331 28 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:331:28
775 movq -56(%rbp), %rdx
776 movw %dx, %si
777 movzwl %si, %edi
778 callq __OSSwapInt16
779 movzwl %ax, %edi
780 movw %di, %ax
781 .loc 7 331 16 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:331:16
782 movw %ax, -78(%rbp)
783 .loc 7 332 7 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:332:7
784 movw -78(%rbp), %ax
785 movw %ax, -16(%rbp)
786 .loc 7 333 16 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:333:16
787 movq $3, -72(%rbp)
788 .loc 7 335 4 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:335:4
789 jmp LBB10_13
790Ltmp60:
791LBB10_9:
792 .loc 7 335 22 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:335:22
793 cmpq $24, -56(%rbp)
794Ltmp61:
795 .loc 7 335 14 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:335:14
796 jb LBB10_11
797## BB#10:
798Ltmp62:
799 .loc 7 337 19 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:337:19
800 movzbl -33(%rbp), %eax
801 .loc 7 337 30 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:337:30
802 addl $24, %eax
803 .loc 7 337 19 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:337:19
804 movb %al, %cl
805 .loc 7 337 16 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:337:16
806 movb %cl, -17(%rbp)
807 .loc 7 338 26 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:338:26
808 movq -56(%rbp), %rdx
809 movb %dl, %cl
810 .loc 7 338 15 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:338:15
811 movb %cl, -79(%rbp)
812 .loc 7 339 7 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:339:7
813 movb -79(%rbp), %cl
814 movb %cl, -16(%rbp)
815 .loc 7 340 16 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:340:16
816 movq $2, -72(%rbp)
817 .loc 7 342 4 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:342:4
818 jmp LBB10_12
819Ltmp63:
820LBB10_11:
821 .loc 7 344 18 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:344:18
822 movzbl -33(%rbp), %eax
823 .loc 7 344 40 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:344:40
824 movq -56(%rbp), %rcx
825 .loc 7 344 31 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:344:31
826 movb %cl, %dl
827 movzbl %dl, %esi
828 .loc 7 344 29 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:344:29
829 addl %esi, %eax
830 .loc 7 344 18 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:344:18
831 movb %al, %dl
832 .loc 7 344 16 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:344:16
833 movb %dl, -17(%rbp)
834 .loc 7 345 16 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:345:16
835 movq $1, -72(%rbp)
836Ltmp64:
837LBB10_12:
838 .loc 7 0 16 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:0:16
839 jmp LBB10_13
840LBB10_13:
841 jmp LBB10_14
842LBB10_14:
843 jmp LBB10_15
844LBB10_15:
845 leaq -17(%rbp), %rsi
846 .loc 7 347 30 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:347:30
847 movq -32(%rbp), %rdi
848 .loc 7 347 50 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:347:50
849 movq -72(%rbp), %rdx
850 .loc 7 347 60 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:347:60
851 movq -64(%rbp), %rcx
852 .loc 7 347 4 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:347:4
853 callq _UsefulOutBuf_InsertData
854 movq ___stack_chk_guard@GOTPCREL(%rip), %rcx
855 movq (%rcx), %rcx
856 movq -8(%rbp), %rdx
857 cmpq %rdx, %rcx
858 jne LBB10_17
859## BB#16:
860 .loc 7 348 1 is_stmt 1 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:348:1
861 addq $80, %rsp
862 popq %rbp
863 retq
864LBB10_17:
865 .loc 7 0 0 is_stmt 0 ## /Users/laurencelundblade/Code/QCBOR/master/src/qcbor_encode.c:0:0
866 callq ___stack_chk_fail
867Ltmp65:
868Lfunc_end10:
869 .cfi_endproc
Laurence Lundblade067035b2018-11-28 17:35:25 -0800870
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800871*/
Laurence Lundblade067035b2018-11-28 17:35:25 -0800872
873
874