dump.hpp (20996B)
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_ */