Path: blob/master/dep/rapidyaml/include/c4/dump.hpp
4261 views
#ifndef C4_DUMP_HPP_1#define C4_DUMP_HPP_23#include <c4/substr.hpp>45namespace c4 {67C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")8910//-----------------------------------------------------------------------------11//-----------------------------------------------------------------------------12//-----------------------------------------------------------------------------13/** type of the function to dump characters */14using DumperPfn = void (*)(csubstr buf);151617//-----------------------------------------------------------------------------18//-----------------------------------------------------------------------------19//-----------------------------------------------------------------------------2021template<DumperPfn dumpfn, class Arg>22inline size_t dump(substr buf, Arg const& a)23{24size_t sz = to_chars(buf, a); // need to serialize to the buffer25if(C4_LIKELY(sz <= buf.len))26dumpfn(buf.first(sz));27return sz;28}2930template<class DumperFn, class Arg>31inline size_t dump(DumperFn &&dumpfn, substr buf, Arg const& a)32{33size_t sz = to_chars(buf, a); // need to serialize to the buffer34if(C4_LIKELY(sz <= buf.len))35dumpfn(buf.first(sz));36return sz;37}3839template<DumperPfn dumpfn>40inline size_t dump(substr buf, csubstr a)41{42if(buf.len)43dumpfn(a); // dump directly, no need to serialize to the buffer44return 0; // no space was used in the buffer45}4647template<class DumperFn>48inline size_t dump(DumperFn &&dumpfn, substr buf, csubstr a)49{50if(buf.len)51dumpfn(a); // dump directly, no need to serialize to the buffer52return 0; // no space was used in the buffer53}5455template<DumperPfn dumpfn, size_t N>56inline size_t dump(substr buf, const char (&a)[N])57{58if(buf.len)59dumpfn(csubstr(a)); // dump directly, no need to serialize to the buffer60return 0; // no space was used in the buffer61}6263template<class DumperFn, size_t N>64inline size_t dump(DumperFn &&dumpfn, substr buf, const char (&a)[N])65{66if(buf.len)67dumpfn(csubstr(a)); // dump directly, no need to serialize to the buffer68return 0; // no space was used in the buffer69}707172//-----------------------------------------------------------------------------73//-----------------------------------------------------------------------------74//-----------------------------------------------------------------------------7576/** */77struct DumpResults78{79enum : size_t { noarg = (size_t)-1 };80size_t bufsize = 0;81size_t lastok = noarg;82bool success_until(size_t expected) const { return lastok == noarg ? false : lastok >= expected; }83bool write_arg(size_t arg) const { return lastok == noarg || arg > lastok; }84size_t argfail() const { return lastok + 1; }85};868788//-----------------------------------------------------------------------------89//-----------------------------------------------------------------------------90//-----------------------------------------------------------------------------9192/// @cond dev93// terminates the variadic recursion94template<class DumperFn>95size_t cat_dump(DumperFn &&, substr)96{97return 0;98}99100// terminates the variadic recursion101template<DumperPfn dumpfn>102size_t cat_dump(substr)103{104return 0;105}106/// @endcond107108/** take the function pointer as a function argument */109template<class DumperFn, class Arg, class... Args>110size_t cat_dump(DumperFn &&dumpfn, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)111{112size_t size_for_a = dump(dumpfn, buf, a);113if(C4_UNLIKELY(size_for_a > buf.len))114buf = buf.first(0); // ensure no more calls115size_t size_for_more = cat_dump(dumpfn, buf, more...);116return size_for_more > size_for_a ? size_for_more : size_for_a;117}118119/** take the function pointer as a template argument */120template<DumperPfn dumpfn,class Arg, class... Args>121size_t cat_dump(substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)122{123size_t size_for_a = dump<dumpfn>(buf, a);124if(C4_LIKELY(size_for_a > buf.len))125buf = buf.first(0); // ensure no more calls126size_t size_for_more = cat_dump<dumpfn>(buf, more...);127return size_for_more > size_for_a ? size_for_more : size_for_a;128}129130131//-----------------------------------------------------------------------------132//-----------------------------------------------------------------------------133//-----------------------------------------------------------------------------134135/// @cond dev136namespace detail {137138// terminates the variadic recursion139template<DumperPfn dumpfn, class Arg>140DumpResults cat_dump_resume(size_t currarg, DumpResults results, substr buf, Arg const& C4_RESTRICT a)141{142if(C4_LIKELY(results.write_arg(currarg)))143{144size_t sz = dump<dumpfn>(buf, a); // yield to the specialized function145if(currarg == results.lastok + 1 && sz <= buf.len)146results.lastok = currarg;147results.bufsize = sz > results.bufsize ? sz : results.bufsize;148}149return results;150}151152// terminates the variadic recursion153template<class DumperFn, class Arg>154DumpResults cat_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a)155{156if(C4_LIKELY(results.write_arg(currarg)))157{158size_t sz = dump(dumpfn, buf, a); // yield to the specialized function159if(currarg == results.lastok + 1 && sz <= buf.len)160results.lastok = currarg;161results.bufsize = sz > results.bufsize ? sz : results.bufsize;162}163return results;164}165166template<DumperPfn dumpfn, class Arg, class... Args>167DumpResults cat_dump_resume(size_t currarg, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)168{169results = detail::cat_dump_resume<dumpfn>(currarg, results, buf, a);170return detail::cat_dump_resume<dumpfn>(currarg + 1u, results, buf, more...);171}172173template<class DumperFn, class Arg, class... Args>174DumpResults cat_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)175{176results = detail::cat_dump_resume(currarg, dumpfn, results, buf, a);177return detail::cat_dump_resume(currarg + 1u, dumpfn, results, buf, more...);178}179} // namespace detail180/// @endcond181182183template<DumperPfn dumpfn, class Arg, class... Args>184C4_ALWAYS_INLINE DumpResults cat_dump_resume(DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)185{186if(results.bufsize > buf.len)187return results;188return detail::cat_dump_resume<dumpfn>(0u, results, buf, a, more...);189}190191template<class DumperFn, class Arg, class... Args>192C4_ALWAYS_INLINE DumpResults cat_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)193{194if(results.bufsize > buf.len)195return results;196return detail::cat_dump_resume(0u, dumpfn, results, buf, a, more...);197}198199template<DumperPfn dumpfn, class Arg, class... Args>200C4_ALWAYS_INLINE DumpResults cat_dump_resume(substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)201{202return detail::cat_dump_resume<dumpfn>(0u, DumpResults{}, buf, a, more...);203}204205template<class DumperFn, class Arg, class... Args>206C4_ALWAYS_INLINE DumpResults cat_dump_resume(DumperFn &&dumpfn, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)207{208return detail::cat_dump_resume(0u, dumpfn, DumpResults{}, buf, a, more...);209}210211212//-----------------------------------------------------------------------------213//-----------------------------------------------------------------------------214//-----------------------------------------------------------------------------215216/// @cond dev217// terminate the recursion218template<class DumperFn, class Sep>219size_t catsep_dump(DumperFn &&, substr, Sep const& C4_RESTRICT)220{221return 0;222}223224// terminate the recursion225template<DumperPfn dumpfn, class Sep>226size_t catsep_dump(substr, Sep const& C4_RESTRICT)227{228return 0;229}230/// @endcond231232/** take the function pointer as a function argument */233template<class DumperFn, class Sep, class Arg, class... Args>234size_t catsep_dump(DumperFn &&dumpfn, substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)235{236size_t sz = dump(dumpfn, buf, a);237if(C4_UNLIKELY(sz > buf.len))238buf = buf.first(0); // ensure no more calls239if C4_IF_CONSTEXPR (sizeof...(more) > 0)240{241size_t szsep = dump(dumpfn, buf, sep);242if(C4_UNLIKELY(szsep > buf.len))243buf = buf.first(0); // ensure no more calls244sz = sz > szsep ? sz : szsep;245}246size_t size_for_more = catsep_dump(dumpfn, buf, sep, more...);247return size_for_more > sz ? size_for_more : sz;248}249250/** take the function pointer as a template argument */251template<DumperPfn dumpfn, class Sep, class Arg, class... Args>252size_t catsep_dump(substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)253{254size_t sz = dump<dumpfn>(buf, a);255if(C4_UNLIKELY(sz > buf.len))256buf = buf.first(0); // ensure no more calls257if C4_IF_CONSTEXPR (sizeof...(more) > 0)258{259size_t szsep = dump<dumpfn>(buf, sep);260if(C4_UNLIKELY(szsep > buf.len))261buf = buf.first(0); // ensure no more calls262sz = sz > szsep ? sz : szsep;263}264size_t size_for_more = catsep_dump<dumpfn>(buf, sep, more...);265return size_for_more > sz ? size_for_more : sz;266}267268269//-----------------------------------------------------------------------------270//-----------------------------------------------------------------------------271//-----------------------------------------------------------------------------272273/// @cond dev274namespace detail {275template<DumperPfn dumpfn, class Arg>276void catsep_dump_resume_(size_t currarg, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Arg const& C4_RESTRICT a)277{278if(C4_LIKELY(results->write_arg(currarg)))279{280size_t sz = dump<dumpfn>(*buf, a);281results->bufsize = sz > results->bufsize ? sz : results->bufsize;282if(C4_LIKELY(sz <= buf->len))283results->lastok = currarg;284else285buf->len = 0;286}287}288289template<class DumperFn, class Arg>290void catsep_dump_resume_(size_t currarg, DumperFn &&dumpfn, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Arg const& C4_RESTRICT a)291{292if(C4_LIKELY(results->write_arg(currarg)))293{294size_t sz = dump(dumpfn, *buf, a);295results->bufsize = sz > results->bufsize ? sz : results->bufsize;296if(C4_LIKELY(sz <= buf->len))297results->lastok = currarg;298else299buf->len = 0;300}301}302303template<DumperPfn dumpfn, class Sep, class Arg>304C4_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)305{306detail::catsep_dump_resume_<dumpfn>(currarg, results, buf, a);307}308309template<class DumperFn, class Sep, class Arg>310C4_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)311{312detail::catsep_dump_resume_(currarg, dumpfn, results, buf, a);313}314315template<DumperPfn dumpfn, class Sep, class Arg, class... Args>316C4_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)317{318detail::catsep_dump_resume_<dumpfn>(currarg , results, buf, a);319detail::catsep_dump_resume_<dumpfn>(currarg + 1u, results, buf, sep);320detail::catsep_dump_resume <dumpfn>(currarg + 2u, results, buf, sep, more...);321}322323template<class DumperFn, class Sep, class Arg, class... Args>324C4_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)325{326detail::catsep_dump_resume_(currarg , dumpfn, results, buf, a);327detail::catsep_dump_resume_(currarg + 1u, dumpfn, results, buf, sep);328detail::catsep_dump_resume (currarg + 2u, dumpfn, results, buf, sep, more...);329}330} // namespace detail331/// @endcond332333334template<DumperPfn dumpfn, class Sep, class... Args>335C4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumpResults results, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)336{337detail::catsep_dump_resume<dumpfn>(0u, &results, &buf, sep, more...);338return results;339}340341template<class DumperFn, class Sep, class... Args>342C4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)343{344detail::catsep_dump_resume(0u, dumpfn, &results, &buf, sep, more...);345return results;346}347348template<DumperPfn dumpfn, class Sep, class... Args>349C4_ALWAYS_INLINE DumpResults catsep_dump_resume(substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)350{351DumpResults results;352detail::catsep_dump_resume<dumpfn>(0u, &results, &buf, sep, more...);353return results;354}355356template<class DumperFn, class Sep, class... Args>357C4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumperFn &&dumpfn, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more)358{359DumpResults results;360detail::catsep_dump_resume(0u, dumpfn, &results, &buf, sep, more...);361return results;362}363364365//-----------------------------------------------------------------------------366//-----------------------------------------------------------------------------367//-----------------------------------------------------------------------------368369/** take the function pointer as a function argument */370template<class DumperFn>371C4_ALWAYS_INLINE size_t format_dump(DumperFn &&dumpfn, substr buf, csubstr fmt)372{373// we can dump without using buf374// but we'll only dump if the buffer is ok375if(C4_LIKELY(buf.len > 0 && fmt.len))376dumpfn(fmt);377return 0u;378}379380/** take the function pointer as a function argument */381template<DumperPfn dumpfn>382C4_ALWAYS_INLINE size_t format_dump(substr buf, csubstr fmt)383{384// we can dump without using buf385// but we'll only dump if the buffer is ok386if(C4_LIKELY(buf.len > 0 && fmt.len > 0))387dumpfn(fmt);388return 0u;389}390391/** take the function pointer as a function argument */392template<class DumperFn, class Arg, class... Args>393size_t format_dump(DumperFn &&dumpfn, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)394{395// we can dump without using buf396// but we'll only dump if the buffer is ok397size_t pos = fmt.find("{}"); // @todo use _find_fmt()398if(C4_UNLIKELY(pos == csubstr::npos))399{400if(C4_LIKELY(buf.len > 0 && fmt.len > 0))401dumpfn(fmt);402return 0u;403}404if(C4_LIKELY(buf.len > 0 && pos > 0))405dumpfn(fmt.first(pos)); // we can dump without using buf406fmt = fmt.sub(pos + 2); // skip {} do this before assigning to pos again407pos = dump(dumpfn, buf, a);408if(C4_UNLIKELY(pos > buf.len))409buf.len = 0; // ensure no more calls to dump410size_t size_for_more = format_dump(dumpfn, buf, fmt, more...);411return size_for_more > pos ? size_for_more : pos;412}413414/** take the function pointer as a template argument */415template<DumperPfn dumpfn, class Arg, class... Args>416size_t format_dump(substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)417{418// we can dump without using buf419// but we'll only dump if the buffer is ok420size_t pos = fmt.find("{}"); // @todo use _find_fmt()421if(C4_UNLIKELY(pos == csubstr::npos))422{423if(C4_LIKELY(buf.len > 0 && fmt.len > 0))424dumpfn(fmt);425return 0u;426}427if(C4_LIKELY(buf.len > 0 && pos > 0))428dumpfn(fmt.first(pos)); // we can dump without using buf429fmt = fmt.sub(pos + 2); // skip {} do this before assigning to pos again430pos = dump<dumpfn>(buf, a);431if(C4_UNLIKELY(pos > buf.len))432buf.len = 0; // ensure no more calls to dump433size_t size_for_more = format_dump<dumpfn>(buf, fmt, more...);434return size_for_more > pos ? size_for_more : pos;435}436437438//-----------------------------------------------------------------------------439//-----------------------------------------------------------------------------440//-----------------------------------------------------------------------------441442/// @cond dev443namespace detail {444445template<DumperPfn dumpfn>446DumpResults format_dump_resume(size_t currarg, DumpResults results, substr buf, csubstr fmt)447{448// we can dump without using buf449// but we'll only dump if the buffer is ok450if(C4_LIKELY(buf.len > 0))451{452dumpfn(fmt);453results.lastok = currarg;454}455return results;456}457458template<class DumperFn>459DumpResults format_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt)460{461// we can dump without using buf462// but we'll only dump if the buffer is ok463if(C4_LIKELY(buf.len > 0))464{465dumpfn(fmt);466results.lastok = currarg;467}468return results;469}470471template<DumperPfn dumpfn, class Arg, class... Args>472DumpResults format_dump_resume(size_t currarg, DumpResults results, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)473{474// we need to process the format even if we're not475// going to print the first arguments because we're resuming476size_t pos = fmt.find("{}"); // @todo use _find_fmt()477// we can dump without using buf478// but we'll only dump if the buffer is ok479if(C4_LIKELY(results.write_arg(currarg)))480{481if(C4_UNLIKELY(pos == csubstr::npos))482{483if(C4_LIKELY(buf.len > 0))484{485results.lastok = currarg;486dumpfn(fmt);487}488return results;489}490if(C4_LIKELY(buf.len > 0))491{492results.lastok = currarg;493dumpfn(fmt.first(pos));494}495}496fmt = fmt.sub(pos + 2);497if(C4_LIKELY(results.write_arg(currarg + 1)))498{499pos = dump<dumpfn>(buf, a);500results.bufsize = pos > results.bufsize ? pos : results.bufsize;501if(C4_LIKELY(pos <= buf.len))502results.lastok = currarg + 1;503else504buf.len = 0;505}506return detail::format_dump_resume<dumpfn>(currarg + 2u, results, buf, fmt, more...);507}508/// @endcond509510511template<class DumperFn, class Arg, class... Args>512DumpResults format_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more)513{514// we need to process the format even if we're not515// going to print the first arguments because we're resuming516size_t pos = fmt.find("{}"); // @todo use _find_fmt()517// we can dump without using buf518// but we'll only dump if the buffer is ok519if(C4_LIKELY(results.write_arg(currarg)))520{521if(C4_UNLIKELY(pos == csubstr::npos))522{523if(C4_LIKELY(buf.len > 0))524{525results.lastok = currarg;526dumpfn(fmt);527}528return results;529}530if(C4_LIKELY(buf.len > 0))531{532results.lastok = currarg;533dumpfn(fmt.first(pos));534}535}536fmt = fmt.sub(pos + 2);537if(C4_LIKELY(results.write_arg(currarg + 1)))538{539pos = dump(dumpfn, buf, a);540results.bufsize = pos > results.bufsize ? pos : results.bufsize;541if(C4_LIKELY(pos <= buf.len))542results.lastok = currarg + 1;543else544buf.len = 0;545}546return detail::format_dump_resume(currarg + 2u, dumpfn, results, buf, fmt, more...);547}548} // namespace detail549550551template<DumperPfn dumpfn, class... Args>552C4_ALWAYS_INLINE DumpResults format_dump_resume(DumpResults results, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)553{554return detail::format_dump_resume<dumpfn>(0u, results, buf, fmt, more...);555}556557template<class DumperFn, class... Args>558C4_ALWAYS_INLINE DumpResults format_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)559{560return detail::format_dump_resume(0u, dumpfn, results, buf, fmt, more...);561}562563564template<DumperPfn dumpfn, class... Args>565C4_ALWAYS_INLINE DumpResults format_dump_resume(substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)566{567return detail::format_dump_resume<dumpfn>(0u, DumpResults{}, buf, fmt, more...);568}569570template<class DumperFn, class... Args>571C4_ALWAYS_INLINE DumpResults format_dump_resume(DumperFn &&dumpfn, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more)572{573return detail::format_dump_resume(0u, dumpfn, DumpResults{}, buf, fmt, more...);574}575576C4_SUPPRESS_WARNING_GCC_CLANG_POP577578} // namespace c4579580581#endif /* C4_DUMP_HPP_ */582583584