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


Ignore:
Timestamp:
2019-06-06T12:15:29Z (5 years ago)
Author:
GitHub <noreply@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2a103b5, e28175d
Parents:
83b64a59 (diff), 42e91ae (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.
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2019-06-06 12:15:29)
git-committer:
GitHub <noreply@…> (2019-06-06 12:15:29)
Message:

Merge pull request #169 from le-jzr/strtolwip

Removes internal str_uint() function in favor of the one in strtol.c.
Fixes handling of a bunch of corner cases.
The expected behavior of str_uint*_t() functions should be unchanged.

File:
1 edited

Legend:

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

    r83b64a59 rb401b33  
    789789        str_ncpy(dest, size + 1, src, size);
    790790        return dest;
    791 }
    792 
    793 /** Convert string to uint64_t (internal variant).
    794  *
    795  * @param nptr   Pointer to string.
    796  * @param endptr Pointer to the first invalid character is stored here.
    797  * @param base   Zero or number between 2 and 36 inclusive.
    798  * @param neg    Indication of unary minus is stored here.
    799  * @apram result Result of the conversion.
    800  *
    801  * @return EOK if conversion was successful.
    802  *
    803  */
    804 static errno_t str_uint(const char *nptr, char **endptr, unsigned int base,
    805     bool *neg, uint64_t *result)
    806 {
    807         assert(endptr != NULL);
    808         assert(neg != NULL);
    809         assert(result != NULL);
    810 
    811         *neg = false;
    812         const char *str = nptr;
    813 
    814         /* Ignore leading whitespace */
    815         while (isspace(*str))
    816                 str++;
    817 
    818         if (*str == '-') {
    819                 *neg = true;
    820                 str++;
    821         } else if (*str == '+')
    822                 str++;
    823 
    824         if (base == 0) {
    825                 /* Decode base if not specified */
    826                 base = 10;
    827 
    828                 if (*str == '0') {
    829                         base = 8;
    830                         str++;
    831 
    832                         switch (*str) {
    833                         case 'b':
    834                         case 'B':
    835                                 base = 2;
    836                                 str++;
    837                                 break;
    838                         case 'o':
    839                         case 'O':
    840                                 base = 8;
    841                                 str++;
    842                                 break;
    843                         case 'd':
    844                         case 'D':
    845                         case 't':
    846                         case 'T':
    847                                 base = 10;
    848                                 str++;
    849                                 break;
    850                         case 'x':
    851                         case 'X':
    852                                 base = 16;
    853                                 str++;
    854                                 break;
    855                         default:
    856                                 str--;
    857                         }
    858                 }
    859         } else {
    860                 /* Check base range */
    861                 if ((base < 2) || (base > 36)) {
    862                         *endptr = (char *) str;
    863                         return EINVAL;
    864                 }
    865         }
    866 
    867         *result = 0;
    868         const char *startstr = str;
    869 
    870         while (*str != 0) {
    871                 unsigned int digit;
    872 
    873                 if ((*str >= 'a') && (*str <= 'z'))
    874                         digit = *str - 'a' + 10;
    875                 else if ((*str >= 'A') && (*str <= 'Z'))
    876                         digit = *str - 'A' + 10;
    877                 else if ((*str >= '0') && (*str <= '9'))
    878                         digit = *str - '0';
    879                 else
    880                         break;
    881 
    882                 if (digit >= base)
    883                         break;
    884 
    885                 uint64_t prev = *result;
    886                 *result = (*result) * base + digit;
    887 
    888                 if (*result < prev) {
    889                         /* Overflow */
    890                         *endptr = (char *) str;
    891                         return EOVERFLOW;
    892                 }
    893 
    894                 str++;
    895         }
    896 
    897         if (str == startstr) {
    898                 /*
    899                  * No digits were decoded => first invalid character is
    900                  * the first character of the string.
    901                  */
    902                 str = nptr;
    903         }
    904 
    905         *endptr = (char *) str;
    906 
    907         if (str == nptr)
    908                 return EINVAL;
    909 
    910         return EOK;
    911 }
    912 
    913 /** Convert string to uint64_t.
    914  *
    915  * @param nptr   Pointer to string.
    916  * @param endptr If not NULL, pointer to the first invalid character
    917  *               is stored here.
    918  * @param base   Zero or number between 2 and 36 inclusive.
    919  * @param strict Do not allow any trailing characters.
    920  * @param result Result of the conversion.
    921  *
    922  * @return EOK if conversion was successful.
    923  *
    924  */
    925 errno_t str_uint64_t(const char *nptr, char **endptr, unsigned int base,
    926     bool strict, uint64_t *result)
    927 {
    928         assert(result != NULL);
    929 
    930         bool neg;
    931         char *lendptr;
    932         errno_t ret = str_uint(nptr, &lendptr, base, &neg, result);
    933 
    934         if (endptr != NULL)
    935                 *endptr = (char *) lendptr;
    936 
    937         if (ret != EOK)
    938                 return ret;
    939 
    940         /* Do not allow negative values */
    941         if (neg)
    942                 return EINVAL;
    943 
    944         /*
    945          * Check whether we are at the end of
    946          * the string in strict mode
    947          */
    948         if ((strict) && (*lendptr != 0))
    949                 return EINVAL;
    950 
    951         return EOK;
    952791}
    953792
Note: See TracChangeset for help on using the changeset viewer.