source: mainline/uspace/lib/c/generic/str.c@ 74017ce

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 74017ce was 16bfcd3, checked in by jzr <zarevucky.jiri@…>, 8 years ago

Fix up headers.

  • Property mode set to 100644
File size: 44.6 KB
Line 
1/*
2 * Copyright (c) 2005 Martin Decky
3 * Copyright (c) 2008 Jiri Svoboda
4 * Copyright (c) 2011 Martin Sucha
5 * Copyright (c) 2011 Oleg Romanenko
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * - The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/** @addtogroup libc
33 * @{
34 */
35/** @file
36 */
37
38#include <str.h>
39#include <stdlib.h>
40#include <stddef.h>
41#include <assert.h>
42#include <stdint.h>
43#include <ctype.h>
44#include <malloc.h>
45#include <errno.h>
46#include <align.h>
47#include <mem.h>
48#include <limits.h>
49
50/** Check the condition if wchar_t is signed */
51#ifdef __WCHAR_UNSIGNED__
52 #define WCHAR_SIGNED_CHECK(cond) (true)
53#else
54 #define WCHAR_SIGNED_CHECK(cond) (cond)
55#endif
56
57/** Byte mask consisting of lowest @n bits (out of 8) */
58#define LO_MASK_8(n) ((uint8_t) ((1 << (n)) - 1))
59
60/** Byte mask consisting of lowest @n bits (out of 32) */
61#define LO_MASK_32(n) ((uint32_t) ((1 << (n)) - 1))
62
63/** Byte mask consisting of highest @n bits (out of 8) */
64#define HI_MASK_8(n) (~LO_MASK_8(8 - (n)))
65
66/** Number of data bits in a UTF-8 continuation byte */
67#define CONT_BITS 6
68
69/** Decode a single character from a string.
70 *
71 * Decode a single character from a string of size @a size. Decoding starts
72 * at @a offset and this offset is moved to the beginning of the next
73 * character. In case of decoding error, offset generally advances at least
74 * by one. However, offset is never moved beyond size.
75 *
76 * @param str String (not necessarily NULL-terminated).
77 * @param offset Byte offset in string where to start decoding.
78 * @param size Size of the string (in bytes).
79 *
80 * @return Value of decoded character, U_SPECIAL on decoding error or
81 * NULL if attempt to decode beyond @a size.
82 *
83 */
84wchar_t str_decode(const char *str, size_t *offset, size_t size)
85{
86 if (*offset + 1 > size)
87 return 0;
88
89 /* First byte read from string */
90 uint8_t b0 = (uint8_t) str[(*offset)++];
91
92 /* Determine code length */
93
94 unsigned int b0_bits; /* Data bits in first byte */
95 unsigned int cbytes; /* Number of continuation bytes */
96
97 if ((b0 & 0x80) == 0) {
98 /* 0xxxxxxx (Plain ASCII) */
99 b0_bits = 7;
100 cbytes = 0;
101 } else if ((b0 & 0xe0) == 0xc0) {
102 /* 110xxxxx 10xxxxxx */
103 b0_bits = 5;
104 cbytes = 1;
105 } else if ((b0 & 0xf0) == 0xe0) {
106 /* 1110xxxx 10xxxxxx 10xxxxxx */
107 b0_bits = 4;
108 cbytes = 2;
109 } else if ((b0 & 0xf8) == 0xf0) {
110 /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
111 b0_bits = 3;
112 cbytes = 3;
113 } else {
114 /* 10xxxxxx -- unexpected continuation byte */
115 return U_SPECIAL;
116 }
117
118 if (*offset + cbytes > size)
119 return U_SPECIAL;
120
121 wchar_t ch = b0 & LO_MASK_8(b0_bits);
122
123 /* Decode continuation bytes */
124 while (cbytes > 0) {
125 uint8_t b = (uint8_t) str[(*offset)++];
126
127 /* Must be 10xxxxxx */
128 if ((b & 0xc0) != 0x80)
129 return U_SPECIAL;
130
131 /* Shift data bits to ch */
132 ch = (ch << CONT_BITS) | (wchar_t) (b & LO_MASK_8(CONT_BITS));
133 cbytes--;
134 }
135
136 return ch;
137}
138
139/** Decode a single character from a string to the left.
140 *
141 * Decode a single character from a string of size @a size. Decoding starts
142 * at @a offset and this offset is moved to the beginning of the previous
143 * character. In case of decoding error, offset generally decreases at least
144 * by one. However, offset is never moved before 0.
145 *
146 * @param str String (not necessarily NULL-terminated).
147 * @param offset Byte offset in string where to start decoding.
148 * @param size Size of the string (in bytes).
149 *
150 * @return Value of decoded character, U_SPECIAL on decoding error or
151 * NULL if attempt to decode beyond @a start of str.
152 *
153 */
154wchar_t str_decode_reverse(const char *str, size_t *offset, size_t size)
155{
156 if (*offset == 0)
157 return 0;
158
159 size_t processed = 0;
160 /* Continue while continuation bytes found */
161 while (*offset > 0 && processed < 4) {
162 uint8_t b = (uint8_t) str[--(*offset)];
163
164 if (processed == 0 && (b & 0x80) == 0) {
165 /* 0xxxxxxx (Plain ASCII) */
166 return b & 0x7f;
167 }
168 else if ((b & 0xe0) == 0xc0 || (b & 0xf0) == 0xe0 ||
169 (b & 0xf8) == 0xf0) {
170 /* Start byte */
171 size_t start_offset = *offset;
172 return str_decode(str, &start_offset, size);
173 }
174 else if ((b & 0xc0) != 0x80) {
175 /* Not a continuation byte */
176 return U_SPECIAL;
177 }
178 processed++;
179 }
180 /* Too many continuation bytes */
181 return U_SPECIAL;
182}
183
184/** Encode a single character to string representation.
185 *
186 * Encode a single character to string representation (i.e. UTF-8) and store
187 * it into a buffer at @a offset. Encoding starts at @a offset and this offset
188 * is moved to the position where the next character can be written to.
189 *
190 * @param ch Input character.
191 * @param str Output buffer.
192 * @param offset Byte offset where to start writing.
193 * @param size Size of the output buffer (in bytes).
194 *
195 * @return EOK if the character was encoded successfully, EOVERFLOW if there
196 * was not enough space in the output buffer or EINVAL if the character
197 * code was invalid.
198 */
199int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t size)
200{
201 if (*offset >= size)
202 return EOVERFLOW;
203
204 if (!chr_check(ch))
205 return EINVAL;
206
207 /* Unsigned version of ch (bit operations should only be done
208 on unsigned types). */
209 uint32_t cc = (uint32_t) ch;
210
211 /* Determine how many continuation bytes are needed */
212
213 unsigned int b0_bits; /* Data bits in first byte */
214 unsigned int cbytes; /* Number of continuation bytes */
215
216 if ((cc & ~LO_MASK_32(7)) == 0) {
217 b0_bits = 7;
218 cbytes = 0;
219 } else if ((cc & ~LO_MASK_32(11)) == 0) {
220 b0_bits = 5;
221 cbytes = 1;
222 } else if ((cc & ~LO_MASK_32(16)) == 0) {
223 b0_bits = 4;
224 cbytes = 2;
225 } else if ((cc & ~LO_MASK_32(21)) == 0) {
226 b0_bits = 3;
227 cbytes = 3;
228 } else {
229 /* Codes longer than 21 bits are not supported */
230 return EINVAL;
231 }
232
233 /* Check for available space in buffer */
234 if (*offset + cbytes >= size)
235 return EOVERFLOW;
236
237 /* Encode continuation bytes */
238 unsigned int i;
239 for (i = cbytes; i > 0; i--) {
240 str[*offset + i] = 0x80 | (cc & LO_MASK_32(CONT_BITS));
241 cc = cc >> CONT_BITS;
242 }
243
244 /* Encode first byte */
245 str[*offset] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1);
246
247 /* Advance offset */
248 *offset += cbytes + 1;
249
250 return EOK;
251}
252
253/** Get size of string.
254 *
255 * Get the number of bytes which are used by the string @a str (excluding the
256 * NULL-terminator).
257 *
258 * @param str String to consider.
259 *
260 * @return Number of bytes used by the string
261 *
262 */
263size_t str_size(const char *str)
264{
265 size_t size = 0;
266
267 while (*str++ != 0)
268 size++;
269
270 return size;
271}
272
273/** Get size of wide string.
274 *
275 * Get the number of bytes which are used by the wide string @a str (excluding the
276 * NULL-terminator).
277 *
278 * @param str Wide string to consider.
279 *
280 * @return Number of bytes used by the wide string
281 *
282 */
283size_t wstr_size(const wchar_t *str)
284{
285 return (wstr_length(str) * sizeof(wchar_t));
286}
287
288/** Get size of string with length limit.
289 *
290 * Get the number of bytes which are used by up to @a max_len first
291 * characters in the string @a str. If @a max_len is greater than
292 * the length of @a str, the entire string is measured (excluding the
293 * NULL-terminator).
294 *
295 * @param str String to consider.
296 * @param max_len Maximum number of characters to measure.
297 *
298 * @return Number of bytes used by the characters.
299 *
300 */
301size_t str_lsize(const char *str, size_t max_len)
302{
303 size_t len = 0;
304 size_t offset = 0;
305
306 while (len < max_len) {
307 if (str_decode(str, &offset, STR_NO_LIMIT) == 0)
308 break;
309
310 len++;
311 }
312
313 return offset;
314}
315
316/** Get size of string with size limit.
317 *
318 * Get the number of bytes which are used by the string @a str
319 * (excluding the NULL-terminator), but no more than @max_size bytes.
320 *
321 * @param str String to consider.
322 * @param max_size Maximum number of bytes to measure.
323 *
324 * @return Number of bytes used by the string
325 *
326 */
327size_t str_nsize(const char *str, size_t max_size)
328{
329 size_t size = 0;
330
331 while ((*str++ != 0) && (size < max_size))
332 size++;
333
334 return size;
335}
336
337/** Get size of wide string with size limit.
338 *
339 * Get the number of bytes which are used by the wide string @a str
340 * (excluding the NULL-terminator), but no more than @max_size bytes.
341 *
342 * @param str Wide string to consider.
343 * @param max_size Maximum number of bytes to measure.
344 *
345 * @return Number of bytes used by the wide string
346 *
347 */
348size_t wstr_nsize(const wchar_t *str, size_t max_size)
349{
350 return (wstr_nlength(str, max_size) * sizeof(wchar_t));
351}
352
353/** Get size of wide string with length limit.
354 *
355 * Get the number of bytes which are used by up to @a max_len first
356 * wide characters in the wide string @a str. If @a max_len is greater than
357 * the length of @a str, the entire wide string is measured (excluding the
358 * NULL-terminator).
359 *
360 * @param str Wide string to consider.
361 * @param max_len Maximum number of wide characters to measure.
362 *
363 * @return Number of bytes used by the wide characters.
364 *
365 */
366size_t wstr_lsize(const wchar_t *str, size_t max_len)
367{
368 return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
369}
370
371/** Get number of characters in a string.
372 *
373 * @param str NULL-terminated string.
374 *
375 * @return Number of characters in string.
376 *
377 */
378size_t str_length(const char *str)
379{
380 size_t len = 0;
381 size_t offset = 0;
382
383 while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
384 len++;
385
386 return len;
387}
388
389/** Get number of characters in a wide string.
390 *
391 * @param str NULL-terminated wide string.
392 *
393 * @return Number of characters in @a str.
394 *
395 */
396size_t wstr_length(const wchar_t *wstr)
397{
398 size_t len = 0;
399
400 while (*wstr++ != 0)
401 len++;
402
403 return len;
404}
405
406/** Get number of characters in a string with size limit.
407 *
408 * @param str NULL-terminated string.
409 * @param size Maximum number of bytes to consider.
410 *
411 * @return Number of characters in string.
412 *
413 */
414size_t str_nlength(const char *str, size_t size)
415{
416 size_t len = 0;
417 size_t offset = 0;
418
419 while (str_decode(str, &offset, size) != 0)
420 len++;
421
422 return len;
423}
424
425/** Get number of characters in a string with size limit.
426 *
427 * @param str NULL-terminated string.
428 * @param size Maximum number of bytes to consider.
429 *
430 * @return Number of characters in string.
431 *
432 */
433size_t wstr_nlength(const wchar_t *str, size_t size)
434{
435 size_t len = 0;
436 size_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
437 size_t offset = 0;
438
439 while ((offset < limit) && (*str++ != 0)) {
440 len++;
441 offset += sizeof(wchar_t);
442 }
443
444 return len;
445}
446
447/** Get character display width on a character cell display.
448 *
449 * @param ch Character
450 * @return Width of character in cells.
451 */
452size_t chr_width(wchar_t ch)
453{
454 return 1;
455}
456
457/** Get string display width on a character cell display.
458 *
459 * @param str String
460 * @return Width of string in cells.
461 */
462size_t str_width(const char *str)
463{
464 size_t width = 0;
465 size_t offset = 0;
466 wchar_t ch;
467
468 while ((ch = str_decode(str, &offset, STR_NO_LIMIT)) != 0)
469 width += chr_width(ch);
470
471 return width;
472}
473
474/** Check whether character is plain ASCII.
475 *
476 * @return True if character is plain ASCII.
477 *
478 */
479bool ascii_check(wchar_t ch)
480{
481 if (WCHAR_SIGNED_CHECK(ch >= 0) && (ch <= 127))
482 return true;
483
484 return false;
485}
486
487/** Check whether character is valid
488 *
489 * @return True if character is a valid Unicode code point.
490 *
491 */
492bool chr_check(wchar_t ch)
493{
494 if (WCHAR_SIGNED_CHECK(ch >= 0) && (ch <= 1114111))
495 return true;
496
497 return false;
498}
499
500/** Compare two NULL terminated strings.
501 *
502 * Do a char-by-char comparison of two NULL-terminated strings.
503 * The strings are considered equal iff their length is equal
504 * and both strings consist of the same sequence of characters.
505 *
506 * A string S1 is less than another string S2 if it has a character with
507 * lower value at the first character position where the strings differ.
508 * If the strings differ in length, the shorter one is treated as if
509 * padded by characters with a value of zero.
510 *
511 * @param s1 First string to compare.
512 * @param s2 Second string to compare.
513 *
514 * @return 0 if the strings are equal, -1 if the first is less than the second,
515 * 1 if the second is less than the first.
516 *
517 */
518int str_cmp(const char *s1, const char *s2)
519{
520 wchar_t c1 = 0;
521 wchar_t c2 = 0;
522
523 size_t off1 = 0;
524 size_t off2 = 0;
525
526 while (true) {
527 c1 = str_decode(s1, &off1, STR_NO_LIMIT);
528 c2 = str_decode(s2, &off2, STR_NO_LIMIT);
529
530 if (c1 < c2)
531 return -1;
532
533 if (c1 > c2)
534 return 1;
535
536 if (c1 == 0 || c2 == 0)
537 break;
538 }
539
540 return 0;
541}
542
543/** Compare two NULL terminated strings with length limit.
544 *
545 * Do a char-by-char comparison of two NULL-terminated strings.
546 * The strings are considered equal iff
547 * min(str_length(s1), max_len) == min(str_length(s2), max_len)
548 * and both strings consist of the same sequence of characters,
549 * up to max_len characters.
550 *
551 * A string S1 is less than another string S2 if it has a character with
552 * lower value at the first character position where the strings differ.
553 * If the strings differ in length, the shorter one is treated as if
554 * padded by characters with a value of zero. Only the first max_len
555 * characters are considered.
556 *
557 * @param s1 First string to compare.
558 * @param s2 Second string to compare.
559 * @param max_len Maximum number of characters to consider.
560 *
561 * @return 0 if the strings are equal, -1 if the first is less than the second,
562 * 1 if the second is less than the first.
563 *
564 */
565int str_lcmp(const char *s1, const char *s2, size_t max_len)
566{
567 wchar_t c1 = 0;
568 wchar_t c2 = 0;
569
570 size_t off1 = 0;
571 size_t off2 = 0;
572
573 size_t len = 0;
574
575 while (true) {
576 if (len >= max_len)
577 break;
578
579 c1 = str_decode(s1, &off1, STR_NO_LIMIT);
580 c2 = str_decode(s2, &off2, STR_NO_LIMIT);
581
582 if (c1 < c2)
583 return -1;
584
585 if (c1 > c2)
586 return 1;
587
588 if (c1 == 0 || c2 == 0)
589 break;
590
591 ++len;
592 }
593
594 return 0;
595
596}
597
598/** Compare two NULL terminated strings in case-insensitive manner.
599 *
600 * Do a char-by-char comparison of two NULL-terminated strings.
601 * The strings are considered equal iff their length is equal
602 * and both strings consist of the same sequence of characters
603 * when converted to lower case.
604 *
605 * A string S1 is less than another string S2 if it has a character with
606 * lower value at the first character position where the strings differ.
607 * If the strings differ in length, the shorter one is treated as if
608 * padded by characters with a value of zero.
609 *
610 * @param s1 First string to compare.
611 * @param s2 Second string to compare.
612 *
613 * @return 0 if the strings are equal, -1 if the first is less than the second,
614 * 1 if the second is less than the first.
615 *
616 */
617int str_casecmp(const char *s1, const char *s2)
618{
619 wchar_t c1 = 0;
620 wchar_t c2 = 0;
621
622 size_t off1 = 0;
623 size_t off2 = 0;
624
625 while (true) {
626 c1 = tolower(str_decode(s1, &off1, STR_NO_LIMIT));
627 c2 = tolower(str_decode(s2, &off2, STR_NO_LIMIT));
628
629 if (c1 < c2)
630 return -1;
631
632 if (c1 > c2)
633 return 1;
634
635 if (c1 == 0 || c2 == 0)
636 break;
637 }
638
639 return 0;
640}
641
642/** Compare two NULL terminated strings with length limit in case-insensitive
643 * manner.
644 *
645 * Do a char-by-char comparison of two NULL-terminated strings.
646 * The strings are considered equal iff
647 * min(str_length(s1), max_len) == min(str_length(s2), max_len)
648 * and both strings consist of the same sequence of characters,
649 * up to max_len characters.
650 *
651 * A string S1 is less than another string S2 if it has a character with
652 * lower value at the first character position where the strings differ.
653 * If the strings differ in length, the shorter one is treated as if
654 * padded by characters with a value of zero. Only the first max_len
655 * characters are considered.
656 *
657 * @param s1 First string to compare.
658 * @param s2 Second string to compare.
659 * @param max_len Maximum number of characters to consider.
660 *
661 * @return 0 if the strings are equal, -1 if the first is less than the second,
662 * 1 if the second is less than the first.
663 *
664 */
665int str_lcasecmp(const char *s1, const char *s2, size_t max_len)
666{
667 wchar_t c1 = 0;
668 wchar_t c2 = 0;
669
670 size_t off1 = 0;
671 size_t off2 = 0;
672
673 size_t len = 0;
674
675 while (true) {
676 if (len >= max_len)
677 break;
678
679 c1 = tolower(str_decode(s1, &off1, STR_NO_LIMIT));
680 c2 = tolower(str_decode(s2, &off2, STR_NO_LIMIT));
681
682 if (c1 < c2)
683 return -1;
684
685 if (c1 > c2)
686 return 1;
687
688 if (c1 == 0 || c2 == 0)
689 break;
690
691 ++len;
692 }
693
694 return 0;
695
696}
697
698/** Test whether p is a prefix of s.
699 *
700 * Do a char-by-char comparison of two NULL-terminated strings
701 * and determine if p is a prefix of s.
702 *
703 * @param s The string in which to look
704 * @param p The string to check if it is a prefix of s
705 *
706 * @return true iff p is prefix of s else false
707 *
708 */
709bool str_test_prefix(const char *s, const char *p)
710{
711 wchar_t c1 = 0;
712 wchar_t c2 = 0;
713
714 size_t off1 = 0;
715 size_t off2 = 0;
716
717 while (true) {
718 c1 = str_decode(s, &off1, STR_NO_LIMIT);
719 c2 = str_decode(p, &off2, STR_NO_LIMIT);
720
721 if (c2 == 0)
722 return true;
723
724 if (c1 != c2)
725 return false;
726
727 if (c1 == 0)
728 break;
729 }
730
731 return false;
732}
733
734/** Copy string.
735 *
736 * Copy source string @a src to destination buffer @a dest.
737 * No more than @a size bytes are written. If the size of the output buffer
738 * is at least one byte, the output string will always be well-formed, i.e.
739 * null-terminated and containing only complete characters.
740 *
741 * @param dest Destination buffer.
742 * @param count Size of the destination buffer (must be > 0).
743 * @param src Source string.
744 *
745 */
746void str_cpy(char *dest, size_t size, const char *src)
747{
748 /* There must be space for a null terminator in the buffer. */
749 assert(size > 0);
750
751 size_t src_off = 0;
752 size_t dest_off = 0;
753
754 wchar_t ch;
755 while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) {
756 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
757 break;
758 }
759
760 dest[dest_off] = '\0';
761}
762
763/** Copy size-limited substring.
764 *
765 * Copy prefix of string @a src of max. size @a size to destination buffer
766 * @a dest. No more than @a size bytes are written. The output string will
767 * always be well-formed, i.e. null-terminated and containing only complete
768 * characters.
769 *
770 * No more than @a n bytes are read from the input string, so it does not
771 * have to be null-terminated.
772 *
773 * @param dest Destination buffer.
774 * @param count Size of the destination buffer (must be > 0).
775 * @param src Source string.
776 * @param n Maximum number of bytes to read from @a src.
777 *
778 */
779void str_ncpy(char *dest, size_t size, const char *src, size_t n)
780{
781 /* There must be space for a null terminator in the buffer. */
782 assert(size > 0);
783
784 size_t src_off = 0;
785 size_t dest_off = 0;
786
787 wchar_t ch;
788 while ((ch = str_decode(src, &src_off, n)) != 0) {
789 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
790 break;
791 }
792
793 dest[dest_off] = '\0';
794}
795
796/** Append one string to another.
797 *
798 * Append source string @a src to string in destination buffer @a dest.
799 * Size of the destination buffer is @a dest. If the size of the output buffer
800 * is at least one byte, the output string will always be well-formed, i.e.
801 * null-terminated and containing only complete characters.
802 *
803 * @param dest Destination buffer.
804 * @param count Size of the destination buffer.
805 * @param src Source string.
806 */
807void str_append(char *dest, size_t size, const char *src)
808{
809 size_t dstr_size;
810
811 dstr_size = str_size(dest);
812 if (dstr_size >= size)
813 return;
814
815 str_cpy(dest + dstr_size, size - dstr_size, src);
816}
817
818/** Convert space-padded ASCII to string.
819 *
820 * Common legacy text encoding in hardware is 7-bit ASCII fitted into
821 * a fixed-width byte buffer (bit 7 always zero), right-padded with spaces
822 * (ASCII 0x20). Convert space-padded ascii to string representation.
823 *
824 * If the text does not fit into the destination buffer, the function converts
825 * as many characters as possible and returns EOVERFLOW.
826 *
827 * If the text contains non-ASCII bytes (with bit 7 set), the whole string is
828 * converted anyway and invalid characters are replaced with question marks
829 * (U_SPECIAL) and the function returns EIO.
830 *
831 * Regardless of return value upon return @a dest will always be well-formed.
832 *
833 * @param dest Destination buffer
834 * @param size Size of destination buffer
835 * @param src Space-padded ASCII.
836 * @param n Size of the source buffer in bytes.
837 *
838 * @return EOK on success, EOVERFLOW if the text does not fit
839 * destination buffer, EIO if the text contains
840 * non-ASCII bytes.
841 */
842int spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n)
843{
844 size_t sidx;
845 size_t didx;
846 size_t dlast;
847 uint8_t byte;
848 int rc;
849 int result;
850
851 /* There must be space for a null terminator in the buffer. */
852 assert(size > 0);
853 result = EOK;
854
855 didx = 0;
856 dlast = 0;
857 for (sidx = 0; sidx < n; ++sidx) {
858 byte = src[sidx];
859 if (!ascii_check(byte)) {
860 byte = U_SPECIAL;
861 result = EIO;
862 }
863
864 rc = chr_encode(byte, dest, &didx, size - 1);
865 if (rc != EOK) {
866 assert(rc == EOVERFLOW);
867 dest[didx] = '\0';
868 return rc;
869 }
870
871 /* Remember dest index after last non-empty character */
872 if (byte != 0x20)
873 dlast = didx;
874 }
875
876 /* Terminate string after last non-empty character */
877 dest[dlast] = '\0';
878 return result;
879}
880
881/** Convert wide string to string.
882 *
883 * Convert wide string @a src to string. The output is written to the buffer
884 * specified by @a dest and @a size. @a size must be non-zero and the string
885 * written will always be well-formed.
886 *
887 * @param dest Destination buffer.
888 * @param size Size of the destination buffer.
889 * @param src Source wide string.
890 */
891void wstr_to_str(char *dest, size_t size, const wchar_t *src)
892{
893 wchar_t ch;
894 size_t src_idx;
895 size_t dest_off;
896
897 /* There must be space for a null terminator in the buffer. */
898 assert(size > 0);
899
900 src_idx = 0;
901 dest_off = 0;
902
903 while ((ch = src[src_idx++]) != 0) {
904 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
905 break;
906 }
907
908 dest[dest_off] = '\0';
909}
910
911/** Convert UTF16 string to string.
912 *
913 * Convert utf16 string @a src to string. The output is written to the buffer
914 * specified by @a dest and @a size. @a size must be non-zero and the string
915 * written will always be well-formed. Surrogate pairs also supported.
916 *
917 * @param dest Destination buffer.
918 * @param size Size of the destination buffer.
919 * @param src Source utf16 string.
920 *
921 * @return EOK, if success, negative otherwise.
922 */
923int utf16_to_str(char *dest, size_t size, const uint16_t *src)
924{
925 size_t idx = 0, dest_off = 0;
926 wchar_t ch;
927 int rc = EOK;
928
929 /* There must be space for a null terminator in the buffer. */
930 assert(size > 0);
931
932 while (src[idx]) {
933 if ((src[idx] & 0xfc00) == 0xd800) {
934 if (src[idx + 1] && (src[idx + 1] & 0xfc00) == 0xdc00) {
935 ch = 0x10000;
936 ch += (src[idx] & 0x03FF) << 10;
937 ch += (src[idx + 1] & 0x03FF);
938 idx += 2;
939 }
940 else
941 break;
942 } else {
943 ch = src[idx];
944 idx++;
945 }
946 rc = chr_encode(ch, dest, &dest_off, size - 1);
947 if (rc != EOK)
948 break;
949 }
950 dest[dest_off] = '\0';
951 return rc;
952}
953
954/** Convert string to UTF16 string.
955 *
956 * Convert string @a src to utf16 string. The output is written to the buffer
957 * specified by @a dest and @a dlen. @a dlen must be non-zero and the string
958 * written will always be well-formed. Surrogate pairs also supported.
959 *
960 * @param dest Destination buffer.
961 * @param dlen Number of utf16 characters that fit in the destination buffer.
962 * @param src Source string.
963 *
964 * @return EOK, if success, negative otherwise.
965 */
966int str_to_utf16(uint16_t *dest, size_t dlen, const char *src)
967{
968 int rc = EOK;
969 size_t offset = 0;
970 size_t idx = 0;
971 wchar_t c;
972
973 assert(dlen > 0);
974
975 while ((c = str_decode(src, &offset, STR_NO_LIMIT)) != 0) {
976 if (c > 0x10000) {
977 if (idx + 2 >= dlen - 1) {
978 rc = EOVERFLOW;
979 break;
980 }
981 c = (c - 0x10000);
982 dest[idx] = 0xD800 | (c >> 10);
983 dest[idx + 1] = 0xDC00 | (c & 0x3FF);
984 idx++;
985 } else {
986 dest[idx] = c;
987 }
988
989 idx++;
990 if (idx >= dlen - 1) {
991 rc = EOVERFLOW;
992 break;
993 }
994 }
995
996 dest[idx] = '\0';
997 return rc;
998}
999
1000/** Get size of UTF-16 string.
1001 *
1002 * Get the number of words which are used by the UTF-16 string @a ustr
1003 * (excluding the NULL-terminator).
1004 *
1005 * @param ustr UTF-16 string to consider.
1006 *
1007 * @return Number of words used by the UTF-16 string
1008 *
1009 */
1010size_t utf16_wsize(const uint16_t *ustr)
1011{
1012 size_t wsize = 0;
1013
1014 while (*ustr++ != 0)
1015 wsize++;
1016
1017 return wsize;
1018}
1019
1020
1021/** Convert wide string to new string.
1022 *
1023 * Convert wide string @a src to string. Space for the new string is allocated
1024 * on the heap.
1025 *
1026 * @param src Source wide string.
1027 * @return New string.
1028 */
1029char *wstr_to_astr(const wchar_t *src)
1030{
1031 char dbuf[STR_BOUNDS(1)];
1032 char *str;
1033 wchar_t ch;
1034
1035 size_t src_idx;
1036 size_t dest_off;
1037 size_t dest_size;
1038
1039 /* Compute size of encoded string. */
1040
1041 src_idx = 0;
1042 dest_size = 0;
1043
1044 while ((ch = src[src_idx++]) != 0) {
1045 dest_off = 0;
1046 if (chr_encode(ch, dbuf, &dest_off, STR_BOUNDS(1)) != EOK)
1047 break;
1048 dest_size += dest_off;
1049 }
1050
1051 str = malloc(dest_size + 1);
1052 if (str == NULL)
1053 return NULL;
1054
1055 /* Encode string. */
1056
1057 src_idx = 0;
1058 dest_off = 0;
1059
1060 while ((ch = src[src_idx++]) != 0) {
1061 if (chr_encode(ch, str, &dest_off, dest_size) != EOK)
1062 break;
1063 }
1064
1065 str[dest_size] = '\0';
1066 return str;
1067}
1068
1069
1070/** Convert string to wide string.
1071 *
1072 * Convert string @a src to wide string. The output is written to the
1073 * buffer specified by @a dest and @a dlen. @a dlen must be non-zero
1074 * and the wide string written will always be null-terminated.
1075 *
1076 * @param dest Destination buffer.
1077 * @param dlen Length of destination buffer (number of wchars).
1078 * @param src Source string.
1079 */
1080void str_to_wstr(wchar_t *dest, size_t dlen, const char *src)
1081{
1082 size_t offset;
1083 size_t di;
1084 wchar_t c;
1085
1086 assert(dlen > 0);
1087
1088 offset = 0;
1089 di = 0;
1090
1091 do {
1092 if (di >= dlen - 1)
1093 break;
1094
1095 c = str_decode(src, &offset, STR_NO_LIMIT);
1096 dest[di++] = c;
1097 } while (c != '\0');
1098
1099 dest[dlen - 1] = '\0';
1100}
1101
1102/** Convert string to wide string.
1103 *
1104 * Convert string @a src to wide string. A new wide NULL-terminated
1105 * string will be allocated on the heap.
1106 *
1107 * @param src Source string.
1108 */
1109wchar_t *str_to_awstr(const char *str)
1110{
1111 size_t len = str_length(str);
1112
1113 wchar_t *wstr = calloc(len+1, sizeof(wchar_t));
1114 if (wstr == NULL)
1115 return NULL;
1116
1117 str_to_wstr(wstr, len + 1, str);
1118 return wstr;
1119}
1120
1121/** Find first occurence of character in string.
1122 *
1123 * @param str String to search.
1124 * @param ch Character to look for.
1125 *
1126 * @return Pointer to character in @a str or NULL if not found.
1127 */
1128char *str_chr(const char *str, wchar_t ch)
1129{
1130 wchar_t acc;
1131 size_t off = 0;
1132 size_t last = 0;
1133
1134 while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
1135 if (acc == ch)
1136 return (char *) (str + last);
1137 last = off;
1138 }
1139
1140 return NULL;
1141}
1142
1143/** Removes specified trailing characters from a string.
1144 *
1145 * @param str String to remove from.
1146 * @param ch Character to remove.
1147 */
1148void str_rtrim(char *str, wchar_t ch)
1149{
1150 size_t off = 0;
1151 size_t pos = 0;
1152 wchar_t c;
1153 bool update_last_chunk = true;
1154 char *last_chunk = NULL;
1155
1156 while ((c = str_decode(str, &off, STR_NO_LIMIT))) {
1157 if (c != ch) {
1158 update_last_chunk = true;
1159 last_chunk = NULL;
1160 } else if (update_last_chunk) {
1161 update_last_chunk = false;
1162 last_chunk = (str + pos);
1163 }
1164 pos = off;
1165 }
1166
1167 if (last_chunk)
1168 *last_chunk = '\0';
1169}
1170
1171/** Removes specified leading characters from a string.
1172 *
1173 * @param str String to remove from.
1174 * @param ch Character to remove.
1175 */
1176void str_ltrim(char *str, wchar_t ch)
1177{
1178 wchar_t acc;
1179 size_t off = 0;
1180 size_t pos = 0;
1181 size_t str_sz = str_size(str);
1182
1183 while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
1184 if (acc != ch)
1185 break;
1186 else
1187 pos = off;
1188 }
1189
1190 if (pos > 0) {
1191 memmove(str, &str[pos], str_sz - pos);
1192 pos = str_sz - pos;
1193 str[pos] = '\0';
1194 }
1195}
1196
1197/** Find last occurence of character in string.
1198 *
1199 * @param str String to search.
1200 * @param ch Character to look for.
1201 *
1202 * @return Pointer to character in @a str or NULL if not found.
1203 */
1204char *str_rchr(const char *str, wchar_t ch)
1205{
1206 wchar_t acc;
1207 size_t off = 0;
1208 size_t last = 0;
1209 const char *res = NULL;
1210
1211 while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
1212 if (acc == ch)
1213 res = (str + last);
1214 last = off;
1215 }
1216
1217 return (char *) res;
1218}
1219
1220/** Insert a wide character into a wide string.
1221 *
1222 * Insert a wide character into a wide string at position
1223 * @a pos. The characters after the position are shifted.
1224 *
1225 * @param str String to insert to.
1226 * @param ch Character to insert to.
1227 * @param pos Character index where to insert.
1228 @ @param max_pos Characters in the buffer.
1229 *
1230 * @return True if the insertion was sucessful, false if the position
1231 * is out of bounds.
1232 *
1233 */
1234bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos)
1235{
1236 size_t len = wstr_length(str);
1237
1238 if ((pos > len) || (pos + 1 > max_pos))
1239 return false;
1240
1241 size_t i;
1242 for (i = len; i + 1 > pos; i--)
1243 str[i + 1] = str[i];
1244
1245 str[pos] = ch;
1246
1247 return true;
1248}
1249
1250/** Remove a wide character from a wide string.
1251 *
1252 * Remove a wide character from a wide string at position
1253 * @a pos. The characters after the position are shifted.
1254 *
1255 * @param str String to remove from.
1256 * @param pos Character index to remove.
1257 *
1258 * @return True if the removal was sucessful, false if the position
1259 * is out of bounds.
1260 *
1261 */
1262bool wstr_remove(wchar_t *str, size_t pos)
1263{
1264 size_t len = wstr_length(str);
1265
1266 if (pos >= len)
1267 return false;
1268
1269 size_t i;
1270 for (i = pos + 1; i <= len; i++)
1271 str[i - 1] = str[i];
1272
1273 return true;
1274}
1275
1276/** Convert string to a number.
1277 * Core of strtol and strtoul functions.
1278 *
1279 * @param nptr Pointer to string.
1280 * @param endptr If not NULL, function stores here pointer to the first
1281 * invalid character.
1282 * @param base Zero or number between 2 and 36 inclusive.
1283 * @param sgn It's set to 1 if minus found.
1284 * @return Result of conversion.
1285 */
1286static unsigned long
1287_strtoul(const char *nptr, char **endptr, int base, char *sgn)
1288{
1289 unsigned char c;
1290 unsigned long result = 0;
1291 unsigned long a, b;
1292 const char *str = nptr;
1293 const char *tmpptr;
1294
1295 while (isspace(*str))
1296 str++;
1297
1298 if (*str == '-') {
1299 *sgn = 1;
1300 ++str;
1301 } else if (*str == '+')
1302 ++str;
1303
1304 if (base) {
1305 if ((base == 1) || (base > 36)) {
1306 /* FIXME: set errno to EINVAL */
1307 return 0;
1308 }
1309 if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
1310 (str[1] == 'X'))) {
1311 str += 2;
1312 }
1313 } else {
1314 base = 10;
1315
1316 if (*str == '0') {
1317 base = 8;
1318 if ((str[1] == 'X') || (str[1] == 'x')) {
1319 base = 16;
1320 str += 2;
1321 }
1322 }
1323 }
1324
1325 tmpptr = str;
1326
1327 while (*str) {
1328 c = *str;
1329 c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
1330 (c <= '9' ? c - '0' : 0xff)));
1331 if (c >= base) {
1332 break;
1333 }
1334
1335 a = (result & 0xff) * base + c;
1336 b = (result >> 8) * base + (a >> 8);
1337
1338 if (b > (ULONG_MAX >> 8)) {
1339 /* overflow */
1340 /* FIXME: errno = ERANGE*/
1341 return ULONG_MAX;
1342 }
1343
1344 result = (b << 8) + (a & 0xff);
1345 ++str;
1346 }
1347
1348 if (str == tmpptr) {
1349 /*
1350 * No number was found => first invalid character is the first
1351 * character of the string.
1352 */
1353 /* FIXME: set errno to EINVAL */
1354 str = nptr;
1355 result = 0;
1356 }
1357
1358 if (endptr)
1359 *endptr = (char *) str;
1360
1361 if (nptr == str) {
1362 /*FIXME: errno = EINVAL*/
1363 return 0;
1364 }
1365
1366 return result;
1367}
1368
1369/** Convert initial part of string to long int according to given base.
1370 * The number may begin with an arbitrary number of whitespaces followed by
1371 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
1372 * inserted and the number will be taken as hexadecimal one. If the base is 0
1373 * and the number begin with a zero, number will be taken as octal one (as with
1374 * base 8). Otherwise the base 0 is taken as decimal.
1375 *
1376 * @param nptr Pointer to string.
1377 * @param endptr If not NULL, function stores here pointer to the first
1378 * invalid character.
1379 * @param base Zero or number between 2 and 36 inclusive.
1380 * @return Result of conversion.
1381 */
1382long int strtol(const char *nptr, char **endptr, int base)
1383{
1384 char sgn = 0;
1385 unsigned long number = 0;
1386
1387 number = _strtoul(nptr, endptr, base, &sgn);
1388
1389 if (number > LONG_MAX) {
1390 if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
1391 /* FIXME: set 0 to errno */
1392 return number;
1393 }
1394 /* FIXME: set ERANGE to errno */
1395 return (sgn ? LONG_MIN : LONG_MAX);
1396 }
1397
1398 return (sgn ? -number : number);
1399}
1400
1401/** Duplicate string.
1402 *
1403 * Allocate a new string and copy characters from the source
1404 * string into it. The duplicate string is allocated via sleeping
1405 * malloc(), thus this function can sleep in no memory conditions.
1406 *
1407 * The allocation cannot fail and the return value is always
1408 * a valid pointer. The duplicate string is always a well-formed
1409 * null-terminated UTF-8 string, but it can differ from the source
1410 * string on the byte level.
1411 *
1412 * @param src Source string.
1413 *
1414 * @return Duplicate string.
1415 *
1416 */
1417char *str_dup(const char *src)
1418{
1419 size_t size = str_size(src) + 1;
1420 char *dest = (char *) malloc(size);
1421 if (dest == NULL)
1422 return (char *) NULL;
1423
1424 str_cpy(dest, size, src);
1425 return dest;
1426}
1427
1428/** Duplicate string with size limit.
1429 *
1430 * Allocate a new string and copy up to @max_size bytes from the source
1431 * string into it. The duplicate string is allocated via sleeping
1432 * malloc(), thus this function can sleep in no memory conditions.
1433 * No more than @max_size + 1 bytes is allocated, but if the size
1434 * occupied by the source string is smaller than @max_size + 1,
1435 * less is allocated.
1436 *
1437 * The allocation cannot fail and the return value is always
1438 * a valid pointer. The duplicate string is always a well-formed
1439 * null-terminated UTF-8 string, but it can differ from the source
1440 * string on the byte level.
1441 *
1442 * @param src Source string.
1443 * @param n Maximum number of bytes to duplicate.
1444 *
1445 * @return Duplicate string.
1446 *
1447 */
1448char *str_ndup(const char *src, size_t n)
1449{
1450 size_t size = str_size(src);
1451 if (size > n)
1452 size = n;
1453
1454 char *dest = (char *) malloc(size + 1);
1455 if (dest == NULL)
1456 return (char *) NULL;
1457
1458 str_ncpy(dest, size + 1, src, size);
1459 return dest;
1460}
1461
1462/** Convert initial part of string to unsigned long according to given base.
1463 * The number may begin with an arbitrary number of whitespaces followed by
1464 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
1465 * inserted and the number will be taken as hexadecimal one. If the base is 0
1466 * and the number begin with a zero, number will be taken as octal one (as with
1467 * base 8). Otherwise the base 0 is taken as decimal.
1468 *
1469 * @param nptr Pointer to string.
1470 * @param endptr If not NULL, function stores here pointer to the first
1471 * invalid character
1472 * @param base Zero or number between 2 and 36 inclusive.
1473 * @return Result of conversion.
1474 */
1475unsigned long strtoul(const char *nptr, char **endptr, int base)
1476{
1477 char sgn = 0;
1478 unsigned long number = 0;
1479
1480 number = _strtoul(nptr, endptr, base, &sgn);
1481
1482 return (sgn ? -number : number);
1483}
1484
1485/** Split string by delimiters.
1486 *
1487 * @param s String to be tokenized. May not be NULL.
1488 * @param delim String with the delimiters.
1489 * @param next Variable which will receive the pointer to the
1490 * continuation of the string following the first
1491 * occurrence of any of the delimiter characters.
1492 * May be NULL.
1493 * @return Pointer to the prefix of @a s before the first
1494 * delimiter character. NULL if no such prefix
1495 * exists.
1496 */
1497char *str_tok(char *s, const char *delim, char **next)
1498{
1499 char *start, *end;
1500
1501 if (!s)
1502 return NULL;
1503
1504 size_t len = str_size(s);
1505 size_t cur;
1506 size_t tmp;
1507 wchar_t ch;
1508
1509 /* Skip over leading delimiters. */
1510 for (tmp = cur = 0;
1511 (ch = str_decode(s, &tmp, len)) && str_chr(delim, ch); /**/)
1512 cur = tmp;
1513 start = &s[cur];
1514
1515 /* Skip over token characters. */
1516 for (tmp = cur;
1517 (ch = str_decode(s, &tmp, len)) && !str_chr(delim, ch); /**/)
1518 cur = tmp;
1519 end = &s[cur];
1520 if (next)
1521 *next = (ch ? &s[tmp] : &s[cur]);
1522
1523 if (start == end)
1524 return NULL; /* No more tokens. */
1525
1526 /* Overwrite delimiter with NULL terminator. */
1527 *end = '\0';
1528 return start;
1529}
1530
1531/** Convert string to uint64_t (internal variant).
1532 *
1533 * @param nptr Pointer to string.
1534 * @param endptr Pointer to the first invalid character is stored here.
1535 * @param base Zero or number between 2 and 36 inclusive.
1536 * @param neg Indication of unary minus is stored here.
1537 * @apram result Result of the conversion.
1538 *
1539 * @return EOK if conversion was successful.
1540 *
1541 */
1542static int str_uint(const char *nptr, char **endptr, unsigned int base,
1543 bool *neg, uint64_t *result)
1544{
1545 assert(endptr != NULL);
1546 assert(neg != NULL);
1547 assert(result != NULL);
1548
1549 *neg = false;
1550 const char *str = nptr;
1551
1552 /* Ignore leading whitespace */
1553 while (isspace(*str))
1554 str++;
1555
1556 if (*str == '-') {
1557 *neg = true;
1558 str++;
1559 } else if (*str == '+')
1560 str++;
1561
1562 if (base == 0) {
1563 /* Decode base if not specified */
1564 base = 10;
1565
1566 if (*str == '0') {
1567 base = 8;
1568 str++;
1569
1570 switch (*str) {
1571 case 'b':
1572 case 'B':
1573 base = 2;
1574 str++;
1575 break;
1576 case 'o':
1577 case 'O':
1578 base = 8;
1579 str++;
1580 break;
1581 case 'd':
1582 case 'D':
1583 case 't':
1584 case 'T':
1585 base = 10;
1586 str++;
1587 break;
1588 case 'x':
1589 case 'X':
1590 base = 16;
1591 str++;
1592 break;
1593 default:
1594 str--;
1595 }
1596 }
1597 } else {
1598 /* Check base range */
1599 if ((base < 2) || (base > 36)) {
1600 *endptr = (char *) str;
1601 return EINVAL;
1602 }
1603 }
1604
1605 *result = 0;
1606 const char *startstr = str;
1607
1608 while (*str != 0) {
1609 unsigned int digit;
1610
1611 if ((*str >= 'a') && (*str <= 'z'))
1612 digit = *str - 'a' + 10;
1613 else if ((*str >= 'A') && (*str <= 'Z'))
1614 digit = *str - 'A' + 10;
1615 else if ((*str >= '0') && (*str <= '9'))
1616 digit = *str - '0';
1617 else
1618 break;
1619
1620 if (digit >= base)
1621 break;
1622
1623 uint64_t prev = *result;
1624 *result = (*result) * base + digit;
1625
1626 if (*result < prev) {
1627 /* Overflow */
1628 *endptr = (char *) str;
1629 return EOVERFLOW;
1630 }
1631
1632 str++;
1633 }
1634
1635 if (str == startstr) {
1636 /*
1637 * No digits were decoded => first invalid character is
1638 * the first character of the string.
1639 */
1640 str = nptr;
1641 }
1642
1643 *endptr = (char *) str;
1644
1645 if (str == nptr)
1646 return EINVAL;
1647
1648 return EOK;
1649}
1650
1651/** Convert string to uint8_t.
1652 *
1653 * @param nptr Pointer to string.
1654 * @param endptr If not NULL, pointer to the first invalid character
1655 * is stored here.
1656 * @param base Zero or number between 2 and 36 inclusive.
1657 * @param strict Do not allow any trailing characters.
1658 * @param result Result of the conversion.
1659 *
1660 * @return EOK if conversion was successful.
1661 *
1662 */
1663int str_uint8_t(const char *nptr, const char **endptr, unsigned int base,
1664 bool strict, uint8_t *result)
1665{
1666 assert(result != NULL);
1667
1668 bool neg;
1669 char *lendptr;
1670 uint64_t res;
1671 int ret = str_uint(nptr, &lendptr, base, &neg, &res);
1672
1673 if (endptr != NULL)
1674 *endptr = (char *) lendptr;
1675
1676 if (ret != EOK)
1677 return ret;
1678
1679 /* Do not allow negative values */
1680 if (neg)
1681 return EINVAL;
1682
1683 /* Check whether we are at the end of
1684 the string in strict mode */
1685 if ((strict) && (*lendptr != 0))
1686 return EINVAL;
1687
1688 /* Check for overflow */
1689 uint8_t _res = (uint8_t) res;
1690 if (_res != res)
1691 return EOVERFLOW;
1692
1693 *result = _res;
1694
1695 return EOK;
1696}
1697
1698/** Convert string to uint16_t.
1699 *
1700 * @param nptr Pointer to string.
1701 * @param endptr If not NULL, pointer to the first invalid character
1702 * is stored here.
1703 * @param base Zero or number between 2 and 36 inclusive.
1704 * @param strict Do not allow any trailing characters.
1705 * @param result Result of the conversion.
1706 *
1707 * @return EOK if conversion was successful.
1708 *
1709 */
1710int str_uint16_t(const char *nptr, const char **endptr, unsigned int base,
1711 bool strict, uint16_t *result)
1712{
1713 assert(result != NULL);
1714
1715 bool neg;
1716 char *lendptr;
1717 uint64_t res;
1718 int ret = str_uint(nptr, &lendptr, base, &neg, &res);
1719
1720 if (endptr != NULL)
1721 *endptr = (char *) lendptr;
1722
1723 if (ret != EOK)
1724 return ret;
1725
1726 /* Do not allow negative values */
1727 if (neg)
1728 return EINVAL;
1729
1730 /* Check whether we are at the end of
1731 the string in strict mode */
1732 if ((strict) && (*lendptr != 0))
1733 return EINVAL;
1734
1735 /* Check for overflow */
1736 uint16_t _res = (uint16_t) res;
1737 if (_res != res)
1738 return EOVERFLOW;
1739
1740 *result = _res;
1741
1742 return EOK;
1743}
1744
1745/** Convert string to uint32_t.
1746 *
1747 * @param nptr Pointer to string.
1748 * @param endptr If not NULL, pointer to the first invalid character
1749 * is stored here.
1750 * @param base Zero or number between 2 and 36 inclusive.
1751 * @param strict Do not allow any trailing characters.
1752 * @param result Result of the conversion.
1753 *
1754 * @return EOK if conversion was successful.
1755 *
1756 */
1757int str_uint32_t(const char *nptr, const char **endptr, unsigned int base,
1758 bool strict, uint32_t *result)
1759{
1760 assert(result != NULL);
1761
1762 bool neg;
1763 char *lendptr;
1764 uint64_t res;
1765 int ret = str_uint(nptr, &lendptr, base, &neg, &res);
1766
1767 if (endptr != NULL)
1768 *endptr = (char *) lendptr;
1769
1770 if (ret != EOK)
1771 return ret;
1772
1773 /* Do not allow negative values */
1774 if (neg)
1775 return EINVAL;
1776
1777 /* Check whether we are at the end of
1778 the string in strict mode */
1779 if ((strict) && (*lendptr != 0))
1780 return EINVAL;
1781
1782 /* Check for overflow */
1783 uint32_t _res = (uint32_t) res;
1784 if (_res != res)
1785 return EOVERFLOW;
1786
1787 *result = _res;
1788
1789 return EOK;
1790}
1791
1792/** Convert string to uint64_t.
1793 *
1794 * @param nptr Pointer to string.
1795 * @param endptr If not NULL, pointer to the first invalid character
1796 * is stored here.
1797 * @param base Zero or number between 2 and 36 inclusive.
1798 * @param strict Do not allow any trailing characters.
1799 * @param result Result of the conversion.
1800 *
1801 * @return EOK if conversion was successful.
1802 *
1803 */
1804int str_uint64_t(const char *nptr, const char **endptr, unsigned int base,
1805 bool strict, uint64_t *result)
1806{
1807 assert(result != NULL);
1808
1809 bool neg;
1810 char *lendptr;
1811 int ret = str_uint(nptr, &lendptr, base, &neg, result);
1812
1813 if (endptr != NULL)
1814 *endptr = (char *) lendptr;
1815
1816 if (ret != EOK)
1817 return ret;
1818
1819 /* Do not allow negative values */
1820 if (neg)
1821 return EINVAL;
1822
1823 /* Check whether we are at the end of
1824 the string in strict mode */
1825 if ((strict) && (*lendptr != 0))
1826 return EINVAL;
1827
1828 return EOK;
1829}
1830
1831/** Convert string to size_t.
1832 *
1833 * @param nptr Pointer to string.
1834 * @param endptr If not NULL, pointer to the first invalid character
1835 * is stored here.
1836 * @param base Zero or number between 2 and 36 inclusive.
1837 * @param strict Do not allow any trailing characters.
1838 * @param result Result of the conversion.
1839 *
1840 * @return EOK if conversion was successful.
1841 *
1842 */
1843int str_size_t(const char *nptr, const char **endptr, unsigned int base,
1844 bool strict, size_t *result)
1845{
1846 assert(result != NULL);
1847
1848 bool neg;
1849 char *lendptr;
1850 uint64_t res;
1851 int ret = str_uint(nptr, &lendptr, base, &neg, &res);
1852
1853 if (endptr != NULL)
1854 *endptr = (char *) lendptr;
1855
1856 if (ret != EOK)
1857 return ret;
1858
1859 /* Do not allow negative values */
1860 if (neg)
1861 return EINVAL;
1862
1863 /* Check whether we are at the end of
1864 the string in strict mode */
1865 if ((strict) && (*lendptr != 0))
1866 return EINVAL;
1867
1868 /* Check for overflow */
1869 size_t _res = (size_t) res;
1870 if (_res != res)
1871 return EOVERFLOW;
1872
1873 *result = _res;
1874
1875 return EOK;
1876}
1877
1878void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
1879{
1880 if (val > UINT64_C(10000000000000000000)) {
1881 *rv = val / UINT64_C(1000000000000000000);
1882 *suffix = 'Z';
1883 } else if (val > UINT64_C(1000000000000000000)) {
1884 *rv = val / UINT64_C(1000000000000000);
1885 *suffix = 'E';
1886 } else if (val > UINT64_C(1000000000000000)) {
1887 *rv = val / UINT64_C(1000000000000);
1888 *suffix = 'T';
1889 } else if (val > UINT64_C(1000000000000)) {
1890 *rv = val / UINT64_C(1000000000);
1891 *suffix = 'G';
1892 } else if (val > UINT64_C(1000000000)) {
1893 *rv = val / UINT64_C(1000000);
1894 *suffix = 'M';
1895 } else if (val > UINT64_C(1000000)) {
1896 *rv = val / UINT64_C(1000);
1897 *suffix = 'k';
1898 } else {
1899 *rv = val;
1900 *suffix = ' ';
1901 }
1902}
1903
1904void bin_order_suffix(const uint64_t val, uint64_t *rv, const char **suffix,
1905 bool fixed)
1906{
1907 if (val > UINT64_C(1152921504606846976)) {
1908 *rv = val / UINT64_C(1125899906842624);
1909 *suffix = "EiB";
1910 } else if (val > UINT64_C(1125899906842624)) {
1911 *rv = val / UINT64_C(1099511627776);
1912 *suffix = "TiB";
1913 } else if (val > UINT64_C(1099511627776)) {
1914 *rv = val / UINT64_C(1073741824);
1915 *suffix = "GiB";
1916 } else if (val > UINT64_C(1073741824)) {
1917 *rv = val / UINT64_C(1048576);
1918 *suffix = "MiB";
1919 } else if (val > UINT64_C(1048576)) {
1920 *rv = val / UINT64_C(1024);
1921 *suffix = "KiB";
1922 } else {
1923 *rv = val;
1924 if (fixed)
1925 *suffix = "B ";
1926 else
1927 *suffix = "B";
1928 }
1929}
1930
1931/** @}
1932 */
Note: See TracBrowser for help on using the repository browser.