return checkError(err, &encoder, outPayload, size);
}
-static int64_t OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* valArray)
+static int64_t OCConvertArrayItem(CborEncoder* array, const OCRepPayloadValueArray* valArray,
+ size_t index)
{
- CborEncoder array;
int64_t err = 0;
-
- err = err | cbor_encoder_create_array(parent, &array, CborIndefiniteLength);
- err = err | cbor_encode_uint(&array, valArray->type);
- for(int i = 0; i < MAX_REP_ARRAY_DEPTH; ++i)
+ switch (valArray->type)
{
- err = err | cbor_encode_uint(&array, valArray->dimensions[i]);
+ case OCREP_PROP_NULL:
+ OC_LOG(ERROR, TAG, "ConvertArray Invalid NULL");
+ err = CborUnknownError;
+ break;
+ case OCREP_PROP_INT:
+ err = err | cbor_encode_int(array, valArray->iArray[index]);
+ break;
+ case OCREP_PROP_DOUBLE:
+ err = err | cbor_encode_double(array, valArray->dArray[index]);
+ break;
+ case OCREP_PROP_BOOL:
+ err = err | cbor_encode_boolean(array, valArray->bArray[index]);
+ break;
+ case OCREP_PROP_STRING:
+ if (!valArray->strArray[index])
+ {
+ err = err | cbor_encode_null(array);
+ }
+ else
+ {
+ err = err | cbor_encode_text_string(array, valArray->strArray[index],
+ strlen(valArray->strArray[index]));
+ }
+ break;
+ case OCREP_PROP_OBJECT:
+ if (!valArray->objArray[index])
+ {
+ err = err | cbor_encode_null(array);
+ }
+ else
+ {
+ err = OCConvertSingleRepPayload(array, valArray->objArray[index]);
+ }
+ break;
+ case OCREP_PROP_ARRAY:
+ OC_LOG(ERROR, TAG, "ConvertArray Invalid child array");
+ err = CborUnknownError;
+ break;
}
- size_t dimTotal = calcDimTotal(valArray->dimensions);
+ return err;
+}
+static int64_t OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* valArray)
+{
+ CborEncoder array;
+ int64_t err = 0;
+
+ err = err | cbor_encoder_create_array(parent, &array, valArray->dimensions[0]);
- for(size_t i = 0; i < dimTotal; ++i)
+ for (size_t i = 0; i < valArray->dimensions[0];++i)
{
- switch(valArray->type)
+ if (valArray->dimensions[1] != 0)
{
- case OCREP_PROP_NULL:
- OC_LOG(ERROR, TAG, "ConvertArray Invalid NULL");
- err = CborUnknownError;
- break;
- case OCREP_PROP_INT:
- err = err | cbor_encode_int(&array, valArray->iArray[i]);
- break;
- case OCREP_PROP_DOUBLE:
- err = err | cbor_encode_double(&array, valArray->dArray[i]);
- break;
- case OCREP_PROP_BOOL:
- err = err | cbor_encode_boolean(&array, valArray->bArray[i]);
- break;
- case OCREP_PROP_STRING:
- if (!valArray->strArray[i])
- {
- err = err | cbor_encode_null(&array);
- }
- else
- {
- err = err | cbor_encode_text_string(&array, valArray->strArray[i],
- strlen(valArray->strArray[i]));
- }
- break;
- case OCREP_PROP_OBJECT:
- if (!valArray->objArray[i])
+ CborEncoder array2;
+ err = err | cbor_encoder_create_array(&array, &array2, valArray->dimensions[1]);
+
+ for (size_t j = 0; j < valArray->dimensions[1]; ++j)
+ {
+ if (valArray->dimensions[2] != 0)
{
- err = err | cbor_encode_null(&array);
+ CborEncoder array3;
+ err = err | cbor_encoder_create_array(&array2, &array3,
+ valArray->dimensions[2]);
+
+ for(size_t k = 0; k < valArray->dimensions[2]; ++k)
+ {
+ OCConvertArrayItem(&array3, valArray,
+ j * valArray->dimensions[2] +
+ i * valArray->dimensions[2] * valArray->dimensions[1] +
+ k);
+ }
+ err = err | cbor_encoder_close_container(&array2, &array3);
}
else
{
- err = OCConvertSingleRepPayload(&array, valArray->objArray[i]);
+ OCConvertArrayItem(&array2, valArray,
+ i * valArray->dimensions[1] + j);
}
- break;
- case OCREP_PROP_ARRAY:
- OC_LOG(ERROR, TAG, "ConvertArray Invalid child array");
- err = CborUnknownError;
- break;
+ }
+ err = err | cbor_encoder_close_container(&array, &array2);
+ }
+ else
+ {
+ OCConvertArrayItem(&array, valArray, i);
}
}
-
err = err | cbor_encoder_close_container(parent, &array);
return err;
}
}
}
-static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
+static OCRepPayloadPropType DecodeCborType(CborType type)
+{
+ switch (type)
+ {
+ case CborNullType:
+ return OCREP_PROP_NULL;
+ case CborIntegerType:
+ return OCREP_PROP_INT;
+ case CborDoubleType:
+ return OCREP_PROP_DOUBLE;
+ case CborBooleanType:
+ return OCREP_PROP_BOOL;
+ case CborTextStringType:
+ return OCREP_PROP_STRING;
+ case CborMapType:
+ return OCREP_PROP_OBJECT;
+ case CborArrayType:
+ return OCREP_PROP_ARRAY;
+ default:
+ return OCREP_PROP_NULL;
+ }
+}
+static bool OCParseArrayFindDimensionsAndType(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
+ OCRepPayloadPropType* type)
{
+ bool err = false;
CborValue insideArray;
+ *type = OCREP_PROP_NULL;
+ dimensions[0] = dimensions[1] = dimensions[2] = 0;
+
+ err = err || cbor_value_enter_container(parent, &insideArray);
+
+ while (cbor_value_is_valid(&insideArray))
+ {
+ OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
+
+ if (tempType == OCREP_PROP_ARRAY)
+ {
+ size_t subdim[MAX_REP_ARRAY_DEPTH];
+ tempType = OCREP_PROP_NULL;
+ err = err || OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
+
+ if (subdim[2] != 0)
+ {
+ OC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
+ }
+
+ dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
+ dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
+
+ if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL
+ && *type != tempType)
+ {
+ OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
+ return true;
+ }
+ else if (*type == OCREP_PROP_NULL)
+ {
+ // We don't know the type of this array yet, so the assignment is OK
+ *type = tempType;
+ }
+ }
+ else if (*type == OCREP_PROP_NULL)
+ {
+ // We don't know the type of this array yet, so the assignment is OK
+ *type = tempType;
+ }
+ // tempType is allowed to be NULL, since it might now know the answer yet
+ else if (tempType != OCREP_PROP_NULL && *type != tempType)
+ {
+ // this is an invalid situation!
+ OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
+ return true;
+ }
+
+ ++dimensions[0];
+ cbor_value_advance(&insideArray);
+ }
+
+ return err;
+}
+
+static size_t getAllocSize(OCRepPayloadPropType type)
+{
+ switch (type)
+ {
+ case OCREP_PROP_INT:
+ return sizeof (int64_t);
+ case OCREP_PROP_DOUBLE:
+ return sizeof (double);
+ case OCREP_PROP_BOOL:
+ return sizeof (bool);
+ case OCREP_PROP_STRING:
+ return sizeof (char*);
+ case OCREP_PROP_OBJECT:
+ return sizeof (OCRepPayload*);
+ default:
+ return 0;
+ }
+}
+
+static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
+{
+ return
+ (dimensions[1] == 0 ? 1 : dimensions[1]) *
+ (dimensions[2] == 0 ? 1 : dimensions[2]) *
+ elementNum;
+}
+
+static bool OCParseArrayFillArray(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
+ OCRepPayloadPropType type, void* targetArray)
+{
bool err = false;
- uint64_t tempInt = 0;
+ CborValue insideArray;
+
+ err = err || cbor_value_enter_container(parent, &insideArray);
+
+ size_t i = 0;
+ char* tempStr = NULL;
+ size_t tempLen = 0;
+ OCRepPayload* tempPl = NULL;
+
+ size_t newdim[MAX_REP_ARRAY_DEPTH];
+ newdim[0] = dimensions[1];
+ newdim[1] = dimensions[2];
+ newdim[2] = 0;
+
+ while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
+ {
+ if (cbor_value_get_type(&insideArray) != CborNullType)
+ {
+ switch (type)
+ {
+ case OCREP_PROP_INT:
+ if (dimensions[1] == 0)
+ {
+ err = err || cbor_value_get_int64(&insideArray,
+ &(((int64_t*)targetArray)[i]));
+ }
+ else
+ {
+ err = err || OCParseArrayFillArray(&insideArray, newdim,
+ type,
+ &(((int64_t*)targetArray)[arrayStep(dimensions, i)])
+ );
+ }
+ break;
+ case OCREP_PROP_DOUBLE:
+ if (dimensions[1] == 0)
+ {
+ err = err || cbor_value_get_double(&insideArray,
+ &(((double*)targetArray)[i]));
+ }
+ else
+ {
+ err = err || OCParseArrayFillArray(&insideArray, newdim,
+ type,
+ &(((double*)targetArray)[arrayStep(dimensions, i)])
+ );
+ }
+ break;
+ case OCREP_PROP_BOOL:
+ if (dimensions[1] == 0)
+ {
+ err = err || cbor_value_get_boolean(&insideArray,
+ &(((bool*)targetArray)[i]));
+ }
+ else
+ {
+ err = err || OCParseArrayFillArray(&insideArray, newdim,
+ type,
+ &(((bool*)targetArray)[arrayStep(dimensions, i)])
+ );
+ }
+ break;
+ case OCREP_PROP_STRING:
+ if (dimensions[1] == 0)
+ {
+ err = err || cbor_value_dup_text_string(&insideArray,
+ &tempStr, &tempLen, NULL);
+ ((char**)targetArray)[i] = tempStr;
+ tempStr = NULL;
+ }
+ else
+ {
+ err = err || OCParseArrayFillArray(&insideArray, newdim,
+ type,
+ &(((char**)targetArray)[arrayStep(dimensions, i)])
+ );
+ }
+ break;
+ case OCREP_PROP_OBJECT:
+ if (dimensions[1] == 0)
+ {
+ err = err || OCParseSingleRepPayload(&tempPl, &insideArray);
+ ((OCRepPayload**)targetArray)[i] = tempPl;
+ tempPl = NULL;
+ }
+ else
+ {
+ err = err || OCParseArrayFillArray(&insideArray, newdim,
+ type,
+ &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)])
+ );
+ }
+ break;
+ default:
+ OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
+ err = true;
+ break;
+ }
+ }
+ ++i;
+ err = err || cbor_value_advance(&insideArray);
+ }
+
+ return err;
+}
+
+static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
+{
OCRepPayloadPropType type;
size_t dimensions[MAX_REP_ARRAY_DEPTH];
- err = err || cbor_value_enter_container(container, &insideArray);
+ bool err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
- err = err || cbor_value_get_uint64(&insideArray, &tempInt);
- err = err || cbor_value_advance_fixed(&insideArray);
- type = (OCRepPayloadPropType)tempInt;
+ if (err)
+ {
+ OC_LOG(ERROR, TAG, "Array details weren't clear");
+ return err;
+ }
- for(int i = 0; i < MAX_REP_ARRAY_DEPTH; ++ i)
+ if (type == OCREP_PROP_NULL)
{
- err = err || cbor_value_get_uint64(&insideArray, &tempInt);
- err = err || cbor_value_advance_fixed(&insideArray);
- dimensions[i] = tempInt;
+ err = err || OCRepPayloadSetNull(out, name);
+ err = err || cbor_value_advance(container);
+ return err;
}
size_t dimTotal = calcDimTotal(dimensions);
+ size_t allocSize = getAllocSize(type);
+ void* arr = OICCalloc(dimTotal, allocSize);
- void* arr = NULL;
- char* tempStr;
- size_t len;
- OCRepPayload* pl;
- switch(type)
+ if (!arr)
+ {
+ OC_LOG(ERROR, TAG, "Array Parse allocation failed");
+ return true;
+ }
+
+ err = err || OCParseArrayFillArray(container, dimensions, type, arr);
+
+ switch (type)
{
case OCREP_PROP_INT:
- arr = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
- if (arr)
- {
- for(size_t i = 0; i < dimTotal && !err; ++i)
- {
- err = err || cbor_value_get_int64(&insideArray, &(((int64_t*)arr)[i]));
- err = err || cbor_value_advance_fixed(&insideArray);
- }
- if(err || !OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
- {
- OICFree(arr);
- err = true;
- }
- }
- else
+ if (err || !OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
{
+ OICFree(arr);
err = true;
}
break;
case OCREP_PROP_DOUBLE:
- arr = (double*)OICMalloc(dimTotal * sizeof(double));
- if(arr)
- {
- for(size_t i = 0; i < dimTotal && !err; ++i)
- {
- err = err || cbor_value_get_double(&insideArray, &(((double*)arr)[i]));
- err = err || cbor_value_advance_fixed(&insideArray);
- }
- if(err || !OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
- {
- OICFree(arr);
- err = true;
- }
- }
- else
+ if (err || !OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
{
+ OICFree(arr);
err = true;
}
break;
case OCREP_PROP_BOOL:
- arr = (bool*)OICMalloc(dimTotal * sizeof(bool));
- if(arr)
- {
- for(size_t i = 0; i < dimTotal && !err; ++i)
- {
- err = err || cbor_value_get_boolean(&insideArray, &(((bool*)arr)[i]));
- err = err || cbor_value_advance_fixed(&insideArray);
- }
- if(err || !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
- {
- OICFree(arr);
- err = true;
- }
- }
- else
+ if (err || !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
{
+ OICFree(arr);
err = true;
}
break;
case OCREP_PROP_STRING:
- arr = (char**)OICCalloc(dimTotal, sizeof(char*));
- if(arr)
+ if (err || !OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
{
- for(size_t i = 0; i < dimTotal && !err; ++i)
- {
- if (!cbor_type_is_null(&insideArray))
- {
- err = err || cbor_value_dup_text_string(&insideArray, &tempStr,
- &len, NULL);
- ((char**)arr)[i] = tempStr;
- }
- err = err || cbor_value_advance(&insideArray);
- }
- if(err || !OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
+ for(size_t i = 0; i < dimTotal; ++i)
{
- OICFree(arr);
- err = true;
+ OICFree(((char**)arr)[i]);
}
- }
- else
- {
+ OICFree(arr);
err = true;
}
break;
case OCREP_PROP_OBJECT:
- arr = (OCRepPayload**)OICCalloc(dimTotal, sizeof(OCRepPayload*));
- if(arr)
+ if (err || !OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions))
{
- for(size_t i = 0; i < dimTotal && !err; ++i)
- {
- if (!cbor_type_is_null(&insideArray))
- {
- pl = NULL;
- err = err || OCParseSingleRepPayload(&pl, &insideArray);
- ((OCRepPayload**)arr)[i] = pl;
- }
- err = err || cbor_value_advance(&insideArray);
- }
- if(err || !OCRepPayloadSetPropObjectArrayAsOwner(out, name,
- (OCRepPayload**)arr, dimensions))
+ for(size_t i = 0; i < dimTotal; ++i)
{
- OICFree(arr);
- err = true;
+ OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
}
- }
- else
- {
+ OICFree(arr);
err = true;
}
break;