diff --git a/Atlas/PresentationBridge.cpp b/Atlas/PresentationBridge.cpp index b5654a1e..4b6d8673 100644 --- a/Atlas/PresentationBridge.cpp +++ b/Atlas/PresentationBridge.cpp @@ -22,7 +22,7 @@ namespace Atlas { PresentationBridge::PresentationBridge(std::stringstream& stream) : - mStream(stream) + mStream(stream), mMaxItemsPerLevel(0), mIsSkipEntry(false), mStartFilterLevel(1) { mStream.precision(6); } @@ -46,26 +46,36 @@ void PresentationBridge::streamEnd() void PresentationBridge::mapMapItem(const std::string& name) { - mStream << mPadding << name << std::endl; + if (checkAndUpdateMaxItemCounter()) { + mStream << mPadding << name << std::endl; + } addPadding(); } void PresentationBridge::mapListItem(const std::string& name) { + if (checkAndUpdateMaxItemCounter()) { + mStream << mPadding << name << std::endl; + } mMapsInList.push(0); - mStream << mPadding << name << std::endl; addPadding(); } void PresentationBridge::mapIntItem(const std::string& name, long i) { - mStream << mPadding << name << ": " << i << std::endl; + if (checkAndUpdateMaxItemCounter()) { + mStream << mPadding << name << ": " << i << std::endl; + } } void PresentationBridge::mapFloatItem(const std::string& name, double d) { - mStream << mPadding << name << ": " << std::fixed << d << std::endl; + if (checkAndUpdateMaxItemCounter()) { + mStream << mPadding << name << ": " << std::fixed << d << std::endl; + } } void PresentationBridge::mapStringItem(const std::string& name, const std::string& s) { - mStream << mPadding << name << ": " << s << std::endl; + if (checkAndUpdateMaxItemCounter()) { + mStream << mPadding << name << ": " << s << std::endl; + } } void PresentationBridge::mapEnd() { @@ -74,15 +84,18 @@ void PresentationBridge::mapEnd() void PresentationBridge::listMapItem() { - //Check if we've already printed a map for this list, and if so print a separator int items = mMapsInList.top(); - if (items) { - mStream << mPadding << "---" << std::endl; + if (checkAndUpdateMaxItemCounter()) { + //Check if we've already printed a map for this list, and if so print a separator + if (items) { + mStream << mPadding << "---" << std::endl; + } } mMapsInList.pop(); mMapsInList.push(items + 1); addPadding(); } + void PresentationBridge::listListItem() { mMapsInList.push(0); @@ -90,15 +103,21 @@ void PresentationBridge::listListItem() } void PresentationBridge::listIntItem(long i) { - mStream << mPadding << ": " << i << std::endl; + if (checkAndUpdateMaxItemCounter()) { + mStream << mPadding << ": " << i << std::endl; + } } void PresentationBridge::listFloatItem(double d) { - mStream << mPadding << ": " << d << std::endl; + if (checkAndUpdateMaxItemCounter()) { + mStream << mPadding << ": " << d << std::endl; + } } void PresentationBridge::listStringItem(const std::string& s) { - mStream << mPadding << ": " << s << std::endl; + if (checkAndUpdateMaxItemCounter()) { + mStream << mPadding << ": " << s << std::endl; + } } void PresentationBridge::listEnd() { @@ -107,12 +126,55 @@ void PresentationBridge::listEnd() } void PresentationBridge::addPadding() { + mEntriesPerLevelCounter.push_back(0); mPadding += " "; } void PresentationBridge::removePadding() { + size_t itemsThisLevel = mEntriesPerLevelCounter.back(); + bool wasSkipping = mIsSkipEntry; + mEntriesPerLevelCounter.pop_back(); + if (mMaxItemsPerLevel) { + size_t level = 0; + for (size_t entry : mEntriesPerLevelCounter) { + mIsSkipEntry = entry >= mMaxItemsPerLevel && level >= mStartFilterLevel; + level++; + } + } + + if (wasSkipping != mIsSkipEntry) { + mStream << mPadding << "... (" << (itemsThisLevel - mMaxItemsPerLevel) << " more items) ..." << std::endl; + } + mPadding.erase(mPadding.end() - 2, mPadding.end()); } +void PresentationBridge::setMaxItemsPerLevel(size_t maxItems) +{ + mMaxItemsPerLevel = maxItems; +} + +void PresentationBridge::setStartFilteringLevel(size_t startFilteringLevel) +{ + mStartFilterLevel = startFilteringLevel; +} + +bool PresentationBridge::checkAndUpdateMaxItemCounter() +{ + + if (mMaxItemsPerLevel && !mEntriesPerLevelCounter.empty() && mEntriesPerLevelCounter.size() > mStartFilterLevel) { + size_t& itemsInLevel = mEntriesPerLevelCounter.back(); + itemsInLevel++; + if (itemsInLevel >= mMaxItemsPerLevel) { + mIsSkipEntry = true; + } + if (mIsSkipEntry) { + return false; + } + } + return true; +} + + } diff --git a/Atlas/PresentationBridge.h b/Atlas/PresentationBridge.h index a460f034..670601ac 100644 --- a/Atlas/PresentationBridge.h +++ b/Atlas/PresentationBridge.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "Bridge.h" namespace Atlas @@ -55,12 +56,34 @@ class PresentationBridge: public Atlas::Bridge virtual void listStringItem(const std::string&); virtual void listEnd(); + /** + * Sets the max number of items to print per level. + * + * This is useful to prevent too much output. + * + * @param maxItems The max number of items. 0 disables this feature (which is the default). + */ + void setMaxItemsPerLevel(size_t maxItems); + + /** + * Sets the level at which filtering, if setMaxItemsPerLevel() has been called, should occur. + * Default is 1 (i.e. print everything for the top level). + * @param startFilteringLevel At which level filtering should start. + */ + void setStartFilteringLevel(size_t startFilteringLevel); + private: void addPadding(); void removePadding(); + /** + * Checks if the current item should be printed or not, depending on if mMaxItemsPerLevel is set. + * @return True if the current item should be printed. + */ + bool checkAndUpdateMaxItemCounter(); + std::string mPadding; std::stringstream& mStream; @@ -71,6 +94,27 @@ class PresentationBridge: public Atlas::Bridge * This is used to determine if we should print a separator to make it easier to see where a new map starts. */ std::stack mMapsInList; + + /** + * If set to > 0 denotes the max number of items to print (per level). + */ + size_t mMaxItemsPerLevel; + + /** + * Set to true when entries should be skipped because the max number of items for a level has been reached. + */ + bool mIsSkipEntry; + + /** + * Denotes the level at which filtering through the mMaxItemsPerLevel field should occur. + * Set by default to 1 (i.e. always print all entries on the first level). + */ + size_t mStartFilterLevel; + + /** + * Keeps track of the number of entries in each level. Used when mMaxItemsPerLevel is > 0. + */ + std::deque mEntriesPerLevelCounter; }; }