diff options
Diffstat (limited to 'server/src/util.cppm')
| -rw-r--r-- | server/src/util.cppm | 109 |
1 files changed, 30 insertions, 79 deletions
diff --git a/server/src/util.cppm b/server/src/util.cppm index bdccf10..2857fe5 100644 --- a/server/src/util.cppm +++ b/server/src/util.cppm | |||
| @@ -13,7 +13,7 @@ struct overloaded : Ts... | |||
| 13 | using Ts::operator()...; | 13 | using Ts::operator()...; |
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | export constexpr auto parse_double( | 16 | constexpr auto parse_double( |
| 17 | std::string_view s, | 17 | std::string_view s, |
| 18 | std::chars_format fmt = std::chars_format::general) noexcept | 18 | std::chars_format fmt = std::chars_format::general) noexcept |
| 19 | -> std::optional<double> | 19 | -> std::optional<double> |
| @@ -30,7 +30,7 @@ export constexpr auto parse_double( | |||
| 30 | } | 30 | } |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | export constexpr auto parse_float( | 33 | constexpr auto parse_float( |
| 34 | std::string_view s, | 34 | std::string_view s, |
| 35 | std::chars_format fmt = std::chars_format::general) noexcept | 35 | std::chars_format fmt = std::chars_format::general) noexcept |
| 36 | -> std::optional<float> | 36 | -> std::optional<float> |
| @@ -47,7 +47,7 @@ export constexpr auto parse_float( | |||
| 47 | } | 47 | } |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | export template <class T> | 50 | template <class T> |
| 51 | class aolist : public std::enable_shared_from_this<aolist<T>> | 51 | class aolist : public std::enable_shared_from_this<aolist<T>> |
| 52 | { | 52 | { |
| 53 | T v_; | 53 | T v_; |
| @@ -72,7 +72,7 @@ public: | |||
| 72 | auto value() const noexcept -> T const& { return v_; } | 72 | auto value() const noexcept -> T const& { return v_; } |
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | export constexpr auto size_from_int(int x) -> std::optional<std::size_t> | 75 | constexpr auto size_from_int(int x) -> std::optional<std::size_t> |
| 76 | { | 76 | { |
| 77 | static_assert( | 77 | static_assert( |
| 78 | sizeof(int) <= sizeof(std::size_t), | 78 | sizeof(int) <= sizeof(std::size_t), |
| @@ -82,7 +82,7 @@ export constexpr auto size_from_int(int x) -> std::optional<std::size_t> | |||
| 82 | return static_cast<std::size_t>(x); | 82 | return static_cast<std::size_t>(x); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | export constexpr auto int_from_size(std::size_t x) -> std::optional<int> | 85 | constexpr auto int_from_size(std::size_t x) -> std::optional<int> |
| 86 | { | 86 | { |
| 87 | constexpr auto int_max = size_from_int(std::numeric_limits<int>::max()); | 87 | constexpr auto int_max = size_from_int(std::numeric_limits<int>::max()); |
| 88 | static_assert(int_max.has_value()); | 88 | static_assert(int_max.has_value()); |
| @@ -91,7 +91,7 @@ export constexpr auto int_from_size(std::size_t x) -> std::optional<int> | |||
| 91 | return static_cast<int>(x); | 91 | return static_cast<int>(x); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | export class zstring_view | 94 | class zstring_view |
| 95 | { | 95 | { |
| 96 | char const* s_; | 96 | char const* s_; |
| 97 | std::size_t length_; | 97 | std::size_t length_; |
| @@ -107,13 +107,16 @@ public: | |||
| 107 | { | 107 | { |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | auto length() const -> std::size_t { return length_; } | 110 | constexpr auto length() const -> std::size_t { return length_; } |
| 111 | 111 | ||
| 112 | auto c_str() const -> char const* { return s_; } | 112 | constexpr auto c_str() const -> char const* { return s_; } |
| 113 | 113 | ||
| 114 | operator std::string_view() const { return std::string_view{s_, length_}; } | 114 | constexpr operator std::string_view() const |
| 115 | { | ||
| 116 | return std::string_view{s_, length_}; | ||
| 117 | } | ||
| 115 | 118 | ||
| 116 | operator char const*() const { return s_; } | 119 | constexpr operator char const*() const { return s_; } |
| 117 | }; | 120 | }; |
| 118 | 121 | ||
| 119 | // View for null-terminated strings for which we might not | 122 | // View for null-terminated strings for which we might not |
| @@ -123,7 +126,7 @@ public: | |||
| 123 | // | 126 | // |
| 124 | // It is undefined behavior to assign to a lazy_zstring_view when | 127 | // It is undefined behavior to assign to a lazy_zstring_view when |
| 125 | // it is in use by other threads. | 128 | // it is in use by other threads. |
| 126 | export class lazy_zstring_view | 129 | class lazy_zstring_view |
| 127 | { | 130 | { |
| 128 | static constexpr auto unset_length = std::numeric_limits<std::size_t>::max(); | 131 | static constexpr auto unset_length = std::numeric_limits<std::size_t>::max(); |
| 129 | 132 | ||
| @@ -136,70 +139,21 @@ public: | |||
| 136 | : s_{s}, length_{s ? unset_length : 0} | 139 | : s_{s}, length_{s ? unset_length : 0} |
| 137 | { | 140 | { |
| 138 | } | 141 | } |
| 142 | lazy_zstring_view(lazy_zstring_view const& sv) noexcept; | ||
| 143 | lazy_zstring_view(lazy_zstring_view&& sv) noexcept; | ||
| 139 | 144 | ||
| 140 | ~lazy_zstring_view() = default; | 145 | ~lazy_zstring_view() = default; |
| 141 | 146 | ||
| 142 | lazy_zstring_view(lazy_zstring_view const& sv) noexcept | 147 | auto operator=(lazy_zstring_view const& rhs) noexcept -> lazy_zstring_view&; |
| 143 | : s_{sv.s_}, length_{sv.length_.load(std::memory_order_acquire)} | 148 | auto operator=(lazy_zstring_view&& rhs) noexcept -> lazy_zstring_view&; |
| 144 | { | ||
| 145 | } | ||
| 146 | |||
| 147 | lazy_zstring_view(lazy_zstring_view&& sv) noexcept | ||
| 148 | : s_{sv.s_}, length_{sv.length_.load(std::memory_order_acquire)} | ||
| 149 | { | ||
| 150 | } | ||
| 151 | |||
| 152 | auto operator=(lazy_zstring_view const& rhs) noexcept -> lazy_zstring_view& | ||
| 153 | { | ||
| 154 | if (this != &rhs) | ||
| 155 | { | ||
| 156 | s_ = rhs.s_; | ||
| 157 | length_.store( | ||
| 158 | rhs.length_.load(std::memory_order_acquire), | ||
| 159 | std::memory_order_release); | ||
| 160 | } | ||
| 161 | return *this; | ||
| 162 | } | ||
| 163 | |||
| 164 | auto operator=(lazy_zstring_view&& rhs) noexcept -> lazy_zstring_view& | ||
| 165 | { | ||
| 166 | return *this = rhs; // use the copy assignment operator | ||
| 167 | } | ||
| 168 | |||
| 169 | auto length() const noexcept -> std::size_t | ||
| 170 | { | ||
| 171 | if (auto v = length_.load(std::memory_order_acquire); v != unset_length) | ||
| 172 | return v; | ||
| 173 | auto l = std::char_traits<char>::length(s_); | ||
| 174 | length_.store(l, std::memory_order_release); | ||
| 175 | return l; | ||
| 176 | } | ||
| 177 | |||
| 178 | auto c_str() const noexcept -> char const* { return s_; } | ||
| 179 | 149 | ||
| 180 | operator std::string_view() const noexcept | 150 | auto length() const noexcept -> std::size_t; |
| 181 | { | 151 | auto c_str() const noexcept -> char const*; |
| 182 | return std::string_view{s_, length()}; | ||
| 183 | } | ||
| 184 | 152 | ||
| 185 | operator char const*() const noexcept { return s_; } | 153 | operator std::string_view() const noexcept; |
| 154 | operator char const*() const noexcept; | ||
| 186 | 155 | ||
| 187 | auto operator==(std::string_view sv) const noexcept -> bool | 156 | auto operator==(std::string_view sv) const noexcept -> bool; |
| 188 | { | ||
| 189 | if (auto v = length_.load(std::memory_order_acquire); v != unset_length) | ||
| 190 | if (sv.length() != v) | ||
| 191 | return false; | ||
| 192 | auto res = std::char_traits<char>::compare(s_, sv.data(), sv.length()); | ||
| 193 | if (res != 0) | ||
| 194 | return false; | ||
| 195 | // Strings are equal for sv.length() characters. | ||
| 196 | if (s_[sv.length()] != '\0') | ||
| 197 | return false; | ||
| 198 | // Strings are actually equal, and we have just found out the | ||
| 199 | // length of this string, so we might as well set it. | ||
| 200 | length_.store(sv.length(), std::memory_order_release); | ||
| 201 | return true; | ||
| 202 | } | ||
| 203 | }; | 157 | }; |
| 204 | 158 | ||
| 205 | constexpr auto operator""_zsv(char const* s, std::size_t length) noexcept | 159 | constexpr auto operator""_zsv(char const* s, std::size_t length) noexcept |
| @@ -208,12 +162,9 @@ constexpr auto operator""_zsv(char const* s, std::size_t length) noexcept | |||
| 208 | return zstring_view{s, length}; | 162 | return zstring_view{s, length}; |
| 209 | } | 163 | } |
| 210 | 164 | ||
| 211 | auto operator==(zstring_view lhs, zstring_view rhs) -> bool | 165 | auto operator==(zstring_view lhs, zstring_view rhs) -> bool; |
| 212 | { | ||
| 213 | return std::string_view{lhs} == std::string_view{rhs}; | ||
| 214 | } | ||
| 215 | 166 | ||
| 216 | export constexpr auto split_on(std::string_view s, char c) | 167 | constexpr auto split_on(std::string_view s, char c) |
| 217 | -> std::pair<std::string_view, std::optional<std::string_view>> | 168 | -> std::pair<std::string_view, std::optional<std::string_view>> |
| 218 | { | 169 | { |
| 219 | if (auto i = s.find(c); i != std::string_view::npos) | 170 | if (auto i = s.find(c); i != std::string_view::npos) |
| @@ -221,10 +172,10 @@ export constexpr auto split_on(std::string_view s, char c) | |||
| 221 | return std::make_pair(s, std::nullopt); | 172 | return std::make_pair(s, std::nullopt); |
| 222 | } | 173 | } |
| 223 | 174 | ||
| 224 | export template <class T> | 175 | template <class T> |
| 225 | class not_null; | 176 | class not_null; |
| 226 | 177 | ||
| 227 | export template <class T> | 178 | template <class T> |
| 228 | class not_null<T*> | 179 | class not_null<T*> |
| 229 | { | 180 | { |
| 230 | T* p_; | 181 | T* p_; |
| @@ -264,10 +215,10 @@ public: | |||
| 264 | 215 | ||
| 265 | auto operator->() const noexcept -> T* { return p_; } | 216 | auto operator->() const noexcept -> T* { return p_; } |
| 266 | }; | 217 | }; |
| 267 | export template <class T> | 218 | template <class T> |
| 268 | explicit not_null(T*) -> not_null<T*>; | 219 | explicit not_null(T*) -> not_null<T*>; |
| 269 | 220 | ||
| 270 | export template <> | 221 | template <> |
| 271 | class not_null<lazy_zstring_view> | 222 | class not_null<lazy_zstring_view> |
| 272 | { | 223 | { |
| 273 | lazy_zstring_view s_; | 224 | lazy_zstring_view s_; |
| @@ -285,6 +236,6 @@ public: | |||
| 285 | operator std::string_view() const noexcept { return s_; } | 236 | operator std::string_view() const noexcept { return s_; } |
| 286 | operator char const*() const noexcept { return s_; } | 237 | operator char const*() const noexcept { return s_; } |
| 287 | }; | 238 | }; |
| 288 | export explicit not_null(lazy_zstring_view s) -> not_null<lazy_zstring_view>; | 239 | explicit not_null(lazy_zstring_view s) -> not_null<lazy_zstring_view>; |
| 289 | 240 | ||
| 290 | } // namespace routemon::util | 241 | } // namespace routemon::util |