]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2011 New Dream Network | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #ifndef CEPH_COMMON_STRTOL_H | |
16 | #define CEPH_COMMON_STRTOL_H | |
17 | ||
f91f0fd5 | 18 | #include <charconv> |
f91f0fd5 TL |
19 | #include <cinttypes> |
20 | #include <cstdlib> | |
21 | #include <optional> | |
7c673cae | 22 | #include <string> |
f91f0fd5 TL |
23 | #include <string_view> |
24 | #include <system_error> | |
25 | #include <type_traits> | |
26 | ||
27 | ||
28 | namespace ceph { | |
f91f0fd5 TL |
29 | // Wrappers around std::from_chars. |
30 | // | |
31 | // Why do we want this instead of strtol and friends? Because the | |
32 | // string doesn't have to be NUL-terminated! (Also, for a lot of | |
33 | // purposes, just putting a string_view in and getting an optional out | |
34 | // is friendly.) | |
35 | // | |
36 | // Returns the found number on success. Returns an empty optional on | |
37 | // failure OR on trailing characters. | |
20effc67 | 38 | // Sadly GCC < 11 is missing the floating point versions. |
f91f0fd5 TL |
39 | template<typename T> |
40 | auto parse(std::string_view s, int base = 10) | |
41 | -> std::enable_if_t<std::is_integral_v<T>, std::optional<T>> | |
42 | { | |
43 | T t; | |
44 | auto r = std::from_chars(s.data(), s.data() + s.size(), t, base); | |
45 | if ((r.ec != std::errc{}) || (r.ptr != s.data() + s.size())) { | |
46 | return std::nullopt; | |
47 | } | |
48 | return t; | |
49 | } | |
50 | ||
51 | // As above, but succeed on trailing characters and trim the supplied | |
52 | // string_view to remove the parsed number. Set the supplied | |
53 | // string_view to empty if it ends with the number. | |
54 | template<typename T> | |
55 | auto consume(std::string_view& s, int base = 10) | |
56 | -> std::enable_if_t<std::is_integral_v<T>, std::optional<T>> | |
57 | { | |
58 | T t; | |
59 | auto r = std::from_chars(s.data(), s.data() + s.size(), t, base); | |
60 | if (r.ec != std::errc{}) | |
61 | return std::nullopt; | |
62 | ||
63 | if (r.ptr == s.data() + s.size()) { | |
64 | s = std::string_view{}; | |
65 | } else { | |
66 | s.remove_prefix(r.ptr - s.data()); | |
67 | } | |
68 | return t; | |
69 | } | |
f91f0fd5 | 70 | } // namespace ceph |
7c673cae | 71 | |
f67539c2 TL |
72 | bool strict_strtob(const char* str, std::string *err); |
73 | ||
74 | long long strict_strtoll(std::string_view str, int base, std::string *err); | |
7c673cae | 75 | |
f67539c2 | 76 | int strict_strtol(std::string_view str, int base, std::string *err); |
7c673cae | 77 | |
20effc67 | 78 | double strict_strtod(std::string_view str, std::string *err); |
7c673cae | 79 | |
20effc67 | 80 | float strict_strtof(std::string_view str, std::string *err); |
7c673cae | 81 | |
20effc67 | 82 | uint64_t strict_iecstrtoll(std::string_view str, std::string *err); |
1adf2230 AA |
83 | |
84 | template<typename T> | |
20effc67 | 85 | T strict_iec_cast(std::string_view str, std::string *err); |
7c673cae FG |
86 | |
87 | template<typename T> | |
20effc67 | 88 | T strict_si_cast(std::string_view str, std::string *err); |
7c673cae FG |
89 | |
90 | /* On enter buf points to the end of the buffer, e.g. where the least | |
91 | * significant digit of the input number will be printed. Returns pointer to | |
92 | * where the most significant digit were printed, including zero padding. | |
93 | * Does NOT add zero at the end of buffer, this is responsibility of the caller. | |
94 | */ | |
95 | template<typename T, const unsigned base = 10, const unsigned width = 1> | |
96 | static inline | |
97 | char* ritoa(T u, char *buf) | |
98 | { | |
f67539c2 | 99 | static_assert(std::is_unsigned_v<T>, "signed types are not supported"); |
7c673cae FG |
100 | static_assert(base <= 16, "extend character map below to support higher bases"); |
101 | unsigned digits = 0; | |
102 | while (u) { | |
103 | *--buf = "0123456789abcdef"[u % base]; | |
104 | u /= base; | |
105 | digits++; | |
106 | } | |
107 | while (digits++ < width) | |
108 | *--buf = '0'; | |
109 | return buf; | |
110 | } | |
111 | ||
112 | #endif |