Import TinyCBOR

This does not match any upstream version, but rather the "dev" branch at
https://github.com/thiagomacieira/tinycbor/. I've found myself
completely out of time to finish developing the TinyCBOR buffer
integration and zero-copy support.

Change-Id: I9741f017961b410c910dfffd150133cbf6fbe678
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Thiago Macieira 2017-12-17 13:58:20 -08:00
parent 5968a445e1
commit 0619055430
20 changed files with 6858 additions and 0 deletions

81
src/3rdparty/tinycbor/.gitignore vendored Normal file
View File

@ -0,0 +1,81 @@
# Frequent generated files
callgrind.out.*
pcviewer.cfg
*~
*.a
*.la
*.core
*.d
*.dylib
*.moc
*.o
*.obj
*.orig
*.swp
*.rej
*.so
*.so.*
*.pbxuser
*.mode1
*.mode1v3
*_pch.h.cpp
*_resource.rc
.#*
*.*#
core
.qmake.cache
.qmake.stash
.qmake.vars
.device.vars
tags
.DS_Store
*.debug
Makefile*
*.prl
*.app
*.pro.user*
*.qmlproject.user*
*.gcov
*.gcda
*.gcno
*.flc
.*.swp
tinycbor.pc
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
*.exe.embed.manifest
*.exe_manifest.rc
*.exe_manifest.res
# MinGW generated files
*.Debug
*.Release
# INTEGRITY generated files
*.gpj
*.int
*.ael
*.dla
*.dnm
*.dep
*.map
bin
doc
lib
src/cjson
src/doxygen.log
!/Makefile
.config

21
src/3rdparty/tinycbor/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Intel Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

13
src/3rdparty/tinycbor/README vendored Normal file
View File

@ -0,0 +1,13 @@
Concise Binary Object Representation (CBOR) Library
---------------------------------------------------
To build TinyCBOR:
make
If you want to change the compiler or pass extra compiler flags:
make CC=clang CFLAGS="-m32 -Oz" LDFLAGS="-m32"
Documentation: https://intel.github.io/tinycbor/current/

1
src/3rdparty/tinycbor/VERSION vendored Normal file
View File

@ -0,0 +1 @@
0.6.0

View File

@ -0,0 +1,14 @@
{
"Id": "tinycbor",
"Name": "TinyCBOR",
"QDocModule": "qtcore",
"QtUsage": "Used for QCborStreamReader and QCborStreamWriter.",
"Description": "Concise Binary Object Representation (CBOR) Library",
"Homepage": "https://github.com/intel/tinycbor",
"License": "MIT License",
"LicenseId": "MIT",
"LicenseFile": "LICENSE",
"Version": "0.6+patches",
"Copyright": "Copyright (C) 2018 Intel Corporation"
}

669
src/3rdparty/tinycbor/src/cbor.h vendored Normal file
View File

@ -0,0 +1,669 @@
/****************************************************************************
**
** Copyright (C) 2018 Intel Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#ifndef CBOR_H
#define CBOR_H
#ifndef assert
#include <assert.h>
#endif
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "tinycbor-version.h"
#define TINYCBOR_VERSION ((TINYCBOR_VERSION_MAJOR << 16) | (TINYCBOR_VERSION_MINOR << 8) | TINYCBOR_VERSION_PATCH)
#ifdef __cplusplus
extern "C" {
#else
#include <stdbool.h>
#endif
#ifndef SIZE_MAX
/* Some systems fail to define SIZE_MAX in <stdint.h>, even though C99 requires it...
* Conversion from signed to unsigned is defined in 6.3.1.3 (Signed and unsigned integers) p2,
* which says: "the value is converted by repeatedly adding or subtracting one more than the
* maximum value that can be represented in the new type until the value is in the range of the
* new type."
* So -1 gets converted to size_t by adding SIZE_MAX + 1, which results in SIZE_MAX.
*/
# define SIZE_MAX ((size_t)-1)
#endif
#ifndef CBOR_API
# define CBOR_API
#endif
#ifndef CBOR_PRIVATE_API
# define CBOR_PRIVATE_API
#endif
#ifndef CBOR_INLINE_API
# if defined(__cplusplus)
# define CBOR_INLINE inline
# define CBOR_INLINE_API inline
# else
# define CBOR_INLINE_API static CBOR_INLINE
# if defined(_MSC_VER)
# define CBOR_INLINE __inline
# elif defined(__GNUC__)
# define CBOR_INLINE __inline__
# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
# define CBOR_INLINE inline
# else
# define CBOR_INLINE
# endif
# endif
#endif
typedef enum CborType {
CborIntegerType = 0x00,
CborByteStringType = 0x40,
CborTextStringType = 0x60,
CborArrayType = 0x80,
CborMapType = 0xa0,
CborTagType = 0xc0,
CborSimpleType = 0xe0,
CborBooleanType = 0xf5,
CborNullType = 0xf6,
CborUndefinedType = 0xf7,
CborHalfFloatType = 0xf9,
CborFloatType = 0xfa,
CborDoubleType = 0xfb,
CborInvalidType = 0xff /* equivalent to the break byte, so it will never be used */
} CborType;
typedef uint64_t CborTag;
typedef enum CborKnownTags {
CborDateTimeStringTag = 0,
CborUnixTime_tTag = 1,
CborPositiveBignumTag = 2,
CborNegativeBignumTag = 3,
CborDecimalTag = 4,
CborBigfloatTag = 5,
CborCOSE_Encrypt0Tag = 16,
CborCOSE_Mac0Tag = 17,
CborCOSE_Sign1Tag = 18,
CborExpectedBase64urlTag = 21,
CborExpectedBase64Tag = 22,
CborExpectedBase16Tag = 23,
CborEncodedCborTag = 24,
CborUrlTag = 32,
CborBase64urlTag = 33,
CborBase64Tag = 34,
CborRegularExpressionTag = 35,
CborMimeMessageTag = 36,
CborCOSE_EncryptTag = 96,
CborCOSE_MacTag = 97,
CborCOSE_SignTag = 98,
CborSignatureTag = 55799
} CborKnownTags;
/* #define the constants so we can check with #ifdef */
#define CborDateTimeStringTag CborDateTimeStringTag
#define CborUnixTime_tTag CborUnixTime_tTag
#define CborPositiveBignumTag CborPositiveBignumTag
#define CborNegativeBignumTag CborNegativeBignumTag
#define CborDecimalTag CborDecimalTag
#define CborBigfloatTag CborBigfloatTag
#define CborCOSE_Encrypt0Tag CborCOSE_Encrypt0Tag
#define CborCOSE_Mac0Tag CborCOSE_Mac0Tag
#define CborCOSE_Sign1Tag CborCOSE_Sign1Tag
#define CborExpectedBase64urlTag CborExpectedBase64urlTag
#define CborExpectedBase64Tag CborExpectedBase64Tag
#define CborExpectedBase16Tag CborExpectedBase16Tag
#define CborEncodedCborTag CborEncodedCborTag
#define CborUrlTag CborUrlTag
#define CborBase64urlTag CborBase64urlTag
#define CborBase64Tag CborBase64Tag
#define CborRegularExpressionTag CborRegularExpressionTag
#define CborMimeMessageTag CborMimeMessageTag
#define CborCOSE_EncryptTag CborCOSE_EncryptTag
#define CborCOSE_MacTag CborCOSE_MacTag
#define CborCOSE_SignTag CborCOSE_SignTag
#define CborSignatureTag CborSignatureTag
/* Error API */
typedef enum CborError {
CborNoError = 0,
/* errors in all modes */
CborUnknownError,
CborErrorUnknownLength, /* request for length in array, map, or string with indeterminate length */
CborErrorAdvancePastEOF,
CborErrorIO,
/* parser errors streaming errors */
CborErrorGarbageAtEnd = 256,
CborErrorUnexpectedEOF,
CborErrorUnexpectedBreak,
CborErrorUnknownType, /* can only happen in major type 7 */
CborErrorIllegalType, /* type not allowed here */
CborErrorIllegalNumber,
CborErrorIllegalSimpleType, /* types of value less than 32 encoded in two bytes */
CborErrorLastStringChunk, /* not really an error */
/* parser errors in strict mode parsing only */
CborErrorUnknownSimpleType = 512,
CborErrorUnknownTag,
CborErrorInappropriateTagForType,
CborErrorDuplicateObjectKeys,
CborErrorInvalidUtf8TextString,
CborErrorExcludedType,
CborErrorExcludedValue,
CborErrorImproperValue,
CborErrorOverlongEncoding,
CborErrorMapKeyNotString,
CborErrorMapNotSorted,
CborErrorMapKeysNotUnique,
/* encoder errors */
CborErrorTooManyItems = 768,
CborErrorTooFewItems,
/* internal implementation errors */
CborErrorDataTooLarge = 1024,
CborErrorNestingTooDeep,
CborErrorUnsupportedType,
CborErrorUnimplementedValidation,
/* errors in converting to JSON */
CborErrorJsonObjectKeyIsAggregate = 1280,
CborErrorJsonObjectKeyNotString,
CborErrorJsonNotImplemented,
CborErrorOutOfMemory = (int) (~0U / 2 + 1),
CborErrorInternalError = (int) (~0U / 2) /* INT_MAX on two's complement machines */
} CborError;
CBOR_API const char *cbor_error_string(CborError error);
/* Encoder API */
typedef enum CborEncoderAppendType
{
CborEncoderAppendCborData = 0,
CborEncoderAppendStringData = 1
} CborEncoderAppendType;
typedef CborError (*CborEncoderWriteFunction)(void *, const void *, size_t, CborEncoderAppendType);
enum CborEncoderFlags
{
CborIteratorFlag_WriterFunction = 0x01,
CborIteratorFlag_ContainerIsMap_ = 0x20
};
struct CborEncoder
{
union {
uint8_t *ptr;
ptrdiff_t bytes_needed;
CborEncoderWriteFunction writer;
} data;
uint8_t *end;
size_t remaining;
int flags;
};
typedef struct CborEncoder CborEncoder;
static const size_t CborIndefiniteLength = SIZE_MAX;
CBOR_API void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags);
CBOR_API void cbor_encoder_init_writer(CborEncoder *encoder, CborEncoderWriteFunction writer, void *);
CBOR_API CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value);
CBOR_API CborError cbor_encode_int(CborEncoder *encoder, int64_t value);
CBOR_API CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value);
CBOR_API CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value);
CBOR_API CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag);
CBOR_API CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length);
CBOR_INLINE_API CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string)
{ return cbor_encode_text_string(encoder, string, strlen(string)); }
CBOR_API CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length);
CBOR_API CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value);
CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value)
{ return cbor_encode_simple_value(encoder, (int)value - 1 + (CborBooleanType & 0x1f)); }
CBOR_INLINE_API CborError cbor_encode_null(CborEncoder *encoder)
{ return cbor_encode_simple_value(encoder, CborNullType & 0x1f); }
CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder)
{ return cbor_encode_simple_value(encoder, CborUndefinedType & 0x1f); }
CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value)
{ return cbor_encode_floating_point(encoder, CborHalfFloatType, value); }
CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value)
{ return cbor_encode_floating_point(encoder, CborFloatType, &value); }
CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value)
{ return cbor_encode_floating_point(encoder, CborDoubleType, &value); }
CBOR_API CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length);
CBOR_API CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length);
CBOR_API CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder);
CBOR_API CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder);
CBOR_INLINE_API uint8_t *_cbor_encoder_get_buffer_pointer(const CborEncoder *encoder)
{
return encoder->data.ptr;
}
CBOR_INLINE_API size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer)
{
return (size_t)(encoder->data.ptr - buffer);
}
CBOR_INLINE_API size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder)
{
return encoder->end ? 0 : (size_t)encoder->data.bytes_needed;
}
/* Parser API */
enum CborParserGlobalFlags
{
CborParserFlag_ExternalSource = 0x01
};
enum CborParserIteratorFlags
{
CborIteratorFlag_IntegerValueIs64Bit = 0x01,
CborIteratorFlag_IntegerValueTooLarge = 0x02,
CborIteratorFlag_NegativeInteger = 0x04,
CborIteratorFlag_IteratingStringChunks = 0x08,
CborIteratorFlag_UnknownLength = 0x10,
CborIteratorFlag_ContainerIsMap = 0x20,
CborIteratorFlag_NextIsMapKey = 0x40
};
struct CborValue;
struct CborParserOperations
{
bool (*can_read_bytes)(void *token, size_t len);
void *(*read_bytes)(void *token, void *dst, size_t offset, size_t len);
void (*advance_bytes)(void *token, size_t len);
CborError (*transfer_string)(void *token, const void **userptr, size_t offset, size_t len);
};
struct CborParser
{
union {
const uint8_t *end;
const struct CborParserOperations *ops;
} source;
enum CborParserGlobalFlags flags;
};
typedef struct CborParser CborParser;
struct CborValue
{
const CborParser *parser;
union {
const uint8_t *ptr;
void *token;
} source;
uint32_t remaining;
uint16_t extra;
uint8_t type;
uint8_t flags;
};
typedef struct CborValue CborValue;
CBOR_API CborError cbor_parser_init(const uint8_t *buffer, size_t size, int flags, CborParser *parser, CborValue *it);
CBOR_API CborError cbor_parser_init_reader(const struct CborParserOperations *ops, CborParser *parser, CborValue *it, void *token);
CBOR_API CborError cbor_value_validate_basic(const CborValue *it);
CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it)
{ return it->remaining == 0; }
CBOR_INLINE_API const uint8_t *cbor_value_get_next_byte(const CborValue *it)
{ return it->source.ptr; }
CBOR_API CborError cbor_value_reparse(CborValue *it);
CBOR_API CborError cbor_value_advance_fixed(CborValue *it);
CBOR_API CborError cbor_value_advance(CborValue *it);
CBOR_INLINE_API bool cbor_value_is_container(const CborValue *it)
{ return it->type == CborArrayType || it->type == CborMapType; }
CBOR_API CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed);
CBOR_API CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed);
CBOR_PRIVATE_API uint64_t _cbor_value_decode_int64_internal(const CborValue *value);
CBOR_INLINE_API uint64_t _cbor_value_extract_int64_helper(const CborValue *value)
{
return value->flags & CborIteratorFlag_IntegerValueTooLarge ?
_cbor_value_decode_int64_internal(value) : value->extra;
}
CBOR_INLINE_API bool cbor_value_is_valid(const CborValue *value)
{ return value && value->type != CborInvalidType; }
CBOR_INLINE_API CborType cbor_value_get_type(const CborValue *value)
{ return (CborType)value->type; }
/* Null & undefined type */
CBOR_INLINE_API bool cbor_value_is_null(const CborValue *value)
{ return value->type == CborNullType; }
CBOR_INLINE_API bool cbor_value_is_undefined(const CborValue *value)
{ return value->type == CborUndefinedType; }
/* Booleans */
CBOR_INLINE_API bool cbor_value_is_boolean(const CborValue *value)
{ return value->type == CborBooleanType; }
CBOR_INLINE_API CborError cbor_value_get_boolean(const CborValue *value, bool *result)
{
assert(cbor_value_is_boolean(value));
*result = !!value->extra;
return CborNoError;
}
/* Simple types */
CBOR_INLINE_API bool cbor_value_is_simple_type(const CborValue *value)
{ return value->type == CborSimpleType; }
CBOR_INLINE_API CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result)
{
assert(cbor_value_is_simple_type(value));
*result = (uint8_t)value->extra;
return CborNoError;
}
/* Integers */
CBOR_INLINE_API bool cbor_value_is_integer(const CborValue *value)
{ return value->type == CborIntegerType; }
CBOR_INLINE_API bool cbor_value_is_unsigned_integer(const CborValue *value)
{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger) == 0; }
CBOR_INLINE_API bool cbor_value_is_negative_integer(const CborValue *value)
{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger); }
CBOR_INLINE_API CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result)
{
assert(cbor_value_is_integer(value));
*result = _cbor_value_extract_int64_helper(value);
return CborNoError;
}
CBOR_INLINE_API CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result)
{
assert(cbor_value_is_unsigned_integer(value));
*result = _cbor_value_extract_int64_helper(value);
return CborNoError;
}
CBOR_INLINE_API CborError cbor_value_get_int64(const CborValue *value, int64_t *result)
{
assert(cbor_value_is_integer(value));
*result = (int64_t) _cbor_value_extract_int64_helper(value);
if (value->flags & CborIteratorFlag_NegativeInteger)
*result = -*result - 1;
return CborNoError;
}
CBOR_INLINE_API CborError cbor_value_get_int(const CborValue *value, int *result)
{
assert(cbor_value_is_integer(value));
*result = (int) _cbor_value_extract_int64_helper(value);
if (value->flags & CborIteratorFlag_NegativeInteger)
*result = -*result - 1;
return CborNoError;
}
CBOR_API CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result);
CBOR_API CborError cbor_value_get_int_checked(const CborValue *value, int *result);
CBOR_INLINE_API bool cbor_value_is_length_known(const CborValue *value)
{ return (value->flags & CborIteratorFlag_UnknownLength) == 0; }
/* Tags */
CBOR_INLINE_API bool cbor_value_is_tag(const CborValue *value)
{ return value->type == CborTagType; }
CBOR_INLINE_API CborError cbor_value_get_tag(const CborValue *value, CborTag *result)
{
assert(cbor_value_is_tag(value));
*result = _cbor_value_extract_int64_helper(value);
return CborNoError;
}
CBOR_API CborError cbor_value_skip_tag(CborValue *it);
/* Strings */
CBOR_INLINE_API bool cbor_value_is_byte_string(const CborValue *value)
{ return value->type == CborByteStringType; }
CBOR_INLINE_API bool cbor_value_is_text_string(const CborValue *value)
{ return value->type == CborTextStringType; }
CBOR_INLINE_API CborError cbor_value_get_string_length(const CborValue *value, size_t *length)
{
assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value));
if (!cbor_value_is_length_known(value))
return CborErrorUnknownLength;
uint64_t v = _cbor_value_extract_int64_helper(value);
*length = (size_t)v;
if (*length != v)
return CborErrorDataTooLarge;
return CborNoError;
}
CBOR_PRIVATE_API CborError _cbor_value_copy_string(const CborValue *value, void *buffer,
size_t *buflen, CborValue *next);
CBOR_PRIVATE_API CborError _cbor_value_dup_string(const CborValue *value, void **buffer,
size_t *buflen, CborValue *next);
CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length);
CBOR_INLINE_API CborError cbor_value_copy_text_string(const CborValue *value, char *buffer,
size_t *buflen, CborValue *next)
{
assert(cbor_value_is_text_string(value));
return _cbor_value_copy_string(value, buffer, buflen, next);
}
CBOR_INLINE_API CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer,
size_t *buflen, CborValue *next)
{
assert(cbor_value_is_byte_string(value));
return _cbor_value_copy_string(value, buffer, buflen, next);
}
CBOR_INLINE_API CborError cbor_value_dup_text_string(const CborValue *value, char **buffer,
size_t *buflen, CborValue *next)
{
assert(cbor_value_is_text_string(value));
return _cbor_value_dup_string(value, (void **)buffer, buflen, next);
}
CBOR_INLINE_API CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer,
size_t *buflen, CborValue *next)
{
assert(cbor_value_is_byte_string(value));
return _cbor_value_dup_string(value, (void **)buffer, buflen, next);
}
CBOR_PRIVATE_API CborError _cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr,
size_t *len, CborValue *next);
CBOR_API CborError cbor_value_get_string_chunk_size(CborValue *value, size_t *len);
CBOR_INLINE_API CborError cbor_value_get_text_string_chunk(const CborValue *value, const char **bufferptr,
size_t *len, CborValue *next)
{
assert(cbor_value_is_text_string(value));
return _cbor_value_get_string_chunk(value, (const void **)bufferptr, len, next);
}
CBOR_INLINE_API CborError cbor_value_get_byte_string_chunk(const CborValue *value, const uint8_t **bufferptr,
size_t *len, CborValue *next)
{
assert(cbor_value_is_byte_string(value));
return _cbor_value_get_string_chunk(value, (const void **)bufferptr, len, next);
}
CBOR_API CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result);
/* Maps and arrays */
CBOR_INLINE_API bool cbor_value_is_array(const CborValue *value)
{ return value->type == CborArrayType; }
CBOR_INLINE_API bool cbor_value_is_map(const CborValue *value)
{ return value->type == CborMapType; }
CBOR_INLINE_API CborError cbor_value_get_array_length(const CborValue *value, size_t *length)
{
assert(cbor_value_is_array(value));
if (!cbor_value_is_length_known(value))
return CborErrorUnknownLength;
uint64_t v = _cbor_value_extract_int64_helper(value);
*length = (size_t)v;
if (*length != v)
return CborErrorDataTooLarge;
return CborNoError;
}
CBOR_INLINE_API CborError cbor_value_get_map_length(const CborValue *value, size_t *length)
{
assert(cbor_value_is_map(value));
if (!cbor_value_is_length_known(value))
return CborErrorUnknownLength;
uint64_t v = _cbor_value_extract_int64_helper(value);
*length = (size_t)v;
if (*length != v)
return CborErrorDataTooLarge;
return CborNoError;
}
CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element);
/* Floating point */
CBOR_INLINE_API bool cbor_value_is_half_float(const CborValue *value)
{ return value->type == CborHalfFloatType; }
CBOR_INLINE_API CborError cbor_value_get_half_float(const CborValue *value, void *result)
{
assert(cbor_value_is_half_float(value));
assert((value->flags & CborIteratorFlag_IntegerValueTooLarge) == 0);
/* size has been computed already */
memcpy(result, &value->extra, sizeof(value->extra));
return CborNoError;
}
CBOR_INLINE_API bool cbor_value_is_float(const CborValue *value)
{ return value->type == CborFloatType; }
CBOR_INLINE_API CborError cbor_value_get_float(const CborValue *value, float *result)
{
assert(cbor_value_is_float(value));
assert(value->flags & CborIteratorFlag_IntegerValueTooLarge);
uint32_t data = (uint32_t)_cbor_value_decode_int64_internal(value);
memcpy(result, &data, sizeof(*result));
return CborNoError;
}
CBOR_INLINE_API bool cbor_value_is_double(const CborValue *value)
{ return value->type == CborDoubleType; }
CBOR_INLINE_API CborError cbor_value_get_double(const CborValue *value, double *result)
{
assert(cbor_value_is_double(value));
assert(value->flags & CborIteratorFlag_IntegerValueTooLarge);
uint64_t data = _cbor_value_decode_int64_internal(value);
memcpy(result, &data, sizeof(*result));
return CborNoError;
}
/* Validation API */
enum CborValidationFlags {
/* Bit mapping:
* bits 0-7 (8 bits): canonical format
* bits 8-11 (4 bits): canonical format & strict mode
* bits 12-20 (8 bits): strict mode
* bits 21-31 (10 bits): other
*/
CborValidateShortestIntegrals = 0x0001,
CborValidateShortestFloatingPoint = 0x0002,
CborValidateShortestNumbers = CborValidateShortestIntegrals | CborValidateShortestFloatingPoint,
CborValidateNoIndeterminateLength = 0x0100,
CborValidateMapIsSorted = 0x0200 | CborValidateNoIndeterminateLength,
CborValidateCanonicalFormat = 0x0fff,
CborValidateMapKeysAreUnique = 0x1000 | CborValidateMapIsSorted,
CborValidateTagUse = 0x2000,
CborValidateUtf8 = 0x4000,
CborValidateStrictMode = 0xfff00,
CborValidateMapKeysAreString = 0x100000,
CborValidateNoUndefined = 0x200000,
CborValidateNoTags = 0x400000,
CborValidateFiniteFloatingPoint = 0x800000,
/* unused = 0x1000000, */
/* unused = 0x2000000, */
CborValidateNoUnknownSimpleTypesSA = 0x4000000,
CborValidateNoUnknownSimpleTypes = 0x8000000 | CborValidateNoUnknownSimpleTypesSA,
CborValidateNoUnknownTagsSA = 0x10000000,
CborValidateNoUnknownTagsSR = 0x20000000 | CborValidateNoUnknownTagsSA,
CborValidateNoUnknownTags = 0x40000000 | CborValidateNoUnknownTagsSR,
CborValidateCompleteData = (int)0x80000000,
CborValidateStrictest = (int)~0U,
CborValidateBasic = 0
};
CBOR_API CborError cbor_value_validate(const CborValue *it, int flags);
/* Human-readable (dump) API */
enum CborPrettyFlags {
CborPrettyNumericEncodingIndicators = 0x01,
CborPrettyTextualEncodingIndicators = 0,
CborPrettyIndicateIndeterminateLength = 0x02,
CborPrettyIndicateIndetermineLength = CborPrettyIndicateIndeterminateLength, /* deprecated */
CborPrettyIndicateOverlongNumbers = 0x04,
CborPrettyShowStringFragments = 0x100,
CborPrettyMergeStringFragments = 0,
CborPrettyDefaultFlags = CborPrettyIndicateIndeterminateLength
};
typedef CborError (*CborStreamFunction)(void *token, const char *fmt, ...)
#ifdef __GNUC__
__attribute__((__format__(printf, 2, 3)))
#endif
;
CBOR_API CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags);
/* The following API requires a hosted C implementation (uses FILE*) */
#if !defined(__STDC_HOSTED__) || __STDC_HOSTED__-0 == 1
CBOR_API CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags);
CBOR_API CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value);
CBOR_INLINE_API CborError cbor_value_to_pretty(FILE *out, const CborValue *value)
{
CborValue copy = *value;
return cbor_value_to_pretty_advance_flags(out, &copy, CborPrettyDefaultFlags);
}
#endif /* __STDC_HOSTED__ check */
#ifdef __cplusplus
}
#endif
#endif /* CBOR_H */

