source: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/strings.c@ 453

Last change on this file since 453 was 453, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 29.1 KB
Line 
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#include <stdlib.h>
5#include <string.h>
6#include <stdarg.h>
7#include <stdio.h>
8
9#include "azure_c_shared_utility/gballoc.h"
10#include "azure_c_shared_utility/strings.h"
11#include "azure_c_shared_utility/optimize_size.h"
12#include "azure_c_shared_utility/xlogging.h"
13
14static const char hexToASCII[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
15
16typedef struct STRING_TAG
17{
18 char* s;
19} STRING;
20
21/*this function will allocate a new string with just '\0' in it*/
22/*return NULL if it fails*/
23/* Codes_SRS_STRING_07_001: [STRING_new shall allocate a new STRING_HANDLE pointing to an empty string.] */
24STRING_HANDLE STRING_new(void)
25{
26 STRING* result;
27 if ((result = (STRING*)malloc(sizeof(STRING))) != NULL)
28 {
29 if ((result->s = (char*)malloc(1)) != NULL)
30 {
31 result->s[0] = '\0';
32 }
33 else
34 {
35 /* Codes_SRS_STRING_07_002: [STRING_new shall return an NULL STRING_HANDLE on any error that is encountered.] */
36 LogError("Failure allocating in STRING_new.");
37 free(result);
38 result = NULL;
39 }
40 }
41 return (STRING_HANDLE)result;
42}
43
44/*Codes_SRS_STRING_02_001: [STRING_clone shall produce a new string having the same content as the handle string.*/
45STRING_HANDLE STRING_clone(STRING_HANDLE handle)
46{
47 STRING* result;
48 /*Codes_SRS_STRING_02_002: [If parameter handle is NULL then STRING_clone shall return NULL.]*/
49 if (handle == NULL)
50 {
51 result = NULL;
52 }
53 else
54 {
55 /*Codes_SRS_STRING_02_003: [If STRING_clone fails for any reason, it shall return NULL.] */
56 if ((result = (STRING*)malloc(sizeof(STRING))) != NULL)
57 {
58 STRING* source = (STRING*)handle;
59 /*Codes_SRS_STRING_02_003: [If STRING_clone fails for any reason, it shall return NULL.] */
60 size_t sourceLen = strlen(source->s);
61 if ((result->s = (char*)malloc(sourceLen + 1)) == NULL)
62 {
63 LogError("Failure allocating clone value.");
64 free(result);
65 result = NULL;
66 }
67 else
68 {
69 (void)memcpy(result->s, source->s, sourceLen + 1);
70 }
71 }
72 else
73 {
74 /*not much to do, result is NULL from malloc*/
75 }
76 }
77 return (STRING_HANDLE)result;
78}
79
80/* Codes_SRS_STRING_07_003: [STRING_construct shall allocate a new string with the value of the specified const char*.] */
81STRING_HANDLE STRING_construct(const char* psz)
82{
83 STRING_HANDLE result;
84 if (psz == NULL)
85 {
86 /* Codes_SRS_STRING_07_005: [If the supplied const char* is NULL STRING_construct shall return a NULL value.] */
87 result = NULL;
88 }
89 else
90 {
91 STRING* str;
92 if ((str = (STRING*)malloc(sizeof(STRING))) != NULL)
93 {
94 size_t nLen = strlen(psz) + 1;
95 if ((str->s = (char*)malloc(nLen)) != NULL)
96 {
97 (void)memcpy(str->s, psz, nLen);
98 result = (STRING_HANDLE)str;
99 }
100 /* Codes_SRS_STRING_07_032: [STRING_construct encounters any error it shall return a NULL value.] */
101 else
102 {
103 LogError("Failure allocating constructed value.");
104 free(str);
105 result = NULL;
106 }
107 }
108 else
109 {
110 /* Codes_SRS_STRING_07_032: [STRING_construct encounters any error it shall return a NULL value.] */
111 LogError("Failure allocating value.");
112 result = NULL;
113 }
114 }
115 return result;
116}
117
118#if defined(__GNUC__)
119__attribute__ ((format (printf, 1, 2)))
120#endif
121STRING_HANDLE STRING_construct_sprintf(const char* format, ...)
122{
123 STRING* result;
124
125#ifdef STRINGS_C_SPRINTF_BUFFER_SIZE
126 size_t maxBufSize = STRINGS_C_SPRINTF_BUFFER_SIZE;
127 char buf[STRINGS_C_SPRINTF_BUFFER_SIZE];
128#else
129 size_t maxBufSize = 0;
130 char* buf = NULL;
131#endif
132
133 if (format != NULL)
134 {
135 va_list arg_list;
136 int length;
137 va_start(arg_list, format);
138
139 /* Codes_SRS_STRING_07_041: [STRING_construct_sprintf shall determine the size of the resulting string and allocate the necessary memory.] */
140 length = vsnprintf(buf, maxBufSize, format, arg_list);
141 va_end(arg_list);
142 if (length > 0)
143 {
144 result = (STRING*)malloc(sizeof(STRING));
145 if (result != NULL)
146 {
147 result->s = (char*)malloc(length+1);
148 if (result->s != NULL)
149 {
150 va_start(arg_list, format);
151 if (vsnprintf(result->s, length+1, format, arg_list) < 0)
152 {
153 /* Codes_SRS_STRING_07_040: [If any error is encountered STRING_construct_sprintf shall return NULL.] */
154 free(result->s);
155 free(result);
156 result = NULL;
157 LogError("Failure: vsnprintf formatting failed.");
158 }
159 va_end(arg_list);
160 }
161 else
162 {
163 /* Codes_SRS_STRING_07_040: [If any error is encountered STRING_construct_sprintf shall return NULL.] */
164 free(result);
165 result = NULL;
166 LogError("Failure: allocation sprintf value failed.");
167 }
168 }
169 else
170 {
171 LogError("Failure: allocation failed.");
172 }
173 }
174 else if (length == 0)
175 {
176 result = (STRING*)STRING_new();
177 }
178 else
179 {
180 /* Codes_SRS_STRING_07_039: [If the parameter format is NULL then STRING_construct_sprintf shall return NULL.] */
181 result = NULL;
182 LogError("Failure: vsnprintf return 0 length");
183 }
184 }
185 else
186 {
187 LogError("Failure: invalid argument.");
188 result = NULL;
189 }
190 /* Codes_SRS_STRING_07_045: [STRING_construct_sprintf shall allocate a new string with the value of the specified printf formated const char. ] */
191 return (STRING_HANDLE)result;
192}
193
194/*this function will return a new STRING with the memory for the actual string passed in as a parameter.*/
195/*return NULL if it fails.*/
196/* The supplied memory must have been allocated with malloc! */
197/* Codes_SRS_STRING_07_006: [STRING_new_with_memory shall return a STRING_HANDLE by using the supplied char* memory.] */
198STRING_HANDLE STRING_new_with_memory(const char* memory)
199{
200 STRING* result;
201 if (memory == NULL)
202 {
203 /* Codes_SRS_STRING_07_007: [STRING_new_with_memory shall return a NULL STRING_HANDLE if the supplied char* is NULL.] */
204 result = NULL;
205 }
206 else
207 {
208 if ((result = (STRING*)malloc(sizeof(STRING))) != NULL)
209 {
210 result->s = (char*)memory;
211 }
212 else
213 {
214 LogError("Failure: allocating memory string");
215 }
216 }
217 return (STRING_HANDLE)result;
218}
219
220/* Codes_SRS_STRING_07_008: [STRING_new_quoted shall return a valid STRING_HANDLE Copying the supplied const char* value surrounded by quotes.] */
221STRING_HANDLE STRING_new_quoted(const char* source)
222{
223 STRING* result;
224 if (source == NULL)
225 {
226 /* Codes_SRS_STRING_07_009: [STRING_new_quoted shall return a NULL STRING_HANDLE if the supplied const char* is NULL.] */
227 result = NULL;
228 }
229 else if ((result = (STRING*)malloc(sizeof(STRING))) != NULL)
230 {
231 size_t sourceLength = strlen(source);
232 if ((result->s = (char*)malloc(sourceLength + 3)) != NULL)
233 {
234 result->s[0] = '"';
235 (void)memcpy(result->s + 1, source, sourceLength);
236 result->s[sourceLength + 1] = '"';
237 result->s[sourceLength + 2] = '\0';
238 }
239 else
240 {
241 /* Codes_SRS_STRING_07_031: [STRING_new_quoted shall return a NULL STRING_HANDLE if any error is encountered.] */
242 LogError("Failure allocating quoted string value.");
243 free(result);
244 result = NULL;
245 }
246 }
247 return (STRING_HANDLE)result;
248}
249
250/*this function takes a regular const char* and turns in into "this is a\"JSON\" strings\u0008" (starting and ending quote included)*/
251/*the newly created handle needs to be disposed of with STRING_delete*/
252/*returns NULL if there are errors*/
253STRING_HANDLE STRING_new_JSON(const char* source)
254{
255 STRING* result;
256 if (source == NULL)
257 {
258 /*Codes_SRS_STRING_02_011: [If source is NULL then STRING_new_JSON shall return NULL.] */
259 result = NULL;
260 LogError("invalid arg (NULL)");
261 }
262 else
263 {
264 size_t i;
265 size_t nControlCharacters = 0; /*counts how many characters are to be expanded from 1 character to \uxxxx (6 characters)*/
266 size_t nEscapeCharacters = 0;
267 size_t vlen = strlen(source);
268
269 for (i = 0; i < vlen; i++)
270 {
271 /*Codes_SRS_STRING_02_014: [If any character has the value outside [1...127] then STRING_new_JSON shall fail and return NULL.] */
272 if ((unsigned char)source[i] >= 128) /*this be a UNICODE character begin*/
273 {
274 break;
275 }
276 else
277 {
278 if (source[i] <= 0x1F)
279 {
280 nControlCharacters++;
281 }
282 else if (
283 (source[i] == '"') ||
284 (source[i] == '\\') ||
285 (source[i] == '/')
286 )
287 {
288 nEscapeCharacters++;
289 }
290 }
291 }
292
293 if (i < vlen)
294 {
295 result = NULL;
296 LogError("invalid character in input string");
297 }
298 else
299 {
300 if ((result = (STRING*)malloc(sizeof(STRING))) == NULL)
301 {
302 /*Codes_SRS_STRING_02_021: [If the complete JSON representation cannot be produced, then STRING_new_JSON shall fail and return NULL.] */
303 LogError("malloc json failure");
304 }
305 else if ((result->s = (char*)malloc(vlen + 5 * nControlCharacters + nEscapeCharacters + 3)) == NULL)
306 {
307 /*Codes_SRS_STRING_02_021: [If the complete JSON representation cannot be produced, then STRING_new_JSON shall fail and return NULL.] */
308 free(result);
309 result = NULL;
310 LogError("malloc failed");
311 }
312 else
313 {
314 size_t pos = 0;
315 /*Codes_SRS_STRING_02_012: [The string shall begin with the quote character.] */
316 result->s[pos++] = '"';
317 for (i = 0; i < vlen; i++)
318 {
319 if (source[i] <= 0x1F)
320 {
321 /*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.]*/
322 result->s[pos++] = '\\';
323 result->s[pos++] = 'u';
324 result->s[pos++] = '0';
325 result->s[pos++] = '0';
326 result->s[pos++] = hexToASCII[(source[i] & 0xF0) >> 4]; /*high nibble*/
327 result->s[pos++] = hexToASCII[source[i] & 0x0F]; /*low nibble*/
328 }
329 else if (source[i] == '"')
330 {
331 /*Codes_SRS_STRING_02_016: [If the character is " (quote) then it shall be repsented as \".] */
332 result->s[pos++] = '\\';
333 result->s[pos++] = '"';
334 }
335 else if (source[i] == '\\')
336 {
337 /*Codes_SRS_STRING_02_017: [If the character is \ (backslash) then it shall represented as \\.] */
338 result->s[pos++] = '\\';
339 result->s[pos++] = '\\';
340 }
341 else if (source[i] == '/')
342 {
343 /*Codes_SRS_STRING_02_018: [If the character is / (slash) then it shall be represented as \/.] */
344 result->s[pos++] = '\\';
345 result->s[pos++] = '/';
346 }
347 else
348 {
349 /*Codes_SRS_STRING_02_013: [The string shall copy the characters of source "as they are" (until the '\0' character) with the following exceptions:] */
350 result->s[pos++] = source[i];
351 }
352 }
353 /*Codes_SRS_STRING_02_020: [The string shall end with " (quote).] */
354 result->s[pos++] = '"';
355 /*zero terminating it*/
356 result->s[pos] = '\0';
357 }
358 }
359
360 }
361 return (STRING_HANDLE)result;
362}
363
364/*this function will concatenate to the string s1 the string s2, resulting in s1+s2*/
365/*returns 0 if success*/
366/*any other error code is failure*/
367/* 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.] */
368int STRING_concat(STRING_HANDLE handle, const char* s2)
369{
370 int result;
371 if ((handle == NULL) || (s2 == NULL))
372 {
373 /* Codes_SRS_STRING_07_013: [STRING_concat shall return a nonzero number if an error is encountered.] */
374 result = MU_FAILURE;
375 }
376 else
377 {
378 STRING* s1 = (STRING*)handle;
379 size_t s1Length = strlen(s1->s);
380 size_t s2Length = strlen(s2);
381 char* temp = (char*)realloc(s1->s, s1Length + s2Length + 1);
382 if (temp == NULL)
383 {
384 /* Codes_SRS_STRING_07_013: [STRING_concat shall return a nonzero number if an error is encountered.] */
385 LogError("Failure reallocating value.");
386 result = MU_FAILURE;
387 }
388 else
389 {
390 s1->s = temp;
391 (void)memcpy(s1->s + s1Length, s2, s2Length + 1);
392 result = 0;
393 }
394 }
395 return result;
396}
397
398/*this function will concatenate to the string s1 the string s2, resulting in s1+s2*/
399/*returns 0 if success*/
400/*any other error code is failure*/
401/* Codes_SRS_STRING_07_034: [String_Concat_with_STRING shall concatenate a given STRING_HANDLE variable with a source STRING_HANDLE.] */
402int STRING_concat_with_STRING(STRING_HANDLE s1, STRING_HANDLE s2)
403{
404 int result;
405 if ((s1 == NULL) || (s2 == NULL))
406 {
407 /* Codes_SRS_STRING_07_035: [String_Concat_with_STRING shall return a nonzero number if an error is encountered.] */
408 LogError("Invalid argument specified");
409 result = MU_FAILURE;
410 }
411 else
412 {
413 STRING* dest = (STRING*)s1;
414 STRING* src = (STRING*)s2;
415
416 size_t s1Length = strlen(dest->s);
417 size_t s2Length = strlen(src->s);
418 char* temp = (char*)realloc(dest->s, s1Length + s2Length + 1);
419 if (temp == NULL)
420 {
421 /* Codes_SRS_STRING_07_035: [String_Concat_with_STRING shall return a nonzero number if an error is encountered.] */
422 LogError("Failure reallocating value");
423 result = MU_FAILURE;
424 }
425 else
426 {
427 dest->s = temp;
428 /* Codes_SRS_STRING_07_034: [String_Concat_with_STRING shall concatenate a given STRING_HANDLE variable with a source STRING_HANDLE.] */
429 (void)memcpy(dest->s + s1Length, src->s, s2Length + 1);
430 result = 0;
431 }
432 }
433 return result;
434}
435
436/*this function will copy the string from s2 to s1*/
437/*returns 0 if success*/
438/*any other error code is failure*/
439/* Codes_SRS_STRING_07_016: [STRING_copy shall copy the const char* into the supplied STRING_HANDLE.] */
440int STRING_copy(STRING_HANDLE handle, const char* s2)
441{
442 int result;
443 if ((handle == NULL) || (s2 == NULL))
444 {
445 /* Codes_SRS_STRING_07_017: [STRING_copy shall return a nonzero value if any of the supplied parameters are NULL.] */
446 result = MU_FAILURE;
447 }
448 else
449 {
450 STRING* s1 = (STRING*)handle;
451 /* 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.] */
452 if (s1->s != s2)
453 {
454 size_t s2Length = strlen(s2);
455 char* temp = (char*)realloc(s1->s, s2Length + 1);
456 if (temp == NULL)
457 {
458 LogError("Failure reallocating value.");
459 /* Codes_SRS_STRING_07_027: [STRING_copy shall return a nonzero value if any error is encountered.] */
460 result = MU_FAILURE;
461 }
462 else
463 {
464 s1->s = temp;
465 memmove(s1->s, s2, s2Length + 1);
466 result = 0;
467 }
468 }
469 else
470 {
471 /* Codes_SRS_STRING_07_033: [If overlapping pointer address is given to STRING_copy the behavior is undefined.] */
472 result = 0;
473 }
474 }
475 return result;
476}
477
478/*this function will copy n chars from s2 to the string s1, resulting in n chars only from s2 being stored in s1.*/
479/*returns 0 if success*/
480/*any other error code is failure*/
481/* Codes_SRS_STRING_07_018: [STRING_copy_n shall copy the number of characters in const char* or the size_t whichever is lesser.] */
482int STRING_copy_n(STRING_HANDLE handle, const char* s2, size_t n)
483{
484 int result;
485 if ((handle == NULL) || (s2 == NULL))
486 {
487 /* Codes_SRS_STRING_07_019: [STRING_copy_n shall return a nonzero value if STRING_HANDLE or const char* is NULL.] */
488 result = MU_FAILURE;
489 }
490 else
491 {
492 STRING* s1 = (STRING*)handle;
493 size_t s2Length = strlen(s2);
494 char* temp;
495 if (s2Length > n)
496 {
497 s2Length = n;
498 }
499
500 temp = (char*)realloc(s1->s, s2Length + 1);
501 if (temp == NULL)
502 {
503 LogError("Failure reallocating value.");
504 /* Codes_SRS_STRING_07_028: [STRING_copy_n shall return a nonzero value if any error is encountered.] */
505 result = MU_FAILURE;
506 }
507 else
508 {
509 s1->s = temp;
510 (void)memcpy(s1->s, s2, s2Length);
511 s1->s[s2Length] = 0;
512 result = 0;
513 }
514
515 }
516 return result;
517}
518
519#if defined(__GNUC__)
520__attribute__ ((format (printf, 2, 3)))
521#endif
522int STRING_sprintf(STRING_HANDLE handle, const char* format, ...)
523{
524 int result;
525
526#ifdef STRINGS_C_SPRINTF_BUFFER_SIZE
527 size_t maxBufSize = STRINGS_C_SPRINTF_BUFFER_SIZE;
528 char buf[STRINGS_C_SPRINTF_BUFFER_SIZE];
529#else
530 size_t maxBufSize = 0;
531 char* buf = NULL;
532#endif
533
534 if (handle == NULL || format == NULL)
535 {
536 /* Codes_SRS_STRING_07_042: [if the parameters s1 or format are NULL then STRING_sprintf shall return non zero value.] */
537 LogError("Invalid arg (NULL)");
538 result = MU_FAILURE;
539 }
540 else
541 {
542 va_list arg_list;
543 int s2Length;
544 va_start(arg_list, format);
545
546 s2Length = vsnprintf(buf, maxBufSize, format, arg_list);
547 va_end(arg_list);
548 if (s2Length < 0)
549 {
550 /* Codes_SRS_STRING_07_043: [If any error is encountered STRING_sprintf shall return a non zero value.] */
551 LogError("Failure vsnprintf return < 0");
552 result = MU_FAILURE;
553 }
554 else if (s2Length == 0)
555 {
556 // Don't need to reallocate and nothing should be added
557 result = 0;
558 }
559 else
560 {
561 STRING* s1 = (STRING*)handle;
562 char* temp;
563 size_t s1Length = strlen(s1->s);
564 temp = (char*)realloc(s1->s, s1Length + s2Length + 1);
565 if (temp != NULL)
566 {
567 s1->s = temp;
568 va_start(arg_list, format);
569 if (vsnprintf(s1->s + s1Length, s1Length + s2Length + 1, format, arg_list) < 0)
570 {
571 /* Codes_SRS_STRING_07_043: [If any error is encountered STRING_sprintf shall return a non zero value.] */
572 LogError("Failure vsnprintf formatting error");
573 s1->s[s1Length] = '\0';
574 result = MU_FAILURE;
575 }
576 else
577 {
578 /* Codes_SRS_STRING_07_044: [On success STRING_sprintf shall return 0.]*/
579 result = 0;
580 }
581 va_end(arg_list);
582 }
583 else
584 {
585 /* Codes_SRS_STRING_07_043: [If any error is encountered STRING_sprintf shall return a non zero value.] */
586 LogError("Failure unable to reallocate memory");
587 result = MU_FAILURE;
588 }
589 }
590 }
591 return result;
592}
593
594/*this function will quote the string passed as argument string =>"string"*/
595/*returns 0 if success*/ /*doesn't change the string otherwise*/
596/*any other error code is failure*/
597/* Codes_SRS_STRING_07_014: [STRING_quote shall "quote" the supplied STRING_HANDLE and return 0 on success.] */
598int STRING_quote(STRING_HANDLE handle)
599{
600 int result;
601 if (handle == NULL)
602 {
603 /* Codes_SRS_STRING_07_015: [STRING_quote shall return a nonzero value if any of the supplied parameters are NULL.] */
604 result = MU_FAILURE;
605 }
606 else
607 {
608 STRING* s1 = (STRING*)handle;
609 size_t s1Length = strlen(s1->s);
610 char* temp = (char*)realloc(s1->s, s1Length + 2 + 1);/*2 because 2 quotes, 1 because '\0'*/
611 if (temp == NULL)
612 {
613 LogError("Failure reallocating value.");
614 /* Codes_SRS_STRING_07_029: [STRING_quote shall return a nonzero value if any error is encountered.] */
615 result = MU_FAILURE;
616 }
617 else
618 {
619 s1->s = temp;
620 memmove(s1->s + 1, s1->s, s1Length);
621 s1->s[0] = '"';
622 s1->s[s1Length + 1] = '"';
623 s1->s[s1Length + 2] = '\0';
624 result = 0;
625 }
626 }
627 return result;
628}
629/*this function will revert a string to an empty state*/
630/*Returns 0 if the revert was succesful*/
631/* Codes_SRS_STRING_07_022: [STRING_empty shall revert the STRING_HANDLE to an empty state.] */
632int STRING_empty(STRING_HANDLE handle)
633{
634 int result;
635 if (handle == NULL)
636 {
637 /* Codes_SRS_STRING_07_023: [STRING_empty shall return a nonzero value if the STRING_HANDLE is NULL.] */
638 result = MU_FAILURE;
639 }
640 else
641 {
642 STRING* s1 = (STRING*)handle;
643 char* temp = (char*)realloc(s1->s, 1);
644 if (temp == NULL)
645 {
646 LogError("Failure reallocating value.");
647 /* Codes_SRS_STRING_07_030: [STRING_empty shall return a nonzero value if the STRING_HANDLE is NULL.] */
648 result = MU_FAILURE;
649 }
650 else
651 {
652 s1->s = temp;
653 s1->s[0] = '\0';
654 result = 0;
655 }
656 }
657 return result;
658}
659
660/*this function will deallocate a string constructed by str_new*/
661/* Codes_SRS_STRING_07_010: [STRING_delete will free the memory allocated by the STRING_HANDLE.] */
662void STRING_delete(STRING_HANDLE handle)
663{
664 /* Codes_SRS_STRING_07_011: [STRING_delete will not attempt to free anything with a NULL STRING_HANDLE.] */
665 if (handle != NULL)
666 {
667 STRING* value = (STRING*)handle;
668 free(value->s);
669 value->s = NULL;
670 free(value);
671 }
672}
673
674/* Codes_SRS_STRING_07_020: [STRING_c_str shall return the const char* associated with the given STRING_HANDLE.] */
675const char* STRING_c_str(STRING_HANDLE handle)
676{
677 const char* result;
678 if (handle != NULL)
679 {
680 result = ((STRING*)handle)->s;
681 }
682 else
683 {
684 /* Codes_SRS_STRING_07_021: [STRING_c_str shall return NULL if the STRING_HANDLE is NULL.] */
685 result = NULL;
686 }
687 return result;
688}
689
690/* Codes_SRS_STRING_07_024: [STRING_length shall return the length of the underlying char* for the given handle] */
691size_t STRING_length(STRING_HANDLE handle)
692{
693 size_t result = 0;
694 /* Codes_SRS_STRING_07_025: [STRING_length shall return zero if the given handle is NULL.] */
695 if (handle != NULL)
696 {
697 STRING* value = (STRING*)handle;
698 result = strlen(value->s);
699 }
700 return result;
701}
702
703/*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.]*/
704STRING_HANDLE STRING_construct_n(const char* psz, size_t n)
705{
706 STRING_HANDLE result;
707 /*Codes_SRS_STRING_02_008: [If psz is NULL then STRING_construct_n shall return NULL.] */
708 if (psz == NULL)
709 {
710 result = NULL;
711 LogError("invalid arg (NULL)");
712 }
713 else
714 {
715 size_t len = strlen(psz);
716 /*Codes_SRS_STRING_02_009: [If n is bigger than the size of the string psz, then STRING_construct_n shall return NULL.] */
717 if (n > len)
718 {
719 result = NULL;
720 LogError("invalig arg (n is bigger than the size of the string)");
721 }
722 else
723 {
724 STRING* str;
725 if ((str = (STRING*)malloc(sizeof(STRING))) != NULL)
726 {
727 if ((str->s = (char*)malloc(len + 1)) != NULL)
728 {
729 (void)memcpy(str->s, psz, n);
730 str->s[n] = '\0';
731 result = (STRING_HANDLE)str;
732 }
733 /* Codes_SRS_STRING_02_010: [In all other error cases, STRING_construct_n shall return NULL.] */
734 else
735 {
736 LogError("Failure allocating value.");
737 free(str);
738 result = NULL;
739 }
740 }
741 else
742 {
743 /* Codes_SRS_STRING_02_010: [In all other error cases, STRING_construct_n shall return NULL.] */
744 result = NULL;
745 }
746 }
747 }
748 return result;
749}
750
751/* 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.] */
752int STRING_compare(STRING_HANDLE s1, STRING_HANDLE s2)
753{
754 int result;
755 if (s1 == NULL && s2 == NULL)
756 {
757 /* Codes_SRS_STRING_07_035: [If h1 and h2 are both NULL then STRING_compare shall return 0.]*/
758 result = 0;
759 }
760 else if (s1 == NULL)
761 {
762 /* Codes_SRS_STRING_07_036: [If h1 is NULL and h2 is nonNULL then STRING_compare shall return 1.]*/
763 result = 1;
764 }
765 else if (s2 == NULL)
766 {
767 /* Codes_SRS_STRING_07_037: [If h2 is NULL and h1 is nonNULL then STRING_compare shall return -1.] */
768 result = -1;
769 }
770 else
771 {
772 /* Codes_SRS_STRING_07_038: [STRING_compare shall compare the char s variable using the strcmp function.] */
773 STRING* value1 = (STRING*)s1;
774 STRING* value2 = (STRING*)s2;
775 result = strcmp(value1->s, value2->s);
776 }
777 return result;
778}
779
780STRING_HANDLE STRING_from_byte_array(const unsigned char* source, size_t size)
781{
782 STRING* result;
783 /*Codes_SRS_STRING_02_022: [ If source is NULL and size > 0 then STRING_from_BUFFER shall fail and return NULL. ]*/
784 if ((source == NULL) && (size > 0))
785 {
786 LogError("invalid parameter (NULL)");
787 result = NULL;
788 }
789 else
790 {
791 /*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. ]*/
792 result = (STRING*)malloc(sizeof(STRING));
793 if (result == NULL)
794 {
795 /*Codes_SRS_STRING_02_024: [ If building the string fails, then STRING_from_BUFFER shall fail and return NULL. ]*/
796 LogError("oom - unable to malloc");
797 /*return as is*/
798 }
799 else
800 {
801 /*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. ]*/
802 result->s = (char*)malloc(size + 1);
803 if (result->s == NULL)
804 {
805 /*Codes_SRS_STRING_02_024: [ If building the string fails, then STRING_from_BUFFER shall fail and return NULL. ]*/
806 LogError("oom - unable to malloc");
807 free(result);
808 result = NULL;
809 }
810 else
811 {
812 (void)memcpy(result->s, source, size);
813 result->s[size] = '\0'; /*all is fine*/
814 }
815 }
816 }
817 return (STRING_HANDLE)result;
818}
819
820int STRING_replace(STRING_HANDLE handle, char target, char replace)
821{
822 int result;
823 if (handle == NULL)
824 {
825 /* Codes_SRS_STRING_07_046: [ If handle is NULL STRING_replace shall return a non-zero value. ] */
826 result = MU_FAILURE;
827 }
828 else if (target == replace)
829 {
830 /* Codes_SRS_STRING_07_048: [ If target and replace are equal STRING_replace, shall do nothing shall return zero. ] */
831 result = 0;
832 }
833 else
834 {
835 size_t length;
836 size_t index;
837 /* Codes_SRS_STRING_07_047: [ STRING_replace shall replace all instances of target with replace. ] */
838 STRING* str_value = (STRING*)handle;
839 length = strlen(str_value->s);
840 for (index = 0; index < length; index++)
841 {
842 if (str_value->s[index] == target)
843 {
844 str_value->s[index] = replace;
845 }
846 }
847 /* Codes_SRS_STRING_07_049: [ On success STRING_replace shall return zero. ] */
848 result = 0;
849 }
850 return result;
851}
Note: See TracBrowser for help on using the repository browser.