From 9328d193af0dc03fd2141392cfd23f80f8839489 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 24 Jul 2020 18:18:58 -0700 Subject: [PATCH] indented std::ostream w/ xalloc() --- src/datafmt.cpp | 22 ++++++------- src/pvxs/util.h | 41 +++++++++++++++++++++++ src/type.cpp | 39 +++++++++++----------- src/util.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++++---- src/utilpvt.h | 2 -- 5 files changed, 151 insertions(+), 41 deletions(-) diff --git a/src/datafmt.cpp b/src/datafmt.cpp index 88de1c9..a3a77c3 100644 --- a/src/datafmt.cpp +++ b/src/datafmt.cpp @@ -127,10 +127,9 @@ struct FmtTree { void top(const std::string& member, const FieldDesc *desc, - const FieldStorage* store, - unsigned level=0) + const FieldStorage* store) { - indent(strm, level); + strm<miter) { auto cdesc = desc + pair.second; - top(pair.first, cdesc, store + pair.second, level+1); + Indented I(strm); + top(pair.first, cdesc, store + pair.second); } - indent(strm, level); - strm<<"}"; + strm<(); strm<<" [\n"; for(auto& val : arr) { + Indented I(strm); top(std::string(), Value::Helper::desc(val), - Value::Helper::store_ptr(val), - level+1); + Value::Helper::store_ptr(val)); } - indent(strm, level); - strm<<"]\n"; + strm< instanceSnapshot(); +//! See Indented +struct indent {}; + +PVXS_API +std::ostream& operator<<(std::ostream& strm, const indent&); + +//! Scoped indentation for std::ostream +struct PVXS_API Indented { + explicit Indented(std::ostream& strm, int depth=1); + Indented(const Indented&) = delete; + Indented(Indented&& o) noexcept + :strm(o.strm) + ,depth(o.depth) + { + o.strm = nullptr; + o.depth = 0; + } + ~Indented(); +private: + std::ostream *strm; + int depth; +}; + +struct PVXS_API Detailed { + explicit Detailed(std::ostream& strm, int lvl=1); + Detailed(const Detailed&) = delete; + Detailed(Detailed&& o) noexcept + :strm(o.strm) + ,lvl(o.lvl) + { + o.strm = nullptr; + o.lvl = 0; + } + ~Detailed(); + static + int level(std::ostream& strm); +private: + std::ostream *strm; + int lvl; +}; + } // namespace pvxs #endif // PVXS_UTIL_H diff --git a/src/type.cpp b/src/type.cpp index 6574d2b..5f12129 100644 --- a/src/type.cpp +++ b/src/type.cpp @@ -38,7 +38,7 @@ struct Member::Helper { static void copy_tree(const FieldDesc* desc, Member& node); static - void show_Node(std::ostream& strm, const std::string& name, const Member* node, unsigned level=0); + void show_Node(std::ostream& strm, const std::string& name, const Member* node); }; bool TypeCode::valid() const @@ -387,7 +387,7 @@ Value TypeDef::create() const return Value(desc); } -void Member::Helper::show_Node(std::ostream& strm, const std::string& name, const Member* node, unsigned level) +void Member::Helper::show_Node(std::ostream& strm, const std::string& name, const Member* node) { strm<code; if(!node->id.empty()) @@ -395,10 +395,11 @@ void Member::Helper::show_Node(std::ostream& strm, const std::string& name, cons if(!node->children.empty()) { strm<<" {\n"; for(auto& cnode : node->children) { - indent(strm, level+1); - show_Node(strm, cnode.name, &cnode, level+1); + Indented I(strm); + strm<size())) { auto& fld = desc[idx]; - indent(strm, level); - strm<<"["< "< "< "< "< indentIndex{INT_MIN}; + +std::ostream& operator<<(std::ostream& strm, const indent&) +{ + auto idx = indentIndex.load(std::memory_order_relaxed); + if(idx!=INT_MIN) { + auto n = strm.iword(idx); + for(auto i : range(n)) { + (void)i; + strm<<" "; + } + } + return strm; +} + +Indented::Indented(std::ostream& strm, int depth) + :strm(&strm) + ,depth(depth) +{ + auto idx = indentIndex.load(); + if(idx==INT_MIN) { + auto newidx = std::ostream::xalloc(); + if(indentIndex.compare_exchange_strong(idx, newidx)) { + idx = newidx; + } else { + // lost race. no way to undo xalloc(), so just wasted... + idx = indentIndex.load(); + } + } + strm.iword(idx) += depth; +} + +Indented::~Indented() +{ + if(strm) + strm->iword(indentIndex.load()) -= depth; +} + +// _assume_ only positive indices will be used +static +std::atomic detailIndex{INT_MIN}; + +Detailed::Detailed(std::ostream& strm, int lvl) + :strm(&strm) +{ + auto idx = detailIndex.load(); + if(idx==INT_MIN) { + auto newidx = std::ostream::xalloc(); + if(detailIndex.compare_exchange_strong(idx, newidx)) { + idx = newidx; + } else { + // lost race. no way to undo xalloc(), so just wasted... + idx = detailIndex.load(); + } + } + + auto& ref = strm.iword(idx); + this->lvl = ref; + ref = lvl; +} + +Detailed::~Detailed() +{ + if(strm) + strm->iword(detailIndex.load()) = lvl; +} + +int Detailed::level(std::ostream &strm) +{ + int ret = 0; + auto idx = detailIndex.load(std::memory_order_relaxed); + if(idx==INT_MIN) { + strm<<"Hint: Wrap with pvxs::Detailed()\n"; + } else { + ret = strm.iword(idx); + } + return ret; +} + namespace detail { Escaper::Escaper(const char* v) @@ -434,11 +515,4 @@ int64_t parseTo(const std::string& s) { return ret; } -void indent(std::ostream& strm, unsigned level) { - for(auto i : range(level)) { - (void)i; - strm<<" "; - } -} - }} diff --git a/src/utilpvt.h b/src/utilpvt.h index c868c4e..720aac4 100644 --- a/src/utilpvt.h +++ b/src/utilpvt.h @@ -48,8 +48,6 @@ struct SB { SB& operator<<(const T& i) { strm< struct Range {