C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
numeric_conversion.hpp
1/*
2 * Copyright (c) 2024 The RefValue Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include "basic_string.hpp"
26
27#include <array>
28#include <charconv>
29#include <concepts>
30#include <cstdint>
31#include <optional>
32#include <string>
33#include <string_view>
34#include <system_error>
35#include <type_traits>
36#include <utility>
37
38namespace essence::detail {
39 template <typename T, typename... Args>
40 requires std::is_arithmetic_v<T>
41 std::optional<T> from_string(std::string_view str, Args&&... args)
42 requires requires(
43 T number) { std::from_chars(str.data(), str.data() + str.size(), number, std::forward<Args>(args)...); }
44 {
45 if (str.empty()) {
46 return std::nullopt;
47 }
48
49 if (T result{}; std::from_chars(str.data(), str.data() + str.size(), result, std::forward<Args>(args)...).ec
50 == std::errc{}) {
51 return result;
52 }
53
54 return std::nullopt;
55 }
56
57 template <std_basic_string S, typename T, typename... Args>
58 requires std::is_arithmetic_v<T>
59 S to_string(T number, Args&&... args)
60 requires requires(char* str) { std::to_chars(str, str, number, std::forward<Args>(args)...); }
61 {
62 thread_local std::array<char, 64> buffer{};
63
64 if (auto&& [ptr, ec] =
65 std::to_chars(buffer.data(), buffer.data() + buffer.size(), number, std::forward<Args>(args)...);
66 ec == std::errc{}) {
67 return {buffer.data(), ptr};
68 }
69
70 return {};
71 }
72} // namespace essence::detail
73
74namespace essence {
82 template <std::integral T>
83 std::optional<T> from_string(std::string_view str, std::int32_t base = 10) {
84 return detail::from_string<T>(str, base);
85 }
86
94 template <std::floating_point T>
95 std::optional<T> from_string(std::string_view str, std::chars_format format = std::chars_format::general) {
96 return detail::from_string<T>(str, format);
97 }
98
107 template <std_basic_string S = std::string, std::integral T>
108 S to_string(T number, std::int32_t base = 10) {
109 return detail::to_string<S>(number, base);
110 }
111
119 template <std_basic_string S = std::string, std::floating_point T>
120 S to_string(T number) {
121 return detail::to_string<S>(number);
122 }
123
132 template <std_basic_string S = std::string, std::floating_point T>
133 S to_string(T number, std::chars_format format) {
134 return detail::to_string<S>(number, format);
135 }
136
146 template <std_basic_string S = std::string, std::floating_point T>
147 S to_string(T number, std::chars_format format, std::int32_t precision) {
148 return detail::to_string<S>(number, format, precision);
149 }
150} // namespace essence