diff --git a/pvDataApp/factory/PVArray.cpp b/pvDataApp/factory/PVArray.cpp index cba18ff..89dd863 100644 --- a/pvDataApp/factory/PVArray.cpp +++ b/pvDataApp/factory/PVArray.cpp @@ -97,4 +97,9 @@ PVArray::~PVArray() pImpl->capacity = capacity; } +std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array) +{ + return array.dumpValue(manip.stream, manip.index); +} + }} diff --git a/pvDataApp/factory/PVField.cpp b/pvDataApp/factory/PVField.cpp index da8575e..e4574d9 100644 --- a/pvDataApp/factory/PVField.cpp +++ b/pvDataApp/factory/PVField.cpp @@ -194,17 +194,34 @@ void PVField::toString(StringBuilder buf,int indentLevel) if(pvAuxInfo.get()!=NULL) pvAuxInfo->toString(buf,indentLevel); } -std::ostream& PVField::dumpValue(std::ostream& o) const +std::ostream& operator<<(std::ostream& o, const PVField& f) { - // default implementation - // each PVField class should implement it to avoid switch statement - // and string reallocation - String tmp; - convert->getString(&tmp,this,0); - return o << tmp; -} + std::ostream& ro = f.dumpValue(o); + // TODO I do not want to call getPVAuxInfo() since it lazily creates a new instance of it + //if (f.pvAuxInfo.get()!=NULL) ro << *(f.pvAuxInfo.get()); + return ro; +}; -std::ostream& operator<<(std::ostream& o, const PVField& f) { return f.dumpValue(o); }; +namespace format +{ + std::ostream& operator<<(std::ostream& os, indent_level const& indent) + { + indent_value(os) = indent.level; + return os; + } + + std::ostream& operator<<(std::ostream& os, indent const&) + { + long il = indent_value(os); + std::size_t spaces = static_cast(il) * 4; + return os << std::string(spaces, ' '); + } + + array_at_internal operator<<(std::ostream& str, array_at const& manip) + { + return array_at_internal(manip.index, str); + } +}; void PVField::computeOffset(const PVField * pvField) { const PVStructure * pvTop = pvField->getParent(); diff --git a/pvDataApp/factory/PVStructure.cpp b/pvDataApp/factory/PVStructure.cpp index dc25165..850f6be 100644 --- a/pvDataApp/factory/PVStructure.cpp +++ b/pvDataApp/factory/PVStructure.cpp @@ -702,4 +702,31 @@ static PVFieldPtr findSubField( return PVFieldPtr(); } +std::ostream& PVStructure::dumpValue(std::ostream& o) const +{ + o << format::indent() << getStructure()->getID() << ' ' << getFieldName(); + String extendsName = getExtendsStructureName(); + if(extendsName.length()>0) { + o << " extends " << extendsName; + } + o << std::endl; + { + format::indent_scope s(o); + + PVFieldPtrArray const & fieldsData = getPVFields(); + if (fieldsData.size() != 0) { + size_t length = getStructure()->getNumberFields(); + for(size_t i=0; igetField()->getType(); + if (type == scalar || type == scalarArray) + o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl; + else + o << *(fieldField.get()); + } + } + } + return o; +} + }} diff --git a/pvDataApp/factory/PVStructureArray.cpp b/pvDataApp/factory/PVStructureArray.cpp index fa941ef..b6cba3f 100644 --- a/pvDataApp/factory/PVStructureArray.cpp +++ b/pvDataApp/factory/PVStructureArray.cpp @@ -250,4 +250,27 @@ void PVStructureArray::serialize(ByteBuffer *pbuffer, } } +std::ostream& PVStructureArray::dumpValue(std::ostream& o) const +{ + o << format::indent() << getStructureArray()->getID() << ' ' << getFieldName() << std::endl; + size_t length = getLength(); + if (length > 0) + { + format::indent_scope s(o); + + for (size_t i = 0; i < length; i++) + dumpValue(o, i); + } + + return o; +} + +std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const +{ + PVStructurePtrArray pvArray = *value.get(); + PVStructurePtr pvStructure = pvArray[index]; + return o << *(pvStructure.get()); + return o; +} + }} diff --git a/pvDataApp/pv/pvData.h b/pvDataApp/pv/pvData.h index b04d737..364ee32 100644 --- a/pvDataApp/pv/pvData.h +++ b/pvDataApp/pv/pvData.h @@ -14,10 +14,74 @@ #include #include #include +#include +#include #include #include namespace epics { namespace pvData { + +namespace format { + +struct indent_level +{ + long level; + + indent_level(long l) : level(l) {} +}; + +inline long& indent_value(std::ios_base& ios) +{ + static int indent_index = std::ios_base::xalloc(); + return ios.iword(indent_index); +} + +std::ostream& operator<<(std::ostream& os, indent_level const& indent); +struct indent_scope +{ + long saved_level; + std::ios_base& stream; + + indent_scope(std::ios_base& ios) : + stream(ios) + { + long& l = indent_value(ios); + saved_level = l; + l = saved_level + 1; + } + + ~indent_scope() + { + indent_value(stream) = saved_level; + } +}; + +struct indent +{ +}; + +std::ostream& operator<<(std::ostream& os, indent const&); + +struct array_at +{ + std::size_t index; + + array_at(std::size_t ix) : index(ix) {} +}; + +struct array_at_internal +{ + std::size_t index; + std::ostream& stream; + + array_at_internal(std::size_t ix, std::ostream& str) : index(ix), stream(str) {} +}; + +array_at_internal operator<<(std::ostream& str, array_at const& manip); + +}; + + class PVAuxInfo; class PostHandler; @@ -277,7 +341,7 @@ public: * @param o output stream. * @return The output stream. */ - virtual std::ostream& dumpValue(std::ostream& o) const; + virtual std::ostream& dumpValue(std::ostream& o) const = 0; protected: PVField::shared_pointer getPtrSelf() @@ -453,6 +517,9 @@ public: * @param The capacity. */ virtual void setCapacity(std::size_t capacity) = 0; + + virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0; + protected: PVArray(FieldConstPtr const & field); void setCapacityLength(std::size_t capacity,std::size_t length); @@ -461,6 +528,8 @@ private: friend class PVDataCreate; }; +std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array); + /** * Class provided by caller of get */ @@ -505,8 +574,6 @@ public: */ const ScalarArrayConstPtr getScalarArray() const ; - virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0; - protected: PVScalarArray(ScalarArrayConstPtr const & scalarArray); private: @@ -608,6 +675,10 @@ public: virtual pointer get() const { return &((*value.get())[0]); } virtual vector const & getVector() {return *value;} virtual shared_vector const & getSharedVector() {return value;} + + virtual std::ostream& dumpValue(std::ostream& o) const; + virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const; + protected: PVStructureArray(StructureArrayConstPtr const & structureArray); private: @@ -816,6 +887,9 @@ public: * @param pvFields The array of fields for the structure. */ PVStructure(StructureConstPtr const & structure,PVFieldPtrArray const & pvFields); + + virtual std::ostream& dumpValue(std::ostream& o) const; + private: void fixParentStructure(); static PVFieldPtr nullPVField; @@ -896,7 +970,7 @@ public: std::ostream& dumpValue(std::ostream& o) const { - o << "["; + o << '['; std::size_t len = getLength(); bool first = true; for (std::size_t i = 0; i < len; i++) @@ -904,10 +978,10 @@ public: if (first) first = false; else - o << ","; + o << ','; dumpValue(o, i); } - return o << "]"; + return o << ']'; } std::ostream& dumpValue(std::ostream& o, size_t index) const