source: azure_iot_hub/trunk/azure_iohub/c-utility/src/strings.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

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