Aria 2.0.0
C++23 MVVM framework (C++20 minimum) — reactive, coroutine-first, ABI-layered
Loading...
Searching...
No Matches
converter.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <cstdio>
6#include <functional>
7#include <optional>
8#include <stdexcept>
9#include <string>
10#include <utility>
11
12namespace aria::binding {
13
19class ConversionError : public std::runtime_error {
20public:
21 using std::runtime_error::runtime_error;
22};
23
43template<typename T, typename U>
44struct Converter {
45 std::function<U(const T&)> to_view;
46 std::function<T(const U&)> to_model;
47 std::function<std::optional<T>(const U&)> try_to_model;
48};
49
50namespace converters {
51
53 return {
54 [](const std::string& s) { return s; },
55 [](const std::string& s) { return s; },
56 [](const std::string& s) -> std::optional<std::string> { return s; }
57 };
58}
59
61 return {
62 [](const int& v) { return std::to_string(v); },
63 [](const std::string& s) -> int {
64 try {
65 std::size_t consumed = 0;
66 int v = std::stoi(s, &consumed);
67 // Reject trailing garbage (e.g. "12abc"): stoi returns 12
68 // but `consumed < s.size()` exposes the truncation.
69 if (consumed != s.size()) {
70 throw ConversionError{"int_to_string: trailing chars"};
71 }
72 return v;
73 } catch (const ConversionError&) {
74 throw;
75 } catch (...) {
76 throw ConversionError{"int_to_string: not an integer"};
77 }
78 },
79 [](const std::string& s) -> std::optional<int> {
80 try {
81 std::size_t consumed = 0;
82 int v = std::stoi(s, &consumed);
83 if (consumed != s.size()) return std::nullopt;
84 return v;
85 } catch (...) {
86 return std::nullopt;
87 }
88 }
89 };
90}
91
93 auto to_view = [precision](const double& v) {
94 const int length = std::snprintf(nullptr, 0, "%.*f", precision, v);
95 if (length < 0) throw ConversionError{"double_to_string: formatting failed"};
96 std::string text(static_cast<std::size_t>(length), '\0');
97 std::snprintf(text.data(), text.size() + 1, "%.*f", precision, v);
98 return text;
99 };
100 auto to_model_strict = [](const std::string& s) -> double {
101 try {
102 std::size_t consumed = 0;
103 double v = std::stod(s, &consumed);
104 if (consumed != s.size()) {
105 throw ConversionError{"double_to_string: trailing chars"};
106 }
107 return v;
108 } catch (const ConversionError&) {
109 throw;
110 } catch (...) {
111 throw ConversionError{"double_to_string: not a number"};
112 }
113 };
114 auto try_to_model = [](const std::string& s) -> std::optional<double> {
115 try {
116 std::size_t consumed = 0;
117 double v = std::stod(s, &consumed);
118 if (consumed != s.size()) return std::nullopt;
119 return v;
120 } catch (...) {
121 return std::nullopt;
122 }
123 };
124 return { std::move(to_view), std::move(to_model_strict), std::move(try_to_model) };
125}
126
128 return {
129 [](const bool& v) -> std::string { return v ? "yes" : "no"; },
130 [](const std::string& s) {
131 if (s == "yes" || s == "true" || s == "1") return true;
132 if (s == "no" || s == "false" || s == "0") return false;
133 throw ConversionError{"bool_to_yes_no: not a boolean"};
134 },
135 [](const std::string& s) -> std::optional<bool> {
136 if (s == "yes" || s == "true" || s == "1") return true;
137 if (s == "no" || s == "false" || s == "0") return false;
138 return std::nullopt;
139 }
140 };
141}
142
143} // namespace converters
144} // namespace aria::binding
Thrown by built-in Converter::to_model when the user-provided string cannot be parsed into the target...
Definition converter.hpp:19
Definition converter.hpp:50
Converter< bool, std::string > bool_to_yes_no()
Definition converter.hpp:127
Converter< std::string, std::string > identity_string()
Definition converter.hpp:52
Converter< int, std::string > int_to_string()
Definition converter.hpp:60
Converter< double, std::string > double_to_string(int precision=2)
Definition converter.hpp:92
Definition binding_engine.hpp:25
Bidirectional converter between Model type T and View type U.
Definition converter.hpp:44
std::function< std::optional< T >(const U &)> try_to_model
Definition converter.hpp:47
std::function< U(const T &)> to_view
Definition converter.hpp:45
std::function< T(const U &)> to_model
Definition converter.hpp:46