Ignore:
File:
1 edited

Legend:

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

    r933cadf r9539be6  
    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  */
    1020 static 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  */
    1141 int 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  */
    1180 int 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 
    12151009void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
    12161010{
    1217         if (val > UINT64_C(10000000000000000000)) {
    1218                 *rv = val / UINT64_C(1000000000000000000);
     1011        if (val > 10000000000000000000ULL) {
     1012                *rv = val / 1000000000000000000ULL;
    12191013                *suffix = 'Z';
    1220         } else if (val > UINT64_C(1000000000000000000)) {
    1221                 *rv = val / UINT64_C(1000000000000000);
     1014        } else if (val > 1000000000000000000ULL) {
     1015                *rv = val / 1000000000000000ULL;
    12221016                *suffix = 'E';
    1223         } else if (val > UINT64_C(1000000000000000)) {
    1224                 *rv = val / UINT64_C(1000000000000);
     1017        } else if (val > 1000000000000000ULL) {
     1018                *rv = val / 1000000000000ULL;
    12251019                *suffix = 'T';
    1226         } else if (val > UINT64_C(1000000000000)) {
    1227                 *rv = val / UINT64_C(1000000000);
     1020        } else if (val > 1000000000000ULL) {
     1021                *rv = val / 1000000000ULL;
    12281022                *suffix = 'G';
    1229         } else if (val > UINT64_C(1000000000)) {
    1230                 *rv = val / UINT64_C(1000000);
     1023        } else if (val > 1000000000ULL) {
     1024                *rv = val / 1000000ULL;
    12311025                *suffix = 'M';
    1232         } else if (val > UINT64_C(1000000)) {
    1233                 *rv = val / UINT64_C(1000);
     1026        } else if (val > 1000000ULL) {
     1027                *rv = val / 1000ULL;
    12341028                *suffix = 'k';
    12351029        } else {
     
    12391033}
    12401034
    1241 void 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 
    12681035/** @}
    12691036 */
Note: See TracChangeset for help on using the changeset viewer.