676
src/3rdparty/tinycbor/src/cborencoder.c vendored Normal file
View File

@ -0,0 +1,676 @@
/****************************************************************************
**
** Copyright (C) 2018 Intel Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#ifndef _BSD_SOURCE
#define _BSD_SOURCE 1
#endif
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE 1
#endif
#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS 1
#endif
#include "cbor.h"
#include "cborinternal_p.h"
#include "compilersupport_p.h"
#include <stdlib.h>
#include <string.h>
/**
* \defgroup CborEncoding Encoding to CBOR
* \brief Group of functions used to encode data to CBOR.
*
* CborEncoder is used to encode data into a CBOR stream. The outermost
* CborEncoder is initialized by calling cbor_encoder_init(), with the buffer
* where the CBOR stream will be stored. The outermost CborEncoder is usually
* used to encode exactly one item, most often an array or map. It is possible
* to encode more than one item, but care must then be taken on the decoder
* side to ensure the state is reset after each item was decoded.
*
* Nested CborEncoder objects are created using cbor_encoder_create_array() and
* cbor_encoder_create_map(), later closed with cbor_encoder_close_container()
* or cbor_encoder_close_container_checked(). The pairs of creation and closing
* must be exactly matched and their parameters are always the same.
*
* CborEncoder writes directly to the user-supplied buffer, without extra
* buffering. CborEncoder does not allocate memory and CborEncoder objects are
* usually created on the stack of the encoding functions.
*
* The example below initializes a CborEncoder object with a buffer and encodes
* a single integer.
*
* \code
* uint8_t buf[16];
* CborEncoder encoder;
* cbor_encoder_init(&encoder, &buf, sizeof(buf), 0);
* cbor_encode_int(&encoder, some_value);
* \endcode
*
* As explained before, usually the outermost CborEncoder object is used to add
* one array or map, which in turn contains multiple elements. The example
* below creates a CBOR map with one element: a key "foo" and a boolean value.
*
* \code
* uint8_t buf[16];
* CborEncoder encoder, mapEncoder;
* cbor_encoder_init(&encoder, &buf, sizeof(buf), 0);
* cbor_encoder_create_map(&encoder, &mapEncoder, 1);
* cbor_encode_text_stringz(&mapEncoder, "foo");
* cbor_encode_boolean(&mapEncoder, some_value);
* cbor_encoder_close_container(&encoder, &mapEncoder);
* \endcode
*
* <h3 class="groupheader">Error checking and buffer size</h3>
*
* All functions operating on CborEncoder return a condition of type CborError.
* If the encoding was successful, they return CborNoError. Some functions do
* extra checking on the input provided and may return some other error
* conditions (for example, cbor_encode_simple_value() checks that the type is
* of the correct type).
*
* In addition, all functions check whether the buffer has enough bytes to
* encode the item being appended. If that is not possible, they return
* CborErrorOutOfMemory.
*
* It is possible to continue with the encoding of data past the first function
* that returns CborErrorOutOfMemory. CborEncoder functions will not overrun
* the buffer, but will instead count how many more bytes are needed to
* complete the encoding. At the end, you can obtain that count by calling
* cbor_encoder_get_extra_bytes_needed().
*
* \section1 Finalizing the encoding
*
* Once all items have been appended and the containers have all been properly
* closed, the user-supplied buffer will contain the CBOR stream and may be
* immediately used. To obtain the size of the buffer, call
* cbor_encoder_get_buffer_size() with the original buffer pointer.
*
* The example below illustrates how one can encode an item with error checking
* and then pass on the buffer for network sending.
*
* \code
* uint8_t buf[16];
* CborError err;
* CborEncoder encoder, mapEncoder;
* cbor_encoder_init(&encoder, &buf, sizeof(buf), 0);
* err = cbor_encoder_create_map(&encoder, &mapEncoder, 1);
* if (!err)
* return err;
* err = cbor_encode_text_stringz(&mapEncoder, "foo");
* if (!err)
* return err;
* err = cbor_encode_boolean(&mapEncoder, some_value);
* if (!err)
* return err;
* err = cbor_encoder_close_container_checked(&encoder, &mapEncoder);
* if (!err)
* return err;
*
* size_t len = cbor_encoder_get_buffer_size(&encoder, buf);
* send_payload(buf, len);
* return CborNoError;
* \endcode
*
* Finally, the example below expands on the one above and also
* deals with dynamically growing the buffer if the initial allocation wasn't
* big enough. Note the two places where the error checking was replaced with
* an cbor_assertion, showing where the author assumes no error can occur.
*
* \code
* uint8_t *encode_string_array(const char **strings, int n, size_t *bufsize)
* {
* CborError err;
* CborEncoder encoder, arrayEncoder;
* size_t size = 256;
* uint8_t *buf = NULL;
*
* while (1) {
* int i;
* size_t more_bytes;
* uint8_t *nbuf = realloc(buf, size);
* if (nbuf == NULL)
* goto error;
* buf = nbuf;
*
* cbor_encoder_init(&encoder, &buf, size, 0);
* err = cbor_encoder_create_array(&encoder, &arrayEncoder, n);
* cbor_assert(err); // can't fail, the buffer is always big enough
*
* for (i = 0; i < n; ++i) {
* err = cbor_encode_text_stringz(&arrayEncoder, strings[i]);
* if (err && err != CborErrorOutOfMemory)
* goto error;
* }
*
* err = cbor_encoder_close_container_checked(&encoder, &arrayEncoder);
* cbor_assert(err); // shouldn't fail!
*
* more_bytes = cbor_encoder_get_extra_bytes_needed(encoder);
* if (more_size) {
* // buffer wasn't big enough, try again
* size += more_bytes;
* continue;
* }
*
* *bufsize = cbor_encoder_get_buffer_size(encoder, buf);
* return buf;
* }
* error:
* free(buf);
* return NULL;
* }
* \endcode
*/
/**
* \addtogroup CborEncoding
* @{
*/
/**
* \struct CborEncoder
* Structure used to encode to CBOR.
*/
/**
* Initializes a CborEncoder structure \a encoder by pointing it to buffer \a
* buffer of size \a size. The \a flags field is currently unused and must be
* zero.
*/
void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags)
{
encoder->data.ptr = buffer;
encoder->end = buffer + size;
encoder->remaining = 2;
encoder->flags = flags;
}
void cbor_encoder_init_writer(CborEncoder *encoder, CborEncoderWriteFunction writer, void *token)
{
#ifdef CBOR_ENCODER_WRITE_FUNCTION
(void) writer;
#else
encoder->data.writer = writer;
#endif
encoder->end = (uint8_t *)token;
encoder->remaining = 2;
encoder->flags = CborIteratorFlag_WriterFunction;
}
static inline void put16(void *where, uint16_t v)
{
v = cbor_htons(v);
memcpy(where, &v, sizeof(v));
}
/* Note: Since this is currently only used in situations where OOM is the only
* valid error, we KNOW this to be true. Thus, this function now returns just 'true',
* but if in the future, any function starts returning a non-OOM error, this will need
* to be changed to the test. At the moment, this is done to prevent more branches
* being created in the tinycbor output */
static inline bool isOomError(CborError err)
{
if (CBOR_ENCODER_WRITER_CONTROL < 0)
return true;
/* CborErrorOutOfMemory is the only negative error code, intentionally
* so we can write the test like this */
return (int)err < 0;
}
static inline void put32(void *where, uint32_t v)
{
v = cbor_htonl(v);
memcpy(where, &v, sizeof(v));
}
static inline void put64(void *where, uint64_t v)
{
v = cbor_htonll(v);
memcpy(where, &v, sizeof(v));
}
static inline bool would_overflow(CborEncoder *encoder, size_t len)
{
ptrdiff_t remaining = (ptrdiff_t)encoder->end;
remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed;
remaining -= (ptrdiff_t)len;
return unlikely(remaining < 0);
}
static inline void advance_ptr(CborEncoder *encoder, size_t n)
{
if (encoder->end)
encoder->data.ptr += n;
else
encoder->data.bytes_needed += n;
}
static inline CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len,
CborEncoderAppendType appendType)
{
if (CBOR_ENCODER_WRITER_CONTROL >= 0) {
if (encoder->flags & CborIteratorFlag_WriterFunction || CBOR_ENCODER_WRITER_CONTROL != 0) {
# ifdef CBOR_ENCODER_WRITE_FUNCTION
return CBOR_ENCODER_WRITE_FUNCTION(encoder->end, data, len, appendType);
# else
return encoder->data.writer(encoder->end, data, len, appendType);
# endif
}
}
#if CBOR_ENCODER_WRITER_CONTROL <= 0
if (would_overflow(encoder, len)) {
if (encoder->end != NULL) {
len -= encoder->end - encoder->data.ptr;
encoder->end = NULL;
encoder->data.bytes_needed = 0;
}
advance_ptr(encoder, len);
return CborErrorOutOfMemory;
}
memcpy(encoder->data.ptr, data, len);
encoder->data.ptr += len;
#endif
return CborNoError;
}
static inline CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte)
{
return append_to_buffer(encoder, &byte, 1, CborEncoderAppendCborData);
}
static inline CborError encode_number_no_update(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType)
{
/* Little-endian would have been so much more convenient here:
* We could just write at the beginning of buf but append_to_buffer
* only the necessary bytes.
* Since it has to be big endian, do it the other way around:
* write from the end. */
uint64_t buf[2];
uint8_t *const bufend = (uint8_t *)buf + sizeof(buf);
uint8_t *bufstart = bufend - 1;
put64(buf + 1, ui); /* we probably have a bunch of zeros in the beginning */
if (ui < Value8Bit) {
*bufstart += shiftedMajorType;
} else {
uint8_t more = 0;
if (ui > 0xffU)
++more;
if (ui > 0xffffU)
++more;
if (ui > 0xffffffffU)
++more;
bufstart -= (size_t)1 << more;
*bufstart = shiftedMajorType + Value8Bit + more;
}
return append_to_buffer(encoder, bufstart, bufend - bufstart, CborEncoderAppendCborData);
}
static inline void saturated_decrement(CborEncoder *encoder)
{
if (encoder->remaining)
--encoder->remaining;
}
static inline CborError encode_number(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType)
{
saturated_decrement(encoder);
return encode_number_no_update(encoder, ui, shiftedMajorType);
}
/**
* Appends the unsigned 64-bit integer \a value to the CBOR stream provided by
* \a encoder.
*
* \sa cbor_encode_negative_int, cbor_encode_int
*/
CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value)
{
return encode_number(encoder, value, UnsignedIntegerType << MajorTypeShift);
}
/**
* Appends the negative 64-bit integer whose absolute value is \a
* absolute_value to the CBOR stream provided by \a encoder.
*
* If the value \a absolute_value is zero, this function encodes -2^64.
*
* \sa cbor_encode_uint, cbor_encode_int
*/
CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value)
{
return encode_number(encoder, absolute_value - 1, NegativeIntegerType << MajorTypeShift);
}
/**
* Appends the signed 64-bit integer \a value to the CBOR stream provided by
* \a encoder.
*
* \sa cbor_encode_negative_int, cbor_encode_uint
*/
CborError cbor_encode_int(CborEncoder *encoder, int64_t value)
{
/* adapted from code in RFC 7049 appendix C (pseudocode) */
uint64_t ui = value >> 63; /* extend sign to whole length */
uint8_t majorType = ui & 0x20; /* extract major type */
ui ^= value; /* complement negatives */
return encode_number(encoder, ui, majorType);
}
/**
* Appends the CBOR Simple Type of value \a value to the CBOR stream provided by
* \a encoder.
*
* This function may return error CborErrorIllegalSimpleType if the \a value
* variable contains a number that is not a valid simple type.
*/
CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value)
{
#ifndef CBOR_ENCODER_NO_CHECK_USER
/* check if this is a valid simple type */
if (value >= HalfPrecisionFloat && value <= Break)
return CborErrorIllegalSimpleType;
#endif
return encode_number(encoder, value, SimpleTypesType << MajorTypeShift);
}
/**
* Appends the floating-point value of type \a fpType and pointed to by \a
* value to the CBOR stream provided by \a encoder. The value of \a fpType must
* be one of CborHalfFloatType, CborFloatType or CborDoubleType, otherwise the
* behavior of this function is undefined.
*
* This function is useful for code that needs to pass through floating point
* values but does not wish to have the actual floating-point code.
*
* \sa cbor_encode_half_float, cbor_encode_float, cbor_encode_double
*/
CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value)
{
uint8_t buf[1 + sizeof(uint64_t)];
cbor_assert(fpType == CborHalfFloatType || fpType == CborFloatType || fpType == CborDoubleType);
buf[0] = fpType;
unsigned size = 2U << (fpType - CborHalfFloatType);
if (size == 8)
put64(buf + 1, *(const uint64_t*)value);
else if (size == 4)
put32(buf + 1, *(const uint32_t*)value);
else
put16(buf + 1, *(const uint16_t*)value);
saturated_decrement(encoder);
return append_to_buffer(encoder, buf, size + 1, CborEncoderAppendCborData);
}
/**
* Appends the CBOR tag \a tag to the CBOR stream provided by \a encoder.
*
* \sa CborTag
*/
CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag)
{
/* tags don't count towards the number of elements in an array or map */
return encode_number_no_update(encoder, tag, TagType << MajorTypeShift);
}
static CborError encode_string(CborEncoder *encoder, size_t length, uint8_t shiftedMajorType, const void *string)
{
CborError err = encode_number(encoder, length, shiftedMajorType);
if (err && !isOomError(err))
return err;
return append_to_buffer(encoder, string, length, CborEncoderAppendStringData);
}
/**
* \fn CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string)
*
* Appends the null-terminated text string \a string to the CBOR stream
* provided by \a encoder. CBOR requires that \a string be valid UTF-8, but
* TinyCBOR makes no verification of correctness. The terminating null is not
* included in the stream.
*
* \sa cbor_encode_text_string, cbor_encode_byte_string
*/
/**
* Appends the text string \a string of length \a length to the CBOR stream
* provided by \a encoder. CBOR requires that \a string be valid UTF-8, but
* TinyCBOR makes no verification of correctness.
*
* \sa CborError cbor_encode_text_stringz, cbor_encode_byte_string
*/
CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length)
{
return encode_string(encoder, length, ByteStringType << MajorTypeShift, string);
}
/**
* Appends the byte string \a string of length \a length to the CBOR stream
* provided by \a encoder. CBOR byte strings are arbitrary raw data.
*
* \sa cbor_encode_text_stringz, cbor_encode_text_string
*/
CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length)
{
return encode_string(encoder, length, TextStringType << MajorTypeShift, string);
}
#ifdef __GNUC__
__attribute__((noinline))
#endif
static CborError create_container(CborEncoder *encoder, CborEncoder *container, size_t length, uint8_t shiftedMajorType)
{
CborError err;
container->data.ptr = encoder->data.ptr;
container->end = encoder->end;
saturated_decrement(encoder);
container->remaining = length + 1; /* overflow ok on CborIndefiniteLength */
cbor_static_assert((int)CborIteratorFlag_ContainerIsMap_ == (int)CborIteratorFlag_ContainerIsMap);
cbor_static_assert(((MapType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == CborIteratorFlag_ContainerIsMap);
cbor_static_assert(((ArrayType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == 0);
container->flags = shiftedMajorType & CborIteratorFlag_ContainerIsMap;
if (CBOR_ENCODER_WRITER_CONTROL == 0)
container->flags |= encoder->flags & CborIteratorFlag_WriterFunction;
if (length == CborIndefiniteLength) {
container->flags |= CborIteratorFlag_UnknownLength;
err = append_byte_to_buffer(container, shiftedMajorType + IndefiniteLength);
} else {
if (shiftedMajorType & CborIteratorFlag_ContainerIsMap)
container->remaining += length;
err = encode_number_no_update(container, length, shiftedMajorType);
}
return err;
}
/**
* Creates a CBOR array in the CBOR stream provided by \a encoder and
* initializes \a arrayEncoder so that items can be added to the array using
* the CborEncoder functions. The array must be terminated by calling either
* cbor_encoder_close_container() or cbor_encoder_close_container_checked()
* with the same \a encoder and \a arrayEncoder parameters.
*
* The number of items inserted into the array must be exactly \a length items,
* otherwise the stream is invalid. If the number of items is not known when
* creating the array, the constant \ref CborIndefiniteLength may be passed as
* length instead.
*
* \sa cbor_encoder_create_map
*/
CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length)
{
return create_container(encoder, arrayEncoder, length, ArrayType << MajorTypeShift);
}
/**
* Creates a CBOR map in the CBOR stream provided by \a encoder and
* initializes \a mapEncoder so that items can be added to the map using
* the CborEncoder functions. The map must be terminated by calling either
* cbor_encoder_close_container() or cbor_encoder_close_container_checked()
* with the same \a encoder and \a mapEncoder parameters.
*
* The number of pair of items inserted into the map must be exactly \a length
* items, otherwise the stream is invalid. If the number is not known
* when creating the map, the constant \ref CborIndefiniteLength may be passed as
* length instead.
*
* \b{Implementation limitation:} TinyCBOR cannot encode more than SIZE_MAX/2
* key-value pairs in the stream. If the length \a length is larger than this
* value (and is not \ref CborIndefiniteLength), this function returns error
* CborErrorDataTooLarge.
*
* \sa cbor_encoder_create_array
*/
CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length)
{
if (length != CborIndefiniteLength && length > SIZE_MAX / 2)
return CborErrorDataTooLarge;
return create_container(encoder, mapEncoder, length, MapType << MajorTypeShift);
}
/**
* Closes the CBOR container (array or map) provided by \a containerEncoder and
* updates the CBOR stream provided by \a encoder. Both parameters must be the
* same as were passed to cbor_encoder_create_array() or
* cbor_encoder_create_map().
*
* Since version 0.5, this function verifies that the number of items (or pairs
* of items, in the case of a map) was correct. It is no longer necessary to call
* cbor_encoder_close_container_checked() instead.
*
* \sa cbor_encoder_create_array(), cbor_encoder_create_map()
*/
CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder)
{
if (encoder->end && !(encoder->flags & CborIteratorFlag_WriterFunction))
encoder->data.ptr = containerEncoder->data.ptr;
else
encoder->data.bytes_needed = containerEncoder->data.bytes_needed;
encoder->end = containerEncoder->end;
if (containerEncoder->flags & CborIteratorFlag_UnknownLength)
return append_byte_to_buffer(encoder, BreakByte);
if (containerEncoder->remaining != 1)
return containerEncoder->remaining == 0 ? CborErrorTooManyItems : CborErrorTooFewItems;
if (!encoder->end)
return CborErrorOutOfMemory; /* keep the state */
return CborNoError;
}
/**
* \fn CborError cbor_encode_boolean(CborEncoder *encoder, bool value)
*
* Appends the boolean value \a value to the CBOR stream provided by \a encoder.
*/
/**
* \fn CborError cbor_encode_null(CborEncoder *encoder)
*
* Appends the CBOR type representing a null value to the CBOR stream provided
* by \a encoder.
*
* \sa cbor_encode_undefined()
*/
/**
* \fn CborError cbor_encode_undefined(CborEncoder *encoder)
*
* Appends the CBOR type representing an undefined value to the CBOR stream
* provided by \a encoder.
*
* \sa cbor_encode_null()
*/
/**
* \fn CborError cbor_encode_half_float(CborEncoder *encoder, const void *value)
*
* Appends the IEEE 754 half-precision (16-bit) floating point value pointed to
* by \a value to the CBOR stream provided by \a encoder.
*
* \sa cbor_encode_floating_point(), cbor_encode_float(), cbor_encode_double()
*/
/**
* \fn CborError cbor_encode_float(CborEncoder *encoder, float value)
*
* Appends the IEEE 754 single-precision (32-bit) floating point value \a value
* to the CBOR stream provided by \a encoder.
*
* \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_double()
*/
/**
* \fn CborError cbor_encode_double(CborEncoder *encoder, double value)
*
* Appends the IEEE 754 double-precision (64-bit) floating point value \a value
* to the CBOR stream provided by \a encoder.
*
* \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_float()
*/
/**
* \fn size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer)
*
* Returns the total size of the buffer starting at \a buffer after the
* encoding finished without errors. The \a encoder and \a buffer arguments
* must be the same as supplied to cbor_encoder_init().
*
* If the encoding process had errors, the return value of this function is
* meaningless. If the only errors were CborErrorOutOfMemory, instead use
* cbor_encoder_get_extra_bytes_needed() to find out by how much to grow the
* buffer before encoding again.
*
* See \ref CborEncoding for an example of using this function.
*
* \sa cbor_encoder_init(), cbor_encoder_get_extra_bytes_needed(), CborEncoding
*/
/**
* \fn size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder)
*
* Returns how many more bytes the original buffer supplied to
* cbor_encoder_init() needs to be extended by so that no CborErrorOutOfMemory
* condition will happen for the encoding. If the buffer was big enough, this
* function returns 0. The \a encoder must be the original argument as passed
* to cbor_encoder_init().
*
* This function is usually called after an encoding sequence ended with one or
* more CborErrorOutOfMemory errors, but no other error. If any other error
* happened, the return value of this function is meaningless.
*
* See \ref CborEncoding for an example of using this function.
*
* \sa cbor_encoder_init(), cbor_encoder_get_buffer_size(), CborEncoding
*/
/** @} */

View File

@ -0,0 +1,188 @@
/****************************************************************************
**
** Copyright (C) 2018 Intel Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#include "cbor.h"
#ifndef _
# define _(msg) msg
#endif
/**
* \enum CborError
* \ingroup CborGlobals
* The CborError enum contains the possible error values used by the CBOR encoder and decoder.
*
* TinyCBOR functions report success by returning CborNoError, or one error
* condition by returning one of the values below. One exception is the
* out-of-memory condition (CborErrorOutOfMemory), which the functions for \ref
* CborEncoding may report in bit-wise OR with other conditions.
*
* This technique allows code to determine whether the only error condition was
* a lack of buffer space, which may not be a fatal condition if the buffer can
* be resized. Additionally, the functions for \ref CborEncoding may continue
* to be used even after CborErrorOutOfMemory is returned, and instead they
* will simply calculate the extra space needed.
*
* \value CborNoError No error occurred
* \omitvalue CborUnknownError
* \value CborErrorUnknownLength Request for the length of an array, map or string whose length is not provided in the CBOR stream
* \value CborErrorAdvancePastEOF Not enough data in the stream to decode item (decoding would advance past end of stream)
* \value CborErrorIO An I/O error occurred, probably due to an out-of-memory situation
* \value CborErrorGarbageAtEnd Bytes exist past the end of the CBOR stream
* \value CborErrorUnexpectedEOF End of stream reached unexpectedly
* \value CborErrorUnexpectedBreak A CBOR break byte was found where not expected
* \value CborErrorUnknownType An unknown type (future extension to CBOR) was found in the stream
* \value CborErrorIllegalType An invalid type was found while parsing a chunked CBOR string
* \value CborErrorIllegalNumber An illegal initial byte (encoding unspecified additional information) was found
* \value CborErrorIllegalSimpleType An illegal encoding of a CBOR Simple Type of value less than 32 was found
* \omitvalue CborErrorUnknownSimpleType
* \omitvalue CborErrorUnknownTag
* \omitvalue CborErrorInappropriateTagForType
* \omitvalue CborErrorDuplicateObjectKeys
* \value CborErrorInvalidUtf8TextString Illegal UTF-8 encoding found while parsing CBOR Text String
* \value CborErrorTooManyItems Too many items were added to CBOR map or array of pre-determined length
* \value CborErrorTooFewItems Too few items were added to CBOR map or array of pre-determined length
* \value CborErrorDataTooLarge Data item size exceeds TinyCBOR's implementation limits
* \value CborErrorNestingTooDeep Data item nesting exceeds TinyCBOR's implementation limits
* \omitvalue CborErrorUnsupportedType
* \value CborErrorJsonObjectKeyIsAggregate Conversion to JSON failed because the key in a map is a CBOR map or array
* \value CborErrorJsonObjectKeyNotString Conversion to JSON failed because the key in a map is not a text string
* \value CborErrorOutOfMemory During CBOR encoding, the buffer provided is insufficient for encoding the data item;
* in other situations, TinyCBOR failed to allocate memory
* \value CborErrorInternalError An internal error occurred in TinyCBOR
*/
/**
* \ingroup CborGlobals
* Returns the error string corresponding to the CBOR error condition \a error.
*/
const char *cbor_error_string(CborError error)
{
switch (error) {
case CborNoError:
return "";
case CborUnknownError:
return _("unknown error");
case CborErrorOutOfMemory:
return _("out of memory/need more memory");
case CborErrorUnknownLength:
return _("unknown length (attempted to get the length of a map/array/string of indeterminate length");
case CborErrorAdvancePastEOF:
return _("attempted to advance past EOF");
case CborErrorIO:
return _("I/O error");
case CborErrorGarbageAtEnd:
return _("garbage after the end of the content");
case CborErrorUnexpectedEOF:
return _("unexpected end of data");
case CborErrorUnexpectedBreak:
return _("unexpected 'break' byte");
case CborErrorUnknownType:
return _("illegal byte (encodes future extension type)");
case CborErrorIllegalType:
return _("mismatched string type in chunked string");
case CborErrorIllegalNumber:
return _("illegal initial byte (encodes unspecified additional information)");
case CborErrorIllegalSimpleType:
return _("illegal encoding of simple type smaller than 32");
case CborErrorLastStringChunk:
return _("no size available: that was the last string chunk");
case CborErrorUnknownSimpleType:
return _("unknown simple type");
case CborErrorUnknownTag:
return _("unknown tag");
case CborErrorInappropriateTagForType:
return _("inappropriate tag for type");
case CborErrorDuplicateObjectKeys:
return _("duplicate keys in object");
case CborErrorInvalidUtf8TextString:
return _("invalid UTF-8 content in string");
case CborErrorExcludedType:
return _("excluded type found");
case CborErrorExcludedValue:
return _("excluded value found");
case CborErrorImproperValue:
case CborErrorOverlongEncoding:
return _("value encoded in non-canonical form");
case CborErrorMapKeyNotString:
case CborErrorJsonObjectKeyNotString:
return _("key in map is not a string");
case CborErrorMapNotSorted:
return _("map is not sorted");
case CborErrorMapKeysNotUnique:
return _("map keys are not unique");
case CborErrorTooManyItems:
return _("too many items added to encoder");
case CborErrorTooFewItems:
return _("too few items added to encoder");
case CborErrorDataTooLarge:
return _("internal error: data too large");
case CborErrorNestingTooDeep:
return _("internal error: too many nested containers found in recursive function");
case CborErrorUnsupportedType:
return _("unsupported type");
case CborErrorUnimplementedValidation:
return _("validation not implemented for the current parser state");
case CborErrorJsonObjectKeyIsAggregate:
return _("conversion to JSON failed: key in object is an array or map");
case CborErrorJsonNotImplemented:
return _("conversion to JSON failed: open_memstream unavailable");
case CborErrorInternalError:
return _("internal error");
}
return cbor_error_string(CborUnknownError);
}

View File

@ -0,0 +1,247 @@
/****************************************************************************
**
** Copyright (C) 2018 Intel Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#ifndef CBORINTERNAL_P_H
#define CBORINTERNAL_P_H
#include "compilersupport_p.h"
#ifndef CBOR_INTERNAL_API
# define CBOR_INTERNAL_API
#endif
#ifndef CBOR_PARSER_MAX_RECURSIONS
# define CBOR_PARSER_MAX_RECURSIONS 1024
#endif
#ifndef CBOR_ENCODER_WRITER_CONTROL
# define CBOR_ENCODER_WRITER_CONTROL 0
#endif
#ifndef CBOR_PARSER_READER_CONTROL
# define CBOR_PARSER_READER_CONTROL 0
#endif
/*
* CBOR Major types
* Encoded in the high 3 bits of the descriptor byte
* See http://tools.ietf.org/html/rfc7049#section-2.1
*/
typedef enum CborMajorTypes {
UnsignedIntegerType = 0U,
NegativeIntegerType = 1U,
ByteStringType = 2U,
TextStringType = 3U,
ArrayType = 4U,
MapType = 5U, /* a.k.a. object */
TagType = 6U,
SimpleTypesType = 7U
} CborMajorTypes;
/*
* CBOR simple and floating point types
* Encoded in the low 8 bits of the descriptor byte when the
* Major Type is 7.
*/
typedef enum CborSimpleTypes {
FalseValue = 20,
TrueValue = 21,
NullValue = 22,
UndefinedValue = 23,
SimpleTypeInNextByte = 24, /* not really a simple type */
HalfPrecisionFloat = 25, /* ditto */
SinglePrecisionFloat = 26, /* ditto */
DoublePrecisionFloat = 27, /* ditto */
Break = 31
} CborSimpleTypes;
enum {
SmallValueBitLength = 5U,
SmallValueMask = (1U << SmallValueBitLength) - 1, /* 31 */
Value8Bit = 24U,
Value16Bit = 25U,
Value32Bit = 26U,
Value64Bit = 27U,
IndefiniteLength = 31U,
MajorTypeShift = SmallValueBitLength,
MajorTypeMask = (int) (~0U << MajorTypeShift),
BreakByte = (unsigned)Break | (SimpleTypesType << MajorTypeShift)
};
CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *it);
static inline void copy_current_position(CborValue *dst, const CborValue *src)
{
// This "if" is here for pedantry only: the two branches should perform
// the same memory operation.
if (src->parser->flags & CborParserFlag_ExternalSource)
dst->source.token = src->source.token;
else
dst->source.ptr = src->source.ptr;
}
static inline bool can_read_bytes(const CborValue *it, size_t n)
{
if (CBOR_PARSER_READER_CONTROL >= 0) {
if (it->parser->flags & CborParserFlag_ExternalSource || CBOR_PARSER_READER_CONTROL != 0) {
#ifdef CBOR_PARSER_CAN_READ_BYTES_FUNCTION
return CBOR_PARSER_CAN_READ_BYTES_FUNCTION(it->source.token, n);
#else
return it->parser->source.ops->can_read_bytes(it->source.token, n);
#endif
}
}
/* Convert the pointer subtraction to size_t since end >= ptr
* (this prevents issues with (ptrdiff_t)n becoming negative).
*/
return (size_t)(it->parser->source.end - it->source.ptr) >= n;
}
static inline void advance_bytes(CborValue *it, size_t n)
{
if (CBOR_PARSER_READER_CONTROL >= 0) {
if (it->parser->flags & CborParserFlag_ExternalSource || CBOR_PARSER_READER_CONTROL != 0) {
#ifdef CBOR_PARSER_ADVANCE_BYTES_FUNCTION
CBOR_PARSER_ADVANCE_BYTES_FUNCTION(it->source.token, n);
#else
it->parser->source.ops->advance_bytes(it->source.token, n);
#endif
return;
}
}
it->source.ptr += n;
}
static inline CborError transfer_string(CborValue *it, const void **ptr, size_t offset, size_t len)
{
if (CBOR_PARSER_READER_CONTROL >= 0) {
if (it->parser->flags & CborParserFlag_ExternalSource || CBOR_PARSER_READER_CONTROL != 0) {
#ifdef CBOR_PARSER_TRANSFER_STRING_FUNCTION
return CBOR_PARSER_TRANSFER_STRING_FUNCTION(it->source.token, ptr, offset, len);
#else
return it->parser->source.ops->transfer_string(it->source.token, ptr, offset, len);
#endif
}
}
it->source.ptr += offset;
if (can_read_bytes(it, len)) {
*CONST_CAST(const void **, ptr) = it->source.ptr;
it->source.ptr += len;
return CborNoError;
}
return CborErrorUnexpectedEOF;
}
static inline void *read_bytes_unchecked(const CborValue *it, void *dst, size_t offset, size_t n)
{
if (CBOR_PARSER_READER_CONTROL >= 0) {
if (it->parser->flags & CborParserFlag_ExternalSource || CBOR_PARSER_READER_CONTROL != 0) {
#ifdef CBOR_PARSER_READ_BYTES_FUNCTION
return CBOR_PARSER_READ_BYTES_FUNCTION(it->source.token, dst, offset, n);
#else
return it->parser->source.ops->read_bytes(it->source.token, dst, offset, n);
#endif
}
}
return memcpy(dst, it->source.ptr + offset, n);
}
#ifdef __GNUC__
__attribute__((warn_unused_result))
#endif
static inline void *read_bytes(const CborValue *it, void *dst, size_t offset, size_t n)
{
if (can_read_bytes(it, offset + n))
return read_bytes_unchecked(it, dst, offset, n);
return NULL;
}
static inline uint16_t read_uint8(const CborValue *it, size_t offset)
{
uint8_t result;
read_bytes_unchecked(it, &result, offset, sizeof(result));
return result;
}
static inline uint16_t read_uint16(const CborValue *it, size_t offset)
{
uint16_t result;
read_bytes_unchecked(it, &result, offset, sizeof(result));
return cbor_ntohs(result);
}
static inline uint32_t read_uint32(const CborValue *it, size_t offset)
{
uint32_t result;
read_bytes_unchecked(it, &result, offset, sizeof(result));
return cbor_ntohl(result);
}
static inline uint64_t read_uint64(const CborValue *it, size_t offset)
{
uint64_t result;
read_bytes_unchecked(it, &result, offset, sizeof(result));
return cbor_ntohll(result);
}
static inline CborError extract_number_checked(const CborValue *it, uint64_t *value, size_t *bytesUsed)
{
uint8_t descriptor;
size_t bytesNeeded = 0;
/* We've already verified that there's at least one byte to be read */
read_bytes_unchecked(it, &descriptor, 0, 1);
descriptor &= SmallValueMask;
if (descriptor < Value8Bit) {
*value = descriptor;
} else if (unlikely(descriptor > Value64Bit)) {
return CborErrorIllegalNumber;
} else {
bytesNeeded = (size_t)(1 << (descriptor - Value8Bit));
if (!can_read_bytes(it, 1 + bytesNeeded))
return CborErrorUnexpectedEOF;
if (descriptor <= Value16Bit) {
if (descriptor == Value16Bit)
*value = read_uint16(it, 1);
else
*value = read_uint8(it, 1);
} else {
if (descriptor == Value32Bit)
*value = read_uint32(it, 1);
else
*value = read_uint64(it, 1);
}
}
if (bytesUsed)
*bytesUsed = bytesNeeded;
return CborNoError;
}
#endif /* CBORINTERNAL_P_H */

