Revert "Change build option - IP only"
[platform/upstream/iotivity.git] / extlibs / tinycbor / tinycbor / src / cborparser.c
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 Intel Corporation
4 **
5 ** Permission is hereby granted, free of charge, to any person obtaining a copy
6 ** of this software and associated documentation files (the "Software"), to deal
7 ** in the Software without restriction, including without limitation the rights
8 ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 ** copies of the Software, and to permit persons to whom the Software is
10 ** furnished to do so, subject to the following conditions:
11 **
12 ** The above copyright notice and this permission notice shall be included in
13 ** all copies or substantial portions of the Software.
14 **
15 ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 ** THE SOFTWARE.
22 **
23 ****************************************************************************/
24
25 #define _BSD_SOURCE 1
26 #include "cbor.h"
27 #include "cborconstants_p.h"
28 #include "compilersupport_p.h"
29 #include "extract_number_p.h"
30
31 #include <assert.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "assert_p.h"       /* Always include last */
36
37 #ifndef CBOR_PARSER_MAX_RECURSIONS
38 #  define CBOR_PARSER_MAX_RECURSIONS 1024
39 #endif
40
41 /**
42  * \typedef CborValue
43  * This type contains one value parsed from the CBOR stream.
44  *
45  * To get the actual type, use cbor_value_get_type(). Then extract the value
46  * using one of the corresponding functions: cbor_value_get_boolean(), cbor_value_get_int64(),
47  * cbor_value_get_int(), cbor_value_copy_string(), cbor_value_get_array(), cbor_value_get_map(),
48  * cbor_value_get_double(), cbor_value_get_float().
49  *
50  * In C++ and C11 modes, you can additionally use the cbor_value_get_integer()
51  * and cbor_value_get_floating_point() generic functions.
52  *
53  * \omit
54  * Implementation details: the CborValue contains these fields:
55  * \list
56  *   \li ptr: pointer to the actual data
57  *   \li flags: flags from the decoder
58  *   \li extra: partially decoded integer value (0, 1 or 2 bytes)
59  *   \li remaining: remaining items in this collection after this item or UINT32_MAX if length is unknown
60  * \endlist
61  * \endomit
62  */
63
64 static CborError extract_length(const CborParser *parser, const uint8_t **ptr, size_t *len)
65 {
66     uint64_t v;
67     CborError err = extract_number(ptr, parser->end, &v);
68     if (err)
69         return err;
70
71     *len = v;
72     if (v != *len)
73         return CborErrorDataTooLarge;
74     return CborNoError;
75 }
76
77 static bool is_fixed_type(uint8_t type)
78 {
79     return type != CborTextStringType && type != CborByteStringType && type != CborArrayType &&
80            type != CborMapType;
81 }
82
83 static CborError preparse_value(CborValue *it)
84 {
85     const CborParser *parser = it->parser;
86     it->type = CborInvalidType;
87
88     // are we at the end?
89     if (it->ptr == parser->end)
90         return CborErrorUnexpectedEOF;
91
92     uint8_t descriptor = *it->ptr;
93     uint8_t type = descriptor & MajorTypeMask;
94     it->type = type;
95     it->flags = 0;
96     it->extra = (descriptor &= SmallValueMask);
97
98     if (descriptor > Value64Bit) {
99         if (unlikely(descriptor != IndefiniteLength))
100             return type == CborSimpleType ? CborErrorUnknownType : CborErrorIllegalNumber;
101         if (likely(!is_fixed_type(type))) {
102             // special case
103             it->flags |= CborIteratorFlag_UnknownLength;
104             it->type = type;
105             return CborNoError;
106         }
107         return type == CborSimpleType ? CborErrorUnexpectedBreak : CborErrorIllegalNumber;
108     }
109
110     size_t bytesNeeded = descriptor < Value8Bit ? 0 : (1 << (descriptor - Value8Bit));
111     if (bytesNeeded + 1 > (size_t)(parser->end - it->ptr))
112         return CborErrorUnexpectedEOF;
113
114     uint8_t majortype = type >> MajorTypeShift;
115     if (majortype == NegativeIntegerType) {
116         it->flags |= CborIteratorFlag_NegativeInteger;
117         it->type = CborIntegerType;
118     } else if (majortype == SimpleTypesType) {
119         switch (descriptor) {
120         case FalseValue:
121             it->extra = false;
122             it->type = CborBooleanType;
123             break;
124
125         case SinglePrecisionFloat:
126         case DoublePrecisionFloat:
127             it->flags |= CborIteratorFlag_IntegerValueTooLarge;
128             // fall through
129         case TrueValue:
130         case NullValue:
131         case UndefinedValue:
132         case HalfPrecisionFloat:
133             it->type = *it->ptr;
134             break;
135
136         case SimpleTypeInNextByte:
137             it->extra = (uint8_t)it->ptr[1];
138 #ifndef CBOR_PARSER_NO_STRICT_CHECKS
139             if (unlikely(it->extra < 32)) {
140                 it->type = CborInvalidType;
141                 return CborErrorIllegalSimpleType;
142             }
143 #endif
144             break;
145
146         case 28:
147         case 29:
148         case 30:
149         case Break:
150             assert(false);  // these conditions can't be reached
151             return CborErrorUnexpectedBreak;
152         }
153         return CborNoError;
154     }
155
156     // try to decode up to 16 bits
157     if (descriptor < Value8Bit)
158         return CborNoError;
159
160     if (descriptor == Value8Bit)
161         it->extra = (uint8_t)it->ptr[1];
162     else if (descriptor == Value16Bit)
163         it->extra = get16(it->ptr + 1);
164     else
165         it->flags |= CborIteratorFlag_IntegerValueTooLarge;     // Value32Bit or Value64Bit
166     return CborNoError;
167 }
168
169 static CborError preparse_next_value(CborValue *it)
170 {
171     if (it->remaining != UINT32_MAX) {
172         // don't decrement the item count if the current item is tag: they don't count
173         if (it->type != CborTagType && !--it->remaining) {
174             it->type = CborInvalidType;
175             return CborNoError;
176         }
177     } else if (it->remaining == UINT32_MAX && it->ptr != it->parser->end && *it->ptr == (uint8_t)BreakByte) {
178         // end of map or array
179         ++it->ptr;
180         it->type = CborInvalidType;
181         it->remaining = 0;
182         return CborNoError;
183     }
184
185     return preparse_value(it);
186 }
187
188 static CborError advance_internal(CborValue *it)
189 {
190     uint64_t length;
191     CborError err = extract_number(&it->ptr, it->parser->end, &length);
192     assert(err == CborNoError);
193
194     if (it->type == CborByteStringType || it->type == CborTextStringType) {
195         assert(length == (size_t)length);
196         assert((it->flags & CborIteratorFlag_UnknownLength) == 0);
197         it->ptr += length;
198     }
199
200     return preparse_next_value(it);
201 }
202
203 /** \internal
204  *
205  * Decodes the CBOR integer value when it is larger than the 16 bits available
206  * in value->extra. This function requires that value->flags have the
207  * CborIteratorFlag_IntegerValueTooLarge flag set.
208  *
209  * This function is also used to extract single- and double-precision floating
210  * point values (SinglePrecisionFloat == Value32Bit and DoublePrecisionFloat ==
211  * Value64Bit).
212  */
213 uint64_t _cbor_value_decode_int64_internal(const CborValue *value)
214 {
215     assert(value->flags & CborIteratorFlag_IntegerValueTooLarge ||
216            value->type == CborFloatType || value->type == CborDoubleType);
217
218     // since the additional information can only be Value32Bit or Value64Bit,
219     // we just need to test for the one bit those two options differ
220     assert((*value->ptr & SmallValueMask) == Value32Bit || (*value->ptr & SmallValueMask) == Value64Bit);
221     if ((*value->ptr & 1) == (Value32Bit & 1))
222         return get32(value->ptr + 1);
223
224     assert((*value->ptr & SmallValueMask) == Value64Bit);
225     return get64(value->ptr + 1);
226 }
227
228 /**
229  * Initializes the CBOR parser for parsing \a size bytes beginning at \a
230  * buffer. Parsing will use flags set in \a flags. The iterator to the first
231  * element is returned in \a it.
232  *
233  * The \a parser structure needs to remain valid throughout the decoding
234  * process. It is not thread-safe to share one CborParser among multiple
235  * threads iterating at the same time, but the object can be copied so multiple
236  * threads can iterate.
237  *
238  * ### Write how to determine the end pointer
239  * ### Write how to do limited-buffer windowed decoding
240  */
241 CborError cbor_parser_init(const uint8_t *buffer, size_t size, int flags, CborParser *parser, CborValue *it)
242 {
243     memset(parser, 0, sizeof(*parser));
244     parser->end = buffer + size;
245     parser->flags = flags;
246     it->parser = parser;
247     it->ptr = buffer;
248     it->remaining = 1;      // there's one type altogether, usually an array or map
249     return preparse_value(it);
250 }
251
252 /**
253  * Advances the CBOR value \a it by one fixed-size position. Fixed-size types
254  * are: integers, tags, simple types (including boolean, null and undefined
255  * values) and floating point types.
256  *
257  * \sa cbor_value_at_end(), cbor_value_advance(), cbor_value_begin_recurse(), cbor_value_end_recurse()
258  */
259 CborError cbor_value_advance_fixed(CborValue *it)
260 {
261     assert(it->type != CborInvalidType);
262     assert(is_fixed_type(it->type));
263     if (!it->remaining)
264         return CborErrorAdvancePastEOF;
265     return advance_internal(it);
266 }
267
268 static CborError advance_recursive(CborValue *it, int nestingLevel)
269 {
270     if (is_fixed_type(it->type))
271         return advance_internal(it);
272
273     if (!cbor_value_is_container(it)) {
274         size_t len = SIZE_MAX;
275         return _cbor_value_copy_string(it, NULL, &len, it);
276     }
277
278     // map or array
279     if (nestingLevel == CBOR_PARSER_MAX_RECURSIONS)
280         return CborErrorNestingTooDeep;
281
282     CborError err;
283     CborValue recursed;
284     err = cbor_value_enter_container(it, &recursed);
285     if (err)
286         return err;
287     while (!cbor_value_at_end(&recursed)) {
288         err = advance_recursive(&recursed, nestingLevel + 1);
289         if (err)
290             return err;
291     }
292     return cbor_value_leave_container(it, &recursed);
293 }
294
295
296 /**
297  * Advances the CBOR value \a it by one element, skipping over containers.
298  * Unlike cbor_value_advance_fixed(), this function can be called on a CBOR
299  * value of any type. However, if the type is a container (map or array) or a
300  * string with a chunked payload, this function will not run in constant time
301  * and will recurse into itself (it will run on O(n) time for the number of
302  * elements or chunks and will use O(n) memory for the number of nested
303  * containers).
304  *
305  * \sa cbor_value_at_end(), cbor_value_advance_fixed(), cbor_value_begin_recurse(), cbor_value_end_recurse()
306  */
307 CborError cbor_value_advance(CborValue *it)
308 {
309     assert(it->type != CborInvalidType);
310     if (!it->remaining)
311         return CborErrorAdvancePastEOF;
312     return advance_recursive(it, 0);
313 }
314
315 /**
316  * Advances the CBOR value \a it until it no longer points to a tag. If \a it is
317  * already not pointing to a tag, then this function returns it unchanged.
318  *
319  * \sa cbor_value_advance_fixed(), cbor_value_advance()
320  */
321 CborError cbor_value_skip_tag(CborValue *it)
322 {
323     while (cbor_value_is_tag(it)) {
324         CborError err = cbor_value_advance_fixed(it);
325         if (err)
326             return err;
327     }
328     return CborNoError;
329 }
330
331 /**
332  * \fn bool cbor_value_is_container(const CborValue *it)
333  *
334  * Returns true if the \a it value is a container and requires recursion in
335  * order to decode (maps and arrays), false otherwise.
336  */
337
338 /**
339  * Creates a CborValue iterator pointing to the first element of the container
340  * represented by \a it and saves it in \a recursed. The \a it container object
341  * needs to be kept and passed again to cbor_value_leave_container() in order
342  * to continue iterating past this container.
343  *
344  * \sa cbor_value_is_container(), cbor_value_leave_container(), cbor_value_advance()
345  */
346 CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed)
347 {
348     CborError err;
349     assert(cbor_value_is_container(it));
350     *recursed = *it;
351
352     if (it->flags & CborIteratorFlag_UnknownLength) {
353         recursed->remaining = UINT32_MAX;
354         ++recursed->ptr;
355         err = preparse_value(recursed);
356         if (err != CborErrorUnexpectedBreak)
357             return err;
358         // actually, break was expected here
359         // it's just an empty container
360         ++recursed->ptr;
361     } else {
362         uint64_t len;
363         err = extract_number(&recursed->ptr, recursed->parser->end, &len);
364         assert(err == CborNoError);
365
366         recursed->remaining = len;
367         if (recursed->remaining != len || len == UINT32_MAX) {
368             // back track the pointer to indicate where the error occurred
369             recursed->ptr = it->ptr;
370             return CborErrorDataTooLarge;
371         }
372         if (recursed->type == CborMapType) {
373             // maps have keys and values, so we need to multiply by 2
374             if (recursed->remaining > UINT32_MAX / 2) {
375                 // back track the pointer to indicate where the error occurred
376                 recursed->ptr = it->ptr;
377                 return CborErrorDataTooLarge;
378             }
379             recursed->remaining *= 2;
380         }
381         if (len != 0)
382             return preparse_value(recursed);
383     }
384
385     // the case of the empty container
386     recursed->type = CborInvalidType;
387     recursed->remaining = 0;
388     return CborNoError;
389 }
390
391 /**
392  * Updates \a it to point to the next element after the container. The \a
393  * recursed object needs to point to the element obtained either by advancing
394  * the last element of the container (via cbor_value_advance(),
395  * cbor_value_advance_fixed(), a nested cbor_value_leave_container(), or the \c
396  * next pointer from cbor_value_copy_string() or cbor_value_dup_string()).
397  *
398  * \sa cbor_value_enter_container(), cbor_value_at_end()
399  */
400 CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed)
401 {
402     assert(cbor_value_is_container(it));
403     assert(recursed->type == CborInvalidType);
404     it->ptr = recursed->ptr;
405     return preparse_next_value(it);
406 }
407
408 /**
409  * Calculates the length of the string in \a value and stores the result in \a
410  * len. This function is different from cbor_value_get_string_length() in that
411  * it calculates the length even for strings sent in chunks. For that reason,
412  * this function may not run in constant time (it will run in O(n) time on the
413  * number of chunks).
414  *
415  * \note On 32-bit platforms, this function will return error condition of \ref
416  * CborErrorDataTooLarge if the stream indicates a length that is too big to
417  * fit in 32-bit.
418  *
419  * \sa cbor_value_get_string_length(), cbor_value_copy_string(), cbor_value_is_length_known()
420  */
421 CborError cbor_value_calculate_string_length(const CborValue *value, size_t *len)
422 {
423     *len = SIZE_MAX;
424     return _cbor_value_copy_string(value, NULL, len, NULL);
425 }
426
427 /**
428  * \fn CborError cbor_value_dup_text_string(const CborValue *value, char **buffer, size_t *buflen, CborValue *next)
429  *
430  * Allocates memory for the string pointed by \a value and copies it into this
431  * buffer. The pointer to the buffer is stored in \a buffer and the number of
432  * bytes copied is stored in \a len (those variables must not be NULL).
433  *
434  * If \c malloc returns a NULL pointer, this function will return error
435  * condition \ref CborErrorOutOfMemory.
436  *
437  * On success, \c{*buffer} will contain a valid pointer that must be freed by
438  * calling \c{free()}. This is the case even for zero-length strings.
439  *
440  * The \a next pointer, if not null, will be updated to point to the next item
441  * after this string. If \a value points to the last item, then \a next will be
442  * invalid.
443  *
444  * \note This function does not perform UTF-8 validation on the incoming text
445  * string.
446  *
447  * \sa cbor_value_copy_text_string(), cbor_value_dup_byte_string()
448  */
449
450 /**
451  * \fn CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer, size_t *buflen, CborValue *next)
452  *
453  * Allocates memory for the string pointed by \a value and copies it into this
454  * buffer. The pointer to the buffer is stored in \a buffer and the number of
455  * bytes copied is stored in \a len (those variables must not be NULL).
456  *
457  * If \c malloc returns a NULL pointer, this function will return error
458  * condition \ref CborErrorOutOfMemory.
459  *
460  * On success, \c{*buffer} will contain a valid pointer that must be freed by
461  * calling \c{free()}. This is the case even for zero-length strings.
462  *
463  * The \a next pointer, if not null, will be updated to point to the next item
464  * after this string. If \a value points to the last item, then \a next will be
465  * invalid.
466  *
467  * \sa cbor_value_copy_byte_string(), cbor_value_dup_text_string()
468  */
469 CborError _cbor_value_dup_string(const CborValue *value, void **buffer, size_t *buflen, CborValue *next)
470 {
471     assert(buffer);
472     assert(buflen);
473     *buflen = SIZE_MAX;
474     CborError err = _cbor_value_copy_string(value, NULL, buflen, NULL);
475     if (err)
476         return err;
477
478     ++*buflen;
479     *buffer = malloc(*buflen);
480     if (!*buffer) {
481         // out of memory
482         return CborErrorOutOfMemory;
483     }
484     err = _cbor_value_copy_string(value, *buffer, buflen, next);
485     if (err) {
486         free(*buffer);
487         return err;
488     }
489     return CborNoError;
490 }
491
492 // We return uintptr_t so that we can pass memcpy directly as the iteration
493 // function. The choice is to optimize for memcpy, which is used in the base
494 // parser API (cbor_value_copy_string), while memcmp is used in convenience API
495 // only.
496 typedef uintptr_t (*IterateFunction)(char *, const uint8_t *, size_t);
497
498 static uintptr_t iterate_noop(char *dest, const uint8_t *src, size_t len)
499 {
500     (void)dest;
501     (void)src;
502     (void)len;
503     return true;
504 }
505
506 static uintptr_t iterate_memcmp(char *s1, const uint8_t *s2, size_t len)
507 {
508     return memcmp(s1, (const char *)s2, len) == 0;
509 }
510
511 static CborError iterate_string_chunks(const CborValue *value, char *buffer, size_t *buflen,
512                                        bool *result, CborValue *next, IterateFunction func)
513 {
514     assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value));
515
516     size_t total;
517     CborError err;
518     const uint8_t *ptr = value->ptr;
519     if (cbor_value_is_length_known(value)) {
520         // easy case: fixed length
521         err = extract_length(value->parser, &ptr, &total);
522         if (err)
523             return err;
524         if (total > (size_t)(value->parser->end - ptr))
525             return CborErrorUnexpectedEOF;
526         if (total <= *buflen)
527             *result = func(buffer, ptr, total);
528         else
529             *result = false;
530         ptr += total;
531     } else {
532         // chunked
533         ++ptr;
534         total = 0;
535         *result = true;
536         while (true) {
537             size_t chunkLen;
538             size_t newTotal;
539
540             if (ptr == value->parser->end)
541                 return CborErrorUnexpectedEOF;
542
543             if (*ptr == (uint8_t)BreakByte) {
544                 ++ptr;
545                 break;
546             }
547
548             // is this the right type?
549             if ((*ptr & MajorTypeMask) != value->type)
550                 return CborErrorIllegalType;
551
552             err = extract_length(value->parser, &ptr, &chunkLen);
553             if (err)
554                 return err;
555
556             if (unlikely(add_check_overflow(total, chunkLen, &newTotal)))
557                 return CborErrorDataTooLarge;
558
559             if (chunkLen > (size_t)(value->parser->end - ptr))
560                 return CborErrorUnexpectedEOF;
561
562             if (*result && *buflen >= newTotal)
563                 *result = func(buffer + total, ptr, chunkLen);
564             else
565                 *result = false;
566
567             ptr += chunkLen;
568             total = newTotal;
569         }
570     }
571
572     // is there enough room for the ending NUL byte?
573     if (*result && *buflen > total)
574         *result = func(buffer + total, (const uint8_t *)"", 1);
575     *buflen = total;
576
577     if (next) {
578         *next = *value;
579         next->ptr = ptr;
580         return preparse_next_value(next);
581     }
582     return CborNoError;
583 }
584
585 /**
586  * \fn CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, size_t *buflen, CborValue *next)
587  *
588  * Copies the string pointed by \a value into the buffer provided at \a buffer
589  * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not
590  * copy anything and will only update the \a next value.
591  *
592  * If the provided buffer length was too small, this function returns an error
593  * condition of \ref CborErrorOutOfMemory. If you need to calculate the length
594  * of the string in order to preallocate a buffer, use
595  * cbor_value_calculate_string_length().
596  *
597  * On success, this function sets the number of bytes copied to \c{*buflen}. If
598  * the buffer is large enough, this function will insert a null byte after the
599  * last copied byte, to facilitate manipulation of text strings. That byte is
600  * not included in the returned value of \c{*buflen}.
601  *
602  * The \a next pointer, if not null, will be updated to point to the next item
603  * after this string. If \a value points to the last item, then \a next will be
604  * invalid.
605  *
606  * \note This function does not perform UTF-8 validation on the incoming text
607  * string.
608  *
609  * \sa cbor_value_dup_text_string(), cbor_value_copy_byte_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length()
610  */
611
612 /**
613  * \fn CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, size_t *buflen, CborValue *next)
614  *
615  * Copies the string pointed by \a value into the buffer provided at \a buffer
616  * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not
617  * copy anything and will only update the \a next value.
618  *
619  * If the provided buffer length was too small, this function returns an error
620  * condition of \ref CborErrorOutOfMemory. If you need to calculate the length
621  * of the string in order to preallocate a buffer, use
622  * cbor_value_calculate_string_length().
623  *
624  * On success, this function sets the number of bytes copied to \c{*buflen}. If
625  * the buffer is large enough, this function will insert a null byte after the
626  * last copied byte, to facilitate manipulation of null-terminated strings.
627  * That byte is not included in the returned value of \c{*buflen}.
628  *
629  * The \a next pointer, if not null, will be updated to point to the next item
630  * after this string. If \a value points to the last item, then \a next will be
631  * invalid.
632  *
633  * \sa cbor_value_dup_text_string(), cbor_value_copy_text_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length()
634  */
635
636 CborError _cbor_value_copy_string(const CborValue *value, void *buffer,
637                                  size_t *buflen, CborValue *next)
638 {
639     bool copied_all;
640     CborError err = iterate_string_chunks(value, (char*)buffer, buflen, &copied_all, next,
641                                           buffer ? (IterateFunction)memcpy : iterate_noop);
642     return err ? err :
643                  copied_all ? CborNoError : CborErrorOutOfMemory;
644 }
645
646 /**
647  * Compares the entry \a value with the string \a string and store the result
648  * in \a result. If the value is different from \a string or if it is not a
649  * text string, \a result will contain \c false.
650  *
651  * The entry at \a value may be a tagged string. If \a is not a string or a
652  * tagged string, the comparison result will be false.
653  */
654 CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result)
655 {
656     CborValue copy = *value;
657     CborError err = cbor_value_skip_tag(&copy);
658     if (err)
659         return err;
660     if (!cbor_value_is_text_string(&copy)) {
661         *result = false;
662         return CborNoError;
663     }
664
665     size_t len = strlen(string);
666     return iterate_string_chunks(&copy, CONST_CAST(char *, string), &len, result, NULL, iterate_memcmp);
667 }
668
669 /**
670  * Attempts to find the value in map \a map that corresponds to the text string
671  * entry \a string. If the item is found, it is stored in \a result. If no item
672  * is found matching the key, then \a result will contain an element of type
673  * \ref CborInvalidType.
674  *
675  * \note This function may be expensive to execute.
676  */
677 CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element)
678 {
679     assert(cbor_value_is_map(map));
680     size_t len = strlen(string);
681     CborError err = cbor_value_enter_container(map, element);
682     if (err)
683         goto error;
684
685     while (!cbor_value_at_end(element)) {
686         // find the non-tag so we can compare
687         err = cbor_value_skip_tag(element);
688         if (err)
689             goto error;
690         if (cbor_value_is_text_string(element)) {
691             bool equals;
692             size_t dummyLen = len;
693             err = iterate_string_chunks(element, CONST_CAST(char *, string), &dummyLen,
694                                         &equals, element, iterate_memcmp);
695             if (err)
696                 goto error;
697             if (equals)
698                 return preparse_value(element);
699         } else {
700             // skip this key
701             err = cbor_value_advance(element);
702             if (err)
703                 goto error;
704         }
705
706         // skip this value
707         err = cbor_value_skip_tag(element);
708         if (err)
709             goto error;
710         err = cbor_value_advance(element);
711         if (err)
712             goto error;
713     }
714
715     // not found
716     element->type = CborInvalidType;
717     return CborNoError;
718
719 error:
720     element->type = CborInvalidType;
721     return err;
722 }
723
724 /**
725  * Extracts a half-precision floating point from \a value and stores it in \a
726  * result.
727  */
728 CborError cbor_value_get_half_float(const CborValue *value, void *result)
729 {
730     assert(value->type == CborHalfFloatType);
731
732     // size has been computed already
733     uint16_t v = get16(value->ptr + 1);
734     memcpy(result, &v, sizeof(v));
735     return CborNoError;
736 }