| 390 | } |
| 391 | |
| 392 | tl::expected<std::pair<uint64_t, SizeUnitPrefixType>, std::string> |
| 393 | parse_size(const std::string& value) |
| 394 | { |
| 395 | errno = 0; |
| 396 | |
| 397 | char* p; |
| 398 | double result = strtod(value.c_str(), &p); |
| 399 | if (errno != 0 || result < 0 || p == value.c_str() || value.empty()) { |
| 400 | return tl::unexpected(FMT("invalid size: \"{}\"", value)); |
| 401 | } |
| 402 | |
| 403 | while (util::is_space(*p)) { |
| 404 | ++p; |
| 405 | } |
| 406 | |
| 407 | SizeUnitPrefixType prefix_type; |
| 408 | if (*p != '\0') { |
| 409 | prefix_type = *(p + 1) == 'i' ? SizeUnitPrefixType::binary |
| 410 | : SizeUnitPrefixType::decimal; |
| 411 | unsigned multiplier = |
| 412 | prefix_type == SizeUnitPrefixType::binary ? 1024 : 1000; |
| 413 | switch (*p) { |
| 414 | case 'T': |
| 415 | result *= multiplier; |
| 416 | [[fallthrough]]; |
| 417 | case 'G': |
| 418 | result *= multiplier; |
| 419 | [[fallthrough]]; |
| 420 | case 'M': |
| 421 | result *= multiplier; |
| 422 | [[fallthrough]]; |
| 423 | case 'K': |
| 424 | case 'k': |
| 425 | result *= multiplier; |
| 426 | break; |
| 427 | default: |
| 428 | return tl::unexpected(FMT("invalid size: \"{}\"", value)); |
| 429 | } |
| 430 | } else { |
| 431 | result *= 1024 * 1024 * 1024; |
| 432 | prefix_type = SizeUnitPrefixType::binary; |
| 433 | } |
| 434 | |
| 435 | return std::make_pair(static_cast<uint64_t>(result), prefix_type); |
| 436 | } |
| 437 | |
| 438 | tl::expected<mode_t, std::string> |
| 439 | parse_umask(std::string_view value) |
no test coverage detected