Ignore:
File:
1 edited

Legend:

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

    re535eeb r19f857a  
    110110#include <align.h>
    111111#include <debug.h>
    112 #include <macros.h>
    113112
    114113/** Byte mask consisting of lowest @n bits (out of 8) */
     
    538537 * null-terminated and containing only complete characters.
    539538 *
    540  * @param dest  Destination buffer.
     539 * @param dest   Destination buffer.
    541540 * @param count Size of the destination buffer (must be > 0).
    542541 * @param src   Source string.
    543  *
    544542 */
    545543void str_cpy(char *dest, size_t size, const char *src)
    546544{
     545        wchar_t ch;
     546        size_t src_off;
     547        size_t dest_off;
     548
    547549        /* There must be space for a null terminator in the buffer. */
    548550        ASSERT(size > 0);
    549551       
    550         size_t src_off = 0;
    551         size_t dest_off = 0;
    552        
    553         wchar_t ch;
     552        src_off = 0;
     553        dest_off = 0;
     554
    554555        while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) {
    555556                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    556557                        break;
    557558        }
    558        
     559
    559560        dest[dest_off] = '\0';
    560561}
     
    570571 * have to be null-terminated.
    571572 *
    572  * @param dest  Destination buffer.
     573 * @param dest   Destination buffer.
    573574 * @param count Size of the destination buffer (must be > 0).
    574575 * @param src   Source string.
    575  * @param n     Maximum number of bytes to read from @a src.
    576  *
     576 * @param n     Maximum number of bytes to read from @a src.
    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
    580584        /* There must be space for a null terminator in the buffer. */
    581585        ASSERT(size > 0);
    582586       
    583         size_t src_off = 0;
    584         size_t dest_off = 0;
    585        
    586         wchar_t ch;
     587        src_off = 0;
     588        dest_off = 0;
     589
    587590        while ((ch = str_decode(src, &src_off, n)) != 0) {
    588591                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    589592                        break;
    590593        }
    591        
     594
    592595        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  */
    611 char *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  */
    641 char *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;
    652596}
    653597
     
    761705}
    762706
    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  */
    774 static 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                         }
    826                 }
    827         } else {
    828                 /* Check base range */
    829                 if ((base < 2) || (base > 36)) {
    830                         *endptr = (char *) str;
    831                         return EINVAL;
    832                 }
    833         }
    834        
    835         *result = 0;
    836         const char *startstr = str;
    837        
    838         while (*str != 0) {
    839                 unsigned int digit;
    840                
    841                 if ((*str >= 'a') && (*str <= 'z'))
    842                         digit = *str - 'a' + 10;
    843                 else if ((*str >= 'A') && (*str <= 'Z'))
    844                         digit = *str - 'A' + 10;
    845                 else if ((*str >= '0') && (*str <= '9'))
    846                         digit = *str - '0';
    847                 else
    848                         break;
    849                
    850                 if (digit >= base)
    851                         break;
    852                
    853                 uint64_t prev = *result;
    854                 *result = (*result) * base + digit;
    855                
    856                 if (*result < prev) {
    857                         /* Overflow */
    858                         *endptr = (char *) str;
    859                         return EOVERFLOW;
    860                 }
    861                
    862                 str++;
    863         }
    864        
    865         if (str == startstr) {
    866                 /*
    867                  * No digits were decoded => first invalid character is
    868                  * the first character of the string.
    869                  */
    870                 str = nptr;
    871         }
    872        
    873         *endptr = (char *) str;
    874        
    875         if (str == nptr)
    876                 return EINVAL;
    877        
    878         return EOK;
    879 }
    880 
    881 /** Convert string to uint64_t.
    882  *
    883  * @param nptr   Pointer to string.
    884  * @param endptr If not NULL, pointer to the first invalid character
    885  *               is stored here.
    886  * @param base   Zero or number between 2 and 36 inclusive.
    887  * @param strict Do not allow any trailing characters.
    888  * @apram result Result of the conversion.
    889  *
    890  * @return EOK if conversion was successful.
    891  *
    892  */
    893 int str_uint64(const char *nptr, char **endptr, unsigned int base,
    894     bool strict, uint64_t *result)
    895 {
    896         ASSERT(result != NULL);
    897        
    898         bool neg;
    899         char *lendptr;
    900         int ret = str_uint(nptr, &lendptr, base, &neg, result);
    901        
    902         if (endptr != NULL)
    903                 *endptr = (char *) lendptr;
    904        
    905         if (ret != EOK)
    906                 return ret;
    907        
    908         /* Do not allow negative values */
    909         if (neg)
    910                 return EINVAL;
    911        
    912         /* Check whether we are at the end of
    913            the string in strict mode */
    914         if ((strict) && (*lendptr != 0))
    915                 return EINVAL;
    916        
    917         return EOK;
    918 }
    919 
    920 void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
    921 {
    922         if (val > 10000000000000000000ULL) {
    923                 *rv = val / 1000000000000000000ULL;
    924                 *suffix = 'Z';
    925         } else if (val > 1000000000000000000ULL) {
    926                 *rv = val / 1000000000000000ULL;
    927                 *suffix = 'E';
    928         } else if (val > 1000000000000000ULL) {
    929                 *rv = val / 1000000000000ULL;
    930                 *suffix = 'T';
    931         } else if (val > 1000000000000ULL) {
    932                 *rv = val / 1000000000ULL;
    933                 *suffix = 'G';
    934         } else if (val > 1000000000ULL) {
    935                 *rv = val / 1000000ULL;
    936                 *suffix = 'M';
    937         } else if (val > 1000000ULL) {
    938                 *rv = val / 1000ULL;
    939                 *suffix = 'k';
    940         } else {
    941                 *rv = val;
    942                 *suffix = ' ';
    943         }
    944 }
    945 
    946707/** @}
    947708 */
Note: See TracChangeset for help on using the changeset viewer.