Mark Radbourne / Mbed 2 deprecated FXOS8700CQ_To_Azure_IoT

Dependencies:   azure_umqtt_c iothub_mqtt_transport mbed-rtos mbed wolfSSL Socket lwip-eth lwip-sys lwip

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers strings.c Source File

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 }