unformat.cxx 1.2019.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +39 -0
- package/LICENSE +24 -0
- package/README.md +67 -0
- package/package.json +15 -0
- package/unformat.h +341 -0
package/CMakeLists.txt
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.0)
|
|
2
|
+
|
|
3
|
+
project(Unformat)
|
|
4
|
+
|
|
5
|
+
set(CMAKE_CXX_STANDARD 11)
|
|
6
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
7
|
+
|
|
8
|
+
include(DownloadProject/DownloadProject.cmake)
|
|
9
|
+
|
|
10
|
+
# Functional test
|
|
11
|
+
download_project(PROJ googletest
|
|
12
|
+
GIT_REPOSITORY https://github.com/google/googletest.git
|
|
13
|
+
GIT_TAG release-1.8.0
|
|
14
|
+
${UPDATE_DISCONNECTED_IF_AVAILABLE}
|
|
15
|
+
)
|
|
16
|
+
# Prevent GoogleTest from overriding our compiler/linker options
|
|
17
|
+
# when building with Visual Studio
|
|
18
|
+
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
|
19
|
+
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
|
|
20
|
+
add_executable(unformat_test unformat.h unformat_test.cpp)
|
|
21
|
+
target_link_libraries(unformat_test gtest gmock_main)
|
|
22
|
+
|
|
23
|
+
# Benchmark
|
|
24
|
+
if (CMAKE_VERSION VERSION_LESS 3.2)
|
|
25
|
+
set(UPDATE_DISCONNECTED_IF_AVAILABLE "")
|
|
26
|
+
else()
|
|
27
|
+
set(UPDATE_DISCONNECTED_IF_AVAILABLE "UPDATE_DISCONNECTED 1")
|
|
28
|
+
endif()
|
|
29
|
+
|
|
30
|
+
download_project(PROJ benchmark
|
|
31
|
+
GIT_REPOSITORY https://github.com/google/benchmark.git
|
|
32
|
+
GIT_TAG v1.3.0
|
|
33
|
+
${UPDATE_DISCONNECTED_IF_AVAILABLE}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
set(BENCHMARK_ENABLE_TESTING OFF)
|
|
37
|
+
add_subdirectory(${benchmark_SOURCE_DIR} ${benchmark_BINARY_DIR})
|
|
38
|
+
add_executable(unformat_benchmark unformat.h unformat_benchmark.cpp)
|
|
39
|
+
target_link_libraries(unformat_benchmark benchmark)
|
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
|
+
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
+
distribute this software, either in source code form or as a compiled
|
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
+
means.
|
|
7
|
+
|
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
+
of this software dedicate any and all copyright interest in the
|
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
|
11
|
+
of the public at large and to the detriment of our heirs and
|
|
12
|
+
successors. We intend this dedication to be an overt act of
|
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
+
software under copyright law.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
For more information, please refer to <http://unlicense.org>
|
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
**[Source available on GitHub](https://github.com/adamyaxley/Unformat)**
|
|
2
|
+
|
|
3
|
+
# Unformat
|
|
4
|
+
Parsing and extraction of original data from brace style "{}" formatted strings. It basically _unformats_ what you thought was formatted for good. It is developed and maintained by [Adam Yaxley](https://github.com/adamyaxley).
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
Run:
|
|
9
|
+
```bash
|
|
10
|
+
$ npm i unformat.cxx
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then include `unformat.h` as follows:
|
|
14
|
+
```cxx
|
|
15
|
+
#include "node_modules/unformat.cxx/unformat.h"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Example
|
|
19
|
+
Unformat is simple to use and works on all basic types. See the below example for extracting a `std::string` and an 'int'
|
|
20
|
+
```c++
|
|
21
|
+
std::string name;
|
|
22
|
+
int age;
|
|
23
|
+
|
|
24
|
+
unformat("Harry is 18 years old.", "{} is {} years old.", name, age);
|
|
25
|
+
// name == "Harry" and age == 18
|
|
26
|
+
```
|
|
27
|
+
As an optimisation, if the format string is known at compile time, it can be parsed into a constant expression by making use of `ay::make_format`. In tests, this increases runtime speed by a factor of 3 or 4.
|
|
28
|
+
```c++
|
|
29
|
+
std::string name;
|
|
30
|
+
int age;
|
|
31
|
+
|
|
32
|
+
constexpr auto format = ay::make_format("{} is {} years old.");
|
|
33
|
+
unformat("Harry is 18 years old.", format, name, age);
|
|
34
|
+
// name == "Harry" and age == 18
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## How do I use this library?
|
|
38
|
+
Unformat is a single-file header only library so integration is easy. All you need to do is copy `unformat.h` into your project, and away you go.
|
|
39
|
+
|
|
40
|
+
## Public Domain
|
|
41
|
+
This software is completely open source and in the public domain. See LICENSE for details.
|
|
42
|
+
|
|
43
|
+
## Contributing
|
|
44
|
+
Pull requests are very welcome. You may also create Issues and I will have a look into it as soon as I can.
|
|
45
|
+
|
|
46
|
+
## Speed
|
|
47
|
+
Unformat is super awesome back to the future style lightning fast compared to traditional parsing methods. Below is the output from Google Benchmark on unformat_benchmark.cpp. Great Scott!
|
|
48
|
+
```
|
|
49
|
+
Run on (16 X 2993 MHz CPU s)
|
|
50
|
+
03/13/19 18:10:57
|
|
51
|
+
--------------------------------------------------------------------
|
|
52
|
+
Benchmark Time CPU Iterations
|
|
53
|
+
--------------------------------------------------------------------
|
|
54
|
+
Unformat 72 ns 71 ns 8960000
|
|
55
|
+
Unformat_ConstChar 69 ns 70 ns 8960000
|
|
56
|
+
Unformat_ConstexprMakeFormat 36 ns 35 ns 19478261
|
|
57
|
+
StdStringStream 844 ns 854 ns 896000
|
|
58
|
+
StdRegex 9975 ns 10010 ns 64000
|
|
59
|
+
StdScanf 1716 ns 1726 ns 407273
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
<br>
|
|
63
|
+
<br>
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
[](https://nodef.github.io)
|
|
67
|
+

|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "unformat.cxx",
|
|
3
|
+
"version": "1.2019.3",
|
|
4
|
+
"description": "Fastest type-safe parsing library in the world for C++14 or C++17 (up to 300x faster than std::regex); Adam Yaxley (2017).",
|
|
5
|
+
"keywords": ["c", "library", "parsing", "formatting", "unformat", "unformatted", "fast", "safe", "type-safe", "cpp", "c++", "cxx"],
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/nodef/unformat.cxx.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/nodef/unformat.cxx/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/nodef/unformat.cxx#readme"
|
|
15
|
+
}
|
package/unformat.h
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#ifdef _MSC_VER
|
|
4
|
+
#if _MSC_VER >= 1910 && _HAS_CXX17
|
|
5
|
+
#define UNFORMAT_CPP17
|
|
6
|
+
#endif
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
#include <string>
|
|
10
|
+
#ifdef UNFORMAT_CPP17
|
|
11
|
+
#include <string_view>
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
namespace
|
|
15
|
+
{
|
|
16
|
+
template <typename T>
|
|
17
|
+
void unformat_signed_int(const char* input, const char* inputEnd, T& output) noexcept
|
|
18
|
+
{
|
|
19
|
+
output = 0;
|
|
20
|
+
int sign = 1;
|
|
21
|
+
if (*input == '-')
|
|
22
|
+
{
|
|
23
|
+
sign = -1;
|
|
24
|
+
++input;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
#ifndef UNFORMAT_DISABLE_PLUS_SIGN
|
|
28
|
+
// Ignore plus
|
|
29
|
+
if (*input == '+')
|
|
30
|
+
{
|
|
31
|
+
++input;
|
|
32
|
+
}
|
|
33
|
+
#endif
|
|
34
|
+
|
|
35
|
+
while (input != inputEnd)
|
|
36
|
+
{
|
|
37
|
+
output *= 10;
|
|
38
|
+
output += (*input - '0');
|
|
39
|
+
++input;
|
|
40
|
+
}
|
|
41
|
+
output *= sign;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
template <typename T>
|
|
45
|
+
void unformat_unsigned_int(const char* input, const char* inputEnd, T& output) noexcept
|
|
46
|
+
{
|
|
47
|
+
output = 0;
|
|
48
|
+
while (input != inputEnd)
|
|
49
|
+
{
|
|
50
|
+
output *= 10;
|
|
51
|
+
output += (*input - '0');
|
|
52
|
+
++input;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
template <typename T>
|
|
57
|
+
void unformat_real(const char* input, const char* inputEnd, T& output) noexcept
|
|
58
|
+
{
|
|
59
|
+
long double f = 0;
|
|
60
|
+
|
|
61
|
+
// Check for negative
|
|
62
|
+
if (*input == '-')
|
|
63
|
+
{
|
|
64
|
+
f = -f;
|
|
65
|
+
++input;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#ifndef UNFORMAT_DISABLE_PLUS_SIGN
|
|
69
|
+
// Ignore plus
|
|
70
|
+
if (*input == '+')
|
|
71
|
+
{
|
|
72
|
+
++input;
|
|
73
|
+
}
|
|
74
|
+
#endif
|
|
75
|
+
|
|
76
|
+
// Parse units
|
|
77
|
+
while (*input != '.' && input != inputEnd && *input != 'e')
|
|
78
|
+
{
|
|
79
|
+
f *= 10;
|
|
80
|
+
f += (*input - '0');
|
|
81
|
+
++input;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Parse decimal
|
|
85
|
+
if (*input == '.')
|
|
86
|
+
{
|
|
87
|
+
++input;
|
|
88
|
+
long double decimal = 1.0L;
|
|
89
|
+
while (input != inputEnd && *input != 'e')
|
|
90
|
+
{
|
|
91
|
+
decimal *= 0.1L;
|
|
92
|
+
f += (*input - '0') * decimal;
|
|
93
|
+
++input;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Parse exponent
|
|
98
|
+
if (*input == 'e')
|
|
99
|
+
{
|
|
100
|
+
++input;
|
|
101
|
+
if (*input == '+')
|
|
102
|
+
{
|
|
103
|
+
++input; // Skip + as unformat_signed_int can't handle it
|
|
104
|
+
}
|
|
105
|
+
int e;
|
|
106
|
+
unformat_signed_int(input, inputEnd, e);
|
|
107
|
+
f *= pow(10L, e);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
output = static_cast<T>(f);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
namespace ay
|
|
115
|
+
{
|
|
116
|
+
// Not defined on purpose for the general case. Note that you can define custom unformatters by defining new specialisations
|
|
117
|
+
// for this function.
|
|
118
|
+
template <typename T>
|
|
119
|
+
void unformat_arg(const char* input, const char* inputEnd, T& output) noexcept;
|
|
120
|
+
|
|
121
|
+
template <typename T>
|
|
122
|
+
T unformat_arg(const char* input, const char* inputEnd) noexcept
|
|
123
|
+
{
|
|
124
|
+
T output;
|
|
125
|
+
unformat_arg(input, inputEnd, output);
|
|
126
|
+
return output;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
#ifdef UNFORMAT_CPP17
|
|
130
|
+
template <typename T>
|
|
131
|
+
T unformat_arg(std::string_view input) noexcept
|
|
132
|
+
{
|
|
133
|
+
return unformat_arg<T>(input.data(), input.data() + input.length());
|
|
134
|
+
}
|
|
135
|
+
#endif
|
|
136
|
+
|
|
137
|
+
template <typename T>
|
|
138
|
+
T unformat_arg(std::string input) noexcept
|
|
139
|
+
{
|
|
140
|
+
return unformat_arg<T>(input.c_str(), input.c_str() + input.length());
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
template <>
|
|
144
|
+
inline void unformat_arg<char>(const char* input, const char* inputEnd, char& output) noexcept
|
|
145
|
+
{
|
|
146
|
+
output = input[0];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
template <>
|
|
150
|
+
inline void unformat_arg<unsigned char>(const char* input, const char* inputEnd, unsigned char& output) noexcept
|
|
151
|
+
{
|
|
152
|
+
output = input[0];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
#ifdef UNFORMAT_CPP17
|
|
156
|
+
template <>
|
|
157
|
+
inline void unformat_arg<std::string_view>(const char* input, const char* inputEnd, std::string_view& output) noexcept
|
|
158
|
+
{
|
|
159
|
+
output = std::string_view(input, inputEnd - input);
|
|
160
|
+
}
|
|
161
|
+
#endif
|
|
162
|
+
|
|
163
|
+
template <>
|
|
164
|
+
inline void unformat_arg<std::string>(const char* input, const char* inputEnd, std::string& output) noexcept
|
|
165
|
+
{
|
|
166
|
+
output.assign(input, inputEnd - input);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
template <>
|
|
170
|
+
inline void unformat_arg<float>(const char* input, const char* inputEnd, float& output) noexcept
|
|
171
|
+
{
|
|
172
|
+
unformat_real<float>(input, inputEnd, output);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
template <>
|
|
176
|
+
inline void unformat_arg<double>(const char* input, const char* inputEnd, double& output) noexcept
|
|
177
|
+
{
|
|
178
|
+
unformat_real<double>(input, inputEnd, output);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
template <>
|
|
182
|
+
inline void unformat_arg<short>(const char* input, const char* inputEnd, short& output) noexcept
|
|
183
|
+
{
|
|
184
|
+
unformat_signed_int<short>(input, inputEnd, output);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
template <>
|
|
188
|
+
inline void unformat_arg<int>(const char* input, const char* inputEnd, int& output) noexcept
|
|
189
|
+
{
|
|
190
|
+
unformat_signed_int<int>(input, inputEnd, output);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
template <>
|
|
194
|
+
inline void unformat_arg<long>(const char* input, const char* inputEnd, long& output) noexcept
|
|
195
|
+
{
|
|
196
|
+
unformat_signed_int<long>(input, inputEnd, output);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
template <>
|
|
200
|
+
inline void unformat_arg<long long>(const char* input, const char* inputEnd, long long& output) noexcept
|
|
201
|
+
{
|
|
202
|
+
unformat_signed_int<long long>(input, inputEnd, output);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
template <>
|
|
206
|
+
inline void unformat_arg<unsigned short>(const char* input, const char* inputEnd, unsigned short& output) noexcept
|
|
207
|
+
{
|
|
208
|
+
unformat_unsigned_int<unsigned short>(input, inputEnd, output);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
template <>
|
|
212
|
+
inline void unformat_arg<unsigned int>(const char* input, const char* inputEnd, unsigned int& output) noexcept
|
|
213
|
+
{
|
|
214
|
+
unformat_unsigned_int<unsigned int>(input, inputEnd, output);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
template <>
|
|
218
|
+
inline void unformat_arg<unsigned long>(const char* input, const char* inputEnd, unsigned long& output) noexcept
|
|
219
|
+
{
|
|
220
|
+
unformat_unsigned_int<unsigned long>(input, inputEnd, output);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
template <>
|
|
224
|
+
inline void unformat_arg<unsigned long long>(const char* input, const char* inputEnd, unsigned long long& output) noexcept
|
|
225
|
+
{
|
|
226
|
+
unformat_unsigned_int<unsigned long long>(input, inputEnd, output);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
struct format;
|
|
230
|
+
|
|
231
|
+
constexpr format make_format_non_template(const char* str, std::size_t N);
|
|
232
|
+
|
|
233
|
+
struct format
|
|
234
|
+
{
|
|
235
|
+
constexpr format() {}
|
|
236
|
+
|
|
237
|
+
template <std::size_t N>
|
|
238
|
+
constexpr format(const char(&str)[N])
|
|
239
|
+
{
|
|
240
|
+
*this = make_format_non_template(str, N);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
format(const char* str)
|
|
244
|
+
{
|
|
245
|
+
*this = make_format_non_template(str, std::strlen(str));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
static constexpr std::size_t MAX_COUNT{ 16 };
|
|
249
|
+
std::size_t offsets[MAX_COUNT]{};
|
|
250
|
+
char endChar[MAX_COUNT]{};
|
|
251
|
+
std::size_t count{ 0 };
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
template <std::size_t N>
|
|
255
|
+
constexpr format make_format(const char(&str)[N]) noexcept
|
|
256
|
+
{
|
|
257
|
+
return make_format_non_template(str, N);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
constexpr format make_format_non_template(const char* str, std::size_t N)
|
|
261
|
+
{
|
|
262
|
+
format format;
|
|
263
|
+
|
|
264
|
+
std::size_t from = 0;
|
|
265
|
+
for (std::size_t to = 0; to < N - 1; to++)
|
|
266
|
+
{
|
|
267
|
+
if (str[to] == '{' && str[to + 1] == '}')
|
|
268
|
+
{
|
|
269
|
+
if (format.count >= format::MAX_COUNT)
|
|
270
|
+
{
|
|
271
|
+
// Stops compilation in a constexpr context
|
|
272
|
+
throw std::exception("Max number of {} has been exceeded.");
|
|
273
|
+
}
|
|
274
|
+
format.offsets[format.count] = to - from;
|
|
275
|
+
format.endChar[format.count] = str[to + 2]; // May be '\0' which is fine
|
|
276
|
+
++format.count;
|
|
277
|
+
// Advance markers
|
|
278
|
+
from = to + 2;
|
|
279
|
+
to = from;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return format;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Empty function to end recursion, no more args to process
|
|
287
|
+
inline void unformat_internal(std::size_t inputPos, const char* input, const format& format) noexcept
|
|
288
|
+
{
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
template <typename T, typename... TRest>
|
|
292
|
+
void unformat_internal(std::size_t inputPos, const char* input, const format& format, T& first, TRest&... rest) noexcept
|
|
293
|
+
{
|
|
294
|
+
const std::size_t argNo = format.count - sizeof...(rest) - 1;
|
|
295
|
+
|
|
296
|
+
// Get the location of the first brace
|
|
297
|
+
const auto offset = format.offsets[argNo];
|
|
298
|
+
|
|
299
|
+
// Find input string
|
|
300
|
+
inputPos += offset;
|
|
301
|
+
auto inputEnd = inputPos;
|
|
302
|
+
while (input[inputEnd] != format.endChar[argNo])
|
|
303
|
+
{
|
|
304
|
+
++inputEnd;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Process this arg
|
|
308
|
+
unformat_arg(&input[inputPos], &input[inputEnd], first);
|
|
309
|
+
|
|
310
|
+
// Process TRest
|
|
311
|
+
unformat_internal(inputEnd, input, format, rest...);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Parses and extracts data from 'input' given a braced styled "{}" 'format' into 'args...'
|
|
315
|
+
// For example:
|
|
316
|
+
// std::string name, int age;
|
|
317
|
+
// constexpr auto format = make_format("{} is {} years old.");
|
|
318
|
+
// unformat("Harry is 18 years old.", format, name, age);
|
|
319
|
+
//
|
|
320
|
+
// Then the following data is extracted:
|
|
321
|
+
// name == "Harry" and age == 18
|
|
322
|
+
template <typename... Args>
|
|
323
|
+
void unformat(const char* input, const format& format, Args&... args) noexcept
|
|
324
|
+
{
|
|
325
|
+
unformat_internal(0, input, format, args...);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Parses and extracts data from 'input' given a braced styled "{}" 'format' into 'args...'
|
|
329
|
+
// For example:
|
|
330
|
+
// std::string name, int age;
|
|
331
|
+
// constexpr auto format = make_format("{} is {} years old.");
|
|
332
|
+
// unformat("Harry is 18 years old.", format, name, age);
|
|
333
|
+
//
|
|
334
|
+
// Then the following data is extracted:
|
|
335
|
+
// name == "Harry" and age == 18
|
|
336
|
+
template <typename... Args>
|
|
337
|
+
void unformat(const std::string& input, const format& format, Args&... args) noexcept
|
|
338
|
+
{
|
|
339
|
+
unformat_internal(0, input.c_str(), format, args...);
|
|
340
|
+
}
|
|
341
|
+
}
|