A modelling and serializer library for Microsoft Azure IoTHub client applications
Dependents: sht15_remote_monitoring f767zi_mqtt remote_monitoring simplesample_amqp ... more
This library implements a serializer library to be used in projects involving Microsoft Azure IoT Hub connectivity. The code is replicated from https://github.com/Azure/azure-iot-sdks
Diff: datamarshaller.c
- Revision:
- 17:fa1bba4c6053
- Parent:
- 13:16e88f0cfa5f
- Child:
- 21:6d3dea1abd9c
--- a/datamarshaller.c Thu Oct 20 17:08:06 2016 -0700 +++ b/datamarshaller.c Wed Nov 16 21:38:26 2016 -0800 @@ -14,17 +14,19 @@ #include "jsonencoder.h" #include "agenttypesystem.h" #include "azure_c_shared_utility/xlogging.h" +#include "parson.h" +#include "azure_c_shared_utility/vector.h" DEFINE_ENUM_STRINGS(DATA_MARSHALLER_RESULT, DATA_MARSHALLER_RESULT_VALUES); #define LOG_DATA_MARSHALLER_ERROR \ LogError("(result = %s)", ENUM_TO_STRING(DATA_MARSHALLER_RESULT, result)); -typedef struct DATA_MARSHALLER_INSTANCE_TAG +typedef struct DATA_MARSHALLER_HANDLE_DATA_TAG { SCHEMA_MODEL_TYPE_HANDLE ModelHandle; bool IncludePropertyPath; -} DATA_MARSHALLER_INSTANCE; +} DATA_MARSHALLER_HANDLE_DATA; static int NoCloneFunction(void** destination, const void* source) { @@ -39,8 +41,7 @@ DATA_MARSHALLER_HANDLE DataMarshaller_Create(SCHEMA_MODEL_TYPE_HANDLE modelHandle, bool includePropertyPath) { - DATA_MARSHALLER_HANDLE result; - DATA_MARSHALLER_INSTANCE* dataMarshallerInstance; + DATA_MARSHALLER_HANDLE_DATA* result; /*Codes_SRS_DATA_MARSHALLER_99_019:[ DataMarshaller_Create shall return NULL if any argument is NULL.]*/ if ( @@ -50,7 +51,7 @@ result = NULL; LogError("(result = %s)", ENUM_TO_STRING(DATA_MARSHALLER_RESULT, DATA_MARSHALLER_INVALID_ARG)); } - else if ((dataMarshallerInstance = (DATA_MARSHALLER_INSTANCE*)malloc(sizeof(DATA_MARSHALLER_INSTANCE))) == NULL) + else if ((result = (DATA_MARSHALLER_HANDLE_DATA*)malloc(sizeof(DATA_MARSHALLER_HANDLE_DATA))) == NULL) { /* Codes_SRS_DATA_MARSHALLER_99_048:[On any other errors not explicitly specified, DataMarshaller_Create shall return NULL.] */ result = NULL; @@ -59,11 +60,9 @@ else { /*everything ok*/ - dataMarshallerInstance->ModelHandle = modelHandle; - dataMarshallerInstance->IncludePropertyPath = includePropertyPath; - /*Codes_SRS_DATA_MARSHALLER_99_018:[ DataMarshaller_Create shall create a new DataMarshaller instance and on success it shall return a non NULL handle.]*/ - result = dataMarshallerInstance; + result->ModelHandle = modelHandle; + result->IncludePropertyPath = includePropertyPath; } return result; } @@ -74,14 +73,14 @@ if (dataMarshallerHandle != NULL) { /* Codes_SRS_DATA_MARSHALLER_99_022:[ DataMarshaller_Destroy shall free all resources associated with the dataMarshallerHandle argument.] */ - DATA_MARSHALLER_INSTANCE* dataMarshallerInstance = (DATA_MARSHALLER_INSTANCE*)dataMarshallerHandle; + DATA_MARSHALLER_HANDLE_DATA* dataMarshallerInstance = (DATA_MARSHALLER_HANDLE_DATA*)dataMarshallerHandle; free(dataMarshallerInstance); } } DATA_MARSHALLER_RESULT DataMarshaller_SendData(DATA_MARSHALLER_HANDLE dataMarshallerHandle, size_t valueCount, const DATA_MARSHALLER_VALUE* values, unsigned char** destination, size_t* destinationSize) { - DATA_MARSHALLER_INSTANCE* dataMarshallerInstance = (DATA_MARSHALLER_INSTANCE*)dataMarshallerHandle; + DATA_MARSHALLER_HANDLE_DATA* dataMarshallerInstance = (DATA_MARSHALLER_HANDLE_DATA*)dataMarshallerHandle; DATA_MARSHALLER_RESULT result; MULTITREE_HANDLE treeHandle; @@ -100,7 +99,7 @@ else { size_t i; - bool includePropertyPath = dataMarshallerInstance->IncludePropertyPath; + bool includePropertyPath = dataMarshallerInstance->IncludePropertyPath; /* VS complains wrongly that result is not initialized */ result = DATA_MARSHALLER_ERROR; @@ -221,3 +220,152 @@ return result; } + + +DATA_MARSHALLER_RESULT DataMarshaller_SendData_ReportedProperties(DATA_MARSHALLER_HANDLE dataMarshallerHandle, VECTOR_HANDLE values, unsigned char** destination, size_t* destinationSize) +{ + DATA_MARSHALLER_RESULT result; + /*Codes_SRS_DATA_MARSHALLER_02_021: [ If argument dataMarshallerHandle is NULL then DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_INVALID_ARG. ]*/ + /*Codes_SRS_DATA_MARSHALLER_02_008: [ If argument values is NULL then DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_INVALID_ARG. ]*/ + /*Codes_SRS_DATA_MARSHALLER_02_009: [ If argument destination NULL then DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_INVALID_ARG. ]*/ + /*Codes_SRS_DATA_MARSHALLER_02_010: [ If argument destinationSize NULL then DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_INVALID_ARG. ]*/ + if ( + (dataMarshallerHandle == NULL) || + (values == NULL) || + (destination == NULL) || + (destinationSize == NULL) + ) + { + LogError("invalid argument DATA_MARSHALLER_HANDLE dataMarshallerHandle=%p, VECTOR_HANDLE values=%p, unsigned char** destination=%p, size_t* destinationSize=%p", + dataMarshallerHandle, + values, + destination, + destinationSize); + result = DATA_MARSHALLER_INVALID_ARG; + } + else + { + /*Codes_SRS_DATA_MARSHALLER_02_012: [ DataMarshaller_SendData_ReportedProperties shall create an empty JSON_Value. ]*/ + JSON_Value* json = json_value_init_object(); + if (json == NULL) + { + /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/ + LogError("failure calling json_value_init_object"); + result = DATA_MARSHALLER_ERROR; + } + else + { + /*Codes_SRS_DATA_MARSHALLER_02_013: [ DataMarshaller_SendData_ReportedProperties shall get the object behind the JSON_Value by calling json_object. ]*/ + JSON_Object* jsonObject = json_object(json); + if (jsonObject == NULL) + { + /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/ + LogError("failure calling json_object"); + result = DATA_MARSHALLER_ERROR; + } + else + { + size_t nReportedProperties = VECTOR_size(values), nProcessedProperties = 0; + + for (size_t i = 0;i < nReportedProperties; i++) + { + DATA_MARSHALLER_VALUE* v = *(DATA_MARSHALLER_VALUE**)VECTOR_element(values, i); + STRING_HANDLE s = STRING_new(); + if (s == NULL) + { + /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/ + LogError("failure calling STRING_new"); + i = nReportedProperties;/*forces loop to break, result is set in the "if" following this for*/ + } + else + { + /*Codes_SRS_DATA_MARSHALLER_02_014: [ For every reported property, DataMarshaller_SendData_ReportedProperties shall get the reported property's JSON value (as string) by calling AgentDataTypes_ToString. ]*/ + if (AgentDataTypes_ToString(s, v->Value) != AGENT_DATA_TYPES_OK) + { + /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/ + LogError("failure calling AgentDataTypes_ToString"); + i = nReportedProperties;/*forces loop to break, result is set in the "if" following this for*/ + } + else + { + /*Codes_SRS_DATA_MARSHALLER_02_015: [ DataMarshaller_SendData_ReportedProperties shall import the JSON value (as string) by calling json_parse_string. ]*/ + JSON_Value * rightSide = json_parse_string(STRING_c_str(s)); + if (rightSide == NULL) + { + /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/ + LogError("failure calling json_parse_string"); + i = nReportedProperties;/*forces loop to break, result is set in the "if" following this for*/ + } + else + { + char* leftSide; + if (mallocAndStrcpy_s(&leftSide, v->PropertyPath) != 0) + { + /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/ + LogError("failure calling mallocAndStrcpy_s"); + json_value_free(rightSide); + i = nReportedProperties;/*forces loop to break, result is set in the "if" following this for*/ + } + else + { + /*Codes_SRS_DATA_MARSHALLER_02_016: [ DataMarshaller_SendData_ReportedProperties shall replace all the occurences of / with . in the reported property paths. ]*/ + char *whereIsSlash; + while ((whereIsSlash = strchr(leftSide, '/')) != NULL) + { + *whereIsSlash = '.'; + } + + /*Codes_SRS_DATA_MARSHALLER_02_017: [ DataMarshaller_SendData_ReportedProperties shall use json_object_dotset_value passing the reported property path and the imported json value. ]*/ + /*Codes_SRS_DATA_MARSHALLER_02_011: [ DataMarshaller_SendData_ReportedProperties shall ignore the value of includePropertyPath and shall consider it to be true. ]*/ + if (json_object_dotset_value(jsonObject, leftSide, rightSide) != JSONSuccess) + { + /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/ + LogError("failure calling json_object_dotset_value"); + json_value_free(rightSide); + i = nReportedProperties;/*forces loop to break, result is set in the "if" following this for*/ + } + else + { + /*all is fine with this property... */ + nProcessedProperties++; + } + free(leftSide); + } + } + } + STRING_delete(s); + } + } + + if (nProcessedProperties != nReportedProperties) + { + result = DATA_MARSHALLER_ERROR; + /*all properties have NOT been processed*/ + /*return result as is*/ + } + else + { + /*Codes_SRS_DATA_MARSHALLER_02_018: [ DataMarshaller_SendData_ReportedProperties shall use json_serialize_to_string_pretty to produce the output JSON string that fills out parameters destination and destionationSize. ]*/ + char* temp = json_serialize_to_string_pretty(json); + if (temp == NULL) + { + /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/ + LogError("failure calling json_serialize_to_string_pretty "); + result = DATA_MARSHALLER_ERROR; + } + else + { + /*Codes_SRS_DATA_MARSHALLER_02_020: [ Otherwise DataMarshaller_SendData_ReportedProperties shall succeed and return DATA_MARSHALLER_OK. ]*/ + *destination = (unsigned char*)temp; + *destinationSize = strlen(temp); + result = DATA_MARSHALLER_OK; + /*all is fine... */ + } + } + } + json_value_free(json); + } + } + return result; +} + \ No newline at end of file