From f0aa2fe0e06df2a8a47359e50513b001555d7a5f Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 1 May 2013 12:17:58 -0400 Subject: [PATCH] fix printer Don't overflow the stack for deep structures! --- pvDataApp/factory/printer.cpp | 91 ++++++++++++++++++++++++++--------- pvDataApp/pv/printer.h | 2 - 2 files changed, 68 insertions(+), 25 deletions(-) diff --git a/pvDataApp/factory/printer.cpp b/pvDataApp/factory/printer.cpp index 648812d..baf6c8a 100644 --- a/pvDataApp/factory/printer.cpp +++ b/pvDataApp/factory/printer.cpp @@ -1,4 +1,6 @@ +#include + #include "pv/printer.h" namespace { @@ -46,36 +48,79 @@ void PrinterBase::encodeScalar(const PVScalar& pv) {} void PrinterBase::encodeArray(const PVScalarArray&) {} -void PrinterBase::abortField(const PVField&) {} - void PrinterBase::impl_print(const PVField& pv) { - try { - switch(pv.getField()->getType()) { - case scalar: encodeScalar(static_cast(pv)); return; - case scalarArray: encodeArray(static_cast(pv)); return; - case structure: { - const PVStructure &fld = static_cast(pv); - const PVFieldPtrArray& vals = fld.getPVFields(); + /* Depth first recursive iteration. + * Each PV to be printed is appended to the todo queue. + * The last child of a structure is followed by a NULL. + * As the tree is walked structures and structarrays + * are appended to the inprog queue. + */ + std::deque todo, inprog; - beginStructure(fld); - for(size_t i=0, nfld=fld.getStructure()->getNumberFields(); iprint(*vals[i]); - endStructure(fld); + todo.push_back(&pv); + + while(!todo.empty()) { + const PVField *next = todo.front(); + todo.pop_front(); + + if(!next) { + // finished with a structure or structarray, + // now we fall back to its parent. + assert(!inprog.empty()); + switch(inprog.back()->getField()->getType()) { + case structure: + endStructure(*static_cast(inprog.back())); + break; + + case structureArray: + endStructureArray(*static_cast(inprog.back())); + break; + + default: + assert(false); // oops! + return; } - case structureArray: { - const PVStructureArray &fld = static_cast(pv); - const PVStructureArray::pointer vals = fld.get(); + inprog.pop_back(); - beginStructureArray(fld); - for(size_t i=0, nfld=fld.getLength(); iprint(*vals[i]); - endStructureArray(fld); + } else { + // real field + + switch(next->getField()->getType()) { + case scalar: + encodeScalar(*static_cast(next)); + break; + case scalarArray: + encodeArray(*static_cast(next)); + break; + case structure: { + const PVStructure &fld = *static_cast(next); + const PVFieldPtrArray& vals = fld.getPVFields(); + + inprog.push_back(next); + + beginStructure(fld); + for(size_t i=0, nfld=fld.getStructure()->getNumberFields(); i(next); + const PVStructureArray::pointer vals = fld.get(); + + inprog.push_back(next); + + beginStructureArray(fld); + for(size_t i=0, nfld=fld.getLength(); i