first pass at day dates
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 4d31b69..60331d0 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -1987,6 +1987,53 @@
}
+/** TODO: fix this documentation
+ * @brief Convert different epoch date formats in to the QCBOR epoch date format
+ *
+ * pDecodedItem[in,out] The data item to convert.
+ *
+ * @retval QCBOR_ERR_DATE_OVERFLOW
+ * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
+ * @retval QCBOR_ERR_BAD_TAG_CONTENT
+ *
+ * The epoch date tag defined in QCBOR allows for floating-point
+ * dates. It even allows a protocol to flop between date formats when
+ * ever it wants. Floating-point dates aren't that useful as they are
+ * only needed for dates beyond the age of the earth.
+ *
+ * This converts all the date formats into one format of an unsigned
+ * integer plus a floating-point fraction.
+ */
+static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem)
+{
+ QCBORError uReturn = QCBOR_SUCCESS;
+
+ switch (pDecodedItem->uDataType) {
+
+ case QCBOR_TYPE_INT64:
+ pDecodedItem->val.epochDays = pDecodedItem->val.int64;
+ break;
+
+ case QCBOR_TYPE_UINT64:
+ /* This only happens for CBOR type 0 > INT64_MAX so it is
+ * always an overflow.
+ */
+ uReturn = QCBOR_ERR_DATE_OVERFLOW;
+ goto Done;
+ break;
+
+ default:
+ uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
+ goto Done;
+ }
+
+ pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
+
+Done:
+ return uReturn;
+}
+
+
#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
/**
* @brief Decode decimal fractions and big floats.
@@ -2142,6 +2189,8 @@
static const struct StringTagMapEntry StringTagMap[] = {
{CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
+ {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
+
{CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
{CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
{CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
@@ -2255,6 +2304,9 @@
} else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
uReturn = DecodeDateEpoch(pDecodedItem);
+ } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
+ uReturn = DecodeDaysEpoch(pDecodedItem);
+
#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
} else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
uTagToProcess == CBOR_TAG_BIGFLOAT) {
@@ -3830,6 +3882,87 @@
}
+static void ProcessEpochDays(QCBORDecodeContext *pMe,
+ QCBORItem *pItem,
+ uint8_t uTagRequirement,
+ int64_t *pnTime)
+{
+ if(pMe->uLastError != QCBOR_SUCCESS) {
+ // Already in error state, do nothing
+ return;
+ }
+
+ QCBORError uErr;
+
+ const TagSpecification TagSpec =
+ {
+ uTagRequirement,
+ {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+ {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
+ uErr = CheckTagRequirement(TagSpec, pItem);
+ if(uErr != QCBOR_SUCCESS) {
+ goto Done;
+ }
+
+ if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
+ uErr = DecodeDaysEpoch(pItem);
+ if(uErr != QCBOR_SUCCESS) {
+ goto Done;
+ }
+ }
+
+ // Save the tags in the last item's tags in the decode context
+ // for QCBORDecode_GetNthTagOfLast()
+ CopyTags(pMe, pItem);
+
+ *pnTime = pItem->val.epochDate.nSeconds;
+
+Done:
+ pMe->uLastError = (uint8_t)uErr;
+}
+
+void QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
+ uint8_t uTagRequirement,
+ int64_t *pnTime)
+{
+ if(pMe->uLastError != QCBOR_SUCCESS) {
+ // Already in error state, do nothing
+ return;
+ }
+
+ QCBORItem Item;
+ pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
+
+ ProcessEpochDays(pMe, &Item, uTagRequirement, pnTime);
+}
+
+
+void
+QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
+ int64_t nLabel,
+ uint8_t uTagRequirement,
+ int64_t *pnTime)
+{
+ QCBORItem Item;
+ QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+ ProcessEpochDays(pMe, &Item, uTagRequirement, pnTime);
+}
+
+
+void
+QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
+ const char *szLabel,
+ uint8_t uTagRequirement,
+ int64_t *pnTime)
+{
+ QCBORItem Item;
+ QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+ ProcessEpochDays(pMe, &Item, uTagRequirement, pnTime);
+}
+
+
void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,