62
src/3rdparty/tinycbor/src/cborjson.h vendored Normal file
View File

@ -0,0 +1,62 @@
/****************************************************************************
**
** Copyright (C) 2015 Intel Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#ifndef CBORJSON_H
#define CBORJSON_H
#include "cbor.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Conversion to JSON */
enum CborToJsonFlags
{
CborConvertAddMetadata = 1,
CborConvertTagsToObjects = 2,
CborConvertIgnoreTags = 0,
CborConvertObeyByteStringTags = 0,
CborConvertByteStringsToBase64Url = 4,
CborConvertRequireMapStringKeys = 0,
CborConvertStringifyMapKeys = 8,
CborConvertDefaultFlags = 0
};
CBOR_API CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags);
CBOR_INLINE_API CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags)
{
CborValue copy = *value;
return cbor_value_to_json_advance(out, &copy, flags);
}
#ifdef __cplusplus
}
#endif
#endif /* CBORJSON_H */

1545
src/3rdparty/tinycbor/src/cborparser.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,263 @@
/****************************************************************************
**
** Copyright (C) 2017 Intel Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#ifndef COMPILERSUPPORT_H
#define COMPILERSUPPORT_H
#include "cbor.h"
#ifndef _BSD_SOURCE
# define _BSD_SOURCE
#endif
#ifndef _DEFAULT_SOURCE
# define _DEFAULT_SOURCE
#endif
#ifndef assert
# include <assert.h>
#endif
#include <float.h>
#include <math.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#ifndef __cplusplus
# include <stdbool.h>
#endif
#ifdef __F16C__
# include <immintrin.h>
#endif
#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || __cpp_static_assert >= 200410
# define cbor_static_assert(x) static_assert(x, #x)
#elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && (__STDC_VERSION__ > 199901L)
# define cbor_static_assert(x) _Static_assert(x, #x)
#else
# define cbor_static_assert(x) ((void)sizeof(char[2*!!(x) - 1]))
#endif
#if __STDC_VERSION__ >= 199901L || defined(__cplusplus)
/* inline is a keyword */
#else
/* use the definition from cbor.h */
# define inline CBOR_INLINE
#endif
#ifdef NDEBUG
# define cbor_assert(cond) do { if (!(cond)) unreachable(); } while (0)
#else
# define cbor_assert(cond) assert(cond)
#endif
#ifndef STRINGIFY
#define STRINGIFY(x) STRINGIFY2(x)
#endif
#define STRINGIFY2(x) #x
#if !defined(UINT32_MAX) || !defined(INT64_MAX)
/* C89? We can define UINT32_MAX portably, but not INT64_MAX */
# error "Your system has stdint.h but that doesn't define UINT32_MAX or INT64_MAX"
#endif
#ifndef DBL_DECIMAL_DIG
/* DBL_DECIMAL_DIG is C11 */
# define DBL_DECIMAL_DIG 17
#endif
#define DBL_DECIMAL_DIG_STR STRINGIFY(DBL_DECIMAL_DIG)
#if defined(__GNUC__) && defined(__i386__) && !defined(__iamcu__)
# define CBOR_INTERNAL_API_CC __attribute__((regparm(3)))
#elif defined(_MSC_VER) && defined(_M_IX86)
# define CBOR_INTERNAL_API_CC __fastcall
#else
# define CBOR_INTERNAL_API_CC
#endif
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif
#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) || \
(__has_builtin(__builtin_bswap64) && __has_builtin(__builtin_bswap32))
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define cbor_ntohll __builtin_bswap64
# define cbor_htonll __builtin_bswap64
# define cbor_ntohl __builtin_bswap32
# define cbor_htonl __builtin_bswap32
# ifdef __INTEL_COMPILER
# define cbor_ntohs _bswap16
# define cbor_htons _bswap16
# elif (__GNUC__ * 100 + __GNUC_MINOR__ >= 608) || __has_builtin(__builtin_bswap16)
# define cbor_ntohs __builtin_bswap16
# define cbor_htons __builtin_bswap16
# else
# define cbor_ntohs(x) (((uint16_t)x >> 8) | ((uint16_t)x << 8))
# define cbor_htons cbor_ntohs
# endif
# else
# define cbor_ntohll
# define cbor_htonll
# define cbor_ntohl
# define cbor_htonl
# define cbor_ntohs
# define cbor_htons
# endif
#elif defined(__sun)
# include <sys/byteorder.h>
#elif defined(_MSC_VER)
/* MSVC, which implies Windows, which implies little-endian and sizeof(long) == 4 */
# include <stdlib.h>
# define cbor_ntohll _byteswap_uint64
# define cbor_htonll _byteswap_uint64
# define cbor_ntohl _byteswap_ulong
# define cbor_htonl _byteswap_ulong
# define cbor_ntohs _byteswap_ushort
# define cbor_htons _byteswap_ushort
#endif
#ifndef cbor_ntohs
# include <arpa/inet.h>
# define cbor_ntohs ntohs
# define cbor_htons htons
#endif
#ifndef cbor_ntohl
# include <arpa/inet.h>
# define cbor_ntohl ntohl
# define cbor_htonl htonl
#endif
#ifndef cbor_ntohll
# define cbor_ntohll ntohll
# define cbor_htonll htonll
/* ntohll isn't usually defined */
# ifndef ntohll
# if (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
(defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || \
(defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \
(defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \
defined(__ARMEB__) || defined(__MIPSEB__) || defined(__s390__) || defined(__sparc__)
# define ntohll
# define htonll
# elif (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
(defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
(defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && BYTE_ORDER == LITTLE_ENDIAN) || \
defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \
defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64)
# define ntohll(x) ((ntohl((uint32_t)(x)) * UINT64_C(0x100000000)) + (ntohl((x) >> 32)))
# define htonll ntohll
# else
# error "Unable to determine byte order!"
# endif
# endif
#endif
#ifdef __cplusplus
# define CONST_CAST(t, v) const_cast<t>(v)
#else
/* C-style const_cast without triggering a warning with -Wcast-qual */
# define CONST_CAST(t, v) (t)(uintptr_t)(v)
#endif
#ifdef __GNUC__
#ifndef likely
# define likely(x) __builtin_expect(!!(x), 1)
#endif
#ifndef unlikely
# define unlikely(x) __builtin_expect(!!(x), 0)
#endif
# define unreachable() __builtin_unreachable()
#elif defined(_MSC_VER)
# define likely(x) (x)
# define unlikely(x) (x)
# define unreachable() __assume(0)
#else
# define likely(x) (x)
# define unlikely(x) (x)
# define unreachable() do {} while (0)
#endif
static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r)
{
#if ((defined(__GNUC__) && (__GNUC__ >= 5)) && !defined(__INTEL_COMPILER)) || __has_builtin(__builtin_add_overflow)
return __builtin_add_overflow(v1, v2, r);
#else
/* unsigned additions are well-defined */
*r = v1 + v2;
return v1 > v1 + v2;
#endif
}
static inline unsigned short encode_half(double val)
{
#ifdef __F16C__
return _cvtss_sh((float)val, 3);
#else
uint64_t v;
memcpy(&v, &val, sizeof(v));
int sign = v >> 63 << 15;
int exp = (v >> 52) & 0x7ff;
int mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
exp -= 1023;
if (exp == 1024) {
/* infinity or NaN */
exp = 16;
mant >>= 1;
} else if (exp >= 16) {
/* overflow, as largest number */
exp = 15;
mant = 1023;
} else if (exp >= -14) {
/* regular normal */
} else if (exp >= -24) {
/* subnormal */
mant |= 1024;
mant >>= -(exp + 14);
exp = -15;
} else {
/* underflow, make zero */
return 0;
}
/* safe cast here as bit operations above guarantee not to overflow */
return (unsigned short)(sign | ((exp + 15) << 10) | mant);
#endif
}
/* this function was copied & adapted from RFC 7049 Appendix D */
static inline double decode_half(unsigned short half)
{
#ifdef __F16C__
return _cvtsh_ss(half);
#else
int exp = (half >> 10) & 0x1f;
int mant = half & 0x3ff;
double val;
if (exp == 0) val = ldexp(mant, -24);
else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
else val = mant == 0 ? INFINITY : NAN;
return half & 0x8000 ? -val : val;
#endif
}
#endif /* COMPILERSUPPORT_H */

View File

@ -0,0 +1,3 @@
#define TINYCBOR_VERSION_MAJOR 0
#define TINYCBOR_VERSION_MINOR 6
#define TINYCBOR_VERSION_PATCH 0

15
src/3rdparty/tinycbor/tests/.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
Makefile
debug
moc_predefs.h
release
target_wrapper.*
# The executables
cpp/cpp
cpp/cpp.exe
encoder/encoder
encoder/encoder.exe
parser/parser
parser/parser.exe
tojson/tojson
tojson/tojson.exe

View File

@ -0,0 +1,310 @@
/****************************************************************************
**
** Copyright (C) 2018 Intel Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#include <QtTest>
static float myNaNf()
{
uint32_t v = 0x7fc00000;
float f;
memcpy(&f, &v, sizeof(f));
Q_ASSERT(qIsNaN(f));
return f;
}
static float myInff()
{
uint32_t v = 0x7f800000;
float f;
memcpy(&f, &v, sizeof(f));
Q_ASSERT(qIsInf(f));
return f;
}
static float myNInff()
{
uint32_t v = 0xff800000;
float f;
memcpy(&f, &v, sizeof(f));
Q_ASSERT(qIsInf(f));
return f;
}
static double myNaN()
{
uint64_t v = UINT64_C(0x7ff8000000000000);
double f;
memcpy(&f, &v, sizeof(f));
Q_ASSERT(qIsNaN(f));
return f;
}
static double myInf()
{
uint64_t v = UINT64_C(0x7ff0000000000000);
double f;
memcpy(&f, &v, sizeof(f));
Q_ASSERT(qIsInf(f));
return f;
}
static double myNInf()
{
uint64_t v = UINT64_C(0xfff0000000000000);
double f;
memcpy(&f, &v, sizeof(f));
Q_ASSERT(qIsInf(f));
return f;
}
template <size_t N> QByteArray raw(const char (&data)[N])
{
return QByteArray::fromRawData(data, N - 1);
}
struct NegativeInteger { quint64 abs; };
Q_DECLARE_METATYPE(NegativeInteger)
struct SimpleType { uint8_t type; };
Q_DECLARE_METATYPE(SimpleType)
struct Float16Standin { uint16_t val; };
Q_DECLARE_METATYPE(Float16Standin)
struct Tag { CborTag tag; QVariant tagged; };
Q_DECLARE_METATYPE(Tag)
template <typename... Args>
QVariant make_list(const Args &... args)
{
return QVariantList{args...};
}
typedef QVector<QPair<QVariant, QVariant>> Map;
Q_DECLARE_METATYPE(Map)
QVariant make_map(const std::initializer_list<QPair<QVariant, QVariant>> &list)
{
return QVariant::fromValue(Map(list));
}
struct IndeterminateLengthArray : QVariantList { using QVariantList::QVariantList; };
struct IndeterminateLengthMap : Map { using Map::Map; };
Q_DECLARE_METATYPE(IndeterminateLengthArray)
Q_DECLARE_METATYPE(IndeterminateLengthMap)
QVariant make_ilarray(const std::initializer_list<QVariant> &list)
{
return QVariant::fromValue(IndeterminateLengthArray(list));
}
QVariant make_ilmap(const std::initializer_list<QPair<QVariant, QVariant>> &list)
{
return QVariant::fromValue(IndeterminateLengthMap(list));
}
void addColumns()
{
QTest::addColumn<QByteArray>("output");
QTest::addColumn<QVariant>("input");
}
void addFixedData()
{
// unsigned integers
QTest::newRow("0U") << raw("\x00") << QVariant(0U);
QTest::newRow("1U") << raw("\x01") << QVariant(1U);
QTest::newRow("10U") << raw("\x0a") << QVariant(10U);
QTest::newRow("23U") << raw("\x17") << QVariant(23U);
QTest::newRow("24U") << raw("\x18\x18") << QVariant(24U);
QTest::newRow("255U") << raw("\x18\xff") << QVariant(255U);
QTest::newRow("256U") << raw("\x19\x01\x00") << QVariant(256U);
QTest::newRow("65535U") << raw("\x19\xff\xff") << QVariant(65535U);
QTest::newRow("65536U") << raw("\x1a\0\1\x00\x00") << QVariant(65536U);
QTest::newRow("4294967295U") << raw("\x1a\xff\xff\xff\xff") << QVariant(4294967295U);
QTest::newRow("4294967296U") << raw("\x1b\0\0\0\1\0\0\0\0") << QVariant(Q_UINT64_C(4294967296));
QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
<< QVariant(std::numeric_limits<quint64>::max());
// signed integers containing non-negative numbers
QTest::newRow("0") << raw("\x00") << QVariant(0);
QTest::newRow("1") << raw("\x01") << QVariant(1);
QTest::newRow("10") << raw("\x0a") << QVariant(10);
QTest::newRow("23") << raw("\x17") << QVariant(23);
QTest::newRow("24") << raw("\x18\x18") << QVariant(24);
QTest::newRow("255") << raw("\x18\xff") << QVariant(255);
QTest::newRow("256") << raw("\x19\x01\x00") << QVariant(256);
QTest::newRow("65535") << raw("\x19\xff\xff") << QVariant(65535);
QTest::newRow("65536") << raw("\x1a\0\1\x00\x00") << QVariant(65536);
QTest::newRow("4294967295") << raw("\x1a\xff\xff\xff\xff") << QVariant(Q_INT64_C(4294967295));
QTest::newRow("4294967296") << raw("\x1b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(4294967296));
// signed integers containing negative numbers
QTest::newRow("-1") << raw("\x20") << QVariant(-1);
QTest::newRow("-2") << raw("\x21") << QVariant(-2);
QTest::newRow("-24") << raw("\x37") << QVariant(-24);
QTest::newRow("-25") << raw("\x38\x18") << QVariant(-25);
QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << QVariant(-256);
QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << QVariant(-257);
QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << QVariant(-65536);
QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << QVariant(-65537);
QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << QVariant(Q_INT64_C(-4294967296));
QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(-4294967297));
// negative integers
auto neg = [](quint64 v) { return QVariant::fromValue<NegativeInteger>({v}); };
QTest::newRow("negative1") << raw("\x20") << neg(1);
QTest::newRow("negative2") << raw("\x21") << neg(2);
QTest::newRow("negative24") << raw("\x37") << neg(24);
QTest::newRow("negative25") << raw("\x38\x18") << neg(25);
QTest::newRow("negativeUINT8_MAX") << raw("\x38\xff") << neg(256);
QTest::newRow("negativeUINT8_MAX-1") << raw("\x39\x01\x00") << neg(257);
QTest::newRow("negativeUINT16_MAX") << raw("\x39\xff\xff") << neg(65536);
QTest::newRow("negativeUINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << neg(65537);
QTest::newRow("negativeUINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << neg(Q_UINT64_C(4294967296));
QTest::newRow("negativeUINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << neg(Q_UINT64_C(4294967297));
QTest::newRow("negativeUINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
<< neg(std::numeric_limits<quint64>::max());
QTest::newRow("negativeUINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") << neg(0);
QTest::newRow("simple0") << raw("\xe0") << QVariant::fromValue(SimpleType{0});
QTest::newRow("simple19") << raw("\xf3") << QVariant::fromValue(SimpleType{19});
QTest::newRow("false") << raw("\xf4") << QVariant(false);
QTest::newRow("true") << raw("\xf5") << QVariant(true);
QTest::newRow("null") << raw("\xf6") << QVariant::fromValue<void *>(nullptr);
QTest::newRow("undefined") << raw("\xf7") << QVariant();
QTest::newRow("simple32") << raw("\xf8\x20") << QVariant::fromValue(SimpleType{32});
QTest::newRow("simple255") << raw("\xf8\xff") << QVariant::fromValue(SimpleType{255});
// floating point
#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
QTest::newRow("0.f16") << raw("\xf9\0\0") << QVariant::fromValue(Float16Standin{0x0000});
#else
QTest::newRow("0.f16") << raw("\xf9\0\0") << QVariant::fromValue(qfloat16(0));
QTest::newRow("-1.f16") << raw("\xf9\xbc\0") << QVariant::fromValue(qfloat16(-1));
QTest::newRow("1.5f16") << raw("\xf9\x3e\0") << QVariant::fromValue(qfloat16(1.5));
QTest::newRow("nan_f16") << raw("\xf9\x7e\0") << QVariant::fromValue<qfloat16>(myNaNf());
QTest::newRow("-inf_f16") << raw("\xf9\xfc\0") << QVariant::fromValue<qfloat16>(myNInff());
QTest::newRow("+inf_f16") << raw("\xf9\x7c\0") << QVariant::fromValue<qfloat16>(myInff());
#endif
QTest::newRow("0.f") << raw("\xfa\0\0\0\0") << QVariant::fromValue(0.f);
QTest::newRow("0.") << raw("\xfb\0\0\0\0\0\0\0\0") << QVariant(0.);
QTest::newRow("-1.f") << raw("\xfa\xbf\x80\0\0") << QVariant::fromValue(-1.f);
QTest::newRow("-1.") << raw("\xfb\xbf\xf0\0\0\0\0\0\0") << QVariant(-1.);
QTest::newRow("16777215.f") << raw("\xfa\x4b\x7f\xff\xff") << QVariant::fromValue(16777215.f);
QTest::newRow("16777215.") << raw("\xfb\x41\x6f\xff\xff\xe0\0\0\0") << QVariant::fromValue(16777215.);
QTest::newRow("-16777215.f") << raw("\xfa\xcb\x7f\xff\xff") << QVariant(-16777215.f);
QTest::newRow("-16777215.") << raw("\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << QVariant::fromValue(-16777215.);
QTest::newRow("nan_f") << raw("\xfa\x7f\xc0\0\0") << QVariant::fromValue<float>(myNaNf());
QTest::newRow("nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << QVariant(myNaN());
QTest::newRow("-inf_f") << raw("\xfa\xff\x80\0\0") << QVariant::fromValue<float>(myNInff());
QTest::newRow("-inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << QVariant(myNInf());
QTest::newRow("+inf_f") << raw("\xfa\x7f\x80\0\0") << QVariant::fromValue<float>(myInff());
QTest::newRow("+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << QVariant(myInf());
}
void addStringsData()
{
// byte strings
QTest::newRow("emptybytestring") << raw("\x40") << QVariant(QByteArray(""));
QTest::newRow("bytestring1") << raw("\x41 ") << QVariant(QByteArray(" "));
QTest::newRow("bytestring1-nul") << raw("\x41\0") << QVariant(QByteArray("", 1));
QTest::newRow("bytestring5") << raw("\x45Hello") << QVariant(QByteArray("Hello"));
QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234")
<< QVariant(QByteArray("123456789012345678901234"));
QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3')
<< QVariant(QByteArray(256, '3'));
// text strings
QTest::newRow("emptytextstring") << raw("\x60") << QVariant("");
QTest::newRow("textstring1") << raw("\x61 ") << QVariant(" ");
QTest::newRow("textstring1-nul") << raw("\x61\0") << QVariant(QString::fromLatin1("", 1));
QTest::newRow("textstring5") << raw("\x65Hello") << QVariant("Hello");
QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234")
<< QVariant("123456789012345678901234");
QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3')
<< QVariant(QString(256, '3'));
}
void addArraysAndMaps()
{
QTest::newRow("emptyarray") << raw("\x80") << make_list();
QTest::newRow("emptymap") << raw("\xa0") << make_map({});
QTest::newRow("array-0") << raw("\x81\0") << make_list(0);
QTest::newRow("array-{0-0}") << raw("\x82\0\0") << make_list(0, 0);
QTest::newRow("array-Hello") << raw("\x81\x65Hello") << make_list("Hello");
QTest::newRow("array-array-0") << raw("\x81\x81\0") << make_list(make_list(0));
QTest::newRow("array-array-{0-0}") << raw("\x81\x82\0\0") << make_list(make_list(0, 0));
QTest::newRow("array-array-0-0") << raw("\x82\x81\0\0") << make_list(make_list(0),0);
QTest::newRow("array-array-Hello") << raw("\x81\x81\x65Hello") << make_list(make_list("Hello"));
QTest::newRow("map-0:0") << raw("\xa1\0\0") << make_map({{0,0}});
QTest::newRow("map-0:0-1:1") << raw("\xa2\0\0\1\1") << make_map({{0,0}, {1,1}});
QTest::newRow("map-0:{map-0:0-1:1}") << raw("\xa1\0\xa2\0\0\1\1") << make_map({{0, make_map({{0,0}, {1,1}})}});
QTest::newRow("array-map1") << raw("\x81\xa1\0\0") << make_list(make_map({{0,0}}));
QTest::newRow("array-map2") << raw("\x82\xa1\0\0\xa1\1\1") << make_list(make_map({{0,0}}), make_map({{1,1}}));
QTest::newRow("map-array1") << raw("\xa1\x62oc\x81\0") << make_map({{"oc", make_list(0)}});
QTest::newRow("map-array2") << raw("\xa1\x62oc\x84\0\1\2\3") << make_map({{"oc", make_list(0, 1, 2, 3)}});
QTest::newRow("map-array3") << raw("\xa2\x62oc\x82\0\1\2\3") << make_map({{"oc", make_list(0, 1)}, {2, 3}});
// indeterminate length
QTest::newRow("_emptyarray") << raw("\x9f\xff") << QVariant::fromValue(IndeterminateLengthArray{});
QTest::newRow("_emptymap") << raw("\xbf\xff") << make_ilmap({});
QTest::newRow("_array-0") << raw("\x9f\0\xff") << make_ilarray({0});
QTest::newRow("_array-{0-0}") << raw("\x9f\0\0\xff") << make_ilarray({0, 0});
QTest::newRow("_array-Hello") << raw("\x9f\x65Hello\xff") << make_ilarray({"Hello"});
QTest::newRow("_array-array-0") << raw("\x9f\x81\0\xff") << make_ilarray({make_list(0)});
QTest::newRow("_array-_array-0") << raw("\x9f\x9f\0\xff\xff") << make_ilarray({make_ilarray({0})});
QTest::newRow("_array-_array-{0-0}") << raw("\x9f\x9f\0\0\xff\xff") << make_ilarray({make_ilarray({0, 0})});
QTest::newRow("_array-_array-0-0") << raw("\x9f\x9f\0\xff\0\xff") << make_ilarray({make_ilarray({0}),0});
QTest::newRow("_array-_array-Hello") << raw("\x9f\x9f\x65Hello\xff\xff") << make_ilarray({make_ilarray({"Hello"})});
QTest::newRow("_map-0:0") << raw("\xbf\0\0\xff") << make_ilmap({{0,0}});
QTest::newRow("_map-0:0-1:1") << raw("\xbf\0\0\1\1\xff") << make_ilmap({{0,0}, {1,1}});
QTest::newRow("_map-0:{map-0:0-1:1}") << raw("\xbf\0\xa2\0\0\1\1\xff") << make_ilmap({{0, make_map({{0,0}, {1,1}})}});
QTest::newRow("_map-0:{_map-0:0-1:1}") << raw("\xbf\0\xbf\0\0\1\1\xff\xff") << make_ilmap({{0, make_ilmap({{0,0}, {1,1}})}});
QTest::newRow("_array-map1") << raw("\x9f\xa1\0\0\xff") << make_ilarray({make_map({{0,0}})});
QTest::newRow("_array-_map1") << raw("\x9f\xbf\0\0\xff\xff") << make_ilarray({make_ilmap({{0,0}})});
QTest::newRow("_array-map2") << raw("\x9f\xa1\0\0\xa1\1\1\xff") << make_ilarray({make_map({{0,0}}), make_map({{1,1}})});
QTest::newRow("_array-_map2") << raw("\x9f\xbf\0\0\xff\xbf\1\1\xff\xff") << make_ilarray({make_ilmap({{0,0}}), make_ilmap({{1,1}})});
QTest::newRow("_map-array1") << raw("\xbf\x62oc\x81\0\xff") << make_ilmap({{"oc", make_list(0)}});
QTest::newRow("_map-_array1") << raw("\xbf\x62oc\x9f\0\xff\xff") << make_ilmap({{"oc", make_ilarray({0})}});
QTest::newRow("_map-array2") << raw("\xbf\x62oc\x84\0\1\2\3\xff") << make_ilmap({{"oc", make_list(0, 1, 2, 3)}});
QTest::newRow("_map-_array2") << raw("\xbf\x62oc\x9f\0\1\2\3\xff\xff") << make_ilmap({{"oc", make_ilarray({0, 1, 2, 3})}});
QTest::newRow("_map-array3") << raw("\xbf\x62oc\x82\0\1\2\3\xff") << make_ilmap({{"oc", make_list(0, 1)}, {2, 3}});
QTest::newRow("_map-_array3") << raw("\xbf\x62oc\x9f\0\1\xff\2\3\xff") << make_ilmap({{"oc", make_ilarray({0, 1})}, {2, 3}});
// tagged
QTest::newRow("array-1(0)") << raw("\x81\xc1\0") << make_list(QVariant::fromValue(Tag{1, 0}));
QTest::newRow("array-1(map)") << raw("\x81\xc1\xa0") << make_list(QVariant::fromValue(Tag{1, make_map({})}));
QTest::newRow("map-1(2):3(4)") << raw("\xa1\xc1\2\xc3\4") << make_map({{QVariant::fromValue(Tag{1, 2}), QVariant::fromValue(Tag{3, 4})}});
}

View File

@ -0,0 +1,9 @@
SOURCES += tst_encoder.cpp
CONFIG += testcase parallel_test c++11
QT = core testlib
INCLUDEPATH += ../../src
msvc: POST_TARGETDEPS = ../../lib/tinycbor.lib
else: POST_TARGETDEPS += ../../lib/libtinycbor.a
LIBS += $$POST_TARGETDEPS

View File

@ -0,0 +1,496 @@
/****************************************************************************
**
** Copyright (C) 2016 Intel Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#include <QtTest>
#include "cbor.h"
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
#include <qfloat16.h>
#endif
Q_DECLARE_METATYPE(CborError)
namespace QTest {
template<> char *toString<CborError>(const CborError &err)
{
return qstrdup(cbor_error_string(err));
}
}
class tst_Encoder : public QObject
{
Q_OBJECT
private slots:
void fixed_data();
void fixed();
void strings_data();
void strings() { fixed(); }
void arraysAndMaps_data();
void arraysAndMaps() { fixed(); }
void tags_data();
void tags();
void arrays_data() { tags_data(); }
void arrays();
void maps_data() { tags_data(); }
void maps();
void writerApi_data() { tags_data(); }
void writerApi();
void writerApiFail_data() { tags_data(); }
void writerApiFail();
void shortBuffer_data() { tags_data(); }
void shortBuffer();
void tooShortArrays_data() { tags_data(); }
void tooShortArrays();
void tooShortMaps_data() { tags_data(); }
void tooShortMaps();
void tooBigArrays_data() { tags_data(); }
void tooBigArrays();
void tooBigMaps_data() { tags_data(); }
void tooBigMaps();
void illegalSimpleType_data();
void illegalSimpleType();
};
#include "tst_encoder.moc"
#include "data.cpp"
static inline bool isOomError(CborError err)
{
return err == CborErrorOutOfMemory;
}
CborError encodeVariant(CborEncoder *encoder, const QVariant &v)
{
int type = v.userType();
switch (type) {
case QVariant::Int:
case QVariant::LongLong:
return cbor_encode_int(encoder, v.toLongLong());
case QVariant::UInt:
case QVariant::ULongLong:
return cbor_encode_uint(encoder, v.toULongLong());
case QVariant::Bool:
return cbor_encode_boolean(encoder, v.toBool());
case QVariant::Invalid:
return cbor_encode_undefined(encoder);
case QMetaType::VoidStar:
return cbor_encode_null(encoder);
case QVariant::Double:
return cbor_encode_double(encoder, v.toDouble());
case QMetaType::Float:
return cbor_encode_float(encoder, v.toFloat());
case QVariant::String: {
QByteArray string = v.toString().toUtf8();
return cbor_encode_text_string(encoder, string.constData(), string.length());
}
case QVariant::ByteArray: {
QByteArray string = v.toByteArray();
return cbor_encode_byte_string(encoder, reinterpret_cast<const quint8 *>(string.constData()), string.length());
}
default:
if (type == qMetaTypeId<NegativeInteger>())
return cbor_encode_negative_int(encoder, v.value<NegativeInteger>().abs);
if (type == qMetaTypeId<SimpleType>())
return cbor_encode_simple_value(encoder, v.value<SimpleType>().type);
#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
if (type == qMetaTypeId<Float16Standin>())
return cbor_encode_half_float(encoder, v.constData());
#else
if (type == qMetaTypeId<qfloat16>())
return cbor_encode_half_float(encoder, v.constData());
#endif
if (type == qMetaTypeId<Tag>()) {
CborError err = cbor_encode_tag(encoder, v.value<Tag>().tag);
if (err && !isOomError(err))
return err;
return static_cast<CborError>(err | encodeVariant(encoder, v.value<Tag>().tagged));
}
if (type == QVariant::List || type == qMetaTypeId<IndeterminateLengthArray>()) {
CborEncoder sub;
QVariantList list = v.toList();
size_t len = list.length();
if (type == qMetaTypeId<IndeterminateLengthArray>()) {
len = CborIndefiniteLength;
list = v.value<IndeterminateLengthArray>();
}
CborError err = cbor_encoder_create_array(encoder, &sub, len);
if (err && !isOomError(err))
return err;
foreach (const QVariant &v2, list) {
err = static_cast<CborError>(err | encodeVariant(&sub, v2));
if (err && !isOomError(err))
return err;
}
return cbor_encoder_close_container_checked(encoder, &sub);
}
if (type == qMetaTypeId<Map>() || type == qMetaTypeId<IndeterminateLengthMap>()) {
CborEncoder sub;
Map map = v.value<Map>();
size_t len = map.length();
if (type == qMetaTypeId<IndeterminateLengthMap>()) {
len = CborIndefiniteLength;
map = v.value<IndeterminateLengthMap>();
}
CborError err = cbor_encoder_create_map(encoder, &sub, len);
if (err && !isOomError(err))
return err;
for (auto pair : map) {
err = static_cast<CborError>(err | encodeVariant(&sub, pair.first));
if (err && !isOomError(err))
return err;
err = static_cast<CborError>(err | encodeVariant(&sub, pair.second));
if (err && !isOomError(err))
return err;
}
return cbor_encoder_close_container_checked(encoder, &sub);
}
}
return CborErrorUnknownType;
}
void compare(const QVariant &input, const QByteArray &output)
{
QByteArray buffer(output.length(), Qt::Uninitialized);
uint8_t *bufptr = reinterpret_cast<quint8 *>(buffer.data());
CborEncoder encoder;
cbor_encoder_init(&encoder, bufptr, buffer.length(), 0);
QCOMPARE(encodeVariant(&encoder, input), CborNoError);
QCOMPARE(encoder.remaining, size_t(1));
QCOMPARE(cbor_encoder_get_extra_bytes_needed(&encoder), size_t(0));
buffer.resize(int(cbor_encoder_get_buffer_size(&encoder, bufptr)));
QCOMPARE(buffer, output);
}
void tst_Encoder::fixed_data()
{
addColumns();
addFixedData();
}
void tst_Encoder::fixed()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
compare(input, output);
}
void tst_Encoder::strings_data()
{
addColumns();
addStringsData();
}
void tst_Encoder::arraysAndMaps_data()
{
addColumns();
addArraysAndMaps();
}
void tst_Encoder::tags_data()
{
addColumns();
addFixedData();
addStringsData();
addArraysAndMaps();
}
void tst_Encoder::tags()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
compare(QVariant::fromValue(Tag{1, input}), "\xc1" + output);
if (QTest::currentTestFailed()) return;
compare(QVariant::fromValue(Tag{24, input}), "\xd8\x18" + output);
if (QTest::currentTestFailed()) return;
compare(QVariant::fromValue(Tag{255, input}), "\xd8\xff" + output);
if (QTest::currentTestFailed()) return;
compare(QVariant::fromValue(Tag{256, input}), raw("\xd9\1\0") + output);
if (QTest::currentTestFailed()) return;
compare(QVariant::fromValue(Tag{CborSignatureTag, input}), raw("\xd9\xd9\xf7") + output);
if (QTest::currentTestFailed()) return;
compare(QVariant::fromValue(Tag{65535, input}), raw("\xd9\xff\xff") + output);
if (QTest::currentTestFailed()) return;
compare(QVariant::fromValue(Tag{65536, input}), raw("\xda\0\1\0\0") + output);
if (QTest::currentTestFailed()) return;
compare(QVariant::fromValue(Tag{UINT32_MAX, input}), raw("\xda\xff\xff\xff\xff") + output);
if (QTest::currentTestFailed()) return;
compare(QVariant::fromValue(Tag{UINT32_MAX + Q_UINT64_C(1), input}), raw("\xdb\0\0\0\1\0\0\0\0") + output);
if (QTest::currentTestFailed()) return;
compare(QVariant::fromValue(Tag{UINT64_MAX, input}), raw("\xdb\xff\xff\xff\xff\xff\xff\xff\xff") + output);
if (QTest::currentTestFailed()) return;
// nested tags
compare(QVariant::fromValue(Tag{1, QVariant::fromValue(Tag{1, input})}), "\xc1\xc1" + output);
}
void tst_Encoder::arrays()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
compare(make_list(input), "\x81" + output);
if (QTest::currentTestFailed()) return;
compare(make_list(input, input), "\x82" + output + output);
if (QTest::currentTestFailed()) return;
{
QVariantList list{input};
QByteArray longoutput = output;
// make a list with 32 elements (1 << 5)
for (int i = 0; i < 5; ++i) {
list += list;
longoutput += longoutput;
}
compare(list, "\x98\x20" + longoutput);
if (QTest::currentTestFailed()) return;
// now 256 elements (32 << 3)
for (int i = 0; i < 3; ++i) {
list += list;
longoutput += longoutput;
}
compare(list, raw("\x99\1\0") + longoutput);
if (QTest::currentTestFailed()) return;
}
// nested lists
compare(make_list(make_list(input)), "\x81\x81" + output);
if (QTest::currentTestFailed()) return;
compare(make_list(make_list(input, input)), "\x81\x82" + output + output);
if (QTest::currentTestFailed()) return;
compare(make_list(make_list(input), input), "\x82\x81" + output + output);
if (QTest::currentTestFailed()) return;
compare(make_list(make_list(input), make_list(input)), "\x82\x81" + output + "\x81" + output);
}
void tst_Encoder::maps()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
compare(make_map({{1, input}}), "\xa1\1" + output);
if (QTest::currentTestFailed()) return;
compare(make_map({{1, input}, {input, 24}}), "\xa2\1" + output + output + "\x18\x18");
if (QTest::currentTestFailed()) return;
compare(make_map({{input, input}}), "\xa1" + output + output);
if (QTest::currentTestFailed()) return;
{
Map map{{1, input}};
QByteArray longoutput = "\1" + output;
// make a map with 32 elements (1 << 5)
for (int i = 0; i < 5; ++i) {
map += map;
longoutput += longoutput;
}
compare(QVariant::fromValue(map), "\xb8\x20" + longoutput);
if (QTest::currentTestFailed()) return;
// now 256 elements (32 << 3)
for (int i = 0; i < 3; ++i) {
map += map;
longoutput += longoutput;
}
compare(QVariant::fromValue(map), raw("\xb9\1\0") + longoutput);
if (QTest::currentTestFailed()) return;
}
// nested maps
compare(make_map({{1, make_map({{2, input}})}}), "\xa1\1\xa1\2" + output);
if (QTest::currentTestFailed()) return;
compare(make_map({{1, make_map({{2, input}, {input, false}})}}), "\xa1\1\xa2\2" + output + output + "\xf4");
if (QTest::currentTestFailed()) return;
compare(make_map({{1, make_map({{2, input}})}, {input, false}}), "\xa2\1\xa1\2" + output + output + "\xf4");
if (QTest::currentTestFailed()) return;
}
void tst_Encoder::writerApi()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
// instead of writing to a QByteArray like all other tests, write to a QBuffer
QBuffer buffer;
buffer.open(QIODevice::ReadWrite);
auto callback = [](void *token, const void *data, size_t len, CborEncoderAppendType) {
auto buffer = static_cast<QBuffer *>(token);
buffer->write(static_cast<const char *>(data), len);
return CborNoError;
};
CborEncoder encoder;
cbor_encoder_init_writer(&encoder, callback, &buffer);
QCOMPARE(encodeVariant(&encoder, input), CborNoError);
buffer.reset();
QCOMPARE(buffer.readAll(), output);
}
void tst_Encoder::writerApiFail()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
// same as above, but we'll produce an error during writing and we expect
// it to be returned
int callCount = 0;
auto callback = [](void *token, const void *, size_t, CborEncoderAppendType) {
++*static_cast<int *>(token);
return CborErrorIO;
};
CborEncoder encoder;
cbor_encoder_init_writer(&encoder, callback, &callCount);
QCOMPARE(encodeVariant(&encoder, input), CborErrorIO);
QCOMPARE(callCount, 1);
}
void tst_Encoder::shortBuffer()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
QByteArray buffer(output.length(), Qt::Uninitialized);
for (int len = 0; len < output.length(); ++len) {
CborEncoder encoder;
cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), len, 0);
QCOMPARE(encodeVariant(&encoder, input), CborErrorOutOfMemory);
QVERIFY(cbor_encoder_get_extra_bytes_needed(&encoder) != 0);
QCOMPARE(len + cbor_encoder_get_extra_bytes_needed(&encoder), size_t(output.length()));
}
}
void tst_Encoder::tooShortArrays()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
QByteArray buffer(output.length() + 1, Qt::Uninitialized);
CborEncoder encoder, container;
cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), buffer.length(), 0);
QCOMPARE(cbor_encoder_create_array(&encoder, &container, 2), CborNoError);
QCOMPARE(encodeVariant(&container, input), CborNoError);
QCOMPARE(container.remaining, size_t(2));
QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooFewItems);
}
void tst_Encoder::tooShortMaps()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
QByteArray buffer(output.length() + 1, Qt::Uninitialized);
CborEncoder encoder, container;
cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), buffer.length(), 0);
QCOMPARE(cbor_encoder_create_map(&encoder, &container, 2), CborNoError);
QCOMPARE(encodeVariant(&container, input), CborNoError);
QCOMPARE(container.remaining, size_t(4));
QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooFewItems);
}
void tst_Encoder::tooBigArrays()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
QByteArray buffer(output.length() * 2 + 1, Qt::Uninitialized);
CborEncoder encoder, container;
cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), buffer.length(), 0);
QCOMPARE(cbor_encoder_create_array(&encoder, &container, 1), CborNoError);
QCOMPARE(encodeVariant(&container, input), CborNoError);
QCOMPARE(encodeVariant(&container, input), CborNoError);
QCOMPARE(container.remaining, size_t(0));
QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooManyItems);
}
void tst_Encoder::tooBigMaps()
{
QFETCH(QVariant, input);
QFETCH(QByteArray, output);
QByteArray buffer(output.length() * 3 + 1, Qt::Uninitialized);
CborEncoder encoder, container;
cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), buffer.length(), 0);
QCOMPARE(cbor_encoder_create_map(&encoder, &container, 1), CborNoError);
QCOMPARE(encodeVariant(&container, input), CborNoError);
QCOMPARE(encodeVariant(&container, input), CborNoError);
QCOMPARE(encodeVariant(&container, input), CborNoError);
QCOMPARE(container.remaining, size_t(0));
QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooManyItems);
}
void tst_Encoder::illegalSimpleType_data()
{
QTest::addColumn<int>("type");
QTest::newRow("half-float") << 25;
QTest::newRow("float") << 26;
QTest::newRow("double") << 27;
QTest::newRow("28") << 28;
QTest::newRow("29") << 29;
QTest::newRow("30") << 30;
QTest::newRow("31") << 31;
}
void tst_Encoder::illegalSimpleType()
{
QFETCH(int, type);
quint8 buf[2];
CborEncoder encoder;
cbor_encoder_init(&encoder, buf, sizeof(buf), 0);
QCOMPARE(cbor_encode_simple_value(&encoder, type), CborErrorIllegalSimpleType);
}
QTEST_MAIN(tst_Encoder)

View File

@ -0,0 +1,573 @@
#include <QtTest>
#include <limits>
#include <cbor.h>
Q_DECLARE_METATYPE(CborError)
template <size_t N> QByteArray raw(const char (&data)[N])
{
return QByteArray::fromRawData(data, N - 1);
}
void addIntegers()
{
QTest::addColumn<QByteArray>("data");
QTest::addColumn<quint64>("expectedRaw");
QTest::addColumn<qint64>("expectedValue");
QTest::addColumn<bool>("isNegative");
QTest::addColumn<bool>("inInt64Range");
// unsigned integers
QTest::newRow("0") << raw("\x00") << Q_UINT64_C(0) << Q_INT64_C(0) << false << true;
QTest::newRow("1") << raw("\x01") << Q_UINT64_C(1) << Q_INT64_C(1) << false << true;
QTest::newRow("10") << raw("\x0a") << Q_UINT64_C(10) << Q_INT64_C(10) << false << true;
QTest::newRow("23") << raw("\x17") << Q_UINT64_C(23) << Q_INT64_C(23) << false << true;
QTest::newRow("24") << raw("\x18\x18") << Q_UINT64_C(24) << Q_INT64_C(24) << false << true;
QTest::newRow("UINT8_MAX") << raw("\x18\xff") << Q_UINT64_C(255) << Q_INT64_C(255) << false << true;
QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << Q_UINT64_C(256) << Q_INT64_C(256) << false << true;
QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << Q_UINT64_C(65535) << Q_INT64_C(65535) << false << true;
QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << Q_UINT64_C(65536) << Q_INT64_C(65536) << false << true;
QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << Q_UINT64_C(4294967295) << Q_INT64_C(4294967295) << false << true;
QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << Q_UINT64_C(4294967296) << Q_INT64_C(4294967296) << false << true;
QTest::newRow("INT64_MAX") << raw("\x1b" "\x7f\xff\xff\xff" "\xff\xff\xff\xff")
<< quint64(std::numeric_limits<qint64>::max())
<< std::numeric_limits<qint64>::max() << false << true;
QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
<< std::numeric_limits<quint64>::max() << qint64(-123456) << false << false;
// negative integers
QTest::newRow("-1") << raw("\x20") << Q_UINT64_C(0) << Q_INT64_C(-1) << true << true;
QTest::newRow("-2") << raw("\x21") << Q_UINT64_C(1) << Q_INT64_C(-2) << true << true;
QTest::newRow("-24") << raw("\x37") << Q_UINT64_C(23) << Q_INT64_C(-24) << true << true;
QTest::newRow("-25") << raw("\x38\x18") << Q_UINT64_C(24) << Q_INT64_C(-25) << true << true;
QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << Q_UINT64_C(255) << Q_INT64_C(-256) << true << true;
QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << Q_UINT64_C(256) << Q_INT64_C(-257) << true << true;
QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << Q_UINT64_C(65535) << Q_INT64_C(-65536) << true << true;
QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << Q_UINT64_C(65536) << Q_INT64_C(-65537) << true << true;
QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << Q_UINT64_C(4294967295) << Q_INT64_C(-4294967296) << true << true;
QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << Q_UINT64_C(4294967296) << Q_INT64_C(-4294967297) << true << true;
QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
<< quint64(std::numeric_limits<qint64>::max() - 1)
<< (std::numeric_limits<qint64>::min() + 1)
<< true << true;
QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
<< quint64(std::numeric_limits<qint64>::max())
<< std::numeric_limits<qint64>::min()
<< true << true;
QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << Q_UINT64_C(9223372036854775808) << qint64(-123456) << true << false;
QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
<< (std::numeric_limits<quint64>::max() - 1) << qint64(-123456) << true << false;
QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
<< std::numeric_limits<quint64>::max() << qint64(-123456) << true << false;
}
void addColumns()
{
QTest::addColumn<QByteArray>("data");
QTest::addColumn<QString>("expected");
QTest::addColumn<int>("n"); // some aux integer, not added in all columns
}
void addFixedData()
{
// unsigned integers
QTest::newRow("0") << raw("\x00") << "0";
QTest::newRow("1") << raw("\x01") << "1";
QTest::newRow("10") << raw("\x0a") << "10";
QTest::newRow("23") << raw("\x17") << "23";
QTest::newRow("24") << raw("\x18\x18") << "24";
QTest::newRow("UINT8_MAX") << raw("\x18\xff") << "255";
QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << "256";
QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << "65535";
QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << "65536";
QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << "4294967295";
QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << "4294967296";
QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
<< QString::number(std::numeric_limits<uint64_t>::max());
// negative integers
QTest::newRow("-1") << raw("\x20") << "-1";
QTest::newRow("-2") << raw("\x21") << "-2";
QTest::newRow("-24") << raw("\x37") << "-24";
QTest::newRow("-25") << raw("\x38\x18") << "-25";
QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << "-256";
QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << "-257";
QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << "-65536";
QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << "-65537";
QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << "-4294967296";
QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << "-4294967297";
QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
<< QString::number(std::numeric_limits<int64_t>::min() + 1);
QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
<< QString::number(std::numeric_limits<int64_t>::min());
QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << "-9223372036854775809";
QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
<< '-' + QString::number(std::numeric_limits<uint64_t>::max());
QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
<< "-18446744073709551616";
// overlongs
QTest::newRow("0*1") << raw("\x18\x00") << "0_0";
QTest::newRow("0*2") << raw("\x19\x00\x00") << "0_1";
QTest::newRow("0*4") << raw("\x1a\0\0\0\0") << "0_2";
QTest::newRow("0*8") << raw("\x1b\0\0\0\0\0\0\0\0") << "0_3";
QTest::newRow("-1*1") << raw("\x38\x00") << "-1_0";
QTest::newRow("-1*2") << raw("\x39\x00\x00") << "-1_1";
QTest::newRow("-1*4") << raw("\x3a\0\0\0\0") << "-1_2";
QTest::newRow("-1*8") << raw("\x3b\0\0\0\0\0\0\0\0") << "-1_3";
QTest::newRow("simple0") << raw("\xe0") << "simple(0)";
QTest::newRow("simple19") << raw("\xf3") << "simple(19)";
QTest::newRow("false") << raw("\xf4") << "false";
QTest::newRow("true") << raw("\xf5") << "true";
QTest::newRow("null") << raw("\xf6") << "null";
QTest::newRow("undefined") << raw("\xf7") << "undefined";
QTest::newRow("simple32") << raw("\xf8\x20") << "simple(32)";
QTest::newRow("simple255") << raw("\xf8\xff") << "simple(255)";
// floating point
QTest::newRow("0.f16") << raw("\xf9\0\0") << "0.f16";
QTest::newRow("0.f") << raw("\xfa\0\0\0\0") << "0.f";
QTest::newRow("0.") << raw("\xfb\0\0\0\0\0\0\0\0") << "0.";
QTest::newRow("-1.f16") << raw("\xf9\xbc\x00") << "-1.f16";
QTest::newRow("-1.f") << raw("\xfa\xbf\x80\0\0") << "-1.f";
QTest::newRow("-1.") << raw("\xfb\xbf\xf0\0\0\0\0\0\0") << "-1.";
QTest::newRow("65504.f16") << raw("\xf9\x7b\xff") << "65504.f16";
QTest::newRow("16777215.f") << raw("\xfa\x4b\x7f\xff\xff") << "16777215.f";
QTest::newRow("16777215.") << raw("\xfb\x41\x6f\xff\xff\xe0\0\0\0") << "16777215.";
QTest::newRow("-16777215.f") << raw("\xfa\xcb\x7f\xff\xff") << "-16777215.f";
QTest::newRow("-16777215.") << raw("\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << "-16777215.";
QTest::newRow("0.5f16") << raw("\xf9\x38\0") << "0.5f16";
QTest::newRow("0.5f") << raw("\xfa\x3f\0\0\0") << "0.5f";
QTest::newRow("0.5") << raw("\xfb\x3f\xe0\0\0\0\0\0\0") << "0.5";
QTest::newRow("2.f16^11-1") << raw("\xf9\x67\xff") << "2047.f16";
QTest::newRow("2.f^24-1") << raw("\xfa\x4b\x7f\xff\xff") << "16777215.f";
QTest::newRow("2.^53-1") << raw("\xfb\x43\x3f\xff\xff""\xff\xff\xff\xff") << "9007199254740991.";
QTest::newRow("2.f^64-epsilon") << raw("\xfa\x5f\x7f\xff\xff") << "18446742974197923840.f";
QTest::newRow("2.^64-epsilon") << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff") << "18446744073709549568.";
QTest::newRow("2.f^64") << raw("\xfa\x5f\x80\0\0") << "1.8446744073709552e+19f";
QTest::newRow("2.^64") << raw("\xfb\x43\xf0\0\0\0\0\0\0") << "1.8446744073709552e+19";
QTest::newRow("nan_f16") << raw("\xf9\x7e\x00") << "nan";
QTest::newRow("nan_f") << raw("\xfa\x7f\xc0\0\0") << "nan";
QTest::newRow("nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << "nan";
QTest::newRow("-inf_f16") << raw("\xf9\xfc\x00") << "-inf";
QTest::newRow("-inf_f") << raw("\xfa\xff\x80\0\0") << "-inf";
QTest::newRow("-inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << "-inf";
QTest::newRow("+inf_f16") << raw("\xf9\x7c\x00") << "inf";
QTest::newRow("+inf_f") << raw("\xfa\x7f\x80\0\0") << "inf";
QTest::newRow("+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << "inf";
}
void addNonChunkedStringsData()
{
// byte strings
QTest::newRow("emptybytestring") << raw("\x40") << "h''";
QTest::newRow("bytestring1") << raw("\x41 ") << "h'20'";
QTest::newRow("bytestring1-nul") << raw("\x41\0") << "h'00'";
QTest::newRow("bytestring5") << raw("\x45Hello") << "h'48656c6c6f'";
QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234")
<< "h'313233343536373839303132333435363738393031323334'";
QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3')
<< "h'" + QString(256 * 2, '3') + '\'';
// text strings
QTest::newRow("emptytextstring") << raw("\x60") << "\"\"";
QTest::newRow("textstring1") << raw("\x61 ") << "\" \"";
QTest::newRow("textstring1-nul") << raw("\x61\0") << "\"\\u0000\"";
QTest::newRow("textstring5") << raw("\x65Hello") << "\"Hello\"";
QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234")
<< "\"123456789012345678901234\"";
QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3')
<< '"' + QString(256, '3') + '"';
// some strings with UTF-8 content
// we had a bug in the pretty dumper - see issue #54
QTest::newRow("textstringutf8-2char") << raw("\x62\xc2\xa0") << "\"\\u00A0\"";
QTest::newRow("textstringutf8-2char2") << raw("\x64\xc2\xa0\xc2\xa9") << "\"\\u00A0\\u00A9\"";
QTest::newRow("textstringutf8-3char") << raw("\x63\xe2\x88\x80") << "\"\\u2200\"";
QTest::newRow("textstringutf8-4char") << raw("\x64\xf0\x90\x88\x83") << "\"\\uD800\\uDE03\"";
// strings with overlong length
QTest::newRow("emptybytestring*1") << raw("\x58\x00") << "h''_0";
QTest::newRow("emptytextstring*1") << raw("\x78\x00") << "\"\"_0";
QTest::newRow("emptybytestring*2") << raw("\x59\x00\x00") << "h''_1";
QTest::newRow("emptytextstring*2") << raw("\x79\x00\x00") << "\"\"_1";
QTest::newRow("emptybytestring*4") << raw("\x5a\0\0\0\0") << "h''_2";
QTest::newRow("emptytextstring*4") << raw("\x7a\0\0\0\0") << "\"\"_2";
QTest::newRow("emptybytestring*8") << raw("\x5b\0\0\0\0\0\0\0\0") << "h''_3";
QTest::newRow("emptytextstring*8") << raw("\x7b\0\0\0\0\0\0\0\0") << "\"\"_3";
QTest::newRow("bytestring5*1") << raw("\x58\x05Hello") << "h'48656c6c6f'_0";
QTest::newRow("textstring5*1") << raw("\x78\x05Hello") << "\"Hello\"_0";
QTest::newRow("bytestring5*2") << raw("\x59\0\5Hello") << "h'48656c6c6f'_1";
QTest::newRow("textstring5*2") << raw("\x79\0\x05Hello") << "\"Hello\"_1";
QTest::newRow("bytestring5*4") << raw("\x5a\0\0\0\5Hello") << "h'48656c6c6f'_2";
QTest::newRow("textstring5*4") << raw("\x7a\0\0\0\x05Hello") << "\"Hello\"_2";
QTest::newRow("bytestring5*8") << raw("\x5b\0\0\0\0\0\0\0\5Hello") << "h'48656c6c6f'_3";
QTest::newRow("textstring5*8") << raw("\x7b\0\0\0\0\0\0\0\x05Hello") << "\"Hello\"_3";
}
void addStringsData()
{
addNonChunkedStringsData();
// strings with undefined length
QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "(_ )";
QTest::newRow("_emptytextstring") << raw("\x7f\xff") << "(_ )";
QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << "(_ h'')";
QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << "(_ \"\")";
QTest::newRow("_emptybytestring2*1") << raw("\x5f\x58\x00\xff") << "(_ h''_0)";
QTest::newRow("_emptytextstring2*1") << raw("\x7f\x78\x00\xff") << "(_ \"\"_0)";
QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << "(_ h'', h'')";
QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << "(_ \"\", \"\")";
QTest::newRow("_emptybytestring3*2") << raw("\x5f\x59\x00\x00\x40\xff") << "(_ h''_1, h'')";
QTest::newRow("_emptytextstring3*2") << raw("\x7f\x79\x00\x00\x60\xff") << "(_ \"\"_1, \"\")";
QTest::newRow("_bytestring5x2") << raw("\x5f\x43Hel\x42lo\xff") << "(_ h'48656c', h'6c6f')";
QTest::newRow("_textstring5x2") << raw("\x7f\x63Hel\x62lo\xff") << "(_ \"Hel\", \"lo\")";
QTest::newRow("_bytestring5x2*8*4") << raw("\x5f\x5b\0\0\0\0\0\0\0\3Hel\x5a\0\0\0\2lo\xff") << "(_ h'48656c'_3, h'6c6f'_2)";
QTest::newRow("_textstring5x2*8*4") << raw("\x7f\x7b\0\0\0\0\0\0\0\3Hel\x7a\0\0\0\2lo\xff") << "(_ \"Hel\"_3, \"lo\"_2)";
QTest::newRow("_bytestring5x5") << raw("\x5f\x41H\x41""e\x41l\x41l\x41o\xff") << "(_ h'48', h'65', h'6c', h'6c', h'6f')";
QTest::newRow("_textstring5x5") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "(_ \"H\", \"e\", \"l\", \"l\", \"o\")";
QTest::newRow("_bytestring5x6") << raw("\x5f\x41H\x41""e\x40\x41l\x41l\x41o\xff") << "(_ h'48', h'65', h'', h'6c', h'6c', h'6f')";
QTest::newRow("_textstring5x6") << raw("\x7f\x61H\x61""e\x61l\x60\x61l\x61o\xff") << "(_ \"H\", \"e\", \"l\", \"\", \"l\", \"o\")";
}
void addTagsData()
{
// since parseOne() works recursively for tags, we can't test lone tags
QTest::newRow("tag0") << raw("\xc0\x00") << "0(0)";
QTest::newRow("tag1") << raw("\xc1\x00") << "1(0)";
QTest::newRow("tag24") << raw("\xd8\x18\x00") << "24(0)";
QTest::newRow("tag255") << raw("\xd8\xff\x00") << "255(0)";
QTest::newRow("tag256") << raw("\xd9\1\0\x00") << "256(0)";
QTest::newRow("tag65535") << raw("\xd9\xff\xff\x00") << "65535(0)";
QTest::newRow("tag65536") << raw("\xda\0\1\0\0\x00") << "65536(0)";
QTest::newRow("tagUINT32_MAX-1") << raw("\xda\xff\xff\xff\xff\x00") << "4294967295(0)";
QTest::newRow("tagUINT32_MAX") << raw("\xdb\0\0\0\1\0\0\0\0\x00") << "4294967296(0)";
QTest::newRow("tagUINT64_MAX") << raw("\xdb" "\xff\xff\xff\xff" "\xff\xff\xff\xff" "\x00")
<< QString::number(std::numeric_limits<uint64_t>::max()) + "(0)";
// overlong tags
QTest::newRow("tag0*1") << raw("\xd8\0\x00") << "0_0(0)";
QTest::newRow("tag0*2") << raw("\xd9\0\0\x00") << "0_1(0)";
QTest::newRow("tag0*4") << raw("\xda\0\0\0\0\x00") << "0_2(0)";
QTest::newRow("tag0*8") << raw("\xdb\0\0\0\0\0\0\0\0\x00") << "0_3(0)";
// tag other things
QTest::newRow("unixtime") << raw("\xc1\x1a\x55\x4b\xbf\xd3") << "1(1431027667)";
QTest::newRow("rfc3339date") << raw("\xc0\x78\x19" "2015-05-07 12:41:07-07:00")
<< "0(\"2015-05-07 12:41:07-07:00\")";
QTest::newRow("tag6+false") << raw("\xc6\xf4") << "6(false)";
QTest::newRow("tag25+true") << raw("\xd8\x19\xf5") << "25(true)";
QTest::newRow("tag256+null") << raw("\xd9\1\0\xf6") << "256(null)";
QTest::newRow("tag65536+simple32") << raw("\xda\0\1\0\0\xf8\x20") << "65536(simple(32))";
QTest::newRow("float+unixtime") << raw("\xc1\xfa\x4e\xaa\x97\x80") << "1(1431027712.f)";
QTest::newRow("double+unixtime") << raw("\xc1\xfb" "\x41\xd5\x52\xef" "\xf4\xc7\xce\xfe")
<< "1(1431027667.1220088)";
}
void addEmptyContainersData()
{
QTest::newRow("emptyarray") << raw("\x80") << "[]" << 0;
QTest::newRow("emptymap") << raw("\xa0") << "{}" << 0;
QTest::newRow("_emptyarray") << raw("\x9f\xff") << "[_ ]" << -1;
QTest::newRow("_emptymap") << raw("\xbf\xff") << "{_ }" << -1;
}
void addMapMixedData()
{
QTest::newRow("map-0-24") << raw("\xa1\0\x18\x18") << "{0: 24}" << 1;
QTest::newRow("map-0*1-24") << raw("\xa1\x18\0\x18\x18") << "{0_0: 24}" << 1;
QTest::newRow("map-0*1-24*2") << raw("\xa1\x18\0\x19\0\x18") << "{0_0: 24_1}" << 1;
QTest::newRow("map-0*4-24*2") << raw("\xa1\x1a\0\0\0\0\x19\0\x18") << "{0_2: 24_1}" << 1;
QTest::newRow("map-24-0") << raw("\xa1\x18\x18\0") << "{24: 0}" << 1;
QTest::newRow("map-24-0*1") << raw("\xa1\x18\x18\x18\0") << "{24: 0_0}" << 1;
QTest::newRow("map-255-65535") << raw("\xa1\x18\xff\x19\xff\xff") << "{255: 65535}" << 1;
QTest::newRow("_map-0-24") << raw("\xbf\0\x18\x18\xff") << "{_ 0: 24}" << 1;
QTest::newRow("_map-0*1-24") << raw("\xbf\x18\0\x18\x18\xff") << "{_ 0_0: 24}" << 1;
QTest::newRow("_map-0*1-24*2") << raw("\xbf\x18\0\x19\0\x18\xff") << "{_ 0_0: 24_1}" << 1;
QTest::newRow("_map-0*4-24*2") << raw("\xbf\x1a\0\0\0\0\x19\0\x18\xff") << "{_ 0_2: 24_1}" << 1;
QTest::newRow("_map-24-0") << raw("\xbf\x18\x18\0\xff") << "{_ 24: 0}" << 1;
QTest::newRow("_map-24-0*1") << raw("\xbf\x18\x18\x18\0\xff") << "{_ 24: 0_0}" << 1;
QTest::newRow("_map-255-65535") << raw("\xbf\x18\xff\x19\xff\xff\xff") << "{_ 255: 65535}" << 1;
}
void addChunkedStringData()
{
QTest::addColumn<QByteArray>("data");
QTest::addColumn<QString>("concatenated");
QTest::addColumn<QStringList>("chunks");
// non-chunked:
QTest::newRow("emptybytestring") << raw("\x40") << "h''" << QStringList{"h''"};
QTest::newRow("bytestring1") << raw("\x41 ") << "h'20'" << QStringList{"h'20'"};
QTest::newRow("emptytextstring") << raw("\x60") << "\"\"" << QStringList{"\"\""};
QTest::newRow("textstring1") << raw("\x61 ") << "\" \"" << QStringList{"\" \""};
// empty chunked:
QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "h''" << QStringList{};
QTest::newRow("_emptytextstring") << raw("\x7f\xff") << "\"\"" << QStringList{};
QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << "h''" << QStringList{"h''"};
QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << "\"\"" << QStringList{"\"\""};
QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << "h''" << QStringList{"h''", "h''"};
QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << "\"\"" << QStringList{"\"\"", "\"\""};
// regular chunks
QTest::newRow("_bytestring1") << raw("\x5f\x41 \xff") << "h'20'" << QStringList{"h'20'"};
QTest::newRow("_bytestring2") << raw("\x5f\x41 \x41z\xff") << "h'207a'" << QStringList{"h'20'", "h'7a'"};
QTest::newRow("_bytestring3") << raw("\x5f\x41 \x58\x18""123456789012345678901234\x41z\xff")
<< "h'203132333435363738393031323334353637383930313233347a'"
<< QStringList{"h'20'", "h'313233343536373839303132333435363738393031323334'", "h'7a'"};
QTest::newRow("_textstring1") << raw("\x7f\x61 \xff") << "\" \"" << QStringList{"\" \""};
QTest::newRow("_textstring2") << raw("\x7f\x61 \x61z\xff") << "\" z\"" << QStringList{"\" \"", "\"z\""};
QTest::newRow("_textstring3") << raw("\x7f\x61 \x78\x18""123456789012345678901234\x61z\xff")
<< "\" 123456789012345678901234z\""
<< QStringList{"\" \"", "\"123456789012345678901234\"", "\"z\""};
}
void addValidationColumns()
{
QTest::addColumn<QByteArray>("data");
QTest::addColumn<int>("flags"); // future
QTest::addColumn<CborError>("expectedError");
}
void addValidationData()
{
// illegal numbers are future extension points
QTest::newRow("illegal-number-in-unsigned-1") << raw("\x81\x1c") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-unsigned-2") << raw("\x81\x1d") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-unsigned-3") << raw("\x81\x1e") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-unsigned-4") << raw("\x81\x1f") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-negative-1") << raw("\x81\x3c") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-negative-2") << raw("\x81\x3d") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-negative-3") << raw("\x81\x3e") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-negative-4") << raw("\x81\x3f") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-bytearray-length-1") << raw("\x81\x5c") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-bytearray-length-2") << raw("\x81\x5d") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-bytearray-length-3") << raw("\x81\x5e") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-string-length-1") << raw("\x81\x7c") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-string-length-2") << raw("\x81\x7d") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-string-length-3") << raw("\x81\x7e") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-array-length-1") << raw("\x81\x9c") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-array-length-2") << raw("\x81\x9d") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-array-length-3") << raw("\x81\x9e") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-map-length-1") << raw("\x81\xbc") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-map-length-2") << raw("\x81\xbd") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-map-length-3") << raw("\x81\xbe") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-tag-1") << raw("\x81\xdc") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-tag-2") << raw("\x81\xdd") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-tag-3") << raw("\x81\xde") << 0 << CborErrorIllegalNumber;
QTest::newRow("illegal-number-in-tag-4") << raw("\x81\xdf") << 0 << CborErrorIllegalNumber;
QTest::newRow("unsigned-too-short-1-0") << raw("\x81\x18") << 0 << CborErrorUnexpectedEOF; // requires 1 byte, 0 given
QTest::newRow("unsigned-too-short-2-0") << raw("\x81\x19") << 0 << CborErrorUnexpectedEOF; // requires 2 bytes, 0 given
QTest::newRow("unsigned-too-short-2-1") << raw("\x81\x19\x01") << 0 << CborErrorUnexpectedEOF; // etc
QTest::newRow("unsigned-too-short-4-0") << raw("\x81\x1a") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("unsigned-too-short-4-3") << raw("\x81\x1a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("unsigned-too-short-8-0") << raw("\x81\x1b") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("unsigned-too-short-8-7") << raw("\x81\x1b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("negative-length-too-short-1-0") << raw("\x81\x38") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("negative-length-too-short-2-0") << raw("\x81\x39") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("negative-length-too-short-2-1") << raw("\x81\x39\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("negative-length-too-short-4-0") << raw("\x81\x3a") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("negative-length-too-short-4-3") << raw("\x81\x3a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("negative-length-too-short-8-0") << raw("\x81\x3b") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("negative-length-too-short-8-7") << raw("\x81\x3b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-length-too-short-1-0") << raw("\x81\x58") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-length-too-short-2-0") << raw("\x81\x59") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-length-too-short-2-1") << raw("\x81\x59\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-length-too-short-4-0") << raw("\x81\x5a") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-length-too-short-4-3") << raw("\x81\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-length-too-short-8-0") << raw("\x81\x5b") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-length-too-short-8-7") << raw("\x81\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-length-too-short-1-0") << raw("\x81\x78") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-length-too-short-2-0") << raw("\x81\x79") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-length-too-short-2-1") << raw("\x81\x79\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-length-too-short-4-0") << raw("\x81\x7a") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-length-too-short-4-3") << raw("\x81\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-length-too-short-8-0") << raw("\x81\x7b") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-length-too-short-8-7") << raw("\x81\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-length-too-short-1-0") << raw("\x81\x5f\x58") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-length-too-short-2-0") << raw("\x81\x5f\x59") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-length-too-short-2-1") << raw("\x81\x5f\x59\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-length-too-short-4-0") << raw("\x81\x5f\x5a") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-length-too-short-4-3") << raw("\x81\x5f\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-length-too-short-8-0") << raw("\x81\x5f\x5b") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-length-too-short-8-7") << raw("\x81\x5f\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-length-too-short-1-0") << raw("\x81\x7f\x78") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-length-too-short-2-0") << raw("\x81\x7f\x79") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-length-too-short-2-1") << raw("\x81\x7f\x79\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-length-too-short-4-0") << raw("\x81\x7f\x7a") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-length-too-short-4-3") << raw("\x81\x7f\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-length-too-short-8-0") << raw("\x81\x7f\x7b") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-length-too-short-8-7") << raw("\x81\x7f\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-2-length-too-short-1-0") << raw("\x81\x5f\x40\x58") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-2-length-too-short-2-0") << raw("\x81\x5f\x40\x59") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-2-length-too-short-2-1") << raw("\x81\x5f\x40\x59\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-2-length-too-short-4-0") << raw("\x81\x5f\x40\x5a") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-2-length-too-short-4-3") << raw("\x81\x5f\x40\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-2-length-too-short-8-0") << raw("\x81\x5f\x40\x5b") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-2-length-too-short-8-7") << raw("\x81\x5f\x40\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-2-length-too-short-1-0") << raw("\x81\x7f\x60\x78") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-2-length-too-short-2-0") << raw("\x81\x7f\x60\x79") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-2-length-too-short-2-1") << raw("\x81\x7f\x60\x79\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-2-length-too-short-4-0") << raw("\x81\x7f\x60\x7a") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-2-length-too-short-4-3") << raw("\x81\x7f\x60\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-2-length-too-short-8-0") << raw("\x81\x7f\x60\x7b") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-2-length-too-short-8-7") << raw("\x81\x7f\x60\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("array-length-too-short-1-0") << raw("\x81\x98") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("array-length-too-short-2-0") << raw("\x81\x99") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("array-length-too-short-2-1") << raw("\x81\x99\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("array-length-too-short-4-0") << raw("\x81\x9a") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("array-length-too-short-4-3") << raw("\x81\x9a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("array-length-too-short-8-0") << raw("\x81\x9b") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("array-length-too-short-8-7") << raw("\x81\x9b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-length-too-short-1-0") << raw("\x81\xb8") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-length-too-short-2-0") << raw("\x81\xb9") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-length-too-short-2-1") << raw("\x81\xb9\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-length-too-short-4-0") << raw("\x81\xba") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-length-too-short-4-3") << raw("\x81\xba\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-length-too-short-8-0") << raw("\x81\xbb") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-length-too-short-8-7") << raw("\x81\xbb\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("tag-too-short-1-0") << raw("\x81\xd8") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("tag-too-short-2-0") << raw("\x81\xd9") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("tag-too-short-2-1") << raw("\x81\xd9\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("tag-too-short-4-0") << raw("\x81\xda") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("tag-too-short-4-3") << raw("\x81\xda\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("tag-too-short-8-0") << raw("\x81\xdb") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("tag-too-short-8-7") << raw("\x81\xdb\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("fp16-too-short1") << raw("\x81\xf9") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("fp16-too-short2") << raw("\x81\xf9\x00") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("float-too-short1") << raw("\x81\xfa") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("float-too-short2") << raw("\x81\xfa\0\0\0") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("double-too-short1") << raw("\x81\xfb") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("double-too-short2") << raw("\x81\xfb\0\0\0\0\0\0\0") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-too-short1") << raw("\x81\x42z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-too-short2") << raw("\x81\x58\x02z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-too-short3") << raw("\x81\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-too-short4") << raw("\x81\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-too-short1") << raw("\x81\x62z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-too-short2") << raw("\x81\x78\x02z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-too-short3") << raw("\x81\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-too-short4") << raw("\x81\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-too-short1") << raw("\x81\x5f\x42z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-too-short2") << raw("\x81\x5f\x58\x02z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-too-short3") << raw("\x81\x5f\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-too-short4") << raw("\x81\x5f\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-too-short1") << raw("\x81\x7f\x62z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-too-short2") << raw("\x81\x7f\x78\x02z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-too-short3") << raw("\x81\x7f\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-too-short4") << raw("\x81\x7f\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-too-short1x2") << raw("\x81\x5f\x40\x42z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-too-short2x2") << raw("\x81\x5f\x40\x58\x02z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-too-short3x2") << raw("\x81\x5f\x40\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-chunked-too-short4x2") << raw("\x81\x5f\x40\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-too-short1x2") << raw("\x81\x7f\x60\x62z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-too-short2x2") << raw("\x81\x7f\x60\x78\x02z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-too-short3x2") << raw("\x81\x7f\x60\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunked-too-short4x2") << raw("\x81\x7f\x60\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-no-break1") << raw("\x81\x5f") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("bytearray-no-break2") << raw("\x81\x5f\x40") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-no-break1") << raw("\x81\x7f") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-no-break2") << raw("\x81\x7f\x60") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("array-no-break1") << raw("\x81\x9f") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("array-no-break2") << raw("\x81\x9f\0") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-no-break1") << raw("\x81\xbf") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-no-break2") << raw("\x81\xbf\0\0") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-break-after-key") << raw("\x81\xbf\0\xff") << 0 << CborErrorUnexpectedBreak;
QTest::newRow("map-break-after-value-tag") << raw("\x81\xbf\0\xc0\xff") << 0 << CborErrorUnexpectedBreak;
QTest::newRow("map-break-after-value-tag2") << raw("\x81\xbf\0\xd8\x20\xff") << 0 << CborErrorUnexpectedBreak;
// check for pointer additions wrapping over the limit of the address space
CborError tooLargeOn32bit = (sizeof(void *) == 4) ? CborErrorDataTooLarge : CborErrorUnexpectedEOF;
// on 32-bit systems, this is a -1
QTest::newRow("bytearray-wraparound1") << raw("\x81\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-wraparound1") << raw("\x81\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
// on 32-bit systems, a 4GB addition could be dropped
QTest::newRow("bytearray-wraparound2") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
QTest::newRow("string-wraparound2") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
// on 64-bit systems, this could be a -1
QTest::newRow("bytearray-wraparound3") << raw("\x81\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
QTest::newRow("string-wraparound3") << raw("\x81\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
// ditto on chunks
QTest::newRow("bytearray-chunk-wraparound1") << raw("\x81\x5f\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("string-chunk-wraparound1") << raw("\x81\x7f\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
// on 32-bit systems, a 4GB addition could be dropped
QTest::newRow("bytearray-chunk-wraparound2") << raw("\x81\x5f\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
QTest::newRow("string-chunk-wraparound2") << raw("\x81\x7f\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
// on 64-bit systems, this could be a -1
QTest::newRow("bytearray-chunk-wraparound3") << raw("\x81\x5f\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
QTest::newRow("string-chunk-wraparound3") << raw("\x81\x7f\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
QTest::newRow("eof-after-array") << raw("\x81") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("eof-after-array2") << raw("\x81\x78\x20") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("eof-after-array-element") << raw("\x81\x82\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("eof-after-object") << raw("\x81\xa1") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("eof-after-object2") << raw("\x81\xb8\x20") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("eof-after-object-key") << raw("\x81\xa1\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("eof-after-object-value") << raw("\x81\xa2\x01\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("eof-after-tag") << raw("\x81\xc0") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("eof-after-tag2") << raw("\x81\xd8\x20") << 0 << CborErrorUnexpectedEOF;
// major type 7 has future types
QTest::newRow("future-type-28") << raw("\x81\xfc") << 0 << CborErrorUnknownType;
QTest::newRow("future-type-29") << raw("\x81\xfd") << 0 << CborErrorUnknownType;
QTest::newRow("future-type-30") << raw("\x81\xfe") << 0 << CborErrorUnknownType;
QTest::newRow("unexpected-break") << raw("\x81\xff") << 0 << CborErrorUnexpectedBreak;
QTest::newRow("illegal-simple-0") << raw("\x81\xf8\0") << 0 << CborErrorIllegalSimpleType;
QTest::newRow("illegal-simple-31") << raw("\x81\xf8\x1f") << 0 << CborErrorIllegalSimpleType;
// not only too big (UINT_MAX or UINT_MAX+1 in size), but also incomplete
if (sizeof(size_t) < sizeof(uint64_t)) {
QTest::newRow("bytearray-too-big1") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
QTest::newRow("string-too-big1") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
}
QTest::newRow("array-too-big1") << raw("\x81\x9a\xff\xff\xff\xff\0\0\0\0") << 0 << CborErrorDataTooLarge;
QTest::newRow("array-too-big2") << raw("\x81\x9b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
QTest::newRow("object-too-big1") << raw("\x81\xba\xff\xff\xff\xff\0\0\0\0") << 0 << CborErrorDataTooLarge;
QTest::newRow("object-too-big2") << raw("\x81\xbb\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
QTest::newRow("no-break-for-array0") << raw("\x81\x9f") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("no-break-for-array1") << raw("\x81\x9f\x01") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("no-break-string0") << raw("\x81\x7f") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("no-break-string1") << raw("\x81\x7f\x61Z") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("nested-indefinite-length-bytearrays") << raw("\x81\x5f\x5f\xff\xff") << 0 << CborErrorIllegalNumber;
QTest::newRow("nested-indefinite-length-strings") << raw("\x81\x7f\x7f\xff\xff") << 0 << CborErrorIllegalNumber;
QTest::newRow("string-chunk-unsigned") << raw("\x81\x7f\0\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-negative") << raw("\x81\x7f\x20\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-bytearray") << raw("\x81\x7f\x40\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-array") << raw("\x81\x7f\x80\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-map") << raw("\x81\x7f\xa0\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-tag") << raw("\x81\x7f\xc0\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-tagged-string") << raw("\x81\x7f\xc0\x60\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-simple0") << raw("\x81\x7f\xe0\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-false") << raw("\x81\x7f\xf4\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-true") << raw("\x81\x7f\xf5\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-null") << raw("\x81\x7f\xf6\xff") << 0 << CborErrorIllegalType;
QTest::newRow("string-chunk-undefined") << raw("\x81\x7f\xf7\xff") << 0 << CborErrorIllegalType;
QTest::newRow("bytearray-chunk-string") << raw("\x81\x5f\x60\xff") << 0 << CborErrorIllegalType;
QTest::newRow("bytearray-chunk-tagged-bytearray") << raw("\x81\x7f\xc0\x40\xff") << 0 << CborErrorIllegalType;
// RFC 7049 Section 2.2.2 "Indefinite-Length Byte Strings and Text Strings" says
// Text strings with indefinite lengths act the same as byte strings
// with indefinite lengths, except that all their chunks MUST be
// definite-length text strings. Note that this implies that the bytes
// of a single UTF-8 character cannot be spread between chunks: a new
// chunk can only be started at a character boundary.
// This test technically tests the dumper, not the parser.
QTest::newRow("string-utf8-chunk-split") << raw("\x81\x7f\x61\xc2\x61\xa0\xff") << 0 << CborErrorInvalidUtf8TextString;
}

View File

@ -0,0 +1,10 @@
SOURCES += tst_parser.cpp ../../src/cborparser.c
CONFIG += testcase parallel_test c++11
QT = core testlib
DEFINES += CBOR_PARSER_MAX_RECURSIONS=16
INCLUDEPATH += ../../src
msvc: POST_TARGETDEPS = ../../lib/tinycbor.lib
else: POST_TARGETDEPS += ../../lib/libtinycbor.a
LIBS += $$POST_TARGETDEPS

File diff suppressed because it is too large Load Diff