Changeset c47e1a8 in mainline for kernel/generic/src/lib/str.c


Ignore:
Timestamp:
2010-05-21T07:50:04Z (15 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d51ee2b
Parents:
cf8cc36 (diff), 15b592b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge mainline changes (rev. 451)

File:
1 moved

Legend:

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

    rcf8cc36 rc47e1a8  
    102102 */
    103103
    104 #include <string.h>
     104#include <str.h>
    105105#include <print.h>
    106106#include <cpu.h>
     
    110110#include <align.h>
    111111#include <debug.h>
     112#include <macros.h>
    112113
    113114/** Byte mask consisting of lowest @n bits (out of 8) */
     
    537538 * null-terminated and containing only complete characters.
    538539 *
    539  * @param dest   Destination buffer.
     540 * @param dest  Destination buffer.
    540541 * @param count Size of the destination buffer (must be > 0).
    541542 * @param src   Source string.
     543 *
    542544 */
    543545void str_cpy(char *dest, size_t size, const char *src)
    544546{
    545         wchar_t ch;
    546         size_t src_off;
    547         size_t dest_off;
    548 
    549547        /* There must be space for a null terminator in the buffer. */
    550548        ASSERT(size > 0);
    551549       
    552         src_off = 0;
    553         dest_off = 0;
    554 
     550        size_t src_off = 0;
     551        size_t dest_off = 0;
     552       
     553        wchar_t ch;
    555554        while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) {
    556555                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    557556                        break;
    558557        }
    559 
     558       
    560559        dest[dest_off] = '\0';
    561560}
     
    571570 * have to be null-terminated.
    572571 *
    573  * @param dest   Destination buffer.
     572 * @param dest  Destination buffer.
    574573 * @param count Size of the destination buffer (must be > 0).
    575574 * @param src   Source string.
    576  * @param n     Maximum number of bytes to read from @a src.
     575 * @param n     Maximum number of bytes to read from @a src.
     576 *
    577577 */
    578578void str_ncpy(char *dest, size_t size, const char *src, size_t n)
    579579{
    580         wchar_t ch;
    581         size_t src_off;
    582         size_t dest_off;
    583 
    584580        /* There must be space for a null terminator in the buffer. */
    585581        ASSERT(size > 0);
    586582       
    587         src_off = 0;
    588         dest_off = 0;
    589 
     583        size_t src_off = 0;
     584        size_t dest_off = 0;
     585       
     586        wchar_t ch;
    590587        while ((ch = str_decode(src, &src_off, n)) != 0) {
    591588                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    592589                        break;
    593590        }
    594 
     591       
    595592        dest[dest_off] = '\0';
     593}
     594
     595/** Duplicate string.
     596 *
     597 * Allocate a new string and copy characters from the source
     598 * string into it. The duplicate string is allocated via sleeping
     599 * malloc(), thus this function can sleep in no memory conditions.
     600 *
     601 * The allocation cannot fail and the return value is always
     602 * a valid pointer. The duplicate string is always a well-formed
     603 * null-terminated UTF-8 string, but it can differ from the source
     604 * string on the byte level.
     605 *
     606 * @param src Source string.
     607 *
     608 * @return Duplicate string.
     609 *
     610 */
     611char *str_dup(const char *src)
     612{
     613        size_t size = str_size(src) + 1;
     614        char *dest = malloc(size, 0);
     615        ASSERT(dest);
     616       
     617        str_cpy(dest, size, src);
     618        return dest;
     619}
     620
     621/** Duplicate string with size limit.
     622 *
     623 * Allocate a new string and copy up to @max_size bytes from the source
     624 * string into it. The duplicate string is allocated via sleeping
     625 * malloc(), thus this function can sleep in no memory conditions.
     626 * No more than @max_size + 1 bytes is allocated, but if the size
     627 * occupied by the source string is smaller than @max_size + 1,
     628 * less is allocated.
     629 *
     630 * The allocation cannot fail and the return value is always
     631 * a valid pointer. The duplicate string is always a well-formed
     632 * null-terminated UTF-8 string, but it can differ from the source
     633 * string on the byte level.
     634 *
     635 * @param src Source string.
     636 * @param n   Maximum number of bytes to duplicate.
     637 *
     638 * @return Duplicate string.
     639 *
     640 */
     641char *str_ndup(const char *src, size_t n)
     642{
     643        size_t size = str_size(src);
     644        if (size > n)
     645                size = n;
     646       
     647        char *dest = malloc(size + 1, 0);
     648        ASSERT(dest);
     649       
     650        str_ncpy(dest, size + 1, src, size);
     651        return dest;
    596652}
    597653
     
    705761}
    706762
     763/** Convert string to uint64_t (internal variant).
     764 *
     765 * @param nptr   Pointer to string.
     766 * @param endptr Pointer to the first invalid character is stored here.
     767 * @param base   Zero or number between 2 and 36 inclusive.
     768 * @param neg    Indication of unary minus is stored here.
     769 * @apram result Result of the conversion.
     770 *
     771 * @return EOK if conversion was successful.
     772 *
     773 */
     774static int str_uint(const char *nptr, char **endptr, unsigned int base,
     775    bool *neg, uint64_t *result)
     776{
     777        ASSERT(endptr != NULL);
     778        ASSERT(neg != NULL);
     779        ASSERT(result != NULL);
     780       
     781        *neg = false;
     782        const char *str = nptr;
     783       
     784        /* Ignore leading whitespace */
     785        while (isspace(*str))
     786                str++;
     787       
     788        if (*str == '-') {
     789                *neg = true;
     790                str++;
     791        } else if (*str == '+')
     792                str++;
     793       
     794        if (base == 0) {
     795                /* Decode base if not specified */
     796                base = 10;
     797               
     798                if (*str == '0') {
     799                        base = 8;
     800                        str++;
     801                       
     802                        switch (*str) {
     803                        case 'b':
     804                        case 'B':
     805                                base = 2;
     806                                str++;
     807                                break;
     808                        case 'o':
     809                        case 'O':
     810                                base = 8;
     811                                str++;
     812                                break;
     813                        case 'd':
     814                        case 'D':
     815                        case 't':
     816                        case 'T':
     817                                base = 10;
     818                                str++;
     819                                break;
     820                        case 'x':
     821                        case 'X':
     822                                base = 16;
     823                                str++;
     824                                break;
     825                        default:
     826                                str--;
     827                        }
     828                }
     829        } else {
     830                /* Check base range */
     831                if ((base < 2) || (base > 36)) {
     832                        *endptr = (char *) str;
     833                        return EINVAL;
     834                }
     835        }
     836       
     837        *result = 0;
     838        const char *startstr = str;
     839       
     840        while (*str != 0) {
     841                unsigned int digit;
     842               
     843                if ((*str >= 'a') && (*str <= 'z'))
     844                        digit = *str - 'a' + 10;
     845                else if ((*str >= 'A') && (*str <= 'Z'))
     846                        digit = *str - 'A' + 10;
     847                else if ((*str >= '0') && (*str <= '9'))
     848                        digit = *str - '0';
     849                else
     850                        break;
     851               
     852                if (digit >= base)
     853                        break;
     854               
     855                uint64_t prev = *result;
     856                *result = (*result) * base + digit;
     857               
     858                if (*result < prev) {
     859                        /* Overflow */
     860                        *endptr = (char *) str;
     861                        return EOVERFLOW;
     862                }
     863               
     864                str++;
     865        }
     866       
     867        if (str == startstr) {
     868                /*
     869                 * No digits were decoded => first invalid character is
     870                 * the first character of the string.
     871                 */
     872                str = nptr;
     873        }
     874       
     875        *endptr = (char *) str;
     876       
     877        if (str == nptr)
     878                return EINVAL;
     879       
     880        return EOK;
     881}
     882
     883/** Convert string to uint64_t.
     884 *
     885 * @param nptr   Pointer to string.
     886 * @param endptr If not NULL, pointer to the first invalid character
     887 *               is stored here.
     888 * @param base   Zero or number between 2 and 36 inclusive.
     889 * @param strict Do not allow any trailing characters.
     890 * @param result Result of the conversion.
     891 *
     892 * @return EOK if conversion was successful.
     893 *
     894 */
     895int str_uint64(const char *nptr, char **endptr, unsigned int base,
     896    bool strict, uint64_t *result)
     897{
     898        ASSERT(result != NULL);
     899       
     900        bool neg;
     901        char *lendptr;
     902        int ret = str_uint(nptr, &lendptr, base, &neg, result);
     903       
     904        if (endptr != NULL)
     905                *endptr = (char *) lendptr;
     906       
     907        if (ret != EOK)
     908                return ret;
     909       
     910        /* Do not allow negative values */
     911        if (neg)
     912                return EINVAL;
     913       
     914        /* Check whether we are at the end of
     915           the string in strict mode */
     916        if ((strict) && (*lendptr != 0))
     917                return EINVAL;
     918       
     919        return EOK;
     920}
     921
     922void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
     923{
     924        if (val > 10000000000000000000ULL) {
     925                *rv = val / 1000000000000000000ULL;
     926                *suffix = 'Z';
     927        } else if (val > 1000000000000000000ULL) {
     928                *rv = val / 1000000000000000ULL;
     929                *suffix = 'E';
     930        } else if (val > 1000000000000000ULL) {
     931                *rv = val / 1000000000000ULL;
     932                *suffix = 'T';
     933        } else if (val > 1000000000000ULL) {
     934                *rv = val / 1000000000ULL;
     935                *suffix = 'G';
     936        } else if (val > 1000000000ULL) {
     937                *rv = val / 1000000ULL;
     938                *suffix = 'M';
     939        } else if (val > 1000000ULL) {
     940                *rv = val / 1000ULL;
     941                *suffix = 'k';
     942        } else {
     943                *rv = val;
     944                *suffix = ' ';
     945        }
     946}
     947
    707948/** @}
    708949 */
Note: See TracChangeset for help on using the changeset viewer.