| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1 |
// Formatting library for C++ - scanning API proof of concept |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2 |
// |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3 |
// Copyright (c) 2019 - present, Victor Zverovich |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4 |
// All rights reserved. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
5 |
// |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
6 |
// For the license information refer to format.h. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
7 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
8 |
#include <array> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
9 |
#include <cassert> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
10 |
#include <climits> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
11 |
#include <tuple> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
12 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
13 |
#include "fmt/format-inl.h" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
14 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
15 |
FMT_BEGIN_NAMESPACE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
16 |
namespace detail { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
17 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
18 |
inline auto is_whitespace(char c) -> bool { return c == ' ' || c == '\n'; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
19 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
20 |
// If c is a hex digit returns its numeric value, otherwise -1. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
21 |
inline auto to_hex_digit(char c) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
22 |
if (c >= '0' && c <= '9') return c - '0'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
23 |
if (c >= 'a' && c <= 'f') return c - 'a' + 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
24 |
if (c >= 'A' && c <= 'F') return c - 'A' + 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
25 |
return -1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
26 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
27 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
28 |
struct maybe_contiguous_range { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
29 |
const char* begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
30 |
const char* end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
31 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
32 |
explicit operator bool() const { return begin != nullptr; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
33 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
34 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
35 |
class scan_buffer { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
36 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
37 |
const char* ptr_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
38 |
const char* end_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
39 |
bool contiguous_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
40 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
41 |
protected: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
42 |
scan_buffer(const char* ptr, const char* end, bool contiguous) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
43 |
: ptr_(ptr), end_(end), contiguous_(contiguous) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
44 |
~scan_buffer() = default; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
45 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
46 |
void set(span<const char> buf) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
47 |
ptr_ = buf.data; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
48 |
end_ = buf.data + buf.size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
49 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
50 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
51 |
auto ptr() const -> const char* { return ptr_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
52 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
53 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
54 |
scan_buffer(const scan_buffer&) = delete; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
55 |
void operator=(const scan_buffer&) = delete; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
56 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
57 |
// Fills the buffer with more input if available. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
58 |
virtual void consume() = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
59 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
60 |
class sentinel {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
61 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
62 |
class iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
63 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
64 |
const char** ptr_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
65 |
scan_buffer* buf_; // This could be merged with ptr_. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
66 |
char value_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
67 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
68 |
static auto get_sentinel() -> const char** { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
69 |
static const char* ptr = nullptr; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
70 |
return &ptr; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
71 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
72 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
73 |
friend class scan_buffer; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
74 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
75 |
friend auto operator==(iterator lhs, sentinel) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
76 |
return *lhs.ptr_ == nullptr; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
77 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
78 |
friend auto operator!=(iterator lhs, sentinel) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
79 |
return *lhs.ptr_ != nullptr; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
80 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
81 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
82 |
iterator(scan_buffer* buf) : buf_(buf) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
83 |
if (buf->ptr_ == buf->end_) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
84 |
ptr_ = get_sentinel(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
85 |
return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
86 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
87 |
ptr_ = &buf->ptr_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
88 |
value_ = *buf->ptr_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
89 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
90 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
91 |
friend scan_buffer& get_buffer(iterator it) { return *it.buf_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
92 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
93 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
94 |
iterator() : ptr_(get_sentinel()), buf_(nullptr) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
95 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
96 |
auto operator++() -> iterator& { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
97 |
if (!buf_->try_consume()) ptr_ = get_sentinel(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
98 |
value_ = *buf_->ptr_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
99 |
return *this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
100 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
101 |
auto operator++(int) -> iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
102 |
iterator copy = *this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
103 |
++*this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
104 |
return copy; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
105 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
106 |
auto operator*() const -> char { return value_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
107 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
108 |
auto base() const -> const char* { return buf_->ptr_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
109 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
110 |
friend auto to_contiguous(iterator it) -> maybe_contiguous_range; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
111 |
friend auto advance(iterator it, size_t n) -> iterator; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
112 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
113 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
114 |
friend auto to_contiguous(iterator it) -> maybe_contiguous_range { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
115 |
if (it.buf_->is_contiguous()) return {it.buf_->ptr_, it.buf_->end_}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
116 |
return {nullptr, nullptr}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
117 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
118 |
friend auto advance(iterator it, size_t n) -> iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
119 |
FMT_ASSERT(it.buf_->is_contiguous(), ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
120 |
const char*& ptr = it.buf_->ptr_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
121 |
ptr += n; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
122 |
it.value_ = *ptr; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
123 |
if (ptr == it.buf_->end_) it.ptr_ = iterator::get_sentinel(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
124 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
125 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
126 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
127 |
auto begin() -> iterator { return this; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
128 |
auto end() -> sentinel { return {}; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
129 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
130 |
auto is_contiguous() const -> bool { return contiguous_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
131 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
132 |
// Tries consuming a single code unit. Returns true iff there is more input. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
133 |
auto try_consume() -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
134 |
FMT_ASSERT(ptr_ != end_, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
135 |
++ptr_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
136 |
if (ptr_ != end_) return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
137 |
consume(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
138 |
return ptr_ != end_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
139 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
140 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
141 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
142 |
using scan_iterator = scan_buffer::iterator; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
143 |
using scan_sentinel = scan_buffer::sentinel; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
144 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
145 |
class string_scan_buffer final : public scan_buffer { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
146 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
147 |
void consume() override {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
148 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
149 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
150 |
explicit string_scan_buffer(string_view s) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
151 |
: scan_buffer(s.begin(), s.end(), true) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
152 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
153 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
154 |
class file_scan_buffer final : public scan_buffer { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
155 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
156 |
template <typename F, FMT_ENABLE_IF(sizeof(F::_IO_read_ptr) != 0 && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
157 |
!FMT_USE_FALLBACK_FILE)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
158 |
static auto get_file(F* f, int) -> glibc_file<F> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
159 |
return f; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
160 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
161 |
template <typename F, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
162 |
FMT_ENABLE_IF(sizeof(F::_p) != 0 && !FMT_USE_FALLBACK_FILE)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
163 |
static auto get_file(F* f, int) -> apple_file<F> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
164 |
return f; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
165 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
166 |
static auto get_file(FILE* f, ...) -> fallback_file<FILE> { return f; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
167 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
168 |
decltype(get_file(static_cast<FILE*>(nullptr), 0)) file_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
169 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
170 |
// Fills the buffer if it is empty. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
171 |
void fill() { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
172 |
span<const char> buf = file_.get_read_buffer(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
173 |
if (buf.size == 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
174 |
int c = file_.get(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
175 |
// Put the character back since we are only filling the buffer. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
176 |
if (c != EOF) file_.unget(static_cast<char>(c)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
177 |
buf = file_.get_read_buffer(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
178 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
179 |
set(buf); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
180 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
181 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
182 |
void consume() override { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
183 |
// Consume the current buffer content. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
184 |
size_t n = to_unsigned(ptr() - file_.get_read_buffer().data); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
185 |
for (size_t i = 0; i != n; ++i) file_.get(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
186 |
fill(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
187 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
188 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
189 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
190 |
explicit file_scan_buffer(FILE* f) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
191 |
: scan_buffer(nullptr, nullptr, false), file_(f) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
192 |
flockfile(f); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
193 |
fill(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
194 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
195 |
~file_scan_buffer() { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
196 |
FILE* f = file_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
197 |
funlockfile(f); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
198 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
199 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
200 |
} // namespace detail |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
201 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
202 |
template <typename T, typename Char = char> struct scanner { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
203 |
// A deleted default constructor indicates a disabled scanner. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
204 |
scanner() = delete; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
205 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
206 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
207 |
class scan_parse_context { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
208 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
209 |
string_view format_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
210 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
211 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
212 |
using iterator = string_view::iterator; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
213 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
214 |
explicit FMT_CONSTEXPR scan_parse_context(string_view format) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
215 |
: format_(format) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
216 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
217 |
FMT_CONSTEXPR auto begin() const -> iterator { return format_.begin(); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
218 |
FMT_CONSTEXPR auto end() const -> iterator { return format_.end(); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
219 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
220 |
void advance_to(iterator it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
221 |
format_.remove_prefix(detail::to_unsigned(it - begin())); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
222 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
223 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
224 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
225 |
namespace detail { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
226 |
enum class scan_type { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
227 |
none_type, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
228 |
int_type, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
229 |
uint_type, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
230 |
long_long_type, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
231 |
ulong_long_type, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
232 |
string_type, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
233 |
string_view_type, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
234 |
custom_type |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
235 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
236 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
237 |
template <typename Context> struct custom_scan_arg { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
238 |
void* value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
239 |
void (*scan)(void* arg, scan_parse_context& parse_ctx, Context& ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
240 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
241 |
} // namespace detail |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
242 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
243 |
// A scan argument. Context is a template parameter for the compiled API where |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
244 |
// output can be unbuffered. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
245 |
template <typename Context> class basic_scan_arg { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
246 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
247 |
using scan_type = detail::scan_type; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
248 |
scan_type type_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
249 |
union { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
250 |
int* int_value_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
251 |
unsigned* uint_value_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
252 |
long long* long_long_value_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
253 |
unsigned long long* ulong_long_value_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
254 |
std::string* string_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
255 |
string_view* string_view_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
256 |
detail::custom_scan_arg<Context> custom_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
257 |
// TODO: more types |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
258 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
259 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
260 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
261 |
static void scan_custom_arg(void* arg, scan_parse_context& parse_ctx, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
262 |
Context& ctx) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
263 |
auto s = scanner<T>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
264 |
parse_ctx.advance_to(s.parse(parse_ctx)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
265 |
ctx.advance_to(s.scan(*static_cast<T*>(arg), ctx)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
266 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
267 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
268 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
269 |
FMT_CONSTEXPR basic_scan_arg() |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
270 |
: type_(scan_type::none_type), int_value_(nullptr) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
271 |
FMT_CONSTEXPR basic_scan_arg(int& value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
272 |
: type_(scan_type::int_type), int_value_(&value) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
273 |
FMT_CONSTEXPR basic_scan_arg(unsigned& value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
274 |
: type_(scan_type::uint_type), uint_value_(&value) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
275 |
FMT_CONSTEXPR basic_scan_arg(long long& value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
276 |
: type_(scan_type::long_long_type), long_long_value_(&value) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
277 |
FMT_CONSTEXPR basic_scan_arg(unsigned long long& value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
278 |
: type_(scan_type::ulong_long_type), ulong_long_value_(&value) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
279 |
FMT_CONSTEXPR basic_scan_arg(std::string& value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
280 |
: type_(scan_type::string_type), string_(&value) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
281 |
FMT_CONSTEXPR basic_scan_arg(string_view& value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
282 |
: type_(scan_type::string_view_type), string_view_(&value) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
283 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
284 |
FMT_CONSTEXPR basic_scan_arg(T& value) : type_(scan_type::custom_type) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
285 |
custom_.value = &value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
286 |
custom_.scan = scan_custom_arg<T>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
287 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
288 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
289 |
constexpr explicit operator bool() const noexcept { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
290 |
return type_ != scan_type::none_type; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
291 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
292 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
293 |
auto type() const -> detail::scan_type { return type_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
294 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
295 |
template <typename Visitor> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
296 |
auto visit(Visitor&& vis) -> decltype(vis(monostate())) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
297 |
switch (type_) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
298 |
case scan_type::none_type: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
299 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
300 |
case scan_type::int_type: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
301 |
return vis(*int_value_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
302 |
case scan_type::uint_type: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
303 |
return vis(*uint_value_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
304 |
case scan_type::long_long_type: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
305 |
return vis(*long_long_value_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
306 |
case scan_type::ulong_long_type: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
307 |
return vis(*ulong_long_value_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
308 |
case scan_type::string_type: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
309 |
return vis(*string_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
310 |
case scan_type::string_view_type: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
311 |
return vis(*string_view_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
312 |
case scan_type::custom_type: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
313 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
314 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
315 |
return vis(monostate()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
316 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
317 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
318 |
auto scan_custom(const char* parse_begin, scan_parse_context& parse_ctx, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
319 |
Context& ctx) const -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
320 |
if (type_ != scan_type::custom_type) return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
321 |
parse_ctx.advance_to(parse_begin); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
322 |
custom_.scan(custom_.value, parse_ctx, ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
323 |
return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
324 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
325 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
326 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
327 |
class scan_context; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
328 |
using scan_arg = basic_scan_arg<scan_context>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
329 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
330 |
struct scan_args { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
331 |
int size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
332 |
const scan_arg* data; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
333 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
334 |
template <size_t N> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
335 |
FMT_CONSTEXPR scan_args(const std::array<scan_arg, N>& store) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
336 |
: size(N), data(store.data()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
337 |
static_assert(N < INT_MAX, "too many arguments"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
338 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
339 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
340 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
341 |
class scan_context { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
342 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
343 |
detail::scan_buffer& buf_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
344 |
scan_args args_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
345 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
346 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
347 |
using iterator = detail::scan_iterator; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
348 |
using sentinel = detail::scan_sentinel; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
349 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
350 |
explicit FMT_CONSTEXPR scan_context(detail::scan_buffer& buf, scan_args args) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
351 |
: buf_(buf), args_(args) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
352 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
353 |
FMT_CONSTEXPR auto arg(int id) const -> scan_arg { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
354 |
return id < args_.size ? args_.data[id] : scan_arg(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
355 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
356 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
357 |
auto begin() const -> iterator { return buf_.begin(); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
358 |
auto end() const -> sentinel { return {}; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
359 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
360 |
void advance_to(iterator) { buf_.consume(); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
361 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
362 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
363 |
namespace detail { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
364 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
365 |
const char* parse_scan_specs(const char* begin, const char* end, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
366 |
format_specs& specs, scan_type) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
367 |
while (begin != end) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
368 |
switch (to_ascii(*begin)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
369 |
// TODO: parse more scan format specifiers |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
370 |
case 'x': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
371 |
specs.type = presentation_type::hex; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
372 |
++begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
373 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
374 |
case '}': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
375 |
return begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
376 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
377 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
378 |
return begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
379 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
380 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
381 |
template <typename T, FMT_ENABLE_IF(std::is_unsigned<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
382 |
auto read(scan_iterator it, T& value) -> scan_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
383 |
if (it == scan_sentinel()) return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
384 |
char c = *it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
385 |
if (c < '0' || c > '9') report_error("invalid input"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
386 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
387 |
int num_digits = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
388 |
T n = 0, prev = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
389 |
char prev_digit = c; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
390 |
do { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
391 |
prev = n; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
392 |
n = n * 10 + static_cast<unsigned>(c - '0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
393 |
prev_digit = c; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
394 |
c = *++it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
395 |
++num_digits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
396 |
if (c < '0' || c > '9') break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
397 |
} while (it != scan_sentinel()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
398 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
399 |
// Check overflow. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
400 |
if (num_digits <= std::numeric_limits<int>::digits10) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
401 |
value = n; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
402 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
403 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
404 |
unsigned max = to_unsigned((std::numeric_limits<int>::max)()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
405 |
if (num_digits == std::numeric_limits<int>::digits10 + 1 && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
406 |
prev * 10ull + unsigned(prev_digit - '0') <= max) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
407 |
value = n; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
408 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
409 |
report_error("number is too big"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
410 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
411 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
412 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
413 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
414 |
template <typename T, FMT_ENABLE_IF(std::is_unsigned<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
415 |
auto read_hex(scan_iterator it, T& value) -> scan_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
416 |
if (it == scan_sentinel()) return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
417 |
int digit = to_hex_digit(*it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
418 |
if (digit < 0) report_error("invalid input"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
419 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
420 |
int num_digits = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
421 |
T n = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
422 |
do { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
423 |
n = (n << 4) + static_cast<unsigned>(digit); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
424 |
++num_digits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
425 |
digit = to_hex_digit(*++it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
426 |
if (digit < 0) break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
427 |
} while (it != scan_sentinel()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
428 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
429 |
// Check overflow. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
430 |
if (num_digits <= (std::numeric_limits<T>::digits >> 2)) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
431 |
value = n; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
432 |
else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
433 |
report_error("number is too big"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
434 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
435 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
436 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
437 |
template <typename T, FMT_ENABLE_IF(std::is_unsigned<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
438 |
auto read(scan_iterator it, T& value, const format_specs& specs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
439 |
-> scan_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
440 |
if (specs.type == presentation_type::hex) return read_hex(it, value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
441 |
return read(it, value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
442 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
443 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
444 |
template <typename T, FMT_ENABLE_IF(std::is_signed<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
445 |
auto read(scan_iterator it, T& value, const format_specs& specs = {}) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
446 |
-> scan_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
447 |
bool negative = it != scan_sentinel() && *it == '-'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
448 |
if (negative) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
449 |
++it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
450 |
if (it == scan_sentinel()) report_error("invalid input"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
451 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
452 |
using unsigned_type = typename std::make_unsigned<T>::type; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
453 |
unsigned_type abs_value = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
454 |
it = read(it, abs_value, specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
455 |
auto n = static_cast<T>(abs_value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
456 |
value = negative ? -n : n; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
457 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
458 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
459 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
460 |
auto read(scan_iterator it, std::string& value, const format_specs& = {}) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
461 |
-> scan_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
462 |
while (it != scan_sentinel() && *it != ' ') value.push_back(*it++); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
463 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
464 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
465 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
466 |
auto read(scan_iterator it, string_view& value, const format_specs& = {}) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
467 |
-> scan_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
468 |
auto range = to_contiguous(it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
469 |
// This could also be checked at compile time in scan. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
470 |
if (!range) report_error("string_view requires contiguous input"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
471 |
auto p = range.begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
472 |
while (p != range.end && *p != ' ') ++p; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
473 |
size_t size = to_unsigned(p - range.begin); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
474 |
value = {range.begin, size}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
475 |
return advance(it, size); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
476 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
477 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
478 |
auto read(scan_iterator it, monostate, const format_specs& = {}) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
479 |
-> scan_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
480 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
481 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
482 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
483 |
// An argument scanner that uses the default format, e.g. decimal for integers. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
484 |
struct default_arg_scanner { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
485 |
scan_iterator it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
486 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
487 |
template <typename T> FMT_INLINE auto operator()(T&& value) -> scan_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
488 |
return read(it, value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
489 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
490 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
491 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
492 |
// An argument scanner with format specifiers. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
493 |
struct arg_scanner { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
494 |
scan_iterator it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
495 |
const format_specs& specs; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
496 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
497 |
template <typename T> auto operator()(T&& value) -> scan_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
498 |
return read(it, value, specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
499 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
500 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
501 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
502 |
struct scan_handler { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
503 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
504 |
scan_parse_context parse_ctx_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
505 |
scan_context scan_ctx_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
506 |
int next_arg_id_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
507 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
508 |
using sentinel = scan_buffer::sentinel; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
509 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
510 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
511 |
FMT_CONSTEXPR scan_handler(string_view format, scan_buffer& buf, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
512 |
scan_args args) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
513 |
: parse_ctx_(format), scan_ctx_(buf, args), next_arg_id_(0) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
514 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
515 |
auto pos() const -> scan_buffer::iterator { return scan_ctx_.begin(); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
516 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
517 |
void on_text(const char* begin, const char* end) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
518 |
if (begin == end) return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
519 |
auto it = scan_ctx_.begin(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
520 |
for (; begin != end; ++begin, ++it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
521 |
if (it == sentinel() || *begin != *it) on_error("invalid input"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
522 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
523 |
scan_ctx_.advance_to(it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
524 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
525 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
526 |
FMT_CONSTEXPR auto on_arg_id() -> int { return on_arg_id(next_arg_id_++); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
527 |
FMT_CONSTEXPR auto on_arg_id(int id) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
528 |
if (!scan_ctx_.arg(id)) on_error("argument index out of range"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
529 |
return id; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
530 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
531 |
FMT_CONSTEXPR auto on_arg_id(string_view id) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
532 |
if (id.data()) on_error("invalid format"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
533 |
return 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
534 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
535 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
536 |
void on_replacement_field(int arg_id, const char* begin) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
537 |
scan_arg arg = scan_ctx_.arg(arg_id); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
538 |
if (arg.scan_custom(begin, parse_ctx_, scan_ctx_)) return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
539 |
auto it = scan_ctx_.begin(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
540 |
while (it != sentinel() && is_whitespace(*it)) ++it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
541 |
scan_ctx_.advance_to(arg.visit(default_arg_scanner{it})); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
542 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
543 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
544 |
auto on_format_specs(int arg_id, const char* begin, const char* end) -> const |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
545 |
char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
546 |
scan_arg arg = scan_ctx_.arg(arg_id); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
547 |
if (arg.scan_custom(begin, parse_ctx_, scan_ctx_)) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
548 |
return parse_ctx_.begin(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
549 |
auto specs = format_specs(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
550 |
begin = parse_scan_specs(begin, end, specs, arg.type()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
551 |
if (begin == end || *begin != '}') on_error("missing '}' in format string"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
552 |
scan_ctx_.advance_to(arg.visit(arg_scanner{scan_ctx_.begin(), specs})); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
553 |
return begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
554 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
555 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
556 |
FMT_NORETURN void on_error(const char* message) { report_error(message); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
557 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
558 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
559 |
void vscan(detail::scan_buffer& buf, string_view fmt, scan_args args) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
560 |
auto h = detail::scan_handler(fmt, buf, args); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
561 |
detail::parse_format_string<false>(fmt, h); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
562 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
563 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
564 |
template <size_t I, typename... T, FMT_ENABLE_IF(I == sizeof...(T))> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
565 |
void make_args(std::array<scan_arg, sizeof...(T)>&, std::tuple<T...>&) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
566 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
567 |
template <size_t I, typename... T, FMT_ENABLE_IF(I < sizeof...(T))> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
568 |
void make_args(std::array<scan_arg, sizeof...(T)>& args, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
569 |
std::tuple<T...>& values) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
570 |
using element_type = typename std::tuple_element<I, std::tuple<T...>>::type; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
571 |
static_assert(std::is_same<remove_cvref_t<element_type>, element_type>::value, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
572 |
""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
573 |
args[I] = std::get<I>(values); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
574 |
make_args<I + 1>(args, values); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
575 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
576 |
} // namespace detail |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
577 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
578 |
template <typename Range, typename... T> class scan_data { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
579 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
580 |
std::tuple<T...> values_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
581 |
Range range_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
582 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
583 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
584 |
scan_data() = default; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
585 |
scan_data(T... values) : values_(std::move(values)...) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
586 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
587 |
auto value() const -> decltype(std::get<0>(values_)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
588 |
return std::get<0>(values_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
589 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
590 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
591 |
auto values() const -> const std::tuple<T...>& { return values_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
592 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
593 |
auto make_args() -> std::array<scan_arg, sizeof...(T)> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
594 |
auto args = std::array<scan_arg, sizeof...(T)>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
595 |
detail::make_args<0>(args, values_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
596 |
return args; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
597 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
598 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
599 |
auto range() const -> Range { return range_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
600 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
601 |
auto begin() const -> decltype(range_.begin()) { return range_.begin(); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
602 |
auto end() const -> decltype(range_.end()) { return range_.end(); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
603 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
604 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
605 |
template <typename... T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
606 |
auto make_scan_args(T&... args) -> std::array<scan_arg, sizeof...(T)> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
607 |
return {{args...}}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
608 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
609 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
610 |
class scan_error {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
611 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
612 |
// A rudimentary version of std::expected for testing the API shape. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
613 |
template <typename T, typename E> class expected { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
614 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
615 |
T value_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
616 |
bool has_value_ = true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
617 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
618 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
619 |
expected(T value) : value_(std::move(value)) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
620 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
621 |
explicit operator bool() const { return has_value_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
622 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
623 |
auto operator->() const -> const T* { return &value_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
624 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
625 |
auto error() -> E const { return E(); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
626 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
627 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
628 |
template <typename Range, typename... T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
629 |
using scan_result = expected<scan_data<Range, T...>, scan_error>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
630 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
631 |
auto vscan(string_view input, string_view fmt, scan_args args) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
632 |
-> string_view::iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
633 |
auto&& buf = detail::string_scan_buffer(input); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
634 |
detail::vscan(buf, fmt, args); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
635 |
return input.begin() + (buf.begin().base() - input.data()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
636 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
637 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
638 |
// Scans the input and stores the results (in)to args. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
639 |
template <typename... T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
640 |
auto scan_to(string_view input, string_view fmt, T&... args) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
641 |
-> string_view::iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
642 |
return vscan(input, fmt, make_scan_args(args...)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
643 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
644 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
645 |
template <typename... T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
646 |
auto scan(string_view input, string_view fmt) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
647 |
-> scan_result<string_view, T...> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
648 |
auto data = scan_data<string_view, T...>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
649 |
vscan(input, fmt, data.make_args()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
650 |
return data; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
651 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
652 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
653 |
template <typename Range, typename... T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
654 |
FMT_ENABLE_IF(!std::is_convertible<Range, string_view>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
655 |
auto scan_to(Range&& input, string_view fmt, T&... args) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
656 |
-> decltype(std::begin(input)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
657 |
auto it = std::begin(input); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
658 |
detail::vscan(get_buffer(it), fmt, make_scan_args(args...)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
659 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
660 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
661 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
662 |
template <typename... T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
663 |
auto scan_to(FILE* f, string_view fmt, T&... args) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
664 |
auto&& buf = detail::file_scan_buffer(f); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
665 |
detail::vscan(buf, fmt, make_scan_args(args...)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
666 |
return buf.begin() != buf.end(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
667 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
668 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
669 |
FMT_END_NAMESPACE |
|
|
1970-01-01 00:00 |
670 |
|