Changes in uspace/lib/c/generic/str.c [9539be6:933cadf] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/str.c
r9539be6 r933cadf 1007 1007 } 1008 1008 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 1009 1215 void order_suffix(const uint64_t val, uint64_t *rv, char *suffix) 1010 1216 { 1011 if (val > 10000000000000000000ULL) {1012 *rv = val / 1000000000000000000ULL;1217 if (val > UINT64_C(10000000000000000000)) { 1218 *rv = val / UINT64_C(1000000000000000000); 1013 1219 *suffix = 'Z'; 1014 } else if (val > 1000000000000000000ULL) {1015 *rv = val / 1000000000000000ULL;1220 } else if (val > UINT64_C(1000000000000000000)) { 1221 *rv = val / UINT64_C(1000000000000000); 1016 1222 *suffix = 'E'; 1017 } else if (val > 1000000000000000ULL) {1018 *rv = val / 1000000000000ULL;1223 } else if (val > UINT64_C(1000000000000000)) { 1224 *rv = val / UINT64_C(1000000000000); 1019 1225 *suffix = 'T'; 1020 } else if (val > 1000000000000ULL) {1021 *rv = val / 1000000000ULL;1226 } else if (val > UINT64_C(1000000000000)) { 1227 *rv = val / UINT64_C(1000000000); 1022 1228 *suffix = 'G'; 1023 } else if (val > 1000000000ULL) {1024 *rv = val / 1000000ULL;1229 } else if (val > UINT64_C(1000000000)) { 1230 *rv = val / UINT64_C(1000000); 1025 1231 *suffix = 'M'; 1026 } else if (val > 1000000ULL) {1027 *rv = val / 1000ULL;1232 } else if (val > UINT64_C(1000000)) { 1233 *rv = val / UINT64_C(1000); 1028 1234 *suffix = 'k'; 1029 1235 } else { … … 1033 1239 } 1034 1240 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 1035 1268 /** @} 1036 1269 */
Note:
See TracChangeset
for help on using the changeset viewer.