Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/rapidyaml/include/c4/dump.hpp
4261 views
1
#ifndef C4_DUMP_HPP_
2
#define C4_DUMP_HPP_
3
4
#include <c4/substr.hpp>
5
6
namespace c4 {
7
8
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
9
10
11
//-----------------------------------------------------------------------------
12
//-----------------------------------------------------------------------------
13
//-----------------------------------------------------------------------------
14
/** type of the function to dump characters */
15
using DumperPfn = void (*)(csubstr buf);
16
17
18
//-----------------------------------------------------------------------------
19
//-----------------------------------------------------------------------------
20
//-----------------------------------------------------------------------------
21
22
template<DumperPfn dumpfn, class Arg>
23
inline size_t dump(substr buf, Arg const& a)
24
{
25
size_t sz = to_chars(buf, a); // need to serialize to the buffer
26
if(C4_LIKELY(sz <= buf.len))
27
dumpfn(buf.first(sz));
28
return sz;
29
}
30
31
template<class DumperFn, class Arg>
32
inline size_t dump(DumperFn &&dumpfn, substr buf, Arg const& a)
33
{
34
size_t sz = to_chars(buf, a); // need to serialize to the buffer
35
if(C4_LIKELY(sz <= buf.len))
36
dumpfn(buf.first(sz));
37
return sz;
38
}
39
40
template<DumperPfn dumpfn>
41
inline size_t dump(substr buf, csubstr a)
42
{
43
if(buf.len)
44
dumpfn(a); // dump directly, no need to serialize to the buffer
45
return 0; // no space was used in the buffer
46
}
47
48
template<class DumperFn>
49
inline size_t dump(DumperFn &&dumpfn, substr buf, csubstr a)
50
{
51
if(buf.len)
52
dumpfn(a); // dump directly, no need to serialize to the buffer
53
return 0; // no space was used in the buffer
54
}
55
56
template<DumperPfn dumpfn, size_t N>
57
inline size_t dump(substr buf, const char (&a)[N])
58
{
59
if(buf.len)
60
dumpfn(csubstr(a)); // dump directly, no need to serialize to the buffer
61
return 0; // no space was used in the buffer
62
}
63
64
template<class DumperFn, size_t N>
65
inline size_t dump(DumperFn &&dumpfn, substr buf, const char (&a)[N])
66
{
67
if(buf.len)
68
dumpfn(csubstr(a)); // dump directly, no need to serialize to the buffer
69
return 0; // no space was used in the buffer
70
}
71
72
73
//-----------------------------------------------------------------------------
74
//-----------------------------------------------------------------------------
75
//-----------------------------------------------------------------------------
76
77
/** */
78
struct DumpResults
79
{
80
enum : size_t { noarg = (size_t)-1 };
81
size_t bufsize = 0;
82
size_t lastok = noarg;
83
bool success_until(size_t expected) const { return lastok == noarg ? false : lastok >= expected; }
84
bool write_arg(size_t arg) const { return lastok == noarg || arg > lastok; }
85
size_t argfail() const { return lastok + 1; }
86
};
87
88
89
//-----------------------------------------------------------------------------
90
//-----------------------------------------------------------------------------
91
//-----------------------------------------------------------------------------
92
93
/// @cond dev
94
// terminates the variadic recursion
95
template<class DumperFn>
96
size_t cat_dump(DumperFn &&, substr)
97
{
98
return 0;
99
}
100
101
// terminates the variadic recursion
102
template<DumperPfn dumpfn>
103
size_t cat_dump(substr)
104
{
105
return 0;
106
}
107
/// @endcond
108
109
/** take the function pointer as a function argument */
110
template<class DumperFn, class Arg, class... Args>
111
size_t cat_dump(DumperFn &&dumpfn, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
112
{
113
size_t size_for_a = dump(dumpfn, buf, a);
114
if(C4_UNLIKELY(size_for_a > buf.len))
115
buf = buf.first(0); // ensure no more calls
116
size_t size_for_more = cat_dump(dumpfn, buf, more...);
117
return size_for_more > size_for_a ? size_for_more : size_for_a;
118
}
119
120
/** take the function pointer as a template argument */
121
template<DumperPfn dumpfn,class Arg, class... Args>
122
size_t cat_dump(substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
123
{
124
size_t size_for_a = dump<dumpfn>(buf, a);
125
if(C4_LIKELY(size_for_a > buf.len))
126
buf = buf.first(0); // ensure no more calls
127
size_t size_for_more = cat_dump<dumpfn>(buf, more...);
128
return size_for_more > size_for_a ? size_for_more : size_for_a;
129
}
130
131
132
//-----------------------------------------------------------------------------
133
//-----------------------------------------------------------------------------
134
//-----------------------------------------------------------------------------
135
136
/// @cond dev
137
namespace detail {
138
139
// terminates the variadic recursion
140
template<DumperPfn dumpfn, class Arg>
141
DumpResults cat_dump_resume(size_t currarg, DumpResults results, substr buf, Arg const& C4_RESTRICT a)
142
{
143
if(C4_LIKELY(results.write_arg(currarg)))
144
{
145
size_t sz = dump<dumpfn>(buf, a); // yield to the specialized function
146
if(currarg == results.lastok + 1 && sz <= buf.len)
147
results.lastok = currarg;
148
results.bufsize = sz > results.bufsize ? sz : results.bufsize;
149
}
150
return results;
151
}
152
153
// terminates the variadic recursion
154
template<class DumperFn, class Arg>
155
DumpResults cat_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a)
156
{
157
if(C4_LIKELY(results.write_arg(currarg)))
158
{
159
size_t sz = dump(dumpfn, buf, a); // yield to the specialized function
160
if(currarg == results.lastok + 1 && sz <= buf.len)
161
results.lastok = currarg;
162
results.bufsize = sz > results.bufsize ? sz : results.bufsize;
163
}
164
return results;
165
}
166
167
template<DumperPfn dumpfn, class Arg, class... Args>
168
DumpResults cat_dump_resume(size_t currarg, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
169
{
170
results = detail::cat_dump_resume<dumpfn>(currarg, results, buf, a);
171
return detail::cat_dump_resume<dumpfn>(currarg + 1u, results, buf, more...);
172
}
173
174
template<class DumperFn, class Arg, class... Args>
175
DumpResults cat_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
176
{
177
results = detail::cat_dump_resume(currarg, dumpfn, results, buf, a);
178
return detail::cat_dump_resume(currarg + 1u, dumpfn, results, buf, more...);
179
}
180
} // namespace detail
181
/// @endcond
182
183
184
template<DumperPfn dumpfn, class Arg, class... Args>
185
C4_ALWAYS_INLINE DumpResults cat_dump_resume(DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
186
{
187
if(results.bufsize > buf.len)
188
return results;
189
return detail::cat_dump_resume<dumpfn>(0u, results, buf, a, more...);
190
}
191
192
template<class DumperFn, class Arg, class... Args>
193
C4_ALWAYS_INLINE DumpResults cat_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
194
{
195
if(results.bufsize > buf.len)
196
return results;
197
return detail::cat_dump_resume(0u, dumpfn, results, buf, a, more...);
198
}
199
200
template<DumperPfn dumpfn, class Arg, class... Args>
201
C4_ALWAYS_INLINE DumpResults cat_dump_resume(substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
202
{
203
return detail::cat_dump_resume<dumpfn>(0u, DumpResults{}, buf, a, more...);
204
}
205
206
template<class DumperFn, class Arg, class... Args>
207
C4_ALWAYS_INLINE DumpResults cat_dump_resume(DumperFn &&dumpfn, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
208
{
209
return detail::cat_dump_resume(0u, dumpfn, DumpResults{}, buf, a, more...);
210
}
211
212
213
//-----------------------------------------------------------------------------
214
//-----------------------------------------------------------------------------
215
//-----------------------------------------------------------------------------
216
217
/// @cond dev
218
// terminate the recursion
219
template<class DumperFn, class Sep>
220
size_t catsep_dump(DumperFn &&, substr, Sep const& C4_RESTRICT)
221
{
222
return 0;
223
}
224
225
// terminate the recursion
226
template<DumperPfn dumpfn, class Sep>
227
size_t catsep_dump(substr, Sep const& C4_RESTRICT)
228
{
229
return 0;
230
}
231
/// @endcond
232
233
/** take the function pointer as a function argument */
234
template<class DumperFn, class Sep, class Arg, class... Args>
235
size_t catsep_dump(DumperFn &&dumpfn, substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
236
{
237
size_t sz = dump(dumpfn, buf, a);
238
if(C4_UNLIKELY(sz > buf.len))
239
buf = buf.first(0); // ensure no more calls
240
if C4_IF_CONSTEXPR (sizeof...(more) > 0)
241
{
242
size_t szsep = dump(dumpfn, buf, sep);
243
if(C4_UNLIKELY(szsep > buf.len))
244
buf = buf.first(0); // ensure no more calls
245
sz = sz > szsep ? sz : szsep;
246
}
247
size_t size_for_more = catsep_dump(dumpfn, buf, sep, more...);
248
return size_for_more > sz ? size_for_more : sz;
249
}
250
251
/** take the function pointer as a template argument */
252
template<DumperPfn dumpfn, class Sep, class Arg, class... Args>
253
size_t catsep_dump(substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
254
{
255
size_t sz = dump<dumpfn>(buf, a);
256
if(C4_UNLIKELY(sz > buf.len))
257
buf = buf.first(0); // ensure no more calls
258
if C4_IF_CONSTEXPR (sizeof...(more) > 0)
259
{
260
size_t szsep = dump<dumpfn>(buf, sep);
261
if(C4_UNLIKELY(szsep > buf.len))
262
buf = buf.first(0); // ensure no more calls
263
sz = sz > szsep ? sz : szsep;
264
}
265
size_t size_for_more = catsep_dump<dumpfn>(buf, sep, more...);
266
return size_for_more > sz ? size_for_more : sz;
267
}
268
269
270
//-----------------------------------------------------------------------------
271
//-----------------------------------------------------------------------------
272
//-----------------------------------------------------------------------------
273
274
/// @cond dev
275
namespace detail {
276
template<DumperPfn dumpfn, class Arg>
277
void catsep_dump_resume_(size_t currarg, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Arg const& C4_RESTRICT a)
278
{
279
if(C4_LIKELY(results->write_arg(currarg)))
280
{
281
size_t sz = dump<dumpfn>(*buf, a);
282
results->bufsize = sz > results->bufsize ? sz : results->bufsize;
283
if(C4_LIKELY(sz <= buf->len))
284
results->lastok = currarg;
285
else
286
buf->len = 0;
287
}
288
}
289
290
template<class DumperFn, class Arg>
291
void catsep_dump_resume_(size_t currarg, DumperFn &&dumpfn, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Arg const& C4_RESTRICT a)
292
{
293
if(C4_LIKELY(results->write_arg(currarg)))
294
{
295
size_t sz = dump(dumpfn, *buf, a);
296
results->bufsize = sz > results->bufsize ? sz : results->bufsize;
297
if(C4_LIKELY(sz <= buf->len))
298
results->lastok = currarg;
299
else
300
buf->len = 0;
301
}
302
}
303
304
template<DumperPfn dumpfn, class Sep, class Arg>
305
C4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT, Arg const& C4_RESTRICT a)
306
{
307
detail::catsep_dump_resume_<dumpfn>(currarg, results, buf, a);
308
}
309
310
template<class DumperFn, class Sep, class Arg>
311
C4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT, Arg const& C4_RESTRICT a)
312
{
313
detail::catsep_dump_resume_(currarg, dumpfn, results, buf, a);
314
}
315
316
template<DumperPfn dumpfn, class Sep, class Arg, class... Args>
317
C4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
318
{
319
detail::catsep_dump_resume_<dumpfn>(currarg , results, buf, a);
320
detail::catsep_dump_resume_<dumpfn>(currarg + 1u, results, buf, sep);
321
detail::catsep_dump_resume <dumpfn>(currarg + 2u, results, buf, sep, more...);
322
}
323
324
template<class DumperFn, class Sep, class Arg, class... Args>
325
C4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
326
{
327
detail::catsep_dump_resume_(currarg , dumpfn, results, buf, a);
328
detail::catsep_dump_resume_(currarg + 1u, dumpfn, results, buf, sep);
329
detail::catsep_dump_resume (currarg + 2u, dumpfn, results, buf, sep, more...);
330
}
331
} // namespace detail
332
/// @endcond
333
334
335
template<DumperPfn dumpfn, class Sep, class... Args>
336
C4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumpResults results, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)
337
{
338
detail::catsep_dump_resume<dumpfn>(0u, &results, &buf, sep, more...);
339
return results;
340
}
341
342
template<class DumperFn, class Sep, class... Args>
343
C4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)
344
{
345
detail::catsep_dump_resume(0u, dumpfn, &results, &buf, sep, more...);
346
return results;
347
}
348
349
template<DumperPfn dumpfn, class Sep, class... Args>
350
C4_ALWAYS_INLINE DumpResults catsep_dump_resume(substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)
351
{
352
DumpResults results;
353
detail::catsep_dump_resume<dumpfn>(0u, &results, &buf, sep, more...);
354
return results;
355
}
356
357
template<class DumperFn, class Sep, class... Args>
358
C4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumperFn &&dumpfn, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)
359
{
360
DumpResults results;
361
detail::catsep_dump_resume(0u, dumpfn, &results, &buf, sep, more...);
362
return results;
363
}
364
365
366
//-----------------------------------------------------------------------------
367
//-----------------------------------------------------------------------------
368
//-----------------------------------------------------------------------------
369
370
/** take the function pointer as a function argument */
371
template<class DumperFn>
372
C4_ALWAYS_INLINE size_t format_dump(DumperFn &&dumpfn, substr buf, csubstr fmt)
373
{
374
// we can dump without using buf
375
// but we'll only dump if the buffer is ok
376
if(C4_LIKELY(buf.len > 0 && fmt.len))
377
dumpfn(fmt);
378
return 0u;
379
}
380
381
/** take the function pointer as a function argument */
382
template<DumperPfn dumpfn>
383
C4_ALWAYS_INLINE size_t format_dump(substr buf, csubstr fmt)
384
{
385
// we can dump without using buf
386
// but we'll only dump if the buffer is ok
387
if(C4_LIKELY(buf.len > 0 && fmt.len > 0))
388
dumpfn(fmt);
389
return 0u;
390
}
391
392
/** take the function pointer as a function argument */
393
template<class DumperFn, class Arg, class... Args>
394
size_t format_dump(DumperFn &&dumpfn, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
395
{
396
// we can dump without using buf
397
// but we'll only dump if the buffer is ok
398
size_t pos = fmt.find("{}"); // @todo use _find_fmt()
399
if(C4_UNLIKELY(pos == csubstr::npos))
400
{
401
if(C4_LIKELY(buf.len > 0 && fmt.len > 0))
402
dumpfn(fmt);
403
return 0u;
404
}
405
if(C4_LIKELY(buf.len > 0 && pos > 0))
406
dumpfn(fmt.first(pos)); // we can dump without using buf
407
fmt = fmt.sub(pos + 2); // skip {} do this before assigning to pos again
408
pos = dump(dumpfn, buf, a);
409
if(C4_UNLIKELY(pos > buf.len))
410
buf.len = 0; // ensure no more calls to dump
411
size_t size_for_more = format_dump(dumpfn, buf, fmt, more...);
412
return size_for_more > pos ? size_for_more : pos;
413
}
414
415
/** take the function pointer as a template argument */
416
template<DumperPfn dumpfn, class Arg, class... Args>
417
size_t format_dump(substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
418
{
419
// we can dump without using buf
420
// but we'll only dump if the buffer is ok
421
size_t pos = fmt.find("{}"); // @todo use _find_fmt()
422
if(C4_UNLIKELY(pos == csubstr::npos))
423
{
424
if(C4_LIKELY(buf.len > 0 && fmt.len > 0))
425
dumpfn(fmt);
426
return 0u;
427
}
428
if(C4_LIKELY(buf.len > 0 && pos > 0))
429
dumpfn(fmt.first(pos)); // we can dump without using buf
430
fmt = fmt.sub(pos + 2); // skip {} do this before assigning to pos again
431
pos = dump<dumpfn>(buf, a);
432
if(C4_UNLIKELY(pos > buf.len))
433
buf.len = 0; // ensure no more calls to dump
434
size_t size_for_more = format_dump<dumpfn>(buf, fmt, more...);
435
return size_for_more > pos ? size_for_more : pos;
436
}
437
438
439
//-----------------------------------------------------------------------------
440
//-----------------------------------------------------------------------------
441
//-----------------------------------------------------------------------------
442
443
/// @cond dev
444
namespace detail {
445
446
template<DumperPfn dumpfn>
447
DumpResults format_dump_resume(size_t currarg, DumpResults results, substr buf, csubstr fmt)
448
{
449
// we can dump without using buf
450
// but we'll only dump if the buffer is ok
451
if(C4_LIKELY(buf.len > 0))
452
{
453
dumpfn(fmt);
454
results.lastok = currarg;
455
}
456
return results;
457
}
458
459
template<class DumperFn>
460
DumpResults format_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt)
461
{
462
// we can dump without using buf
463
// but we'll only dump if the buffer is ok
464
if(C4_LIKELY(buf.len > 0))
465
{
466
dumpfn(fmt);
467
results.lastok = currarg;
468
}
469
return results;
470
}
471
472
template<DumperPfn dumpfn, class Arg, class... Args>
473
DumpResults format_dump_resume(size_t currarg, DumpResults results, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
474
{
475
// we need to process the format even if we're not
476
// going to print the first arguments because we're resuming
477
size_t pos = fmt.find("{}"); // @todo use _find_fmt()
478
// we can dump without using buf
479
// but we'll only dump if the buffer is ok
480
if(C4_LIKELY(results.write_arg(currarg)))
481
{
482
if(C4_UNLIKELY(pos == csubstr::npos))
483
{
484
if(C4_LIKELY(buf.len > 0))
485
{
486
results.lastok = currarg;
487
dumpfn(fmt);
488
}
489
return results;
490
}
491
if(C4_LIKELY(buf.len > 0))
492
{
493
results.lastok = currarg;
494
dumpfn(fmt.first(pos));
495
}
496
}
497
fmt = fmt.sub(pos + 2);
498
if(C4_LIKELY(results.write_arg(currarg + 1)))
499
{
500
pos = dump<dumpfn>(buf, a);
501
results.bufsize = pos > results.bufsize ? pos : results.bufsize;
502
if(C4_LIKELY(pos <= buf.len))
503
results.lastok = currarg + 1;
504
else
505
buf.len = 0;
506
}
507
return detail::format_dump_resume<dumpfn>(currarg + 2u, results, buf, fmt, more...);
508
}
509
/// @endcond
510
511
512
template<class DumperFn, class Arg, class... Args>
513
DumpResults format_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)
514
{
515
// we need to process the format even if we're not
516
// going to print the first arguments because we're resuming
517
size_t pos = fmt.find("{}"); // @todo use _find_fmt()
518
// we can dump without using buf
519
// but we'll only dump if the buffer is ok
520
if(C4_LIKELY(results.write_arg(currarg)))
521
{
522
if(C4_UNLIKELY(pos == csubstr::npos))
523
{
524
if(C4_LIKELY(buf.len > 0))
525
{
526
results.lastok = currarg;
527
dumpfn(fmt);
528
}
529
return results;
530
}
531
if(C4_LIKELY(buf.len > 0))
532
{
533
results.lastok = currarg;
534
dumpfn(fmt.first(pos));
535
}
536
}
537
fmt = fmt.sub(pos + 2);
538
if(C4_LIKELY(results.write_arg(currarg + 1)))
539
{
540
pos = dump(dumpfn, buf, a);
541
results.bufsize = pos > results.bufsize ? pos : results.bufsize;
542
if(C4_LIKELY(pos <= buf.len))
543
results.lastok = currarg + 1;
544
else
545
buf.len = 0;
546
}
547
return detail::format_dump_resume(currarg + 2u, dumpfn, results, buf, fmt, more...);
548
}
549
} // namespace detail
550
551
552
template<DumperPfn dumpfn, class... Args>
553
C4_ALWAYS_INLINE DumpResults format_dump_resume(DumpResults results, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)
554
{
555
return detail::format_dump_resume<dumpfn>(0u, results, buf, fmt, more...);
556
}
557
558
template<class DumperFn, class... Args>
559
C4_ALWAYS_INLINE DumpResults format_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)
560
{
561
return detail::format_dump_resume(0u, dumpfn, results, buf, fmt, more...);
562
}
563
564
565
template<DumperPfn dumpfn, class... Args>
566
C4_ALWAYS_INLINE DumpResults format_dump_resume(substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)
567
{
568
return detail::format_dump_resume<dumpfn>(0u, DumpResults{}, buf, fmt, more...);
569
}
570
571
template<class DumperFn, class... Args>
572
C4_ALWAYS_INLINE DumpResults format_dump_resume(DumperFn &&dumpfn, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)
573
{
574
return detail::format_dump_resume(0u, dumpfn, DumpResults{}, buf, fmt, more...);
575
}
576
577
C4_SUPPRESS_WARNING_GCC_CLANG_POP
578
579
} // namespace c4
580
581
582
#endif /* C4_DUMP_HPP_ */
583
584