unformat.cxx 1.2019.3 → 1.2019.4

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/README.md CHANGED
@@ -1,21 +1,55 @@
1
1
  **[Source available on GitHub](https://github.com/adamyaxley/Unformat)**
2
2
 
3
3
  # Unformat
4
+
4
5
  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
 
7
+ <br>
8
+
6
9
  ## Installation
7
10
 
8
11
  Run:
9
- ```bash
12
+
13
+ ```sh
10
14
  $ npm i unformat.cxx
11
15
  ```
12
16
 
13
17
  And then include `unformat.h` as follows:
18
+
14
19
  ```cxx
20
+ // main.cxx
15
21
  #include "node_modules/unformat.cxx/unformat.h"
22
+
23
+ int main() { /* ... */ }
24
+ ```
25
+
26
+ And then compile with `clang++` or `g++` as usual.
27
+
28
+ ```bash
29
+ $ clang++ main.cxx # or, use g++
30
+ $ g++ main.cxx
31
+ ```
32
+
33
+ You may also use a simpler approach:
34
+
35
+ ```cxx
36
+ // main.cxx
37
+ #include <unformat.h>
38
+
39
+ int main() { /* ... */ }
40
+ ```
41
+
42
+ If you add the path `node_modules/unformat.cxx` to your compiler's include paths.
43
+
44
+ ```bash
45
+ $ clang++ -I./node_modules/unformat.cxx main.cxx # or, use g++
46
+ $ g++ -I./node_modules/unformat.cxx main.cxx
16
47
  ```
17
48
 
49
+ <br>
50
+
18
51
  ## Quick Example
52
+
19
53
  Unformat is simple to use and works on all basic types. See the below example for extracting a `std::string` and an 'int'
20
54
  ```c++
21
55
  std::string name;
@@ -34,18 +68,31 @@ unformat("Harry is 18 years old.", format, name, age);
34
68
  // name == "Harry" and age == 18
35
69
  ```
36
70
 
71
+ <br>
72
+
37
73
  ## How do I use this library?
74
+
38
75
  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
76
 
77
+ <br>
78
+
40
79
  ## Public Domain
80
+
41
81
  This software is completely open source and in the public domain. See LICENSE for details.
42
82
 
83
+ <br>
84
+
43
85
  ## Contributing
86
+
44
87
  Pull requests are very welcome. You may also create Issues and I will have a look into it as soon as I can.
45
88
 
89
+ <br>
90
+
46
91
  ## Speed
92
+
47
93
  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
- ```
94
+
95
+ ```bash
49
96
  Run on (16 X 2993 MHz CPU s)
50
97
  03/13/19 18:10:57
51
98
  --------------------------------------------------------------------
@@ -63,5 +110,6 @@ StdScanf 1716 ns 1726 ns 407273
63
110
  <br>
64
111
 
65
112
 
113
+ [![SRC](https://img.shields.io/badge/src-repo-green?logo=Org)](https://github.com/adamyaxley/Unformat)
66
114
  [![ORG](https://img.shields.io/badge/org-nodef-green?logo=Org)](https://nodef.github.io)
67
115
  ![](https://ga-beacon.deno.dev/G-RC63DPBH3P:SH3Eq-NoQ9mwgYeHWxu7cw/github.com/nodef/unformat.cxx)
package/package.json CHANGED
@@ -1,15 +1,30 @@
1
1
  {
2
2
  "name": "unformat.cxx",
3
- "version": "1.2019.3",
3
+ "version": "1.2019.4",
4
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",
5
+ "keywords": [
6
+ "cxx",
7
+ "library",
8
+ "parsing",
9
+ "formatting",
10
+ "unformat",
11
+ "unformatted",
12
+ "fast",
13
+ "safe",
14
+ "type-safe"
15
+ ],
16
+ "homepage": "https://github.com/nodef/unformat.cxx#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/nodef/unformat.cxx/issues"
19
+ },
7
20
  "repository": {
8
21
  "type": "git",
9
22
  "url": "git+https://github.com/nodef/unformat.cxx.git"
10
23
  },
11
- "bugs": {
12
- "url": "https://github.com/nodef/unformat.cxx/issues"
13
- },
14
- "homepage": "https://github.com/nodef/unformat.cxx#readme"
24
+ "license": "UNLICENSED",
25
+ "author": "wolfram77@gmail.com",
26
+ "main": "unformat.h",
27
+ "scripts": {
28
+ "test": "bash build.sh test"
29
+ }
15
30
  }
package/unformat.h CHANGED
@@ -1,341 +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
- }
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
+ }
package/CMakeLists.txt DELETED
@@ -1,39 +0,0 @@
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)