Ignore:
File:
1 edited

Legend:

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

    r42e91ae raafed15  
    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
    73 * All rights reserved.
    84 *
     
    107103
    108104#include <str.h>
    109 
     105#include <cpu.h>
     106#include <arch/asm.h>
     107#include <arch.h>
     108#include <errno.h>
     109#include <align.h>
    110110#include <assert.h>
    111 #include <errno.h>
    112 #include <stdbool.h>
    113 #include <stddef.h>
    114 #include <stdint.h>
     111#include <macros.h>
    115112#include <stdlib.h>
    116 
    117 #include <align.h>
    118 #include <macros.h>
    119113
    120114/** Check the condition if wchar_t is signed */
     
    622616}
    623617
    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  */
    634 void 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  */
    661 char *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  */
    690 bool 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  */
    718 bool 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 
    732618/** Duplicate string.
    733619 *
     
    789675        str_ncpy(dest, size + 1, src, size);
    790676        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 */
     689void 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 */
     717char *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 */
     746bool 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 */
     774bool 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 */
     799static 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 */
     920errno_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;
    791947}
    792948
Note: See TracChangeset for help on using the changeset viewer.