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.
Dependencies: azure_umqtt_c iothub_mqtt_transport mbed-rtos mbed wolfSSL Socket lwip-eth lwip-sys lwip
strings.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 // 00005 // PUT NO INCLUDES BEFORE HERE 00006 // 00007 #include <stdlib.h> 00008 #ifdef _CRTDBG_MAP_ALLOC 00009 #include <crtdbg.h> 00010 #endif 00011 #include "azure_c_shared_utility/gballoc.h" 00012 00013 #include <stddef.h> 00014 #include <string.h> 00015 #include <stdarg.h> 00016 #include <stdio.h> 00017 00018 // 00019 // PUT NO CLIENT LIBRARY INCLUDES BEFORE HERE 00020 // 00021 00022 #include "azure_c_shared_utility/strings.h" 00023 #include "azure_c_shared_utility/xlogging.h" 00024 00025 static const char hexToASCII[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 00026 00027 typedef struct STRING_TAG 00028 { 00029 char* s; 00030 }STRING; 00031 00032 /*this function will allocate a new string with just '\0' in it*/ 00033 /*return NULL if it fails*/ 00034 /* Codes_SRS_STRING_07_001: [STRING_new shall allocate a new STRING_HANDLE pointing to an empty string.] */ 00035 STRING_HANDLE STRING_new(void) 00036 { 00037 STRING* result; 00038 if ((result = (STRING*)malloc(sizeof(STRING))) != NULL) 00039 { 00040 if ((result->s = (char*)malloc(1)) != NULL) 00041 { 00042 result->s[0] = '\0'; 00043 } 00044 else 00045 { 00046 /* Codes_SRS_STRING_07_002: [STRING_new shall return an NULL STRING_HANDLE on any error that is encountered.] */ 00047 free(result); 00048 result = NULL; 00049 } 00050 } 00051 return (STRING_HANDLE)result; 00052 } 00053 00054 /*Codes_SRS_STRING_02_001: [STRING_clone shall produce a new string having the same content as the handle string.*/ 00055 STRING_HANDLE STRING_clone(STRING_HANDLE handle) 00056 { 00057 STRING* result; 00058 /*Codes_SRS_STRING_02_002: [If parameter handle is NULL then STRING_clone shall return NULL.]*/ 00059 if (handle == NULL) 00060 { 00061 result = NULL; 00062 } 00063 else 00064 { 00065 /*Codes_SRS_STRING_02_003: [If STRING_clone fails for any reason, it shall return NULL.] */ 00066 if ((result = (STRING*)malloc(sizeof(STRING))) != NULL) 00067 { 00068 STRING* source = (STRING*)handle; 00069 /*Codes_SRS_STRING_02_003: [If STRING_clone fails for any reason, it shall return NULL.] */ 00070 size_t sourceLen = strlen(source->s); 00071 if ((result->s = (char*)malloc(sourceLen + 1)) == NULL) 00072 { 00073 free(result); 00074 result = NULL; 00075 } 00076 else 00077 { 00078 memcpy(result->s, source->s, sourceLen + 1); 00079 } 00080 } 00081 else 00082 { 00083 /*not much to do, result is NULL from malloc*/ 00084 } 00085 } 00086 return (STRING_HANDLE)result; 00087 } 00088 00089 /* Codes_SRS_STRING_07_003: [STRING_construct shall allocate a new string with the value of the specified const char*.] */ 00090 STRING_HANDLE STRING_construct(const char* psz) 00091 { 00092 STRING_HANDLE result; 00093 if (psz == NULL) 00094 { 00095 /* Codes_SRS_STRING_07_005: [If the supplied const char* is NULL STRING_construct shall return a NULL value.] */ 00096 result = NULL; 00097 } 00098 else 00099 { 00100 STRING* str; 00101 if ((str = (STRING*)malloc(sizeof(STRING))) != NULL) 00102 { 00103 size_t nLen = strlen(psz) + 1; 00104 if ((str->s = (char*)malloc(nLen)) != NULL) 00105 { 00106 memcpy(str->s, psz, nLen); 00107 result = (STRING_HANDLE)str; 00108 } 00109 /* Codes_SRS_STRING_07_032: [STRING_construct encounters any error it shall return a NULL value.] */ 00110 else 00111 { 00112 free(str); 00113 result = NULL; 00114 } 00115 } 00116 else 00117 { 00118 /* Codes_SRS_STRING_07_032: [STRING_construct encounters any error it shall return a NULL value.] */ 00119 result = NULL; 00120 } 00121 } 00122 return result; 00123 } 00124 00125 STRING_HANDLE STRING_construct_sprintf(const char* format, ...) 00126 { 00127 STRING* result; 00128 if (format != NULL) 00129 { 00130 va_list arg_list; 00131 int length; 00132 va_start(arg_list, format); 00133 00134 /* Codes_SRS_STRING_07_041: [STRING_construct_sprintf shall determine the size of the resulting string and allocate the necessary memory.] */ 00135 length = vsnprintf(NULL, 0, format, arg_list); 00136 va_end(arg_list); 00137 if (length > 0) 00138 { 00139 result = (STRING*)malloc(sizeof(STRING)); 00140 if (result != NULL) 00141 { 00142 result->s = (char*)malloc(length+1); 00143 if (result->s != NULL) 00144 { 00145 va_start(arg_list, format); 00146 if (vsnprintf(result->s, length+1, format, arg_list) < 0) 00147 { 00148 /* Codes_SRS_STRING_07_040: [If any error is encountered STRING_construct_sprintf shall return NULL.] */ 00149 free(result->s); 00150 free(result); 00151 result = NULL; 00152 LogError("Failure: vsnprintf formatting failed."); 00153 } 00154 va_end(arg_list); 00155 } 00156 else 00157 { 00158 /* Codes_SRS_STRING_07_040: [If any error is encountered STRING_construct_sprintf shall return NULL.] */ 00159 free(result); 00160 result = NULL; 00161 LogError("Failure: allocation failed."); 00162 } 00163 } 00164 else 00165 { 00166 LogError("Failure: allocation failed."); 00167 } 00168 } 00169 else if (length == 0) 00170 { 00171 result = (STRING*)STRING_new(); 00172 } 00173 else 00174 { 00175 /* Codes_SRS_STRING_07_039: [If the parameter format is NULL then STRING_construct_sprintf shall return NULL.] */ 00176 result = NULL; 00177 LogError("Failure: vsnprintf return 0 length"); 00178 } 00179 } 00180 else 00181 { 00182 LogError("Failure: invalid argument."); 00183 result = NULL; 00184 } 00185 /* Codes_SRS_STRING_07_045: [STRING_construct_sprintf shall allocate a new string with the value of the specified printf formated const char. ] */ 00186 return (STRING_HANDLE)result; 00187 } 00188 00189 /*this function will return a new STRING with the memory for the actual string passed in as a parameter.*/ 00190 /*return NULL if it fails.*/ 00191 /* The supplied memory must have been allocated with malloc! */ 00192 /* Codes_SRS_STRING_07_006: [STRING_new_with_memory shall return a STRING_HANDLE by using the supplied char* memory.] */ 00193 STRING_HANDLE STRING_new_with_memory(const char* memory) 00194 { 00195 STRING* result; 00196 if (memory == NULL) 00197 { 00198 /* Codes_SRS_STRING_07_007: [STRING_new_with_memory shall return a NULL STRING_HANDLE if the supplied char* is NULL.] */ 00199 result = NULL; 00200 } 00201 else 00202 { 00203 if ((result = (STRING*)malloc(sizeof(STRING))) != NULL) 00204 { 00205 result->s = (char*)memory; 00206 } 00207 } 00208 return (STRING_HANDLE)result; 00209 } 00210 00211 /* Codes_SRS_STRING_07_008: [STRING_new_quoted shall return a valid STRING_HANDLE Copying the supplied const char* value surrounded by quotes.] */ 00212 STRING_HANDLE STRING_new_quoted(const char* source) 00213 { 00214 STRING* result; 00215 if (source == NULL) 00216 { 00217 /* Codes_SRS_STRING_07_009: [STRING_new_quoted shall return a NULL STRING_HANDLE if the supplied const char* is NULL.] */ 00218 result = NULL; 00219 } 00220 else if ((result = (STRING*)malloc(sizeof(STRING))) != NULL) 00221 { 00222 size_t sourceLength = strlen(source); 00223 if ((result->s = (char*)malloc(sourceLength + 3)) != NULL) 00224 { 00225 result->s[0] = '"'; 00226 memcpy(result->s + 1, source, sourceLength); 00227 result->s[sourceLength + 1] = '"'; 00228 result->s[sourceLength + 2] = '\0'; 00229 } 00230 else 00231 { 00232 /* Codes_SRS_STRING_07_031: [STRING_new_quoted shall return a NULL STRING_HANDLE if any error is encountered.] */ 00233 free(result); 00234 result = NULL; 00235 } 00236 } 00237 return (STRING_HANDLE)result; 00238 } 00239 00240 /*this function takes a regular const char* and turns in into "this is a\"JSON\" strings\u0008" (starting and ending quote included)*/ 00241 /*the newly created handle needs to be disposed of with STRING_delete*/ 00242 /*returns NULL if there are errors*/ 00243 STRING_HANDLE STRING_new_JSON(const char* source) 00244 { 00245 STRING* result; 00246 if (source == NULL) 00247 { 00248 /*Codes_SRS_STRING_02_011: [If source is NULL then STRING_new_JSON shall return NULL.] */ 00249 result = NULL; 00250 LogError("invalid arg (NULL)"); 00251 } 00252 else 00253 { 00254 size_t i; 00255 size_t nControlCharacters = 0; /*counts how many characters are to be expanded from 1 character to \uxxxx (6 characters)*/ 00256 size_t nEscapeCharacters = 0; 00257 size_t vlen = strlen(source); 00258 00259 for (i = 0; i < vlen; i++) 00260 { 00261 /*Codes_SRS_STRING_02_014: [If any character has the value outside [1...127] then STRING_new_JSON shall fail and return NULL.] */ 00262 if ((unsigned char)source[i] >= 128) /*this be a UNICODE character begin*/ 00263 { 00264 break; 00265 } 00266 else 00267 { 00268 if (source[i] <= 0x1F) 00269 { 00270 nControlCharacters++; 00271 } 00272 else if ( 00273 (source[i] == '"') || 00274 (source[i] == '\\') || 00275 (source[i] == '/') 00276 ) 00277 { 00278 nEscapeCharacters++; 00279 } 00280 } 00281 } 00282 00283 if (i < vlen) 00284 { 00285 result = NULL; 00286 LogError("invalid character in input string"); 00287 } 00288 else 00289 { 00290 if ((result = (STRING*)malloc(sizeof(STRING))) == NULL) 00291 { 00292 /*Codes_SRS_STRING_02_021: [If the complete JSON representation cannot be produced, then STRING_new_JSON shall fail and return NULL.] */ 00293 LogError("malloc failure"); 00294 } 00295 else if ((result->s = (char*)malloc(vlen + 5 * nControlCharacters + nEscapeCharacters + 3)) == NULL) 00296 { 00297 /*Codes_SRS_STRING_02_021: [If the complete JSON representation cannot be produced, then STRING_new_JSON shall fail and return NULL.] */ 00298 free(result); 00299 result = NULL; 00300 LogError("malloc failed"); 00301 } 00302 else 00303 { 00304 size_t pos = 0; 00305 /*Codes_SRS_STRING_02_012: [The string shall begin with the quote character.] */ 00306 result->s[pos++] = '"'; 00307 for (i = 0; i < vlen; i++) 00308 { 00309 if (source[i] <= 0x1F) 00310 { 00311 /*Codes_SRS_STRING_02_019: [If the character code is less than 0x20 then it shall be represented as \u00xx, where xx is the hex representation of the character code.]*/ 00312 result->s[pos++] = '\\'; 00313 result->s[pos++] = 'u'; 00314 result->s[pos++] = '0'; 00315 result->s[pos++] = '0'; 00316 result->s[pos++] = hexToASCII[(source[i] & 0xF0) >> 4]; /*high nibble*/ 00317 result->s[pos++] = hexToASCII[source[i] & 0x0F]; /*low nibble*/ 00318 } 00319 else if (source[i] == '"') 00320 { 00321 /*Codes_SRS_STRING_02_016: [If the character is " (quote) then it shall be repsented as \".] */ 00322 result->s[pos++] = '\\'; 00323 result->s[pos++] = '"'; 00324 } 00325 else if (source[i] == '\\') 00326 { 00327 /*Codes_SRS_STRING_02_017: [If the character is \ (backslash) then it shall represented as \\.] */ 00328 result->s[pos++] = '\\'; 00329 result->s[pos++] = '\\'; 00330 } 00331 else if (source[i] == '/') 00332 { 00333 /*Codes_SRS_STRING_02_018: [If the character is / (slash) then it shall be represented as \/.] */ 00334 result->s[pos++] = '\\'; 00335 result->s[pos++] = '/'; 00336 } 00337 else 00338 { 00339 /*Codes_SRS_STRING_02_013: [The string shall copy the characters of source "as they are" (until the '\0' character) with the following exceptions:] */ 00340 result->s[pos++] = source[i]; 00341 } 00342 } 00343 /*Codes_SRS_STRING_02_020: [The string shall end with " (quote).] */ 00344 result->s[pos++] = '"'; 00345 /*zero terminating it*/ 00346 result->s[pos] = '\0'; 00347 } 00348 } 00349 00350 } 00351 return (STRING_HANDLE)result; 00352 } 00353 00354 /*this function will concatenate to the string s1 the string s2, resulting in s1+s2*/ 00355 /*returns 0 if success*/ 00356 /*any other error code is failure*/ 00357 /* Codes_SRS_STRING_07_012: [STRING_concat shall concatenate the given STRING_HANDLE and the const char* value and place the value in the handle.] */ 00358 int STRING_concat(STRING_HANDLE handle, const char* s2) 00359 { 00360 int result; 00361 if ((handle == NULL) || (s2 == NULL)) 00362 { 00363 /* Codes_SRS_STRING_07_013: [STRING_concat shall return a nonzero number if an error is encountered.] */ 00364 result = __LINE__; 00365 } 00366 else 00367 { 00368 STRING* s1 = (STRING*)handle; 00369 size_t s1Length = strlen(s1->s); 00370 size_t s2Length = strlen(s2); 00371 char* temp = (char*)realloc(s1->s, s1Length + s2Length + 1); 00372 if (temp == NULL) 00373 { 00374 /* Codes_SRS_STRING_07_013: [STRING_concat shall return a nonzero number if an error is encountered.] */ 00375 result = __LINE__; 00376 } 00377 else 00378 { 00379 s1->s = temp; 00380 memcpy(s1->s + s1Length, s2, s2Length + 1); 00381 result = 0; 00382 } 00383 } 00384 return result; 00385 } 00386 00387 /*this function will concatenate to the string s1 the string s2, resulting in s1+s2*/ 00388 /*returns 0 if success*/ 00389 /*any other error code is failure*/ 00390 /* Codes_SRS_STRING_07_034: [String_Concat_with_STRING shall concatenate a given STRING_HANDLE variable with a source STRING_HANDLE.] */ 00391 int STRING_concat_with_STRING(STRING_HANDLE s1, STRING_HANDLE s2) 00392 { 00393 int result; 00394 if ((s1 == NULL) || (s2 == NULL)) 00395 { 00396 /* Codes_SRS_STRING_07_035: [String_Concat_with_STRING shall return a nonzero number if an error is encountered.] */ 00397 result = __LINE__; 00398 } 00399 else 00400 { 00401 STRING* dest = (STRING*)s1; 00402 STRING* src = (STRING*)s2; 00403 00404 size_t s1Length = strlen(dest->s); 00405 size_t s2Length = strlen(src->s); 00406 char* temp = (char*)realloc(dest->s, s1Length + s2Length + 1); 00407 if (temp == NULL) 00408 { 00409 /* Codes_SRS_STRING_07_035: [String_Concat_with_STRING shall return a nonzero number if an error is encountered.] */ 00410 result = __LINE__; 00411 } 00412 else 00413 { 00414 dest->s = temp; 00415 /* Codes_SRS_STRING_07_034: [String_Concat_with_STRING shall concatenate a given STRING_HANDLE variable with a source STRING_HANDLE.] */ 00416 memcpy(dest->s + s1Length, src->s, s2Length + 1); 00417 result = 0; 00418 } 00419 } 00420 return result; 00421 } 00422 00423 /*this function will copy the string from s2 to s1*/ 00424 /*returns 0 if success*/ 00425 /*any other error code is failure*/ 00426 /* Codes_SRS_STRING_07_016: [STRING_copy shall copy the const char* into the supplied STRING_HANDLE.] */ 00427 int STRING_copy(STRING_HANDLE handle, const char* s2) 00428 { 00429 int result; 00430 if ((handle == NULL) || (s2 == NULL)) 00431 { 00432 /* Codes_SRS_STRING_07_017: [STRING_copy shall return a nonzero value if any of the supplied parameters are NULL.] */ 00433 result = __LINE__; 00434 } 00435 else 00436 { 00437 STRING* s1 = (STRING*)handle; 00438 /* Codes_SRS_STRING_07_026: [If the underlying char* refered to by s1 handle is equal to char* s2 than STRING_copy shall be a noop and return 0.] */ 00439 if (s1->s != s2) 00440 { 00441 size_t s2Length = strlen(s2); 00442 char* temp = (char*)realloc(s1->s, s2Length + 1); 00443 if (temp == NULL) 00444 { 00445 /* Codes_SRS_STRING_07_027: [STRING_copy shall return a nonzero value if any error is encountered.] */ 00446 result = __LINE__; 00447 } 00448 else 00449 { 00450 s1->s = temp; 00451 memmove(s1->s, s2, s2Length + 1); 00452 result = 0; 00453 } 00454 } 00455 else 00456 { 00457 /* Codes_SRS_STRING_07_033: [If overlapping pointer address is given to STRING_copy the behavior is undefined.] */ 00458 result = 0; 00459 } 00460 } 00461 return result; 00462 } 00463 00464 /*this function will copy n chars from s2 to the string s1, resulting in n chars only from s2 being stored in s1.*/ 00465 /*returns 0 if success*/ 00466 /*any other error code is failure*/ 00467 /* Codes_SRS_STRING_07_018: [STRING_copy_n shall copy the number of characters in const char* or the size_t whichever is lesser.] */ 00468 int STRING_copy_n(STRING_HANDLE handle, const char* s2, size_t n) 00469 { 00470 int result; 00471 if ((handle == NULL) || (s2 == NULL)) 00472 { 00473 /* Codes_SRS_STRING_07_019: [STRING_copy_n shall return a nonzero value if STRING_HANDLE or const char* is NULL.] */ 00474 result = __LINE__; 00475 } 00476 else 00477 { 00478 STRING* s1 = (STRING*)handle; 00479 size_t s2Length = strlen(s2); 00480 char* temp; 00481 if (s2Length > n) 00482 { 00483 s2Length = n; 00484 } 00485 00486 temp = (char*)realloc(s1->s, s2Length + 1); 00487 if (temp == NULL) 00488 { 00489 /* Codes_SRS_STRING_07_028: [STRING_copy_n shall return a nonzero value if any error is encountered.] */ 00490 result = __LINE__; 00491 } 00492 else 00493 { 00494 s1->s = temp; 00495 memcpy(s1->s, s2, s2Length); 00496 s1->s[s2Length] = 0; 00497 result = 0; 00498 } 00499 00500 } 00501 return result; 00502 } 00503 00504 int STRING_sprintf(STRING_HANDLE handle, const char* format, ...) 00505 { 00506 int result; 00507 if (handle == NULL || format == NULL) 00508 { 00509 /* Codes_SRS_STRING_07_042: [if the parameters s1 or format are NULL then STRING_sprintf shall return non zero value.] */ 00510 result = __LINE__; 00511 LogError("Invalid arg (NULL)"); 00512 } 00513 else 00514 { 00515 va_list arg_list; 00516 int s2Length; 00517 va_start(arg_list, format); 00518 00519 s2Length = vsnprintf(NULL, 0, format, arg_list); 00520 va_end(arg_list); 00521 if (s2Length < 0) 00522 { 00523 /* Codes_SRS_STRING_07_043: [If any error is encountered STRING_sprintf shall return a non zero value.] */ 00524 result = __LINE__; 00525 LogError("Failure vsnprintf return < 0"); 00526 } 00527 else if (s2Length == 0) 00528 { 00529 // Don't need to reallocate and nothing should be added 00530 result = 0; 00531 } 00532 else 00533 { 00534 STRING* s1 = (STRING*)handle; 00535 char* temp; 00536 size_t s1Length = strlen(s1->s); 00537 temp = (char*)realloc(s1->s, s1Length + s2Length + 1); 00538 if (temp != NULL) 00539 { 00540 s1->s = temp; 00541 va_start(arg_list, format); 00542 if (vsnprintf(s1->s + s1Length, s1Length + s2Length + 1, format, arg_list) < 0) 00543 { 00544 /* Codes_SRS_STRING_07_043: [If any error is encountered STRING_sprintf shall return a non zero value.] */ 00545 LogError("Failure vsnprintf formatting error"); 00546 s1->s[s1Length] = '\0'; 00547 result = __LINE__; 00548 } 00549 else 00550 { 00551 /* Codes_SRS_STRING_07_044: [On success STRING_sprintf shall return 0.]*/ 00552 result = 0; 00553 } 00554 va_end(arg_list); 00555 } 00556 else 00557 { 00558 /* Codes_SRS_STRING_07_043: [If any error is encountered STRING_sprintf shall return a non zero value.] */ 00559 LogError("Failure unable to reallocate memory"); 00560 result = __LINE__; 00561 } 00562 } 00563 } 00564 return result; 00565 } 00566 00567 /*this function will quote the string passed as argument string =>"string"*/ 00568 /*returns 0 if success*/ /*doesn't change the string otherwise*/ 00569 /*any other error code is failure*/ 00570 /* Codes_SRS_STRING_07_014: [STRING_quote shall "quote" the supplied STRING_HANDLE and return 0 on success.] */ 00571 int STRING_quote(STRING_HANDLE handle) 00572 { 00573 int result; 00574 if (handle == NULL) 00575 { 00576 /* Codes_SRS_STRING_07_015: [STRING_quote shall return a nonzero value if any of the supplied parameters are NULL.] */ 00577 result = __LINE__; 00578 } 00579 else 00580 { 00581 STRING* s1 = (STRING*)handle; 00582 size_t s1Length = strlen(s1->s); 00583 char* temp = (char*)realloc(s1->s, s1Length + 2 + 1);/*2 because 2 quotes, 1 because '\0'*/ 00584 if (temp == NULL) 00585 { 00586 /* Codes_SRS_STRING_07_029: [STRING_quote shall return a nonzero value if any error is encountered.] */ 00587 result = __LINE__; 00588 } 00589 else 00590 { 00591 s1->s = temp; 00592 memmove(s1->s + 1, s1->s, s1Length); 00593 s1->s[0] = '"'; 00594 s1->s[s1Length + 1] = '"'; 00595 s1->s[s1Length + 2] = '\0'; 00596 result = 0; 00597 } 00598 } 00599 return result; 00600 } 00601 /*this function will revert a string to an empty state*/ 00602 /*Returns 0 if the revert was succesful*/ 00603 /* Codes_SRS_STRING_07_022: [STRING_empty shall revert the STRING_HANDLE to an empty state.] */ 00604 int STRING_empty(STRING_HANDLE handle) 00605 { 00606 int result; 00607 if (handle == NULL) 00608 { 00609 /* Codes_SRS_STRING_07_023: [STRING_empty shall return a nonzero value if the STRING_HANDLE is NULL.] */ 00610 result = __LINE__; 00611 } 00612 else 00613 { 00614 STRING* s1 = (STRING*)handle; 00615 char* temp = (char*)realloc(s1->s, 1); 00616 if (temp == NULL) 00617 { 00618 /* Codes_SRS_STRING_07_030: [STRING_empty shall return a nonzero value if the STRING_HANDLE is NULL.] */ 00619 result = __LINE__; 00620 } 00621 else 00622 { 00623 s1->s = temp; 00624 s1->s[0] = '\0'; 00625 result = 0; 00626 } 00627 } 00628 return result; 00629 } 00630 00631 /*this function will deallocate a string constructed by str_new*/ 00632 /* Codes_SRS_STRING_07_010: [STRING_delete will free the memory allocated by the STRING_HANDLE.] */ 00633 void STRING_delete(STRING_HANDLE handle) 00634 { 00635 /* Codes_SRS_STRING_07_011: [STRING_delete will not attempt to free anything with a NULL STRING_HANDLE.] */ 00636 if (handle != NULL) 00637 { 00638 STRING* value = (STRING*)handle; 00639 free(value->s); 00640 value->s = NULL; 00641 free(value); 00642 } 00643 } 00644 00645 /* Codes_SRS_STRING_07_020: [STRING_c_str shall return the const char* associated with the given STRING_HANDLE.] */ 00646 const char* STRING_c_str(STRING_HANDLE handle) 00647 { 00648 const char* result; 00649 if (handle != NULL) 00650 { 00651 result = ((STRING*)handle)->s; 00652 } 00653 else 00654 { 00655 /* Codes_SRS_STRING_07_021: [STRING_c_str shall return NULL if the STRING_HANDLE is NULL.] */ 00656 result = NULL; 00657 } 00658 return result; 00659 } 00660 00661 /* Codes_SRS_STRING_07_024: [STRING_length shall return the length of the underlying char* for the given handle] */ 00662 size_t STRING_length(STRING_HANDLE handle) 00663 { 00664 size_t result = 0; 00665 /* Codes_SRS_STRING_07_025: [STRING_length shall return zero if the given handle is NULL.] */ 00666 if (handle != NULL) 00667 { 00668 STRING* value = (STRING*)handle; 00669 result = strlen(value->s); 00670 } 00671 return result; 00672 } 00673 00674 /*Codes_SRS_STRING_02_007: [STRING_construct_n shall construct a STRING_HANDLE from first "n" characters of the string pointed to by psz parameter.]*/ 00675 STRING_HANDLE STRING_construct_n(const char* psz, size_t n) 00676 { 00677 STRING_HANDLE result; 00678 /*Codes_SRS_STRING_02_008: [If psz is NULL then STRING_construct_n shall return NULL.] */ 00679 if (psz == NULL) 00680 { 00681 result = NULL; 00682 LogError("invalid arg (NULL)"); 00683 } 00684 else 00685 { 00686 size_t len = strlen(psz); 00687 /*Codes_SRS_STRING_02_009: [If n is bigger than the size of the string psz, then STRING_construct_n shall return NULL.] */ 00688 if (n > len) 00689 { 00690 result = NULL; 00691 LogError("invalig arg (n is bigger than the size of the string)"); 00692 } 00693 else 00694 { 00695 STRING* str; 00696 if ((str = (STRING*)malloc(sizeof(STRING))) != NULL) 00697 { 00698 if ((str->s = (char*)malloc(len + 1)) != NULL) 00699 { 00700 memcpy(str->s, psz, n); 00701 str->s[n] = '\0'; 00702 result = (STRING_HANDLE)str; 00703 } 00704 /* Codes_SRS_STRING_02_010: [In all other error cases, STRING_construct_n shall return NULL.] */ 00705 else 00706 { 00707 free(str); 00708 result = NULL; 00709 } 00710 } 00711 else 00712 { 00713 /* Codes_SRS_STRING_02_010: [In all other error cases, STRING_construct_n shall return NULL.] */ 00714 result = NULL; 00715 } 00716 } 00717 } 00718 return result; 00719 } 00720 00721 /* Codes_SRS_STRING_07_034: [STRING_compare returns an integer greater than, equal to, or less than zero, accordingly as the string pointed to by s1 is greater than, equal to, or less than the string s2.] */ 00722 int STRING_compare(STRING_HANDLE s1, STRING_HANDLE s2) 00723 { 00724 int result; 00725 if (s1 == NULL && s2 == NULL) 00726 { 00727 /* Codes_SRS_STRING_07_035: [If h1 and h2 are both NULL then STRING_compare shall return 0.]*/ 00728 result = 0; 00729 } 00730 else if (s1 == NULL) 00731 { 00732 /* Codes_SRS_STRING_07_036: [If h1 is NULL and h2 is nonNULL then STRING_compare shall return 1.]*/ 00733 result = 1; 00734 } 00735 else if (s2 == NULL) 00736 { 00737 /* Codes_SRS_STRING_07_037: [If h2 is NULL and h1 is nonNULL then STRING_compare shall return -1.] */ 00738 result = -1; 00739 } 00740 else 00741 { 00742 /* Codes_SRS_STRING_07_038: [STRING_compare shall compare the char s variable using the strcmp function.] */ 00743 STRING* value1 = (STRING*)s1; 00744 STRING* value2 = (STRING*)s2; 00745 result = strcmp(value1->s, value2->s); 00746 } 00747 return result; 00748 } 00749 00750 STRING_HANDLE STRING_from_byte_array(const unsigned char* source, size_t size) 00751 { 00752 STRING* result; 00753 /*Codes_SRS_STRING_02_022: [ If source is NULL and size > 0 then STRING_from_BUFFER shall fail and return NULL. ]*/ 00754 if ((source == NULL) && (size > 0)) 00755 { 00756 LogError("invalid parameter (NULL)"); 00757 result = NULL; 00758 } 00759 else 00760 { 00761 /*Codes_SRS_STRING_02_023: [ Otherwise, STRING_from_BUFFER shall build a string that has the same content (byte-by-byte) as source and return a non-NULL handle. ]*/ 00762 result = (STRING*)malloc(sizeof(STRING)); 00763 if (result == NULL) 00764 { 00765 /*Codes_SRS_STRING_02_024: [ If building the string fails, then STRING_from_BUFFER shall fail and return NULL. ]*/ 00766 LogError("oom - unable to malloc"); 00767 /*return as is*/ 00768 } 00769 else 00770 { 00771 /*Codes_SRS_STRING_02_023: [ Otherwise, STRING_from_BUFFER shall build a string that has the same content (byte-by-byte) as source and return a non-NULL handle. ]*/ 00772 result->s = (char*)malloc(size + 1); 00773 if (result->s == NULL) 00774 { 00775 /*Codes_SRS_STRING_02_024: [ If building the string fails, then STRING_from_BUFFER shall fail and return NULL. ]*/ 00776 LogError("oom - unable to malloc"); 00777 free(result); 00778 result = NULL; 00779 } 00780 else 00781 { 00782 memcpy(result->s, source, size); 00783 result->s[size] = '\0'; /*all is fine*/ 00784 } 00785 } 00786 } 00787 return (STRING_HANDLE)result; 00788 }
Generated on Wed Jul 13 2022 07:19:04 by
1.7.2