| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
1 |
// Formatting library for C++ - scanning API proof of concept |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
2 |
// |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
3 |
// Copyright (c) 2019 - present, Victor Zverovich |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
4 |
// All rights reserved. |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
5 |
// |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
6 |
// For the license information refer to format.h. |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
7 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
8 |
#include <array> |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
9 |
#include <cassert> |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
10 |
#include <climits> |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
11 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
12 |
#include "fmt/format.h" |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
13 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
14 |
FMT_BEGIN_NAMESPACE |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
15 |
template <typename T, typename Char = char> struct scanner { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
16 |
// A deleted default constructor indicates a disabled scanner. |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
17 |
scanner() = delete; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
18 |
}; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
19 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
20 |
class scan_parse_context { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
21 |
private: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
22 |
string_view format_; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
23 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
24 |
public: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
25 |
using iterator = string_view::iterator; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
26 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
27 |
explicit FMT_CONSTEXPR scan_parse_context(string_view format) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
28 |
: format_(format) {} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
29 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
30 |
FMT_CONSTEXPR iterator begin() const { return format_.begin(); } |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
31 |
FMT_CONSTEXPR iterator end() const { return format_.end(); } |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
32 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
33 |
void advance_to(iterator it) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
34 |
format_.remove_prefix(detail::to_unsigned(it - begin())); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
35 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
36 |
}; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
37 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
38 |
struct scan_context { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
39 |
private: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
40 |
string_view input_; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
41 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
42 |
public: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
43 |
using iterator = const char*; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
44 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
45 |
explicit scan_context(string_view input) : input_(input) {} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
46 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
47 |
iterator begin() const { return input_.data(); } |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
48 |
iterator end() const { return begin() + input_.size(); } |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
49 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
50 |
void advance_to(iterator it) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
51 |
input_.remove_prefix(detail::to_unsigned(it - begin())); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
52 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
53 |
}; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
54 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
55 |
namespace detail { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
56 |
enum class scan_type { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
57 |
none_type, |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
58 |
int_type, |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
59 |
uint_type, |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
60 |
long_long_type, |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
61 |
ulong_long_type, |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
62 |
string_type, |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
63 |
string_view_type, |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
64 |
custom_type |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
65 |
}; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
66 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
67 |
struct custom_scan_arg { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
68 |
void* value; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
69 |
void (*scan)(void* arg, scan_parse_context& parse_ctx, scan_context& ctx); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
70 |
}; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
71 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
72 |
class scan_arg { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
73 |
public: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
74 |
scan_type type; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
75 |
union { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
76 |
int* int_value; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
77 |
unsigned* uint_value; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
78 |
long long* long_long_value; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
79 |
unsigned long long* ulong_long_value; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
80 |
std::string* string; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
81 |
fmt::string_view* string_view; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
82 |
custom_scan_arg custom; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
83 |
// TODO: more types |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
84 |
}; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
85 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
86 |
scan_arg() : type(scan_type::none_type) {} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
87 |
scan_arg(int& value) : type(scan_type::int_type), int_value(&value) {} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
88 |
scan_arg(unsigned& value) : type(scan_type::uint_type), uint_value(&value) {} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
89 |
scan_arg(long long& value) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
90 |
: type(scan_type::long_long_type), long_long_value(&value) {} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
91 |
scan_arg(unsigned long long& value) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
92 |
: type(scan_type::ulong_long_type), ulong_long_value(&value) {} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
93 |
scan_arg(std::string& value) : type(scan_type::string_type), string(&value) {} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
94 |
scan_arg(fmt::string_view& value) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
95 |
: type(scan_type::string_view_type), string_view(&value) {} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
96 |
template <typename T> scan_arg(T& value) : type(scan_type::custom_type) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
97 |
custom.value = &value; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
98 |
custom.scan = scan_custom_arg<T>; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
99 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
100 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
101 |
private: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
102 |
template <typename T> |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
103 |
static void scan_custom_arg(void* arg, scan_parse_context& parse_ctx, |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
104 |
scan_context& ctx) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
105 |
scanner<T> s; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
106 |
parse_ctx.advance_to(s.parse(parse_ctx)); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
107 |
ctx.advance_to(s.scan(*static_cast<T*>(arg), ctx)); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
108 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
109 |
}; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
110 |
} // namespace detail |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
111 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
112 |
struct scan_args { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
113 |
int size; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
114 |
const detail::scan_arg* data; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
115 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
116 |
template <size_t N> |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
117 |
scan_args(const std::array<detail::scan_arg, N>& store) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
118 |
: size(N), data(store.data()) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
119 |
static_assert(N < INT_MAX, "too many arguments"); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
120 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
121 |
}; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
122 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
123 |
namespace detail { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
124 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
125 |
struct scan_handler : error_handler { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
126 |
private: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
127 |
scan_parse_context parse_ctx_; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
128 |
scan_context scan_ctx_; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
129 |
scan_args args_; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
130 |
int next_arg_id_; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
131 |
scan_arg arg_; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
132 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
133 |
template <typename T = unsigned> T read_uint() { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
134 |
T value = 0; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
135 |
auto it = scan_ctx_.begin(), end = scan_ctx_.end(); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
136 |
while (it != end) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
137 |
char c = *it++; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
138 |
if (c < '0' || c > '9') on_error("invalid input"); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
139 |
// TODO: check overflow |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
140 |
value = value * 10 + static_cast<unsigned>(c - '0'); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
141 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
142 |
scan_ctx_.advance_to(it); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
143 |
return value; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
144 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
145 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
146 |
template <typename T = int> T read_int() { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
147 |
auto it = scan_ctx_.begin(), end = scan_ctx_.end(); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
148 |
bool negative = it != end && *it == '-'; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
149 |
if (negative) ++it; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
150 |
scan_ctx_.advance_to(it); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
151 |
const auto value = read_uint<typename std::make_unsigned<T>::type>(); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
152 |
if (negative) return -static_cast<T>(value); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
153 |
return static_cast<T>(value); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
154 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
155 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
156 |
public: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
157 |
scan_handler(string_view format, string_view input, scan_args args) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
158 |
: parse_ctx_(format), scan_ctx_(input), args_(args), next_arg_id_(0) {} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
159 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
160 |
const char* pos() const { return scan_ctx_.begin(); } |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
161 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
162 |
void on_text(const char* begin, const char* end) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
163 |
auto size = to_unsigned(end - begin); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
164 |
auto it = scan_ctx_.begin(); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
165 |
if (it + size > scan_ctx_.end() || |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
166 |
!std::equal(begin, end, make_checked(it, size))) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
167 |
on_error("invalid input"); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
168 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
169 |
scan_ctx_.advance_to(it + size); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
170 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
171 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
172 |
FMT_CONSTEXPR int on_arg_id() { return on_arg_id(next_arg_id_++); } |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
173 |
FMT_CONSTEXPR int on_arg_id(int id) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
174 |
if (id >= args_.size) on_error("argument index out of range"); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
175 |
arg_ = args_.data[id]; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
176 |
return id; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
177 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
178 |
FMT_CONSTEXPR int on_arg_id(string_view id) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
179 |
if (id.data()) on_error("invalid format"); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
180 |
return 0; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
181 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
182 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
183 |
void on_replacement_field(int, const char*) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
184 |
auto it = scan_ctx_.begin(), end = scan_ctx_.end(); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
185 |
switch (arg_.type) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
186 |
case scan_type::int_type: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
187 |
*arg_.int_value = read_int(); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
188 |
break; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
189 |
case scan_type::uint_type: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
190 |
*arg_.uint_value = read_uint(); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
191 |
break; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
192 |
case scan_type::long_long_type: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
193 |
*arg_.long_long_value = read_int<long long>(); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
194 |
break; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
195 |
case scan_type::ulong_long_type: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
196 |
*arg_.ulong_long_value = read_uint<unsigned long long>(); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
197 |
break; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
198 |
case scan_type::string_type: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
199 |
while (it != end && *it != ' ') arg_.string->push_back(*it++); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
200 |
scan_ctx_.advance_to(it); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
201 |
break; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
202 |
case scan_type::string_view_type: { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
203 |
auto s = it; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
204 |
while (it != end && *it != ' ') ++it; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
205 |
*arg_.string_view = fmt::string_view(s, to_unsigned(it - s)); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
206 |
scan_ctx_.advance_to(it); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
207 |
break; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
208 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
209 |
case scan_type::none_type: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
210 |
case scan_type::custom_type: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
211 |
assert(false); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
212 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
213 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
214 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
215 |
const char* on_format_specs(int, const char* begin, const char*) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
216 |
if (arg_.type != scan_type::custom_type) return begin; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
217 |
parse_ctx_.advance_to(begin); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
218 |
arg_.custom.scan(arg_.custom.value, parse_ctx_, scan_ctx_); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
219 |
return parse_ctx_.begin(); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
220 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
221 |
}; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
222 |
} // namespace detail |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
223 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
224 |
template <typename... Args> |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
225 |
std::array<detail::scan_arg, sizeof...(Args)> make_scan_args(Args&... args) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
226 |
return {{args...}}; |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
227 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
228 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
229 |
string_view::iterator vscan(string_view input, string_view format_str, |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
230 |
scan_args args) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
231 |
detail::scan_handler h(format_str, input, args); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
232 |
detail::parse_format_string<false>(format_str, h); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
233 |
return input.begin() + (h.pos() - &*input.begin()); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
234 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
235 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
236 |
template <typename... Args> |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
237 |
string_view::iterator scan(string_view input, string_view format_str, |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
238 |
Args&... args) { |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
239 |
return vscan(input, format_str, make_scan_args(args...)); |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
240 |
} |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
241 |
FMT_END_NAMESPACE |
|
|
1970-01-01 00:00 |
242 |
|