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