Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of azure_c_shared_utility by
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 }
Generated on Tue Jul 12 2022 19:14:38 by
