Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/str.c

    r9539be6 r933cadf  
    10071007}
    10081008
     1009/** Convert string to uint64_t (internal variant).
     1010 *
     1011 * @param nptr   Pointer to string.
     1012 * @param endptr Pointer to the first invalid character is stored here.
     1013 * @param base   Zero or number between 2 and 36 inclusive.
     1014 * @param neg    Indication of unary minus is stored here.
     1015 * @apram result Result of the conversion.
     1016 *
     1017 * @return EOK if conversion was successful.
     1018 *
     1019 */
     1020static int str_uint(const char *nptr, char **endptr, unsigned int base,
     1021    bool *neg, uint64_t *result)
     1022{
     1023        assert(endptr != NULL);
     1024        assert(neg != NULL);
     1025        assert(result != NULL);
     1026       
     1027        *neg = false;
     1028        const char *str = nptr;
     1029       
     1030        /* Ignore leading whitespace */
     1031        while (isspace(*str))
     1032                str++;
     1033       
     1034        if (*str == '-') {
     1035                *neg = true;
     1036                str++;
     1037        } else if (*str == '+')
     1038                str++;
     1039       
     1040        if (base == 0) {
     1041                /* Decode base if not specified */
     1042                base = 10;
     1043               
     1044                if (*str == '0') {
     1045                        base = 8;
     1046                        str++;
     1047                       
     1048                        switch (*str) {
     1049                        case 'b':
     1050                        case 'B':
     1051                                base = 2;
     1052                                str++;
     1053                                break;
     1054                        case 'o':
     1055                        case 'O':
     1056                                base = 8;
     1057                                str++;
     1058                                break;
     1059                        case 'd':
     1060                        case 'D':
     1061                        case 't':
     1062                        case 'T':
     1063                                base = 10;
     1064                                str++;
     1065                                break;
     1066                        case 'x':
     1067                        case 'X':
     1068                                base = 16;
     1069                                str++;
     1070                                break;
     1071                        default:
     1072                                str--;
     1073                        }
     1074                }
     1075        } else {
     1076                /* Check base range */
     1077                if ((base < 2) || (base > 36)) {
     1078                        *endptr = (char *) str;
     1079                        return EINVAL;
     1080                }
     1081        }
     1082       
     1083        *result = 0;
     1084        const char *startstr = str;
     1085       
     1086        while (*str != 0) {
     1087                unsigned int digit;
     1088               
     1089                if ((*str >= 'a') && (*str <= 'z'))
     1090                        digit = *str - 'a' + 10;
     1091                else if ((*str >= 'A') && (*str <= 'Z'))
     1092                        digit = *str - 'A' + 10;
     1093                else if ((*str >= '0') && (*str <= '9'))
     1094                        digit = *str - '0';
     1095                else
     1096                        break;
     1097               
     1098                if (digit >= base)
     1099                        break;
     1100               
     1101                uint64_t prev = *result;
     1102                *result = (*result) * base + digit;
     1103               
     1104                if (*result < prev) {
     1105                        /* Overflow */
     1106                        *endptr = (char *) str;
     1107                        return EOVERFLOW;
     1108                }
     1109               
     1110                str++;
     1111        }
     1112       
     1113        if (str == startstr) {
     1114                /*
     1115                 * No digits were decoded => first invalid character is
     1116                 * the first character of the string.
     1117                 */
     1118                str = nptr;
     1119        }
     1120       
     1121        *endptr = (char *) str;
     1122       
     1123        if (str == nptr)
     1124                return EINVAL;
     1125       
     1126        return EOK;
     1127}
     1128
     1129/** Convert string to uint64_t.
     1130 *
     1131 * @param nptr   Pointer to string.
     1132 * @param endptr If not NULL, pointer to the first invalid character
     1133 *               is stored here.
     1134 * @param base   Zero or number between 2 and 36 inclusive.
     1135 * @param strict Do not allow any trailing characters.
     1136 * @param result Result of the conversion.
     1137 *
     1138 * @return EOK if conversion was successful.
     1139 *
     1140 */
     1141int str_uint64(const char *nptr, char **endptr, unsigned int base,
     1142    bool strict, uint64_t *result)
     1143{
     1144        assert(result != NULL);
     1145       
     1146        bool neg;
     1147        char *lendptr;
     1148        int ret = str_uint(nptr, &lendptr, base, &neg, result);
     1149       
     1150        if (endptr != NULL)
     1151                *endptr = (char *) lendptr;
     1152       
     1153        if (ret != EOK)
     1154                return ret;
     1155       
     1156        /* Do not allow negative values */
     1157        if (neg)
     1158                return EINVAL;
     1159       
     1160        /* Check whether we are at the end of
     1161           the string in strict mode */
     1162        if ((strict) && (*lendptr != 0))
     1163                return EINVAL;
     1164       
     1165        return EOK;
     1166}
     1167
     1168/** Convert string to size_t.
     1169 *
     1170 * @param nptr   Pointer to string.
     1171 * @param endptr If not NULL, pointer to the first invalid character
     1172 *               is stored here.
     1173 * @param base   Zero or number between 2 and 36 inclusive.
     1174 * @param strict Do not allow any trailing characters.
     1175 * @param result Result of the conversion.
     1176 *
     1177 * @return EOK if conversion was successful.
     1178 *
     1179 */
     1180int str_size_t(const char *nptr, char **endptr, unsigned int base,
     1181    bool strict, size_t *result)
     1182{
     1183        assert(result != NULL);
     1184       
     1185        bool neg;
     1186        char *lendptr;
     1187        uint64_t res;
     1188        int ret = str_uint(nptr, &lendptr, base, &neg, &res);
     1189       
     1190        if (endptr != NULL)
     1191                *endptr = (char *) lendptr;
     1192       
     1193        if (ret != EOK)
     1194                return ret;
     1195       
     1196        /* Do not allow negative values */
     1197        if (neg)
     1198                return EINVAL;
     1199       
     1200        /* Check whether we are at the end of
     1201           the string in strict mode */
     1202        if ((strict) && (*lendptr != 0))
     1203                return EINVAL;
     1204       
     1205        /* Check for overflow */
     1206        size_t _res = (size_t) res;
     1207        if (_res != res)
     1208                return EOVERFLOW;
     1209       
     1210        *result = _res;
     1211       
     1212        return EOK;
     1213}
     1214
    10091215void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
    10101216{
    1011         if (val > 10000000000000000000ULL) {
    1012                 *rv = val / 1000000000000000000ULL;
     1217        if (val > UINT64_C(10000000000000000000)) {
     1218                *rv = val / UINT64_C(1000000000000000000);
    10131219                *suffix = 'Z';
    1014         } else if (val > 1000000000000000000ULL) {
    1015                 *rv = val / 1000000000000000ULL;
     1220        } else if (val > UINT64_C(1000000000000000000)) {
     1221                *rv = val / UINT64_C(1000000000000000);
    10161222                *suffix = 'E';
    1017         } else if (val > 1000000000000000ULL) {
    1018                 *rv = val / 1000000000000ULL;
     1223        } else if (val > UINT64_C(1000000000000000)) {
     1224                *rv = val / UINT64_C(1000000000000);
    10191225                *suffix = 'T';
    1020         } else if (val > 1000000000000ULL) {
    1021                 *rv = val / 1000000000ULL;
     1226        } else if (val > UINT64_C(1000000000000)) {
     1227                *rv = val / UINT64_C(1000000000);
    10221228                *suffix = 'G';
    1023         } else if (val > 1000000000ULL) {
    1024                 *rv = val / 1000000ULL;
     1229        } else if (val > UINT64_C(1000000000)) {
     1230                *rv = val / UINT64_C(1000000);
    10251231                *suffix = 'M';
    1026         } else if (val > 1000000ULL) {
    1027                 *rv = val / 1000ULL;
     1232        } else if (val > UINT64_C(1000000)) {
     1233                *rv = val / UINT64_C(1000);
    10281234                *suffix = 'k';
    10291235        } else {
     
    10331239}
    10341240
     1241void bin_order_suffix(const uint64_t val, uint64_t *rv, const char **suffix,
     1242    bool fixed)
     1243{
     1244        if (val > UINT64_C(1152921504606846976)) {
     1245                *rv = val / UINT64_C(1125899906842624);
     1246                *suffix = "EiB";
     1247        } else if (val > UINT64_C(1125899906842624)) {
     1248                *rv = val / UINT64_C(1099511627776);
     1249                *suffix = "TiB";
     1250        } else if (val > UINT64_C(1099511627776)) {
     1251                *rv = val / UINT64_C(1073741824);
     1252                *suffix = "GiB";
     1253        } else if (val > UINT64_C(1073741824)) {
     1254                *rv = val / UINT64_C(1048576);
     1255                *suffix = "MiB";
     1256        } else if (val > UINT64_C(1048576)) {
     1257                *rv = val / UINT64_C(1024);
     1258                *suffix = "KiB";
     1259        } else {
     1260                *rv = val;
     1261                if (fixed)
     1262                        *suffix = "B  ";
     1263                else
     1264                        *suffix = "B";
     1265        }
     1266}
     1267
    10351268/** @}
    10361269 */
Note: See TracChangeset for help on using the changeset viewer.