Azure IoT common library
Dependents: STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more
Diff: optionhandler.c
- Revision:
- 19:2e0811512ceb
- Parent:
- 7:1af47e3a19b6
- Child:
- 48:81866008bba4
--- a/optionhandler.c Fri Jan 13 18:41:15 2017 -0800 +++ b/optionhandler.c Sat Jan 28 09:35:22 2017 -0800 @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +#include <stdlib.h> #include "azure_c_shared_utility/optionhandler.h" #include "azure_c_shared_utility/xlogging.h" #include "azure_c_shared_utility/gballoc.h" @@ -20,6 +21,102 @@ VECTOR_HANDLE storage; }OPTIONHANDLER_HANDLE_DATA; +static OPTIONHANDLER_HANDLE CreateInternal(pfCloneOption cloneOption, pfDestroyOption destroyOption, pfSetOption setOption) +{ + OPTIONHANDLER_HANDLE result; + + result = (OPTIONHANDLER_HANDLE_DATA*)malloc(sizeof(OPTIONHANDLER_HANDLE_DATA)); + if (result == NULL) + { + /*Codes_SRS_OPTIONHANDLER_02_004: [ Otherwise, OptionHandler_Create shall fail and return NULL. ]*/ + LogError("unable to malloc"); + /*return as is*/ + } + else + { + /*Codes_SRS_OPTIONHANDLER_02_002: [ OptionHandler_Create shall create an empty VECTOR that will hold pairs of const char* and void*. ]*/ + result->storage = VECTOR_create(sizeof(OPTION)); + if (result->storage == NULL) + { + /*Codes_SRS_OPTIONHANDLER_02_004: [ Otherwise, OptionHandler_Create shall fail and return NULL. ]*/ + LogError("unable to VECTOR_create"); + free(result); + result = NULL; + } + else + { + /*Codes_SRS_OPTIONHANDLER_02_003: [ If all the operations succeed then OptionHandler_Create shall succeed and return a non-NULL handle. ]*/ + result->cloneOption = cloneOption; + result->destroyOption = destroyOption; + result->setOption = setOption; + /*return as is*/ + } + } + + return result; +} + +static OPTIONHANDLER_RESULT AddOptionInternal(OPTIONHANDLER_HANDLE handle, const char* name, const void* value) +{ + OPTIONHANDLER_RESULT result; + const char* cloneOfName; + if (mallocAndStrcpy_s((char**)&cloneOfName, name) != 0) + { + /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/ + LogError("unable to clone name"); + result = OPTIONHANDLER_ERROR; + } + else + { + /*Codes_SRS_OPTIONHANDLER_02_006: [ OptionHandler_AddProperty shall call pfCloneOption passing name and value. ]*/ + void* cloneOfValue = handle->cloneOption(name, value); + if (cloneOfValue == NULL) + { + /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/ + LogError("unable to clone value"); + free((void*)cloneOfName); + result = OPTIONHANDLER_ERROR; + } + else + { + OPTION temp; + temp.name = cloneOfName; + temp.storage = cloneOfValue; + /*Codes_SRS_OPTIONHANDLER_02_007: [ OptionHandler_AddProperty shall use VECTOR APIs to save the name and the newly created clone of value. ]*/ + if (VECTOR_push_back(handle->storage, &temp, 1) != 0) + { + /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/ + LogError("unable to VECTOR_push_back"); + handle->destroyOption(name, cloneOfValue); + free((void*)cloneOfName); + result = OPTIONHANDLER_ERROR; + } + else + { + /*Codes_SRS_OPTIONHANDLER_02_008: [ If all the operations succed then OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_OK. ]*/ + result = OPTIONHANDLER_OK; + } + } + } + + return result; +} + +static void DestroyInternal(OPTIONHANDLER_HANDLE handle) +{ + /*Codes_SRS_OPTIONHANDLER_02_016: [ Otherwise, OptionHandler_Destroy shall free all used resources. ]*/ + size_t nOptions = VECTOR_size(handle->storage), i; + for (i = 0; i < nOptions; i++) + { + OPTION* option = (OPTION*)VECTOR_element(handle->storage, i); + handle->destroyOption(option->name, option->storage); + free((void*)option->name); + } + + VECTOR_destroy(handle->storage); + free(handle); +} + OPTIONHANDLER_HANDLE OptionHandler_Create(pfCloneOption cloneOption, pfDestroyOption destroyOption, pfSetOption setOption) { /*Codes_SRS_OPTIONHANDLER_02_001: [ OptionHandler_Create shall fail and retun NULL if any parameters are NULL. ]*/ @@ -35,36 +132,64 @@ } else { - result = (OPTIONHANDLER_HANDLE_DATA*)malloc(sizeof(OPTIONHANDLER_HANDLE_DATA)); + result = CreateInternal(cloneOption, destroyOption, setOption); + } + + return result; + +} + +OPTIONHANDLER_HANDLE OptionHandler_Clone(OPTIONHANDLER_HANDLE handler) +{ + OPTIONHANDLER_HANDLE_DATA* result; + + if (handler == NULL) + { + /* Codes_SRS_OPTIONHANDLER_01_010: [ If `handler` is NULL, OptionHandler_Clone shall fail and return NULL. ]*/ + LogError("NULL argument: handler"); + result = NULL; + } + else + { + /* Codes_SRS_OPTIONHANDLER_01_001: [ `OptionHandler_Clone` shall clone an existing option handler instance. ]*/ + /* Codes_SRS_OPTIONHANDLER_01_002: [ On success it shall return a non-NULL handle. ]*/ + /* Codes_SRS_OPTIONHANDLER_01_003: [ `OptionHandler_Clone` shall allocate memory for the new option handler instance. ]*/ + result = CreateInternal(handler->cloneOption, handler->destroyOption, handler->setOption); if (result == NULL) { - /*Codes_SRS_OPTIONHANDLER_02_004: [ Otherwise, OptionHandler_Create shall fail and return NULL. ]*/ - LogError("unable to malloc"); - /*return as is*/ + /* Codes_SRS_OPTIONHANDLER_01_004: [ If allocating memory fails, `OptionHandler_Clone` shall return NULL. ]*/ + LogError("unable to create option handler"); } else { - /*Codes_SRS_OPTIONHANDLER_02_002: [ OptionHandler_Create shall create an empty VECTOR that will hold pairs of const char* and void*. ]*/ - result->storage = VECTOR_create(sizeof(OPTION)); - if (result->storage == NULL) + /* Codes_SRS_OPTIONHANDLER_01_005: [ `OptionHandler_Clone` shall iterate through all the options stored by the option handler to be cloned by using VECTOR's iteration mechanism. ]*/ + size_t option_count = VECTOR_size(handler->storage); + size_t i; + + for (i = 0; i < option_count; i++) { - /*Codes_SRS_OPTIONHANDLER_02_004: [ Otherwise, OptionHandler_Create shall fail and return NULL. ]*/ - LogError("unable to VECTOR_create"); - free(result); - result= NULL; + OPTION* option = (OPTION*)VECTOR_element(handler->storage, i); + + /* Codes_SRS_OPTIONHANDLER_01_006: [ For each option the option name shall be cloned by calling `mallocAndStrcpy_s`. ]*/ + /* Codes_SRS_OPTIONHANDLER_01_007: [ For each option the value shall be cloned by using the cloning function associated with the source option handler `handler`. ]*/ + if (AddOptionInternal(result, option->name, option->storage) != OPTIONHANDLER_OK) + { + /* Codes_SRS_OPTIONHANDLER_01_008: [ If cloning one of the option names fails, `OptionHandler_Clone` shall return NULL. ]*/ + /* Codes_SRS_OPTIONHANDLER_01_009: [ If cloning one of the option values fails, `OptionHandler_Clone` shall return NULL. ]*/ + LogError("Error cloning option %s", option->name); + break; + } } - else + + if (i < option_count) { - /*Codes_SRS_OPTIONHANDLER_02_003: [ If all the operations succeed then OptionHandler_Create shall succeed and return a non-NULL handle. ]*/ - result->cloneOption = cloneOption; - result->destroyOption = destroyOption; - result->setOption = setOption; - /*return as is*/ + DestroyInternal(result); + result = NULL; } } } + return result; - } OPTIONHANDLER_RESULT OptionHandler_AddOption(OPTIONHANDLER_HANDLE handle, const char* name, const void* value) @@ -82,46 +207,9 @@ } else { - const char* cloneOfName; - if (mallocAndStrcpy_s((char**)&cloneOfName, name) != 0) - { - /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/ - LogError("unable to clone name"); - result = OPTIONHANDLER_ERROR; - } - else - { - /*Codes_SRS_OPTIONHANDLER_02_006: [ OptionHandler_AddProperty shall call pfCloneOption passing name and value. ]*/ - void* cloneOfValue = handle->cloneOption(name, value); - if (cloneOfValue == NULL) - { - /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/ - LogError("unable to clone value"); - free((void*)cloneOfName); - result = OPTIONHANDLER_ERROR; - } - else - { - OPTION temp; - temp.name = cloneOfName; - temp.storage = cloneOfValue; - /*Codes_SRS_OPTIONHANDLER_02_007: [ OptionHandler_AddProperty shall use VECTOR APIs to save the name and the newly created clone of value. ]*/ - if (VECTOR_push_back(handle->storage, &temp, 1) != 0) - { - /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/ - LogError("unable to VECTOR_push_back"); - handle->destroyOption(name, cloneOfValue); - free((void*)cloneOfName); - result = OPTIONHANDLER_ERROR; - } - else - { - /*Codes_SRS_OPTIONHANDLER_02_008: [ If all the operations succed then OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_OK. ]*/ - result = OPTIONHANDLER_OK; - } - } - } + result = AddOptionInternal(handle, name, value); } + return result; } @@ -175,16 +263,6 @@ } else { - /*Codes_SRS_OPTIONHANDLER_02_016: [ Otherwise, OptionHandler_Destroy shall free all used resources. ]*/ - size_t nOptions = VECTOR_size(handle->storage), i; - for (i = 0;i < nOptions;i++) - { - OPTION* option = (OPTION*)VECTOR_element(handle->storage, i); - handle->destroyOption(option->name, option->storage); - free((void*)option->name); - } - - VECTOR_destroy(handle->storage); - free(handle); + DestroyInternal(handle); } }