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 connection_string_parser.c Source File

connection_string_parser.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 "azure_c_shared_utility/connection_string_parser.h"
00005 #include "azure_c_shared_utility/map.h"
00006 #include "azure_c_shared_utility/strings.h"
00007 #include "azure_c_shared_utility/string_tokenizer.h"
00008 #include <stdbool.h>
00009 #include "azure_c_shared_utility/optimize_size.h"
00010 #include "azure_c_shared_utility/xlogging.h"
00011 
00012 
00013 MAP_HANDLE connectionstringparser_parse_from_char(const char* connection_string)
00014 {
00015     MAP_HANDLE result;
00016     STRING_HANDLE connString = NULL;
00017 
00018     /* Codes_SRS_CONNECTIONSTRINGPARSER_21_020: [connectionstringparser_parse_from_char shall create a STRING_HANDLE from the connection_string passed in as argument and parse it using the connectionstringparser_parse.]*/
00019     if ((connString = STRING_construct(connection_string)) == NULL)
00020     {
00021         /* Codes_SRS_CONNECTIONSTRINGPARSER_21_021: [If connectionstringparser_parse_from_char get error creating a STRING_HANDLE, it shall return NULL.]*/
00022         LogError("Error constructing connection String");
00023         result = NULL;
00024     }
00025     else
00026     {
00027         result = connectionstringparser_parse(connString);
00028         STRING_delete(connString);
00029     }
00030 
00031     return result;
00032 }
00033 
00034 /* Codes_SRS_CONNECTIONSTRINGPARSER_01_001: [connectionstringparser_parse shall parse all key value pairs from the connection_string passed in as argument and return a new map that holds the key/value pairs.] */
00035 MAP_HANDLE connectionstringparser_parse(STRING_HANDLE connection_string)
00036 {
00037     MAP_HANDLE result;
00038 
00039     if (connection_string == NULL)
00040     {
00041         /* Codes_SRS_CONNECTIONSTRINGPARSER_01_002: [If connection_string is NULL then connectionstringparser_parse shall fail and return NULL.] */
00042         result = NULL;
00043         LogError("NULL connection string passed to tokenizer.");
00044     }
00045     else
00046     {
00047         /* Codes_SRS_CONNECTIONSTRINGPARSER_01_003: [connectionstringparser_parse shall create a STRING tokenizer to be used for parsing the connection string, by calling STRING_TOKENIZER_create.] */
00048         /* Codes_SRS_CONNECTIONSTRINGPARSER_01_004: [connectionstringparser_parse shall start scanning at the beginning of the connection string.] */
00049         STRING_TOKENIZER_HANDLE tokenizer = STRING_TOKENIZER_create(connection_string);
00050         if (tokenizer == NULL)
00051         {
00052             /* Codes_SRS_CONNECTIONSTRINGPARSER_01_015: [If STRING_TOKENIZER_create fails, connectionstringparser_parse shall fail and return NULL.] */
00053             result = NULL;
00054             LogError("Error creating STRING tokenizer.");
00055         }
00056         else
00057         {
00058             /* Codes_SRS_CONNECTIONSTRINGPARSER_01_016: [2 STRINGs shall be allocated in order to hold the to be parsed key and value tokens.] */
00059             STRING_HANDLE token_key_string = STRING_new();
00060             if (token_key_string == NULL)
00061             {
00062                 /* Codes_SRS_CONNECTIONSTRINGPARSER_01_017: [If allocating the STRINGs fails connectionstringparser_parse shall fail and return NULL.] */
00063                 result = NULL;
00064                 LogError("Error creating key token STRING.");
00065             }
00066             else
00067             {
00068                 STRING_HANDLE token_value_string = STRING_new();
00069                 if (token_value_string == NULL)
00070                 {
00071                     /* Codes_SRS_CONNECTIONSTRINGPARSER_01_017: [If allocating the STRINGs fails connectionstringparser_parse shall fail and return NULL.] */
00072                     result = NULL;
00073                     LogError("Error creating value token STRING.");
00074                 }
00075                 else
00076                 {
00077                     result = Map_Create(NULL);
00078                     if (result == NULL)
00079                     {
00080                         /* Codes_SRS_CONNECTIONSTRINGPARSER_01_018: [If creating the result map fails, then connectionstringparser_parse shall return NULL.] */
00081                         LogError("Error creating Map.");
00082                     }
00083                     else
00084                     {
00085                         /* Codes_SRS_CONNECTIONSTRINGPARSER_01_005: [The following actions shall be repeated until parsing is complete:] */
00086                         /* Codes_SRS_CONNECTIONSTRINGPARSER_01_006: [connectionstringparser_parse shall find a token (the key of the key/value pair) delimited by the `=` character, by calling STRING_TOKENIZER_get_next_token.] */
00087                         /* Codes_SRS_CONNECTIONSTRINGPARSER_01_007: [If STRING_TOKENIZER_get_next_token fails, parsing shall be considered complete.] */
00088                         while (STRING_TOKENIZER_get_next_token(tokenizer, token_key_string, "=") == 0)
00089                         {
00090                             bool is_error = false;
00091 
00092                             /* Codes_SRS_CONNECTIONSTRINGPARSER_01_008: [connectionstringparser_parse shall find a token (the value of the key/value pair) delimited by the `;` character, by calling STRING_TOKENIZER_get_next_token.] */
00093                             if (STRING_TOKENIZER_get_next_token(tokenizer, token_value_string, ";") != 0)
00094                             {
00095                                 /* Codes_SRS_CONNECTIONSTRINGPARSER_01_009: [If STRING_TOKENIZER_get_next_token fails, connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
00096                                 is_error = true;
00097                                 LogError("Error reading value token from the connection string.");
00098                             }
00099                             else
00100                             {
00101                                 /* Codes_SRS_CONNECTIONSTRINGPARSER_01_011: [The C strings for the key and value shall be extracted from the previously parsed STRINGs by using STRING_c_str.] */
00102                                 const char* token = STRING_c_str(token_key_string);
00103                                 /* Codes_SRS_CONNECTIONSTRINGPARSER_01_013: [If STRING_c_str fails then connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
00104                                 if ((token == NULL) ||
00105                                     /* Codes_SRS_CONNECTIONSTRINGPARSER_01_019: [If the key length is zero then connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
00106                                     (strlen(token) == 0))
00107                                 {
00108                                     is_error = true;
00109                                     LogError("The key token is NULL or empty.");
00110                                 }
00111                                 else
00112                                 {
00113                                     /* Codes_SRS_CONNECTIONSTRINGPARSER_01_011: [The C strings for the key and value shall be extracted from the previously parsed STRINGs by using STRING_c_str.] */
00114                                     const char* value = STRING_c_str(token_value_string);
00115                                     if (value == NULL)
00116                                     {
00117                                         /* Codes_SRS_CONNECTIONSTRINGPARSER_01_013: [If STRING_c_str fails then connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
00118                                         is_error = true;
00119                                         LogError("Could not get C string for value token.");
00120                                     }
00121                                     else
00122                                     {
00123                                         /* Codes_SRS_CONNECTIONSTRINGPARSER_01_010: [The key and value shall be added to the result map by using Map_Add.] */
00124                                         if (Map_Add(result, token, value) != 0)
00125                                         {
00126                                             /* Codes_SRS_CONNECTIONSTRINGPARSER_01_012: [If Map_Add fails connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
00127                                             is_error = true;
00128                                             LogError("Could not add the key/value pair to the result map.");
00129                                         }
00130                                     }
00131                                 }
00132                             }
00133 
00134                             if (is_error)
00135                             {
00136                                 LogError("Error parsing connection string.");
00137                                 Map_Destroy(result);
00138                                 result = NULL;
00139                                 break;
00140                             }
00141                         }
00142                     }
00143 
00144                     STRING_delete(token_value_string);
00145                 }
00146 
00147                 STRING_delete(token_key_string);
00148             }
00149 
00150             /* Codes_SRS_CONNECTIONSTRINGPARSER_01_014: [After the parsing is complete the previously allocated STRINGs and STRING tokenizer shall be freed by calling STRING_TOKENIZER_destroy.] */
00151             STRING_TOKENIZER_destroy(tokenizer);
00152         }
00153     }
00154 
00155     return result;
00156 }
00157 
00158 /* Codes_SRS_CONNECTIONSTRINGPARSER_21_022: [connectionstringparser_splitHostName_from_char shall split the provided hostName in name and suffix.]*/
00159 int connectionstringparser_splitHostName_from_char(const char* hostName, STRING_HANDLE nameString, STRING_HANDLE suffixString)
00160 {
00161     int result;
00162     const char* runHostName = hostName;
00163 
00164     if ((hostName == NULL) || ((*hostName) == '\0') || ((*hostName) == '.') || (nameString == NULL) || (suffixString == NULL))
00165     {
00166         /* Codes_SRS_CONNECTIONSTRINGPARSER_21_026: [If the hostName is NULL, connectionstringparser_splitHostName_from_char shall return __FAILURE__.]*/
00167         /* Codes_SRS_CONNECTIONSTRINGPARSER_21_027: [If the hostName is an empty string, connectionstringparser_splitHostName_from_char shall return __FAILURE__.]*/
00168         /* Codes_SRS_CONNECTIONSTRINGPARSER_21_028: [If the nameString is NULL, connectionstringparser_splitHostName_from_char shall return __FAILURE__.]*/
00169         /* Codes_SRS_CONNECTIONSTRINGPARSER_21_029: [If the suffixString is NULL, connectionstringparser_splitHostName_from_char shall return __FAILURE__.]*/
00170         /* Codes_SRS_CONNECTIONSTRINGPARSER_21_030: [If the hostName is not a valid host name, connectionstringparser_splitHostName_from_char shall return __FAILURE__.]*/
00171         result = __FAILURE__;
00172     }
00173     else
00174     {
00175         while ((*runHostName) != '\0')
00176         {
00177             if ((*runHostName) == '.')
00178             {
00179                 /* Codes_SRS_CONNECTIONSTRINGPARSER_21_023: [connectionstringparser_splitHostName_from_char shall copy all characters, from the beginning of the hostName to the first `.` to the nameString.]*/
00180                 /* Codes_SRS_CONNECTIONSTRINGPARSER_21_024: [connectionstringparser_splitHostName_from_char shall copy all characters, from the first `.` to the end of the hostName, to the suffixString.]*/
00181                 runHostName++;
00182                 break;
00183             }
00184             runHostName++;
00185         }
00186      
00187         if ((*runHostName) == '\0')
00188         {
00189             /* Codes_SRS_CONNECTIONSTRINGPARSER_21_030: [If the hostName is not a valid host name, connectionstringparser_splitHostName_from_char shall return __FAILURE__.]*/
00190             result = __FAILURE__;
00191         }
00192         else
00193         {
00194             /* Codes_SRS_CONNECTIONSTRINGPARSER_21_023: [connectionstringparser_splitHostName_from_char shall copy all characters, from the beginning of the hostName to the first `.` to the nameString.]*/
00195             if (STRING_copy_n(nameString, hostName, runHostName - hostName - 1) != 0)
00196             {
00197                 /* Codes_SRS_CONNECTIONSTRINGPARSER_21_031: [If connectionstringparser_splitHostName_from_char get error copying the name to the nameString, it shall return __FAILURE__.]*/
00198                 result = __FAILURE__;
00199             }
00200             /* Codes_SRS_CONNECTIONSTRINGPARSER_21_024: [connectionstringparser_splitHostName_from_char shall copy all characters, from the first `.` to the end of the hostName, to the suffixString.]*/
00201             else if (STRING_copy(suffixString, runHostName) != 0)
00202             {
00203                 /* Codes_SRS_CONNECTIONSTRINGPARSER_21_032: [If connectionstringparser_splitHostName_from_char get error copying the suffix to the suffixString, it shall return __FAILURE__.]*/
00204                 result = __FAILURE__;
00205             }
00206             else
00207             {
00208                 /* Codes_SRS_CONNECTIONSTRINGPARSER_21_025: [If connectionstringparser_splitHostName_from_char get success splitting the hostName, it shall return 0.]*/
00209                 result = 0;
00210             }
00211         }
00212     }
00213 
00214     return result;
00215 }
00216 
00217 
00218 int connectionstringparser_splitHostName(STRING_HANDLE hostNameString, STRING_HANDLE nameString, STRING_HANDLE suffixString)
00219 {
00220     int result;
00221 
00222     if (hostNameString == NULL)
00223     {
00224         /* Codes_SRS_CONNECTIONSTRINGPARSER_21_034: [If the hostNameString is NULL, connectionstringparser_splitHostName shall return __FAILURE__.]*/
00225         result = __FAILURE__;
00226     }
00227     else
00228     {
00229         /* Codes_SRS_CONNECTIONSTRINGPARSER_21_033: [connectionstringparser_splitHostName shall convert the hostNameString to a connection_string passed in as argument, and call connectionstringparser_splitHostName_from_char.]*/
00230         result = connectionstringparser_splitHostName_from_char(STRING_c_str(hostNameString), nameString, suffixString);
00231     }
00232 
00233     return result;
00234 }