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

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