Add decoding for bejArray, bejNull, bejString and bejBoolean
Tested:
Tested this locally with unit tests. I will submit unit tests for
review once all the necessary data type decoding changes are submitted.
Signed-off-by: Kasun Athukorala <kasunath@google.com>
Change-Id: Id764bdc4728c4ab2a250f3327e2414c31506bf3d
diff --git a/src/bej_decoder_core.c b/src/bej_decoder_core.c
index c226a52..41b71ed 100644
--- a/src/bej_decoder_core.c
+++ b/src/bej_decoder_core.c
@@ -202,18 +202,20 @@
}
/**
- * @brief Find and return the property name of the current encoded segment.
+ * @brief Find and return the property name of the current encoded segment. If
+ * the params->state.addPropertyName is false, this will return an empty string.
*
* @param[in] params - a valid populated BejHandleTypeFuncParam.
* @return 0 if successful.
*/
-static const char* bejFindPropName(struct BejHandleTypeFuncParam* params)
+static const char* bejGetPropName(struct BejHandleTypeFuncParam* params)
{
const uint8_t* dictionary;
const struct BejDictionaryProperty* prop;
- if (bejGetDictionaryAndProperty(params, params->sflv.tupleS.schema,
- params->sflv.tupleS.sequenceNumber,
- &dictionary, &prop) != 0)
+ if (!params->state.addPropertyName ||
+ (bejGetDictionaryAndProperty(params, params->sflv.tupleS.schema,
+ params->sflv.tupleS.sequenceNumber,
+ &dictionary, &prop) != 0))
{
return "";
}
@@ -378,6 +380,81 @@
}
/**
+ * @brief Decodes a BejArray type SFLV BEJ tuple.
+ *
+ * @param params - a valid BejHandleTypeFuncParam struct.
+ * @return 0 if successful.
+ */
+static int bejHandleBejArray(struct BejHandleTypeFuncParam* params)
+{
+ const uint8_t* dictionary;
+ const struct BejDictionaryProperty* prop;
+ RETURN_IF_IERROR(bejGetDictionaryAndProperty(
+ params, params->sflv.tupleS.schema, params->sflv.tupleS.sequenceNumber,
+ &dictionary, &prop));
+
+ const char* propName = "";
+ if (params->state.addPropertyName)
+ {
+ propName = bejDictGetPropertyName(dictionary, prop->nameOffset,
+ prop->nameLength);
+ }
+
+ RETURN_IF_CALLBACK_IERROR(params->decodedCallback->callbackArrayStart,
+ propName, params->callbacksDataPtr);
+
+ uint64_t elements = rdeGetNnint(params->sflv.value);
+ // If its an empty array, we are done here.
+ if (elements == 0)
+ {
+ RETURN_IF_CALLBACK_IERROR(params->decodedCallback->callbackArrayEnd,
+ params->callbacksDataPtr);
+ }
+ else
+ {
+ // Update the state for next segment decoding.
+ struct BejStackProperty newEnding = {
+ .sectionType = bejSectionArray,
+ .addPropertyName = params->state.addPropertyName,
+ .mainDictPropOffset = params->state.mainDictPropOffset,
+ .annoDictPropOffset = params->state.annoDictPropOffset,
+ .streamEndOffset = params->sflv.valueEndOffset,
+ };
+ RETURN_IF_IERROR(
+ params->stackCallback->stackPush(&newEnding, params->stackDataPtr));
+ // We do not add property names for array elements.
+ params->state.addPropertyName = false;
+ if (params->sflv.tupleS.schema == bejAnnotation)
+ {
+ // Since this array is an annotated type, we need to advance the
+ // annotation dictionary for decoding the next segment.
+ params->state.annoDictPropOffset = prop->childPointerOffset;
+ }
+ else
+ {
+ params->state.mainDictPropOffset = prop->childPointerOffset;
+ }
+ }
+ params->state.encodedStreamOffset = bejGetFirstTupleOffset(params);
+ return 0;
+}
+
+/**
+ * @brief Decodes a BejNull type SFLV BEJ tuple.
+ *
+ * @param params - a valid BejHandleTypeFuncParam struct.
+ * @return 0 if successful.
+ */
+static int bejHandleBejNull(struct BejHandleTypeFuncParam* params)
+{
+ const char* propName = bejGetPropName(params);
+ RETURN_IF_CALLBACK_IERROR(params->decodedCallback->callbackNull, propName,
+ params->callbacksDataPtr);
+ params->state.encodedStreamOffset = params->sflv.valueEndOffset;
+ return bejProcessEnding(params, /*canBeEmpty=*/false);
+}
+
+/**
* @brief Decodes a BejInteger type SFLV BEJ tuple.
*
* @param params - a valid BejHandleTypeFuncParam struct.
@@ -385,11 +462,7 @@
*/
static int bejHandleBejInteger(struct BejHandleTypeFuncParam* params)
{
- const char* propName = "";
- if (params->state.addPropertyName)
- {
- propName = bejFindPropName(params);
- }
+ const char* propName = bejGetPropName(params);
if (params->sflv.valueLength == 0)
{
@@ -408,6 +481,57 @@
}
/**
+ * @brief Decodes a BejString type SFLV BEJ tuple.
+ *
+ * @param params - a valid BejHandleTypeFuncParam struct.
+ * @return 0 if successful.
+ */
+static int bejHandleBejString(struct BejHandleTypeFuncParam* params)
+{
+ // TODO: Handle deferred bindings.
+ const char* propName = bejGetPropName(params);
+
+ if (params->sflv.valueLength == 0)
+ {
+ RETURN_IF_CALLBACK_IERROR(params->decodedCallback->callbackNull,
+ propName, params->callbacksDataPtr);
+ }
+ else
+ {
+ RETURN_IF_CALLBACK_IERROR(params->decodedCallback->callbackString,
+ propName, (const char*)(params->sflv.value),
+ params->callbacksDataPtr);
+ }
+ params->state.encodedStreamOffset = params->sflv.valueEndOffset;
+ return bejProcessEnding(params, /*canBeEmpty=*/false);
+}
+
+/**
+ * @brief Decodes a BejBoolean type SFLV BEJ tuple.
+ *
+ * @param params - a valid BejHandleTypeFuncParam struct.
+ * @return 0 if successful.
+ */
+static int bejHandleBejBoolean(struct BejHandleTypeFuncParam* params)
+{
+ const char* propName = bejGetPropName(params);
+
+ if (params->sflv.valueLength == 0)
+ {
+ RETURN_IF_CALLBACK_IERROR(params->decodedCallback->callbackNull,
+ propName, params->callbacksDataPtr);
+ }
+ else
+ {
+ RETURN_IF_CALLBACK_IERROR(params->decodedCallback->callbackBool,
+ propName, *(params->sflv.value) > 0,
+ params->callbacksDataPtr);
+ }
+ params->state.encodedStreamOffset = params->sflv.valueEndOffset;
+ return bejProcessEnding(params, /*canBeEmpty=*/false);
+}
+
+/**
* @brief Decodes an encoded bej stream.
*
* @param[in] schemaDictionary - main schema dictionary to use.
@@ -475,14 +599,10 @@
RETURN_IF_IERROR(bejHandleBejSet(¶ms));
break;
case bejArray:
- // TODO: Add support for BejArray decoding.
- fprintf(stderr, "No BejArray support\n");
- params.state.encodedStreamOffset = params.sflv.valueEndOffset;
+ RETURN_IF_IERROR(bejHandleBejArray(¶ms));
break;
case bejNull:
- // TODO: Add support for BejNull decoding.
- fprintf(stderr, "No BejNull support\n");
- params.state.encodedStreamOffset = params.sflv.valueEndOffset;
+ RETURN_IF_IERROR(bejHandleBejNull(¶ms));
break;
case bejInteger:
RETURN_IF_IERROR(bejHandleBejInteger(¶ms));
@@ -493,9 +613,7 @@
params.state.encodedStreamOffset = params.sflv.valueEndOffset;
break;
case bejString:
- // TODO: Add support for BejString decoding.
- fprintf(stderr, "No BejString support\n");
- params.state.encodedStreamOffset = params.sflv.valueEndOffset;
+ RETURN_IF_IERROR(bejHandleBejString(¶ms));
break;
case bejReal:
// TODO: Add support for BejReal decoding.
@@ -503,9 +621,7 @@
params.state.encodedStreamOffset = params.sflv.valueEndOffset;
break;
case bejBoolean:
- // TODO: Add support for BejBoolean decoding.
- fprintf(stderr, "No BejBoolean support\n");
- params.state.encodedStreamOffset = params.sflv.valueEndOffset;
+ RETURN_IF_IERROR(bejHandleBejBoolean(¶ms));
break;
case bejBytestring:
// TODO: Add support for BejBytestring decoding.