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