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: schema.c
- Revision:
- 18:58b667752399
- Parent:
- 17:fa1bba4c6053
- Child:
- 21:6d3dea1abd9c
--- a/schema.c Wed Nov 16 21:38:26 2016 -0800 +++ b/schema.c Wed Dec 14 16:00:39 2016 -0800 @@ -44,6 +44,12 @@ const char* Type; } SCHEMA_ACTION_ARGUMENT_HANDLE_DATA; +typedef struct SCHEMA_METHOD_ARGUMENT_HANDLE_DATA_TAG +{ + char* Name; + char* Type; +} SCHEMA_METHOD_ARGUMENT_HANDLE_DATA; + typedef struct SCHEMA_ACTION_HANDLE_DATA_TAG { const char* ActionName; @@ -51,6 +57,12 @@ SCHEMA_ACTION_ARGUMENT_HANDLE* ArgumentHandles; } SCHEMA_ACTION_HANDLE_DATA; +typedef struct SCHEMA_METHOD_HANDLE_DATA_TAG +{ + char* methodName; + VECTOR_HANDLE methodArguments; /*holds SCHEMA_METHOD_ARGUMENT_HANDLE*/ +} SCHEMA_METHOD_HANDLE_DATA; + typedef struct MODEL_IN_MODEL_TAG { pfOnDesiredProperty onDesiredProperty; /*is NULL if not specified or if the model in model is not WITH_DESIRED_PROPERTY*/ @@ -61,6 +73,7 @@ typedef struct SCHEMA_MODEL_TYPE_HANDLE_DATA_TAG { + VECTOR_HANDLE methods; /*holds SCHEMA_METHOD_HANDLE*/ VECTOR_HANDLE desiredProperties; /*holds SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*/ const char* Name; SCHEMA_HANDLE SchemaHandle; @@ -111,6 +124,13 @@ } } +static void DestroyMethodArgument(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle) +{ + free(methodArgumentHandle->Name); + free(methodArgumentHandle->Type); + free(methodArgumentHandle); +} + static void DestroyAction(SCHEMA_ACTION_HANDLE actionHandle) { SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; @@ -129,6 +149,33 @@ } } +static void DestroyMethod(SCHEMA_METHOD_HANDLE methodHandle) +{ + size_t nArguments = VECTOR_size(methodHandle->methodArguments); + + for (size_t j = 0; j < nArguments; j++) + { + SCHEMA_METHOD_ARGUMENT_HANDLE* methodArgumentHandle = VECTOR_element(methodHandle->methodArguments, j); + DestroyMethodArgument(*methodArgumentHandle); + } + free(methodHandle->methodName); + VECTOR_destroy(methodHandle->methodArguments); + free(methodHandle); +} + +static void DestroyMethods(SCHEMA_MODEL_TYPE_HANDLE modelHandle) +{ + size_t nMethods = VECTOR_size(modelHandle->methods); + + for (size_t j = 0; j < nMethods; j++) + { + SCHEMA_METHOD_HANDLE* methodHandle = VECTOR_element(modelHandle->methods, j); + DestroyMethod(*methodHandle); + } + VECTOR_destroy(modelHandle->methods); +} + + static void DestroyStruct(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle) { size_t i; @@ -167,6 +214,8 @@ DestroyAction(modelType->Actions[i]); } + DestroyMethods(modelType); + /*destroy the vector holding the added models. This does not destroy the said models, however, their names shall be*/ for (i = 0; i < VECTOR_size(modelType->models); i++) { @@ -609,6 +658,7 @@ modelType->models = VECTOR_create(sizeof(MODEL_IN_MODEL)); if (modelType->models == NULL) { + /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ LogError("unable to VECTOR_create"); free((void*)modelType->Name); free((void*)modelType); @@ -618,6 +668,7 @@ { if ((modelType->reportedProperties = VECTOR_create(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE))) == NULL) { + /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ LogError("failed to VECTOR_create (reported properties)"); VECTOR_destroy(modelType->models); free((void*)modelType->Name); @@ -627,6 +678,7 @@ } else { + /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ if ((modelType->desiredProperties = VECTOR_create(sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE))) == NULL) { LogError("failure in VECTOR_create (desired properties)"); @@ -638,17 +690,30 @@ } else { - modelType->PropertyCount = 0; - modelType->Properties = NULL; - modelType->ActionCount = 0; - modelType->Actions = NULL; - modelType->SchemaHandle = schemaHandle; - modelType->DeviceCount = 0; + if ((modelType->methods = VECTOR_create(sizeof(SCHEMA_METHOD_HANDLE))) == NULL) + { + LogError("failure in VECTOR_create (desired properties)"); + VECTOR_destroy(modelType->desiredProperties); + VECTOR_destroy(modelType->reportedProperties); + VECTOR_destroy(modelType->models); + free((void*)modelType->Name); + free((void*)modelType); + result = NULL; + } + else + { + modelType->PropertyCount = 0; + modelType->Properties = NULL; + modelType->ActionCount = 0; + modelType->Actions = NULL; + modelType->SchemaHandle = schemaHandle; + modelType->DeviceCount = 0; - schema->ModelTypes[schema->ModelTypeCount] = modelType; - schema->ModelTypeCount++; - /* Codes_SRS_SCHEMA_99_008:[On success, a non-NULL handle shall be returned.] */ - result = (SCHEMA_MODEL_TYPE_HANDLE)modelType; + schema->ModelTypes[schema->ModelTypeCount] = modelType; + schema->ModelTypeCount++; + /* Codes_SRS_SCHEMA_99_008:[On success, a non-NULL handle shall be returned.] */ + result = (SCHEMA_MODEL_TYPE_HANDLE)modelType; + } } } } @@ -873,6 +938,92 @@ return result; } + +static bool methodExists(const void* element, const void* value) +{ + const SCHEMA_METHOD_HANDLE* method = (const SCHEMA_METHOD_HANDLE*)element; + return (strcmp((*method)->methodName, value) == 0); +} + + +SCHEMA_METHOD_HANDLE Schema_CreateModelMethod(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* methodName) +{ + SCHEMA_METHOD_HANDLE result; + + /*Codes_SRS_SCHEMA_02_096: [ If modelTypeHandle is NULL then Schema_CreateModelMethod shall fail and return NULL. ]*/ + /*Codes_SRS_SCHEMA_02_097: [ If methodName is NULL then Schema_CreateModelMethod shall fail and return NULL. ]*/ + if ((modelTypeHandle == NULL) || + (methodName == NULL)) + { + result = NULL; + LogError("invalid argument: SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* methodName=%p", modelTypeHandle, methodName); + } + else + { + /*Codes_SRS_SCHEMA_02_103: [ If methodName already exists, then Schema_CreateModelMethod shall fail and return NULL. ]*/ + if (VECTOR_find_if(modelTypeHandle->methods, methodExists, methodName) != NULL) + { + LogError("method %s already exists", methodName); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_098: [ Schema_CreateModelMethod shall allocate the space for the method. ]*/ + result = malloc(sizeof(SCHEMA_METHOD_HANDLE_DATA)); + if (result == NULL) + { + LogError("failed to malloc"); + /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/ + /*return as is*/ + } + else + { + /*Codes_SRS_SCHEMA_02_099: [ Schema_CreateModelMethod shall create a VECTOR that will hold the method's arguments. ]*/ + result->methodArguments = VECTOR_create(sizeof(SCHEMA_METHOD_ARGUMENT_HANDLE)); + if (result->methodArguments == NULL) + { + /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/ + LogError("failure in VECTOR_create"); + free(result); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_100: [ Schema_CreateModelMethod shall clone methodName ]*/ + if (mallocAndStrcpy_s(&result->methodName, methodName) != 0) + { + /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/ + LogError("failure in mallocAndStrcpy_s"); + VECTOR_destroy(result->methodArguments); + free(result); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_101: [ Schema_CreateModelMethod shall add the new created method to the model's list of methods. ]*/ + if (VECTOR_push_back(modelTypeHandle->methods, &result, 1) != 0) + { + /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/ + LogError("failure in VECTOR_push_back"); + free(result->methodName); + VECTOR_destroy(result->methodArguments); + free(result); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_104: [ Otherwise, Schema_CreateModelMethod shall succeed and return a non-NULL SCHEMA_METHOD_HANDLE. ]*/ + /*return as is*/ + } + } + } + } + } + } + return result; +} + + SCHEMA_RESULT Schema_AddModelActionArgument(SCHEMA_ACTION_HANDLE actionHandle, const char* argumentName, const char* argumentType) { SCHEMA_RESULT result; @@ -973,6 +1124,91 @@ return result; } +static bool methodFindArgumentByBame(const void* element, const void* value) +{ + /*element is a pointer to SCHEMA_METHOD_ARGUMENT_HANDLE*/ + const SCHEMA_METHOD_ARGUMENT_HANDLE* decodedElement = (const SCHEMA_METHOD_ARGUMENT_HANDLE*)element; + const char* name = (const char*)value; + return (strcmp((*decodedElement)->Name, name) == 0); +} + +SCHEMA_RESULT Schema_AddModelMethodArgument(SCHEMA_METHOD_HANDLE methodHandle, const char* argumentName, const char* argumentType) +{ + SCHEMA_RESULT result; + /*Codes_SRS_SCHEMA_02_105: [ If methodHandle is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_106: [ If argumentName is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_107: [ If argumentType is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/ + if ((methodHandle == NULL) || + (argumentName == NULL) || + (argumentType == NULL)) + { + result = SCHEMA_INVALID_ARG; + LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); + } + else + { + /*Codes_SRS_SCHEMA_02_108: [ If argumentName already exists in the list of arguments then then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/ + if (VECTOR_find_if(methodHandle->methodArguments, methodFindArgumentByBame, argumentName) != NULL) + { + LogError("an argument with name %s already exists", argumentName); + result = SCHEMA_INVALID_ARG; + } + else + { + /*Codes_SRS_SCHEMA_02_109: [ Schema_AddModelMethodArgument shall allocate memory for the new argument. ]*/ + SCHEMA_METHOD_ARGUMENT_HANDLE_DATA* argument = malloc(sizeof(SCHEMA_METHOD_ARGUMENT_HANDLE_DATA)); + if (argument == NULL) + { + /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/ + LogError("failure to malloc"); + result = SCHEMA_ERROR; + } + else + { + /*Codes_SRS_SCHEMA_02_110: [ Schema_AddModelMethodArgument shall clone methodHandle. ]*/ + if (mallocAndStrcpy_s(&argument->Name, argumentName) != 0) + { + /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/ + LogError("failure in mallocAndStrcpy_s"); + free(argument); + result = SCHEMA_ERROR; + } + else + { + /*Codes_SRS_SCHEMA_02_111: [ Schema_AddModelMethodArgument shall clone argumentType. ]*/ + if (mallocAndStrcpy_s(&argument->Type, argumentType) != 0) + { + /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/ + LogError("failure in mallocAndStrcpy_s"); + free(argument->Name); + free(argument); + result = SCHEMA_ERROR; + } + else + { + /*Codes_SRS_SCHEMA_02_112: [ Schema_AddModelMethodArgument shall add the created argument to the method's list of arguments. ]*/ + if (VECTOR_push_back(methodHandle->methodArguments, &argument, 1) != 0) + { + /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/ + LogError("failure in VECTOR_push_back"); + free(argument->Name); + free(argument->Type); + free(argument); + result = SCHEMA_ERROR; + } + else + { + /*Codes_SRS_SCHEMA_02_114: [ Otherwise, Schema_AddModelMethodArgument shall succeed and return SCHEMA_OK. ]*/ + result = SCHEMA_OK; + } + } + } + } + } + } + return result; +} + SCHEMA_PROPERTY_HANDLE Schema_GetModelPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName) { SCHEMA_PROPERTY_HANDLE result; @@ -1182,6 +1418,45 @@ return result; } +static bool matchModelMethod(const void* element, const void* value) +{ + /*element is a pointer to SCHEMA_METHOD_HANDLE_DATA*/ + const SCHEMA_METHOD_HANDLE* decodedElement = (const SCHEMA_METHOD_HANDLE* )element; + const char* name = (const char*)value; + return (strcmp((*decodedElement)->methodName, name) == 0); +} + +SCHEMA_METHOD_HANDLE Schema_GetModelMethodByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* methodName) +{ + SCHEMA_METHOD_HANDLE result; + + /*Codes_SRS_SCHEMA_02_115: [ If modelTypeHandle is NULL then Schema_GetModelMethodByName shall fail and return NULL. ]*/ + /*Codes_SRS_SCHEMA_02_116: [ If methodName is NULL then Schema_GetModelMethodByName shall fail and return NULL. ]*/ + if ((modelTypeHandle == NULL) || + (methodName == NULL)) + { + result = NULL; + LogError("invalid arguments SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* methodName=%p", modelTypeHandle, methodName); + } + else + { + /*Codes_SRS_SCHEMA_02_117: [ If a method with the name methodName exists then Schema_GetModelMethodByName shall succeed and returns its handle. ]*/ + SCHEMA_METHOD_HANDLE* found = VECTOR_find_if(modelTypeHandle->methods, matchModelMethod, methodName); + if (found == NULL) + { + /*Codes_SRS_SCHEMA_02_118: [ Otherwise, Schema_GetModelMethodByName shall fail and return NULL. ]*/ + LogError("no such method by name = %s", methodName); + result = NULL; + } + else + { + result = *found; + } + } + + return result; +} + SCHEMA_RESULT Schema_GetModelActionCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* actionCount) { SCHEMA_RESULT result; @@ -1276,6 +1551,29 @@ return result; } +SCHEMA_RESULT Schema_GetModelMethodArgumentCount(SCHEMA_METHOD_HANDLE methodHandle, size_t* argumentCount) +{ + SCHEMA_RESULT result; + + /*Codes_SRS_SCHEMA_02_119: [ If methodHandle is NULL then Schema_GetModelMethodArgumentCount shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_120: [ If argumentCount is NULL then Schema_GetModelMethodArgumentCount shall fail and return SCHEMA_INVALID_ARG. ]*/ + if ((methodHandle == NULL) || + (argumentCount == NULL)) + { + result = SCHEMA_INVALID_ARG; + LogError("(result=%s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); + } + else + { + /*Codes_SRS_SCHEMA_02_121: [ Otherwise, Schema_GetModelMethodArgumentCount shall succeed, return in argumentCount the number of arguments for the method and return SCHEMA_OK. ]*/ + *argumentCount = VECTOR_size(methodHandle->methodArguments); + result = SCHEMA_OK; + } + + return result; +} + + SCHEMA_ACTION_ARGUMENT_HANDLE Schema_GetModelActionArgumentByName(SCHEMA_ACTION_HANDLE actionHandle, const char* actionArgumentName) { SCHEMA_ACTION_ARGUMENT_HANDLE result; @@ -1339,6 +1637,35 @@ return result; } +SCHEMA_METHOD_ARGUMENT_HANDLE Schema_GetModelMethodArgumentByIndex(SCHEMA_METHOD_HANDLE methodHandle, size_t argumentIndex) +{ + SCHEMA_METHOD_ARGUMENT_HANDLE result; + + /*Codes_SRS_SCHEMA_02_122: [ If methodHandle is NULL then Schema_GetModelMethodArgumentByIndex shall fail and return NULL. ]*/ + if (methodHandle == NULL) + { + result = NULL; + LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); + } + else + { + /*Codes_SRS_SCHEMA_02_123: [ If argumentIndex does not exist then Schema_GetModelMethodArgumentByIndex shall fail and return NULL. ]*/ + SCHEMA_METHOD_ARGUMENT_HANDLE *temp = VECTOR_element(methodHandle->methodArguments, argumentIndex); + if (temp == NULL) + { + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_124: [ Otherwise, Schema_GetModelMethodArgumentByIndex shall succeed and return a non-NULL value. ]*/ + result = *temp; + } + } + + return result; +} + + const char* Schema_GetActionArgumentName(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle) { const char* result; @@ -1357,6 +1684,24 @@ return result; } +const char* Schema_GetMethodArgumentName(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle) +{ + const char* result; + /*Codes_SRS_SCHEMA_02_125: [ If methodArgumentHandle is NULL then Schema_GetMethodArgumentName shall fail and return NULL. ]*/ + if (methodArgumentHandle == NULL) + { + result = NULL; + LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); + } + else + { + /*Codes_SRS_SCHEMA_02_126: [ Otherwise, Schema_GetMethodArgumentName shall succeed and return a non-NULL value. ]*/ + result = methodArgumentHandle->Name; + } + return result; +} + + const char* Schema_GetActionArgumentType(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle) { const char* result; @@ -1375,6 +1720,24 @@ return result; } +const char* Schema_GetMethodArgumentType(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle) +{ + const char* result; + /*Codes_SRS_SCHEMA_02_127: [ If methodArgumentHandle is NULL then Schema_GetMethodArgumentType shall fail and return NULL. ]*/ + if (methodArgumentHandle == NULL) + { + result = NULL; + LogError("invalid argument SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle=%p", methodArgumentHandle); + } + else + { + /*Codes_SRS_SCHEMA_02_128: [ Otherwise, Schema_GetMethodArgumentType shall succeed and return a non-NULL value. ]*/ + result = methodArgumentHandle->Type; + } + return result; +} + + SCHEMA_STRUCT_TYPE_HANDLE Schema_CreateStructType(SCHEMA_HANDLE schemaHandle, const char* typeName) { SCHEMA_STRUCT_TYPE_HANDLE result;