Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/lib/str.c

    raafed15 r42e91ae  
    11/*
    22 * Copyright (c) 2001-2004 Jakub Jermar
     3 * Copyright (c) 2005 Martin Decky
     4 * Copyright (c) 2008 Jiri Svoboda
     5 * Copyright (c) 2011 Martin Sucha
     6 * Copyright (c) 2011 Oleg Romanenko
    37 * All rights reserved.
    48 *
     
    103107
    104108#include <str.h>
    105 #include <cpu.h>
    106 #include <arch/asm.h>
    107 #include <arch.h>
     109
     110#include <assert.h>
    108111#include <errno.h>
     112#include <stdbool.h>
     113#include <stddef.h>
     114#include <stdint.h>
     115#include <stdlib.h>
     116
    109117#include <align.h>
    110 #include <assert.h>
    111118#include <macros.h>
    112 #include <stdlib.h>
    113119
    114120/** Check the condition if wchar_t is signed */
     
    616622}
    617623
     624/** Convert wide string to string.
     625 *
     626 * Convert wide string @a src to string. The output is written to the buffer
     627 * specified by @a dest and @a size. @a size must be non-zero and the string
     628 * written will always be well-formed.
     629 *
     630 * @param dest  Destination buffer.
     631 * @param size  Size of the destination buffer.
     632 * @param src   Source wide string.
     633 */
     634void wstr_to_str(char *dest, size_t size, const wchar_t *src)
     635{
     636        wchar_t ch;
     637        size_t src_idx;
     638        size_t dest_off;
     639
     640        /* There must be space for a null terminator in the buffer. */
     641        assert(size > 0);
     642
     643        src_idx = 0;
     644        dest_off = 0;
     645
     646        while ((ch = src[src_idx++]) != 0) {
     647                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
     648                        break;
     649        }
     650
     651        dest[dest_off] = '\0';
     652}
     653
     654/** Find first occurence of character in string.
     655 *
     656 * @param str String to search.
     657 * @param ch  Character to look for.
     658 *
     659 * @return Pointer to character in @a str or NULL if not found.
     660 */
     661char *str_chr(const char *str, wchar_t ch)
     662{
     663        wchar_t acc;
     664        size_t off = 0;
     665        size_t last = 0;
     666
     667        while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
     668                if (acc == ch)
     669                        return (char *) (str + last);
     670                last = off;
     671        }
     672
     673        return NULL;
     674}
     675
     676/** Insert a wide character into a wide string.
     677 *
     678 * Insert a wide character into a wide string at position
     679 * @a pos. The characters after the position are shifted.
     680 *
     681 * @param str     String to insert to.
     682 * @param ch      Character to insert to.
     683 * @param pos     Character index where to insert.
     684 * @param max_pos Characters in the buffer.
     685 *
     686 * @return True if the insertion was sucessful, false if the position
     687 *         is out of bounds.
     688 *
     689 */
     690bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos)
     691{
     692        size_t len = wstr_length(str);
     693
     694        if ((pos > len) || (pos + 1 > max_pos))
     695                return false;
     696
     697        size_t i;
     698        for (i = len; i + 1 > pos; i--)
     699                str[i + 1] = str[i];
     700
     701        str[pos] = ch;
     702
     703        return true;
     704}
     705
     706/** Remove a wide character from a wide string.
     707 *
     708 * Remove a wide character from a wide string at position
     709 * @a pos. The characters after the position are shifted.
     710 *
     711 * @param str String to remove from.
     712 * @param pos Character index to remove.
     713 *
     714 * @return True if the removal was sucessful, false if the position
     715 *         is out of bounds.
     716 *
     717 */
     718bool wstr_remove(wchar_t *str, size_t pos)
     719{
     720        size_t len = wstr_length(str);
     721
     722        if (pos >= len)
     723                return false;
     724
     725        size_t i;
     726        for (i = pos + 1; i <= len; i++)
     727                str[i - 1] = str[i];
     728
     729        return true;
     730}
     731
    618732/** Duplicate string.
    619733 *
     
    675789        str_ncpy(dest, size + 1, src, size);
    676790        return dest;
    677 }
    678 
    679 /** Convert wide string to string.
    680  *
    681  * Convert wide string @a src to string. The output is written to the buffer
    682  * specified by @a dest and @a size. @a size must be non-zero and the string
    683  * written will always be well-formed.
    684  *
    685  * @param dest  Destination buffer.
    686  * @param size  Size of the destination buffer.
    687  * @param src   Source wide string.
    688  */
    689 void wstr_to_str(char *dest, size_t size, const wchar_t *src)
    690 {
    691         wchar_t ch;
    692         size_t src_idx;
    693         size_t dest_off;
    694 
    695         /* There must be space for a null terminator in the buffer. */
    696         assert(size > 0);
    697 
    698         src_idx = 0;
    699         dest_off = 0;
    700 
    701         while ((ch = src[src_idx++]) != 0) {
    702                 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    703                         break;
    704         }
    705 
    706         dest[dest_off] = '\0';
    707 }
    708 
    709 /** Find first occurence of character in string.
    710  *
    711  * @param str String to search.
    712  * @param ch  Character to look for.
    713  *
    714  * @return Pointer to character in @a str or NULL if not found.
    715  *
    716  */
    717 char *str_chr(const char *str, wchar_t ch)
    718 {
    719         wchar_t acc;
    720         size_t off = 0;
    721         size_t last = 0;
    722 
    723         while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
    724                 if (acc == ch)
    725                         return (char *) (str + last);
    726                 last = off;
    727         }
    728 
    729         return NULL;
    730 }
    731 
    732 /** Insert a wide character into a wide string.
    733  *
    734  * Insert a wide character into a wide string at position
    735  * @a pos. The characters after the position are shifted.
    736  *
    737  * @param str     String to insert to.
    738  * @param ch      Character to insert to.
    739  * @param pos     Character index where to insert.
    740  * @param max_pos Characters in the buffer.
    741  *
    742  * @return True if the insertion was sucessful, false if the position
    743  *         is out of bounds.
    744  *
    745  */
    746 bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos)
    747 {
    748         size_t len = wstr_length(str);
    749 
    750         if ((pos > len) || (pos + 1 > max_pos))
    751                 return false;
    752 
    753         size_t i;
    754         for (i = len; i + 1 > pos; i--)
    755                 str[i + 1] = str[i];
    756 
    757         str[pos] = ch;
    758 
    759         return true;
    760 }
    761 
    762 /** Remove a wide character from a wide string.
    763  *
    764  * Remove a wide character from a wide string at position
    765  * @a pos. The characters after the position are shifted.
    766  *
    767  * @param str String to remove from.
    768  * @param pos Character index to remove.
    769  *
    770  * @return True if the removal was sucessful, false if the position
    771  *         is out of bounds.
    772  *
    773  */
    774 bool wstr_remove(wchar_t *str, size_t pos)
    775 {
    776         size_t len = wstr_length(str);
    777 
    778         if (pos >= len)
    779                 return false;
    780 
    781         size_t i;
    782         for (i = pos + 1; i <= len; i++)
    783                 str[i - 1] = str[i];
    784 
    785         return true;
    786 }
    787 
    788 /** Convert string to uint64_t (internal variant).
    789  *
    790  * @param nptr   Pointer to string.
    791  * @param endptr Pointer to the first invalid character is stored here.
    792  * @param base   Zero or number between 2 and 36 inclusive.
    793  * @param neg    Indication of unary minus is stored here.
    794  * @apram result Result of the conversion.
    795  *
    796  * @return EOK if conversion was successful.
    797  *
    798  */
    799 static errno_t str_uint(const char *nptr, char **endptr, unsigned int base,
    800     bool *neg, uint64_t *result)
    801 {
    802         assert(endptr != NULL);
    803         assert(neg != NULL);
    804         assert(result != NULL);
    805 
    806         *neg = false;
    807         const char *str = nptr;
    808 
    809         /* Ignore leading whitespace */
    810         while (isspace(*str))
    811                 str++;
    812 
    813         if (*str == '-') {
    814                 *neg = true;
    815                 str++;
    816         } else if (*str == '+')
    817                 str++;
    818 
    819         if (base == 0) {
    820                 /* Decode base if not specified */
    821                 base = 10;
    822 
    823                 if (*str == '0') {
    824                         base = 8;
    825                         str++;
    826 
    827                         switch (*str) {
    828                         case 'b':
    829                         case 'B':
    830                                 base = 2;
    831                                 str++;
    832                                 break;
    833                         case 'o':
    834                         case 'O':
    835                                 base = 8;
    836                                 str++;
    837                                 break;
    838                         case 'd':
    839                         case 'D':
    840                         case 't':
    841                         case 'T':
    842                                 base = 10;
    843                                 str++;
    844                                 break;
    845                         case 'x':
    846                         case 'X':
    847                                 base = 16;
    848                                 str++;
    849                                 break;
    850                         default:
    851                                 str--;
    852                         }
    853                 }
    854         } else {
    855                 /* Check base range */
    856                 if ((base < 2) || (base > 36)) {
    857                         *endptr = (char *) str;
    858                         return EINVAL;
    859                 }
    860         }
    861 
    862         *result = 0;
    863         const char *startstr = str;
    864 
    865         while (*str != 0) {
    866                 unsigned int digit;
    867 
    868                 if ((*str >= 'a') && (*str <= 'z'))
    869                         digit = *str - 'a' + 10;
    870                 else if ((*str >= 'A') && (*str <= 'Z'))
    871                         digit = *str - 'A' + 10;
    872                 else if ((*str >= '0') && (*str <= '9'))
    873                         digit = *str - '0';
    874                 else
    875                         break;
    876 
    877                 if (digit >= base)
    878                         break;
    879 
    880                 uint64_t prev = *result;
    881                 *result = (*result) * base + digit;
    882 
    883                 if (*result < prev) {
    884                         /* Overflow */
    885                         *endptr = (char *) str;
    886                         return EOVERFLOW;
    887                 }
    888 
    889                 str++;
    890         }
    891 
    892         if (str == startstr) {
    893                 /*
    894                  * No digits were decoded => first invalid character is
    895                  * the first character of the string.
    896                  */
    897                 str = nptr;
    898         }
    899 
    900         *endptr = (char *) str;
    901 
    902         if (str == nptr)
    903                 return EINVAL;
    904 
    905         return EOK;
    906 }
    907 
    908 /** Convert string to uint64_t.
    909  *
    910  * @param nptr   Pointer to string.
    911  * @param endptr If not NULL, pointer to the first invalid character
    912  *               is stored here.
    913  * @param base   Zero or number between 2 and 36 inclusive.
    914  * @param strict Do not allow any trailing characters.
    915  * @param result Result of the conversion.
    916  *
    917  * @return EOK if conversion was successful.
    918  *
    919  */
    920 errno_t str_uint64_t(const char *nptr, char **endptr, unsigned int base,
    921     bool strict, uint64_t *result)
    922 {
    923         assert(result != NULL);
    924 
    925         bool neg;
    926         char *lendptr;
    927         errno_t ret = str_uint(nptr, &lendptr, base, &neg, result);
    928 
    929         if (endptr != NULL)
    930                 *endptr = (char *) lendptr;
    931 
    932         if (ret != EOK)
    933                 return ret;
    934 
    935         /* Do not allow negative values */
    936         if (neg)
    937                 return EINVAL;
    938 
    939         /*
    940          * Check whether we are at the end of
    941          * the string in strict mode
    942          */
    943         if ((strict) && (*lendptr != 0))
    944                 return EINVAL;
    945 
    946         return EOK;
    947791}
    948792
Note: See TracChangeset for help on using the changeset viewer.