Finalize testing of dates; some date bug fixes
diff --git a/README.md b/README.md
index 230d6a3..2bc2bb4 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,10 @@
## Characteristics
**Implemented in C with minimal dependency** – The only dependencies
- are C99, <stdint.h>, <stddef.h>, <stdbool.h> and <string.h> making it
- highly portable. No #ifdefs or compiler options need to be set for it
- to run correctly.
+ are C99, <stdint.h>, <stddef.h>, <stdbool.h> and <string.h> making
+ it highly portable. <math.h> is used too, but it's use can
+ disabled. No #ifdefs or compiler options need to be set for it to
+ run correctly.
**Focused on C / native data representation** – Careful conversion
of CBOR data types in to C data types, carefully handling
@@ -50,10 +51,9 @@
separated from the implementation. It can be put to use without
reading the source.
-**Comprehensive test suite** – Easy to verify on a new platform
- or OS with the test suite. The test suite dependencies are also
- minimal, only additionally requiring <math.h> for floating-point
- tests.
+**Comprehensive test suite** – Easy to verify on a new platform or OS
+ with the test suite. The test suite dependencies are minimal and the
+ same as the library's.
## Code Status
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index 137906a..7a7a132 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -215,11 +215,12 @@
/** The encode or decode completely correctly. */
QCBOR_SUCCESS = 0,
+#define QCBOR_ERR_FIRST_NOT_WELL_FORMED 1 /* QCBOR_ERR_BAD_TYPE_7 */
+
/** During decoding, the CBOR is not valid, primarily a simple type
is encoded in a prohibited way. */
QCBOR_ERR_BAD_TYPE_7 = 1,
-#define QCBOR_ERR_FIRST_NOT_WELL_FORMED QCBOR_ERR_BAD_TYPE_7
/** Returned by QCBORDecode_Finish() if all the inputs bytes have
not been consumed. */
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index bbcf2cd..be6bc1a 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -340,7 +340,7 @@
float fnum;
/** The value for @c uDataType @ref QCBOR_TYPE_DATE_EPOCH.
Floating-point dates that are NaN, +Inifinity or -Inifinity
- decode with the @ref QCBOR_ERR_DATE_OVERFLOW error. */
+ result in the @ref QCBOR_ERR_DATE_OVERFLOW error. */
struct {
int64_t nSeconds;
double fSecondsFraction;
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index adda824..19dc22b 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -265,26 +265,25 @@
representation of the double or float that preserves precision. Zero,
NaN and infinity are always output as a half-precision, each taking
just 2 bytes. This reduces the number of bytes needed to encode
- doubles and floats, especially if the zero, NaN and infinity are
+ double and single-precision, especially if zero, NaN and infinity are
frequently used.
- To avoid use of preferred serialization in the standard configuration when encoding, use
- QCBOREncode_AddDoubleNoPreferred() or
+ To avoid use of preferred serialization in the standard configuration
+ when encoding, use QCBOREncode_AddDoubleNoPreferred() or
QCBOREncode_AddFloatNoPreferred().
This implementation of preferred floating-point serialization and
half-precision does not depend on the CPU having floating-point HW or
the compiler bringing in a (sometimes large) library to compensate
- for lack of CPU support. The implementation uses shifts and masks
- rather than floating-point functions. It does however add object
- code.
+ for lack of CPU support. This implementation uses shifts and masks
+ rather than floating-point functions.
- To reduce object code, define QCBOR_DISABLE_PREFERRED_FLOAT. This
- will eliminate all support for preferred serialization and
- half-precision. An error will be returned when attempting to decode
- half-precision. A float will always be encoded and decoded as 32-bits
- and a double will always be encoded and decoded as 64 bits. This
- will reduce object code by about 900 bytes.
+ To reduce overall object code by about 900 bytes, define
+ QCBOR_DISABLE_PREFERRED_FLOAT. This will eliminate all support for
+ preferred serialization and half-precision. An error will be returned
+ when attempting to decode half-precision. A float will always be
+ encoded and decoded as 32-bits and a double will always be encoded
+ and decoded as 64 bits.
Note that even if QCBOR_DISABLE_PREFERRED_FLOAT is not defined all
the float-point encoding object code can be avoided by never calling
@@ -294,21 +293,20 @@
On CPUs that have no floating-point hardware,
QCBOR_DISABLE_FLOAT_HW_USE should be defined in most cases. If it is
not, then the compiler will bring in possibly large software
- libraries to compensate or QCBOR will not compile. Defining
+ libraries to compensate. Defining
QCBOR_DISABLE_FLOAT_HW_USE reduces object code size on CPUs with
- floating-point hardware by a tiny amount.
+ floating-point hardware by a tiny amount and eliminates the need for <math.h>
- When QCBOR_DISABLE_FLOAT_HW_USE is defined, trying to
- decoding floating point dates will give error @ref QCBOR_ERR_FLOAT_DATE_DISABLED and decoded
- single-precision
- numbers will be returned as @ref QCBOR_TYPE_FLOAT instead of converting them to
- double as usual.
-
+ When QCBOR_DISABLE_FLOAT_HW_USE is defined, trying to decoding
+ floating-point dates will give error @ref
+ QCBOR_ERR_FLOAT_DATE_DISABLED and decoded single-precision numbers
+ will be returned as @ref QCBOR_TYPE_FLOAT instead of converting them
+ to double as usual.
If both QCBOR_DISABLE_FLOAT_HW_USE and QCBOR_DISABLE_PREFERRED_FLOAT
- are defined, then the only thing QCBOR can do is encode/decode a
- C float type as 32-bits and a C double type as 64-bits. Floating-point epoch dates
- will be unsupported.
+ are defined, then the only thing QCBOR can do is encode/decode a C
+ float type as 32-bits and a C double type as 64-bits. Floating-point
+ epoch dates will be unsupported.
Summary Limits of this implementation:
- The entire encoded CBOR must fit into contiguous memory.
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index 2b4ded7..449a28e 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -85,9 +85,7 @@
cleaner decoding code. In some cases the only error check that may be
necessary is the return code from QCBORDecode_Finish().
- The only error check needed is in the Finish call.
-
- On error, a decoder internal error state is set. The error can be
+ The internal error can be
retrived with QCBORDecode_GetError(). Any further attempts to get
specific data types will do nothing so it is safe for code to get
many items without checking the error on each one as long as there is
@@ -108,6 +106,10 @@
another. In such designs, GetNext has to be used and the internal
error checking can't be relied upon.
+ Error reporting when searching maps is not accurate for
+ some errors. They are report as not found rather
+ than overflow and such.
+
----
GetNext will always try to get something. The other Get functions
@@ -643,17 +645,25 @@
@param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
@param[out] pnTime The decoded epoch date.
- This will handle floating-point dates, but always returns them as an int64_t
+ This will handle floating-point dates, but always returns them as an @c int64_t
discarding the fractional part. Use QCBORDecode_GetNext() instead of this to get the
fractional part.
+ Floating-point dates that are plus infinity, minus infinity or NaN (not-a-number) will
+ result in the @ref QCBOR_ERR_DATE_OVERFLOW error. If the QCBOR library
+ is compiled with floating-point disabled, @ref QCBOR_ERR_HW_FLOAT_DISABLED
+ is set. If compiled with preferred float disabled, half-precision dates will result
+ in the @ref QCBOR_ERR_HALF_PRECISION_DISABLED error.
+
See @ref Decode-Errors for discussion on how error handling works.
See @ref Tag-Matcing for discussion on tag requirements.
+
+ See also QCBOREncode_AddDateEpoch() and @ref QCBORItem.
*/
void QCBORDecode_GetEpochDate(QCBORDecodeContext *pCtx,
- uint8_t uTagRequirement,
- int64_t *pnTime);
+ uint8_t uTagRequirement,
+ int64_t *pnTime);
void QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pCtx,
int64_t nLabel,
@@ -1077,43 +1087,42 @@
The next item in the CBOR input must be map or this sets an error.
- This puts the decoder in bounded mode which narrows
- decoding to the map entered and enables
- getting items by label. Note that all items
- in the map must be well-formed and valid to be
- able to search it by label because a full traversal
- is done for each search. If not, the search will
- retun an error for the item that is not well-formed
- and valid. This may not be the item with the label
- that is the subject of the search.
+ This puts the decoder in bounded mode which narrows decoding to the
+ map entered and enables getting items by label.
- Nested maps can be decoded like this by entering
- each map in turn.
+ All items in the map must be well-formed to be able to search it by
+ label because a full traversal is done for each search. If not, the
+ search will retun an error for the item that is not well-formed.
+ This will be the first non-well-formed item which may not be the item
+ with the label that is the target of the search.
- Call QCBORDecode_ExitMap() to exit the current map
- decoding level. When all map decoding layers are exited
- then bounded mode is fully exited.
+ Nested maps can be decoded like this by entering each map in turn.
+
+ Call QCBORDecode_ExitMap() to exit the current map decoding
+ level. When all map decoding layers are exited then bounded mode is
+ fully exited.
While in bounded mode, QCBORDecode_GetNext() works as usual on the
- map and the in-order traversal cursor
- is maintained. It starts out at the first item in the map just entered. Attempts to get items off the end of the
- map will give error @ref QCBOR_ERR_NO_MORE_ITEMS rather going to the next
- item after the map as it would when not in bounded
+ map and the in-order traversal cursor is maintained. It starts out at
+ the first item in the map just entered. Attempts to get items off the
+ end of the map will give error @ref QCBOR_ERR_NO_MORE_ITEMS rather
+ going to the next item after the map as it would when not in bounded
mode.
- Exiting leaves the pre-order cursor at the
- data item following the last entry in the map or at the end of the input CBOR if there nothing after the map.
+ Exiting leaves the pre-order cursor at the data item following the
+ last entry in the map or at the end of the input CBOR if there
+ nothing after the map.
- Entering and Exiting a map is a way to skip over
- an entire map and its contents. After QCBORDecode_ExitMap(),
- the pre-order traversal cursor will be at the
- first item after the map.
+ Entering and Exiting a map is a way to skip over an entire map and
+ its contents. After QCBORDecode_ExitMap(), the pre-order traversal
+ cursor will be at the first item after the map.
See @ref Decode-Errors for discussion on how error handling works.
See also QCBORDecode_EnterArray() and QCBORDecode_EnterBstrWrapped().
- Entering and exiting any nested combination of maps, arrays and bstr-wrapped
- CBOR is supported up to the maximum of @ref QCBOR_MAX_ARRAY_NESTING.
+ Entering and exiting any nested combination of maps, arrays and
+ bstr-wrapped CBOR is supported up to the maximum of @ref
+ QCBOR_MAX_ARRAY_NESTING.
*/
static void QCBORDecode_EnterMap(QCBORDecodeContext *pCtx);
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 00b10cb..d9e6912 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -1094,7 +1094,7 @@
goto Done;
}
- // Loop getting chunk of indefinite string
+ // Loop getting chunks of the indefinite length string
UsefulBufC FullString = NULLUsefulBufC;
for(;;) {
@@ -1610,12 +1610,10 @@
d - (double)pDecodedItem->val.epochDate.nSeconds;
}
#else
- /* Disabling float support causes a floating-point
- date to error in the default below. The above code
- requires floating-point conversion to integers and
- comparison which requires either floating-point HW
- or a SW library. */
+
uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
+ goto Done;
+
#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
break;
@@ -2331,7 +2329,8 @@
*/
do {
uReturn = QCBORDecode_GetNext(pMe, &Item);
- if(uReturn != QCBOR_SUCCESS) {
+ if( QCBORDecode_IsNotWellFormed(uReturn)) {
+ // TODO: also resource limit errors
goto Done;
}
} while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
@@ -2488,12 +2487,15 @@
uReturn = QCBORDecode_GetNext(pMe, &Item);
if(QCBORDecode_IsNotWellFormed(uReturn)) {
/* Got non-well-formed CBOR so map can't even be decoded. */
+ // TODO: also bail out on implementation limits like array too big
goto Done;
}
/* See if item has one of the labels that are of interest */
bool bMatched = false;
for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
+ // TODO: have label filled in on invalid CBOR so error reporting
+ // can work a lot better.
if(MatchLabel(Item, pItemArray[nIndex])) {
/* A label match has been found */
if(uFoundItemBitMap & (0x01ULL << nIndex)) {
@@ -3241,7 +3243,7 @@
{QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT}
};
- // TODO: this will give a unexpected type error instead of
+ // TODO: this will give an unexpected type error instead of
// overflow error for QCBOR_TYPE_UINT64 because TagSpec
// only has three target types.
uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index d882d99..c78b008 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -2296,17 +2296,57 @@
return 0;
}
+/*
+ Test cases covered here. Some items cover more than one of these.
+ positive integer (zero counts as a positive integer)
+ negative integer
+ half-precision float
+ single-precision float
+ double-precision float
-static uint8_t spDateTestInput2[] = {
- 0xbf,
+ float Overflow error
+ Wrong type error for epoch
+ Wrong type error for date string
+ float disabled error
+ half-precision disabled error
+ -Infinity
+ Slightly too large integer
+ Slightly too far from zero
- 0x05,
+ Get epoch by int
+ Get string by int
+ Get epoch by string
+ Get string by string
+ Fail to get epoch by wrong int label
+ Fail to get string by wrong string label
+ Fail to get epoch by string because it is invalid
+ Fail to get epoch by int because it is invalid
+
+ Untagged values
+ */
+static uint8_t spSpiffyDateTestInput[] = {
+ 0x86,
+
+ 0xc1,
+ 0xfb, 0xc3, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // -9.2233720368547748E+18, too negative
+
0xc1, // tag for epoch date
- 0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too large integer
+ 0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too-large integer
+
+ 0xc1, // tag for epoch date
+ 0xf9, 0xfc, 0x00, // Half-precision -Infinity
+
+ 0xc1, // tag for epoch date
+ 0x9f, 0xff, // Erroneous empty array as content for date
+
+ 0xc0, // tag for string date
+ 0xbf, 0xff, // Erroneous empty map as content for date
+
+ 0xbf, // Open a map for tests involving labels.
0x00,
0xc0, // tag for string date
- 0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string
+ 0x6a, '1','9','8','5','-','0','4','-','1','2', // Tagged date string
0x01,
0xc1, // tag for epoch date
@@ -2318,27 +2358,27 @@
// Utagged date string with string label y
0x61, 0x79,
- 0x6a, '2','0','8','5','-','0','4','-','1','2', // Date string
+ 0x6a, '2','0','8','5','-','0','4','-','1','2', // Untagged date string
// Untagged -1000 with label z
0x61, 0x7a,
0x39, 0x03, 0xe7,
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
0x07,
0xc1, // tag for epoch date
0xfb, 0x43, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, // 9223372036854773760 largest supported
+ 0x05,
+ 0xc1,
+ 0xfb, 0xc3, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, // -9223372036854773760 largest negative
+
// Untagged single-precision float with value 3.14 with string label x
0x61, 0x78,
0xFA, 0x40, 0x48, 0xF5, 0xC3,
-#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
// Untagged half-precision float with value -2
0x09,
0xF9, 0xC0, 0x00,
-#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
0xff,
};
@@ -2346,75 +2386,181 @@
int32_t SpiffyDateDecodeTest()
{
QCBORDecodeContext DC;
- //QCBORItem Item;
- QCBORError uError;
- int64_t nEpochDate1, nEpochDate3, nEpochDate6;
- UsefulBufC StringDate1, StringDate2;
+ QCBORError uError;
+ int64_t nEpochDate1, nEpochDate2, nEpochDate3, nEpochDate5,
+ nEpochDate4, nEpochDate6;
+ UsefulBufC StringDate1, StringDate2;
QCBORDecode_Init(&DC,
- UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDateTestInput2),
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSpiffyDateTestInput),
QCBOR_DECODE_MODE_NORMAL);
- QCBORDecode_EnterMap(&DC);
- QCBORDecode_GetEpochDateInMapN(&DC, 5, QCBOR_TAG_REQUIREMENT_MATCH_TAG, &nEpochDate1);
- uError = QCBORDecode_GetAndResetError(&DC);
- if(uError == QCBOR_SUCCESS) {
- return -999;
- }
- QCBORDecode_GetEpochDateInMapN(&DC, 1, QCBOR_TAG_REQUIREMENT_MATCH_TAG, &nEpochDate1);
- QCBORDecode_GetDateStringInMapN(&DC, 0, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &StringDate1);
- QCBORDecode_GetEpochDateInMapN(&DC, 8, QCBOR_TAG_REQUIREMENT_NO_TAG, &nEpochDate3);
- QCBORDecode_GetDateStringInMapSZ(&DC, "y", QCBOR_TAG_REQUIREMENT_NO_TAG, &StringDate2);
- QCBORDecode_GetEpochDateInMapSZ(&DC, "z", QCBOR_TAG_REQUIREMENT_NO_TAG, &nEpochDate6);
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
- int64_t nEpochDate5, nEpochDate2;
- QCBORDecode_GetEpochDateInMapN(&DC, 7, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate2);
- QCBORDecode_GetEpochDateInMapSZ(&DC, "x", QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate5);
-#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
- int64_t nEpochDate4;
- QCBORDecode_GetEpochDateInMapN(&DC, 9, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate4);
-#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+ QCBORDecode_EnterArray(&DC);
- QCBORDecode_ExitMap(&DC);
- uError = QCBORDecode_Finish(&DC);
- if(uError) {
+ // Too-negative integer, -9.2233720368547748E+18
+ QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_MATCH_TAG, &nEpochDate1);
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_DATE_OVERFLOW) {
+ return 1111;
+ }
+
+ // Too-large integer
+ QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_MATCH_TAG, &nEpochDate1);
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_DATE_OVERFLOW) {
return 1;
}
- if(nEpochDate1 != 1400000000) {
- return 100;
+ // Half-precision minus infinity
+ QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_MATCH_TAG, &nEpochDate1);
+ uError = QCBORDecode_GetAndResetError(&DC);
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+ const QCBORError uExpectedforHalfMinusInfinity = QCBOR_ERR_DATE_OVERFLOW;
+#else /* QCBOR_DISABLE_FLOAT_HW_USE */
+ const QCBORError uExpectedforHalfMinusInfinity = QCBOR_ERR_FLOAT_DATE_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
+ const QCBORError uExpectedforHalfMinusInfinity = QCBOR_ERR_HALF_PRECISION_DISABLED;
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+ if(uError != uExpectedforHalfMinusInfinity) {
+ return 2;
}
- if(nEpochDate3 != 0) {
+ // Bad content for epoch date
+ QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_MATCH_TAG, &nEpochDate1);
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_BAD_OPT_TAG) {
+ return 3;
+ }
+
+ // Bad content for string date
+ QCBORDecode_GetDateString(&DC, QCBOR_TAG_REQUIREMENT_MATCH_TAG, &StringDate1);
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_BAD_OPT_TAG) {
+ return 4;
+ }
+
+ QCBORDecode_EnterMap(&DC);
+
+ // Get largest negative double precision epoch date allowed
+ QCBORDecode_GetEpochDateInMapN(&DC, 5, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate2);
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+ if(nEpochDate2 != -9223372036854773760LL) {
+ return 101;
+ }
+#else /* QCBOR_DISABLE_FLOAT_HW_USE */
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_NOT_FOUND) {
return 102;
}
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
- if(nEpochDate6 != -1000) {
- return 105;
- }
-
- if(UsefulBuf_Compare(StringDate1, UsefulBuf_FromSZ("1985-04-12"))) {
- return 106;
- }
-
- if(UsefulBuf_Compare(StringDate2, UsefulBuf_FromSZ("2085-04-12"))) {
- return 107;
- }
-
+ // Get largest double precision epoch date allowed
+ QCBORDecode_GetEpochDateInMapN(&DC, 7, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate2);
#ifndef QCBOR_DISABLE_FLOAT_HW_USE
if(nEpochDate2 != 9223372036854773760ULL) {
return 101;
}
- if(nEpochDate5 != 3) {
- return 104;
+#else /* QCBOR_DISABLE_FLOAT_HW_USE */
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_NOT_FOUND) {
+ return 102;
}
-#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
- if(nEpochDate4 != -2) {
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+ // A single-precision date
+ QCBORDecode_GetEpochDateInMapSZ(&DC, "x", QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate5);
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+ if(nEpochDate5 != 3) {
return 103;
}
-#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+#else /* QCBOR_DISABLE_FLOAT_HW_USE */
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+ return 104;
+ }
#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+ // A half-precision date with value -2
+ QCBORDecode_GetEpochDateInMapN(&DC, 9, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate4);
+#if !defined(QCBOR_DISABLE_FLOAT_HW_USE) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT)
+ if(nEpochDate4 != -2) {
+ return 105;
+ }
+#else
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError == QCBOR_SUCCESS) {
+ return 106;
+ }
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+ // Fail to get an epoch date by string label
+ QCBORDecode_GetEpochDateInMapSZ(&DC, "no-label", QCBOR_TAG_REQUIREMENT_NO_TAG, &nEpochDate6);
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_NOT_FOUND) {
+ return 107;
+ }
+
+ // Fail to get an epoch date by integer label
+ QCBORDecode_GetEpochDateInMapN(&DC, 99999, QCBOR_TAG_REQUIREMENT_NO_TAG, &nEpochDate6);
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_NOT_FOUND) {
+ return 108;
+ }
+
+ // Fail to get a string date by string label
+ QCBORDecode_GetDateStringInMapSZ(&DC, "no-label", QCBOR_TAG_REQUIREMENT_NO_TAG, &StringDate1);
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_NOT_FOUND) {
+ return 109;
+ }
+
+ // Fail to get a string date by integer label
+ QCBORDecode_GetDateStringInMapN(&DC, 99999, QCBOR_TAG_REQUIREMENT_NO_TAG, &StringDate1);
+ uError = QCBORDecode_GetAndResetError(&DC);
+ if(uError != QCBOR_ERR_NOT_FOUND) {
+ return 110;
+ }
+
+ // The rest of these succeed even if float features are disabled
+ // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT
+ QCBORDecode_GetEpochDateInMapN( &DC, 1, QCBOR_TAG_REQUIREMENT_MATCH_TAG, &nEpochDate1);
+ // Tagged date string
+ QCBORDecode_GetDateStringInMapN(&DC, 0, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &StringDate1);
+ // Untagged integer 0
+ QCBORDecode_GetEpochDateInMapN( &DC, 8, QCBOR_TAG_REQUIREMENT_NO_TAG, &nEpochDate3);
+ // Untagged date string
+ QCBORDecode_GetDateStringInMapSZ(&DC, "y", QCBOR_TAG_REQUIREMENT_NO_TAG, &StringDate2);
+ // Untagged -1000 with label z
+ QCBORDecode_GetEpochDateInMapSZ( &DC, "z", QCBOR_TAG_REQUIREMENT_NO_TAG, &nEpochDate6);
+
+ QCBORDecode_ExitMap(&DC);
+ QCBORDecode_ExitArray(&DC);
+ uError = QCBORDecode_Finish(&DC);
+ if(uError) {
+ return 1000;
+ }
+
+ if(nEpochDate1 != 1400000000) {
+ return 200;
+ }
+
+ if(nEpochDate3 != 0) {
+ return 201;
+ }
+
+ if(nEpochDate6 != -1000) {
+ return 202;
+ }
+
+ if(UsefulBuf_Compare(StringDate1, UsefulBuf_FromSZ("1985-04-12"))) {
+ return 203;
+ }
+
+ if(UsefulBuf_Compare(StringDate2, UsefulBuf_FromSZ("2085-04-12"))) {
+ return 204;
+ }
+
return 0;
}