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
string_tokenizer.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/gballoc.h" 00006 #include <stdbool.h> 00007 #include "azure_c_shared_utility/string_tokenizer.h" 00008 #include "azure_c_shared_utility/optimize_size.h" 00009 #include "azure_c_shared_utility/xlogging.h" 00010 #include "azure_c_shared_utility/crt_abstractions.h" 00011 00012 typedef struct STRING_TOKEN_TAG 00013 { 00014 const char* inputString; 00015 const char* currentPos; 00016 size_t sizeOfinputString; 00017 } STRING_TOKEN; 00018 00019 STRING_TOKENIZER_HANDLE STRING_TOKENIZER_create(STRING_HANDLE handle) 00020 { 00021 STRING_TOKENIZER_HANDLE result; 00022 00023 /* Codes_SRS_STRING_04_001: [STRING_TOKENIZER_create shall return an NULL STRING_TOKENIZER_HANDLE if parameter handle is NULL] */ 00024 if (handle == NULL) 00025 { 00026 LogError("Invalid Argument. Handle cannot be NULL."); 00027 result = NULL; 00028 } 00029 else 00030 { 00031 /* Codes_SRS_STRING_04_002: [STRING_TOKENIZER_create shall allocate a new STRING_TOKENIZER_HANDLE having the content of the STRING_HANDLE copied and current position pointing at the beginning of the string] */ 00032 result = STRING_TOKENIZER_create_from_char(STRING_c_str(handle)); 00033 } 00034 00035 return result; 00036 } 00037 00038 extern STRING_TOKENIZER_HANDLE STRING_TOKENIZER_create_from_char(const char* input) 00039 { 00040 STRING_TOKEN *result; 00041 char* inputStringToMalloc; 00042 00043 /* Codes_SRS_STRING_07_001: [STRING_TOKENIZER_create shall return an NULL STRING_TOKENIZER_HANDLE if parameter input is NULL] */ 00044 if (input == NULL) 00045 { 00046 LogError("Invalid Argument. Handle cannot be NULL."); 00047 result = NULL; 00048 } 00049 /* Codes_SRS_STRING_07_002: [STRING_TOKENIZER_create shall allocate a new STRING_TOKENIZER_HANDLE having the content of the STRING_HANDLE copied and current position pointing at the beginning of the string] */ 00050 else if ((result = (STRING_TOKEN*)malloc(sizeof(STRING_TOKEN))) == NULL) 00051 { 00052 LogError("Memory Allocation failed. Cannot allocate STRING_TOKENIZER."); 00053 } 00054 else if ((mallocAndStrcpy_s(&inputStringToMalloc, input)) != 0) 00055 { 00056 LogError("Memory Allocation Failed. Cannot allocate and copy string Content."); 00057 free(result); 00058 result = NULL; 00059 } 00060 else 00061 { 00062 result->inputString = inputStringToMalloc; 00063 result->currentPos = result->inputString; //Current Pos will point to the initial position of Token. 00064 result->sizeOfinputString = strlen(result->inputString); //Calculate Size of Current String 00065 } 00066 return (STRING_TOKENIZER_HANDLE)result; 00067 } 00068 00069 int STRING_TOKENIZER_get_next_token(STRING_TOKENIZER_HANDLE tokenizer, STRING_HANDLE output, const char* delimiters) 00070 { 00071 int result; 00072 /* Codes_SRS_STRING_04_004: [STRING_TOKENIZER_get_next_token shall return a nonzero value if any of the 3 parameters is NULL] */ 00073 if (tokenizer == NULL || output == NULL || delimiters == NULL) 00074 { 00075 result = __FAILURE__; 00076 } 00077 else 00078 { 00079 STRING_TOKEN* token = (STRING_TOKEN*)tokenizer; 00080 /* Codes_SRS_STRING_04_011: [Each subsequent call to STRING_TOKENIZER_get_next_token starts searching from the saved position on t and behaves as described above.] */ 00081 size_t remainingInputStringSize = token->sizeOfinputString - (token->currentPos - token->inputString); 00082 size_t delimitterSize = strlen(delimiters); 00083 00084 /* First Check if we reached the end of the string*/ 00085 /* Codes_SRS_STRING_TOKENIZER_04_014: [STRING_TOKENIZER_get_next_token shall return nonzero value if t contains an empty string.] */ 00086 if (remainingInputStringSize == 0) 00087 { 00088 result = __FAILURE__; 00089 } 00090 else if (delimitterSize == 0) 00091 { 00092 LogError("Empty delimiters parameter."); 00093 result = __FAILURE__; 00094 } 00095 else 00096 { 00097 size_t i; 00098 /* Codes_SRS_STRING_04_005: [STRING_TOKENIZER_get_next_token searches the string inside STRING_TOKENIZER_HANDLE for the first character that is NOT contained in the current delimiter] */ 00099 for (i = 0; i < remainingInputStringSize; i++) 00100 { 00101 size_t j; 00102 00103 bool foundDelimitter = false; 00104 for (j = 0; j < delimitterSize; j++) 00105 { 00106 if (token->currentPos[i] == delimiters[j]) 00107 { 00108 foundDelimitter = true; 00109 break; 00110 } 00111 } 00112 00113 /* Codes_SRS_STRING_04_007: [If such a character is found, STRING_TOKENIZER_get_next_token consider it as the start of a token.] */ 00114 if (!foundDelimitter) 00115 { 00116 break; 00117 } 00118 } 00119 00120 /* Codes_SRS_STRING_04_006: [If no such character is found, then STRING_TOKENIZER_get_next_token shall return a nonzero Value (You've reach the end of the string or the string consists with only delimiters).] */ 00121 //At this point update Current Pos to the character of the last token found or end of String. 00122 token->currentPos += i; 00123 00124 //Update the remainingInputStringSize 00125 remainingInputStringSize -= i; 00126 00127 /* Codes_SRS_STRING_04_006: [If no such character is found, then STRING_TOKENIZER_get_next_token shall return a nonzero Value (You've reach the end of the string or the string consists with only delimiters).] */ 00128 if (remainingInputStringSize == 0) 00129 { 00130 result = __FAILURE__; 00131 } 00132 else 00133 { 00134 bool foundDelimitter = false; 00135 const char* endOfTokenPosition=NULL; 00136 size_t amountOfCharactersToCopy; 00137 size_t j; 00138 //At this point the Current Pos is pointing to a character that is point to a nonDelimiter. So, now search for a Delimiter, till the end of the String. 00139 /*Codes_SRS_STRING_04_008: [STRING_TOKENIZER_get_next_token than searches from the start of a token for a character that is contained in the delimiters string.] */ 00140 /* Codes_SRS_STRING_04_009: [If no such character is found, STRING_TOKENIZER_get_next_token extends the current token to the end of the string inside t, copies the token to output and returns 0.] */ 00141 /* Codes_SRS_STRING_04_010: [If such a character is found, STRING_TOKENIZER_get_next_token consider it the end of the token and copy it's content to output, updates the current position inside t to the next character and returns 0.] */ 00142 for (j = 0; j < delimitterSize; j++) 00143 { 00144 if ((endOfTokenPosition = strchr(token->currentPos, delimiters[j])) != NULL) 00145 { 00146 foundDelimitter = true; 00147 break; 00148 } 00149 } 00150 00151 //If token not found, than update the EndOfToken to the end of the inputString; 00152 if (endOfTokenPosition == NULL) 00153 { 00154 amountOfCharactersToCopy = remainingInputStringSize; 00155 } 00156 else 00157 { 00158 amountOfCharactersToCopy = endOfTokenPosition - token->currentPos; 00159 } 00160 00161 //copy here the string to output. 00162 if (STRING_copy_n(output, token->currentPos, amountOfCharactersToCopy) != 0) 00163 { 00164 LogError("Problem copying token to output String."); 00165 result = __FAILURE__; 00166 } 00167 else 00168 { 00169 //Update the Current position. 00170 //Check if end of String reached so, currentPos points to the end of String. 00171 if (foundDelimitter) 00172 { 00173 token->currentPos += amountOfCharactersToCopy + 1; 00174 } 00175 else 00176 { 00177 token->currentPos += amountOfCharactersToCopy; 00178 } 00179 00180 result = 0; //Result will be on the output. 00181 } 00182 } 00183 } 00184 } 00185 00186 return result; 00187 } 00188 00189 00190 /* Codes_SRS_STRING_TOKENIZER_04_012: [STRING_TOKENIZER_destroy shall free the memory allocated by the STRING_TOKENIZER_create ] */ 00191 void STRING_TOKENIZER_destroy(STRING_TOKENIZER_HANDLE t) 00192 { 00193 /* Codes_SRS_STRING_TOKENIZER_04_013: [When the t argument is NULL, then STRING_TOKENIZER_destroy shall not attempt to free] */ 00194 if (t != NULL) 00195 { 00196 STRING_TOKEN* value = (STRING_TOKEN*)t; 00197 free((char*)value->inputString); 00198 value->inputString = NULL; 00199 free(value); 00200 } 00201 } 00202
Generated on Tue Jul 12 2022 19:14:38 by
