Nigel Rantor / azure_c_shared_utility

Fork of azure_c_shared_utility by Azure IoT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers optionhandler.c Source File

optionhandler.c

00001 // Copyright (c) Microsoft. All rights reserved.
00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
00003 
00004 #include <stdlib.h>
00005 #include "azure_c_shared_utility/optionhandler.h"
00006 #include "azure_c_shared_utility/xlogging.h"
00007 #include "azure_c_shared_utility/gballoc.h"
00008 #include "azure_c_shared_utility/vector.h"
00009 
00010 typedef struct OPTION_TAG
00011 {
00012     const char* name;
00013     void* storage;
00014 }OPTION;
00015 
00016 typedef struct OPTIONHANDLER_HANDLE_DATA_TAG
00017 {
00018     pfCloneOption cloneOption;
00019     pfDestroyOption destroyOption;
00020     pfSetOption setOption;
00021     VECTOR_HANDLE storage;
00022 }OPTIONHANDLER_HANDLE_DATA;
00023 
00024 static OPTIONHANDLER_HANDLE CreateInternal(pfCloneOption cloneOption, pfDestroyOption destroyOption, pfSetOption setOption)
00025 {
00026     OPTIONHANDLER_HANDLE result;
00027 
00028     result = (OPTIONHANDLER_HANDLE_DATA*)malloc(sizeof(OPTIONHANDLER_HANDLE_DATA));
00029     if (result == NULL)
00030     {
00031         /*Codes_SRS_OPTIONHANDLER_02_004: [ Otherwise, OptionHandler_Create shall fail and return NULL. ]*/
00032         LogError("unable to malloc");
00033         /*return as is*/
00034     }
00035     else
00036     {
00037         /*Codes_SRS_OPTIONHANDLER_02_002: [ OptionHandler_Create shall create an empty VECTOR that will hold pairs of const char* and void*. ]*/
00038         result->storage = VECTOR_create(sizeof(OPTION));
00039         if (result->storage == NULL)
00040         {
00041             /*Codes_SRS_OPTIONHANDLER_02_004: [ Otherwise, OptionHandler_Create shall fail and return NULL. ]*/
00042             LogError("unable to VECTOR_create");
00043             free(result);
00044             result = NULL;
00045         }
00046         else
00047         {
00048             /*Codes_SRS_OPTIONHANDLER_02_003: [ If all the operations succeed then OptionHandler_Create shall succeed and return a non-NULL handle. ]*/
00049             result->cloneOption = cloneOption;
00050             result->destroyOption = destroyOption;
00051             result->setOption = setOption;
00052             /*return as is*/
00053         }
00054     }
00055 
00056     return result;
00057 }
00058 
00059 static OPTIONHANDLER_RESULT AddOptionInternal(OPTIONHANDLER_HANDLE handle, const char* name, const void* value)
00060 {
00061     OPTIONHANDLER_RESULT result;
00062     const char* cloneOfName;
00063     if (mallocAndStrcpy_s((char**)&cloneOfName, name) != 0)
00064     {
00065         /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/
00066         LogError("unable to clone name");
00067         result = OPTIONHANDLER_ERROR;
00068     }
00069     else
00070     {
00071         /*Codes_SRS_OPTIONHANDLER_02_006: [ OptionHandler_AddProperty shall call pfCloneOption passing name and value. ]*/
00072         void* cloneOfValue = handle->cloneOption(name, value);
00073         if (cloneOfValue == NULL)
00074         {
00075             /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/
00076             LogError("unable to clone value");
00077             free((void*)cloneOfName);
00078             result = OPTIONHANDLER_ERROR;
00079         }
00080         else
00081         {
00082             OPTION temp;
00083             temp.name = cloneOfName;
00084             temp.storage = cloneOfValue;
00085             /*Codes_SRS_OPTIONHANDLER_02_007: [ OptionHandler_AddProperty shall use VECTOR APIs to save the name and the newly created clone of value. ]*/
00086             if (VECTOR_push_back(handle->storage, &temp, 1) != 0)
00087             {
00088                 /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/
00089                 LogError("unable to VECTOR_push_back");
00090                 handle->destroyOption(name, cloneOfValue);
00091                 free((void*)cloneOfName);
00092                 result = OPTIONHANDLER_ERROR;
00093             }
00094             else
00095             {
00096                 /*Codes_SRS_OPTIONHANDLER_02_008: [ If all the operations succed then OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_OK. ]*/
00097                 result = OPTIONHANDLER_OK;
00098             }
00099         }
00100     }
00101 
00102     return result;
00103 }
00104 
00105 static void DestroyInternal(OPTIONHANDLER_HANDLE handle)
00106 {
00107     /*Codes_SRS_OPTIONHANDLER_02_016: [ Otherwise, OptionHandler_Destroy shall free all used resources. ]*/
00108     size_t nOptions = VECTOR_size(handle->storage), i;
00109     for (i = 0; i < nOptions; i++)
00110     {
00111         OPTION* option = (OPTION*)VECTOR_element(handle->storage, i);
00112         handle->destroyOption(option->name, option->storage);
00113         free((void*)option->name);
00114     }
00115 
00116     VECTOR_destroy(handle->storage);
00117     free(handle);
00118 }
00119 
00120 OPTIONHANDLER_HANDLE OptionHandler_Create(pfCloneOption cloneOption, pfDestroyOption destroyOption, pfSetOption setOption)
00121 {
00122     /*Codes_SRS_OPTIONHANDLER_02_001: [ OptionHandler_Create shall fail and retun NULL if any parameters are NULL. ]*/
00123     OPTIONHANDLER_HANDLE_DATA* result;
00124     if (
00125         (cloneOption == NULL) ||
00126         (destroyOption == NULL) ||
00127         (setOption == NULL)
00128         )
00129     {
00130         LogError("invalid parameter = pfCloneOption cloneOption=%p, pfDestroyOption destroyOption=%p, pfSetOption setOption=%p", cloneOption, destroyOption, setOption);
00131         result = NULL;
00132     }
00133     else
00134     {
00135         result = CreateInternal(cloneOption, destroyOption, setOption);
00136     }
00137 
00138     return result;
00139 
00140 }
00141 
00142 OPTIONHANDLER_HANDLE OptionHandler_Clone(OPTIONHANDLER_HANDLE handler)
00143 {
00144     OPTIONHANDLER_HANDLE_DATA* result;
00145 
00146     if (handler == NULL)
00147     {
00148         /* Codes_SRS_OPTIONHANDLER_01_010: [ If `handler` is NULL, OptionHandler_Clone shall fail and return NULL. ]*/
00149         LogError("NULL argument: handler");
00150         result = NULL;
00151     }
00152     else
00153     {
00154         /* Codes_SRS_OPTIONHANDLER_01_001: [ `OptionHandler_Clone` shall clone an existing option handler instance. ]*/
00155         /* Codes_SRS_OPTIONHANDLER_01_002: [ On success it shall return a non-NULL handle. ]*/
00156         /* Codes_SRS_OPTIONHANDLER_01_003: [ `OptionHandler_Clone` shall allocate memory for the new option handler instance. ]*/
00157         result = CreateInternal(handler->cloneOption, handler->destroyOption, handler->setOption);
00158         if (result == NULL)
00159         {
00160             /* Codes_SRS_OPTIONHANDLER_01_004: [ If allocating memory fails, `OptionHandler_Clone` shall return NULL. ]*/
00161             LogError("unable to create option handler");
00162         }
00163         else
00164         {
00165             /* 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. ]*/
00166             size_t option_count = VECTOR_size(handler->storage);
00167             size_t i;
00168 
00169             for (i = 0; i < option_count; i++)
00170             {
00171                 OPTION* option = (OPTION*)VECTOR_element(handler->storage, i);
00172 
00173                 /* Codes_SRS_OPTIONHANDLER_01_006: [ For each option the option name shall be cloned by calling `mallocAndStrcpy_s`. ]*/
00174                 /* 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`. ]*/
00175                 if (AddOptionInternal(result, option->name, option->storage) != OPTIONHANDLER_OK)
00176                 {
00177                     /* Codes_SRS_OPTIONHANDLER_01_008: [ If cloning one of the option names fails, `OptionHandler_Clone` shall return NULL. ]*/
00178                     /* Codes_SRS_OPTIONHANDLER_01_009: [ If cloning one of the option values fails, `OptionHandler_Clone` shall return NULL. ]*/
00179                     LogError("Error cloning option %s", option->name);
00180                     break;
00181                 }
00182             }
00183 
00184             if (i < option_count)
00185             {
00186                 DestroyInternal(result);
00187                 result = NULL;
00188             }
00189         }
00190     }
00191 
00192     return result;
00193 }
00194 
00195 OPTIONHANDLER_RESULT OptionHandler_AddOption(OPTIONHANDLER_HANDLE handle, const char* name, const void* value)
00196 {
00197     OPTIONHANDLER_RESULT result;
00198     /*Codes_SRS_OPTIONHANDLER_02_001: [ OptionHandler_Create shall fail and retun NULL if any parameters are NULL. ]*/
00199     if (
00200         (handle == NULL) ||
00201         (name == NULL) ||
00202         (value == NULL)
00203         )
00204     {
00205         LogError("invalid arguments: OPTIONHANDLER_HANDLE handle=%p, const char* name=%p, void* value=%p", handle, name, value);
00206         result= OPTIONHANDLER_INVALIDARG;
00207     }
00208     else
00209     {
00210         result = AddOptionInternal(handle, name, value);
00211     }
00212 
00213     return result;
00214 }
00215 
00216 OPTIONHANDLER_RESULT OptionHandler_FeedOptions(OPTIONHANDLER_HANDLE handle, void* destinationHandle)
00217 {
00218     OPTIONHANDLER_RESULT result;
00219     /*Codes_SRS_OPTIONHANDLER_02_010: [ OptionHandler_FeedOptions shall fail and return OPTIONHANDLER_INVALIDARG if any argument is NULL. ]*/
00220     if (
00221         (handle == NULL) ||
00222         (destinationHandle == NULL)
00223         )
00224     {
00225         LogError("invalid arguments OPTIONHANDLER_HANDLE handle=%p, void* destinationHandle=%p", handle, destinationHandle);
00226         result = OPTIONHANDLER_INVALIDARG;
00227     }
00228     else
00229     {
00230         /*Codes_SRS_OPTIONHANDLER_02_011: [ Otherwise, OptionHandler_FeedOptions shall use VECTOR's iteration mechanisms to retrieve pairs of name, value (const char* and void*). ]*/
00231         size_t nOptions = VECTOR_size(handle->storage), i;
00232         for (i = 0;i < nOptions;i++)
00233         {
00234             OPTION* option = (OPTION*)VECTOR_element(handle->storage, i);
00235             /*Codes_SRS_OPTIONHANDLER_02_012: [ OptionHandler_FeedOptions shall call for every pair of name,value setOption passing destinationHandle, name and value. ]*/
00236             if (handle->setOption(destinationHandle, option->name, option->storage) != 0)
00237             {
00238                 LogError("failure while trying to _SetOption");
00239                 break;
00240             }
00241         }
00242             
00243         if (i == nOptions)
00244         {
00245             /*Codes_SRS_OPTIONHANDLER_02_014: [ Otherwise, OptionHandler_FeedOptions shall fail and return OPTIONHANDLER_ERROR. ]*/
00246             result = OPTIONHANDLER_OK;
00247         }
00248         else
00249         {
00250             /*Codes_SRS_OPTIONHANDLER_02_013: [ If all the operations succeed then OptionHandler_FeedOptions shall succeed and return OPTIONHANDLER_OK. ]*/
00251             result = OPTIONHANDLER_ERROR;
00252         }
00253     }
00254     return result;
00255 }
00256 
00257 void OptionHandler_Destroy(OPTIONHANDLER_HANDLE handle)
00258 {   
00259     /*Codes_SRS_OPTIONHANDLER_02_015: [ OptionHandler_Destroy shall do nothing if parameter handle is NULL. ]*/
00260     if (handle == NULL)
00261     {
00262         LogError("invalid argument OPTIONHANDLER_HANDLE handle=%p", handle);
00263     }
00264     else
00265     {
00266         DestroyInternal(handle);
00267     }
00268 }