From 0de32a6e6f672b9982c3e8ca38453eaaa13c112e Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Fri, 20 Nov 2020 15:58:36 +0100 Subject: [PATCH] ENH: improve flexiblity for flat output of items (#1929) - change to a templated implementation instead of relying on the container's writeList() method. This inlines the generation while also adding the flexibility to define different delimiters (at compile time) without the performance penalty of passing run-time parameters. --- applications/test/flatOutput1/Make/files | 3 + applications/test/flatOutput1/Make/options | 2 + .../test/flatOutput1/Test-flatOuput1.C | 103 ++++++++ .../containers/Lists/ListOps/FlatOutput.H | 98 ------- src/OpenFOAM/db/IOstreams/output/FlatOutput.H | 247 ++++++++++++++++++ src/OpenFOAM/global/debug/debug.C | 41 +-- 6 files changed, 379 insertions(+), 115 deletions(-) create mode 100644 applications/test/flatOutput1/Make/files create mode 100644 applications/test/flatOutput1/Make/options create mode 100644 applications/test/flatOutput1/Test-flatOuput1.C delete mode 100644 src/OpenFOAM/containers/Lists/ListOps/FlatOutput.H create mode 100644 src/OpenFOAM/db/IOstreams/output/FlatOutput.H diff --git a/applications/test/flatOutput1/Make/files b/applications/test/flatOutput1/Make/files new file mode 100644 index 0000000000..0179cbe0cc --- /dev/null +++ b/applications/test/flatOutput1/Make/files @@ -0,0 +1,3 @@ +Test-flatOuput1.C + +EXE = $(FOAM_USER_APPBIN)/Test-flatOuput1 diff --git a/applications/test/flatOutput1/Make/options b/applications/test/flatOutput1/Make/options new file mode 100644 index 0000000000..18e6fe47af --- /dev/null +++ b/applications/test/flatOutput1/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = */ +/* EXE_LIBS = */ diff --git a/applications/test/flatOutput1/Test-flatOuput1.C b/applications/test/flatOutput1/Test-flatOuput1.C new file mode 100644 index 0000000000..58e2f7d594 --- /dev/null +++ b/applications/test/flatOutput1/Test-flatOuput1.C @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Description + Simple test of FlatOutput + +\*---------------------------------------------------------------------------*/ + +#include "wordList.H" +#include "ListOps.H" +#include "FlatOutput.H" +#include "IOstreams.H" +#include "macros.H" + +using namespace Foam; + +// For testing various pre-defined formatting +#define printFlatOutput(Content, Format) \ + STRINGIFY(Format) << ": " << flatOutput(Content, FlatOutput::Format{}) + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + wordList words1 + { + "ab", "cd", "ef", "gh", + "ij", "kl", "mn", "op", + "qr", "st", "uv", "wx", "yz" + }; + + { + Info<< nl + << "regular" << nl + << "#----------------" << nl; + + Info<< nl << "operator<< " << words1 << nl; + + Info<< nl << "writeList: "; + words1.writeList(Info) << nl; + } + + Info<< nl + << "Using c++ " << int(__cplusplus) << nl; + + { + Info<< nl + << "flatOutput" << nl + << "#----------------" << nl; + + Info<< nl << "operator<< " << flatOutput(words1) << nl; + + Info<< nl << "write: "; + flatOutput(words1).write(Info) << nl; + + Info<< nl << printFlatOutput(words1, BareComma) << nl; + Info<< nl << printFlatOutput(words1, BareSpace) << nl; + + Info<< nl << printFlatOutput(words1, BraceComma) << nl; + Info<< nl << printFlatOutput(words1, BraceSpace) << nl; + + Info<< nl << printFlatOutput(words1, ParenComma) << nl; + Info<< nl << printFlatOutput(words1, ParenSpace) << nl; + + Info<< nl << printFlatOutput(words1, PointyComma) << nl; + Info<< nl << printFlatOutput(words1, PointySpace) << nl; + + Info<< nl << printFlatOutput(words1, SquareComma) << nl; + Info<< nl << printFlatOutput(words1, SquareSpace) << nl; + } + + + Info<< "\nEnd\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/containers/Lists/ListOps/FlatOutput.H b/src/OpenFOAM/containers/Lists/ListOps/FlatOutput.H deleted file mode 100644 index d6a88aae1a..0000000000 --- a/src/OpenFOAM/containers/Lists/ListOps/FlatOutput.H +++ /dev/null @@ -1,98 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2017 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see . - -Class - Foam::FlatOutput - -Description - Simple output adapter for list output on a single line. - The backend type must support a two-argument \c writeList() method. - -\*---------------------------------------------------------------------------*/ - -#ifndef FlatOutput_H -#define FlatOutput_H - -#include "Ostream.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -// Forward declaration of friend functions and operators -template class FlatOutput; -template -Ostream& operator<<(Ostream& os, const FlatOutput& obj); - - -/*---------------------------------------------------------------------------*\ - Class FlatOutput Declaration -\*---------------------------------------------------------------------------*/ - -template -class FlatOutput -{ - const Container& ref_; - const label len_; - -public: - - //- Construct from components - inline FlatOutput(const Container& obj, label len) - : - ref_(obj), - len_(len) - {} - - //- Ostream operator - inline friend Ostream& operator<< - ( - Ostream& os, - const FlatOutput& wrapped - ) - { - return wrapped.ref_.writeList(os, wrapped.len_); - } -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -//- Global flatOutput function -template -FlatOutput flatOutput(const Container& obj, label len=0) -{ - return FlatOutput(obj, len); -} - - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // diff --git a/src/OpenFOAM/db/IOstreams/output/FlatOutput.H b/src/OpenFOAM/db/IOstreams/output/FlatOutput.H new file mode 100644 index 0000000000..399dd081bd --- /dev/null +++ b/src/OpenFOAM/db/IOstreams/output/FlatOutput.H @@ -0,0 +1,247 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2017-2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Namespace + Foam::FlatOutput + +Description + Various output adaptors, principally to output a list of items + on a single line. + +\*---------------------------------------------------------------------------*/ + +#ifndef FlatOutput_H +#define FlatOutput_H + +#include "Ostream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace FlatOutput +{ + +// Forward Declarations +template class OutputAdaptor; + +} // End namespace FlatOutput + + +// Forward Declarations +template +inline Ostream& operator<< +( + Ostream&, + const FlatOutput::OutputAdaptor& +); + + +namespace FlatOutput +{ + +/*---------------------------------------------------------------------------*\ + Class Decorators Declaration +\*---------------------------------------------------------------------------*/ + +//- List decorators with \c open, \c close and \c separator characters +template +struct Decorators +{ + static constexpr char open = OpenChar; + static constexpr char close = CloseChar; + static constexpr char separator = SepChar; +}; + + +#undef makeDecorator +#define makeDecorator(Name, Open, Close, Sep) \ + /*! \brief Surround with \c Open and \c Close separate with \c Sep */ \ + struct Name : public Decorators {}; + +makeDecorator(BareComma, '\0','\0', ','); +makeDecorator(BareSpace, '\0','\0', ' '); + +makeDecorator(BraceComma, '{','}', ','); +makeDecorator(BraceSpace, '{','}', ' '); + +makeDecorator(ParenComma, '(',')', ','); +makeDecorator(ParenSpace, '(',')', ' '); // Normal default + +makeDecorator(PointyComma, '<','>', ','); +makeDecorator(PointySpace, '<','>', ' '); + +makeDecorator(SquareComma,'[',']', ','); +makeDecorator(SquareSpace,'[',']', ' '); + +#undef makeDecorator + + +/*---------------------------------------------------------------------------*\ + Class OutputAdaptor Declaration +\*---------------------------------------------------------------------------*/ + +//- An output adaptor with a write method and an Ostream operator. +// +// Generate single line (flat) output using the characters specified by +// the templated Delimiters. +// Normally called with the global flatOutput() function. +// For example, +// \code +// +// /* With default parenthesis/space delimiters */ +// Info<< "Names: " << flatOutput(names) << nl; +// +// /* Other delimiters */ +// Info<< flatOutput(names, FlatOutput::SquareComma{}) << nl; +// +// /* User-specified delimiters */ +// Info<< flatOutput(names, FlatOutput::Decorators<'[',')',':'>{}) << nl; +// +// \endcode +// +// \noop +template +class OutputAdaptor +{ + // Private Data + + //- The container of values for output + const Container& values; + +public: + + // Constructors + + //- Construct from component + explicit OutputAdaptor(const Container& obj) + : + values(obj) + {} + + + // Member Functions + + //- Write list using \c open, \c close and \c separator characters + //- specified by Delimiters template, which generally results in + //- a single line without line breaks. + // + // \note Suppresses nul char output. + // No special handling for newline separators. + inline Ostream& write(Ostream& os) const + { + bool started = false; + + // In c++17, can use constexpr if + + if (Delimiters::open) + { + os << Delimiters::open; + } + for (const auto& item : values) + { + if (started) + { + if (Delimiters::separator) + { + os << Delimiters::separator; + } + } + else + { + started = true; + } + os << item; + } + if (Delimiters::close) + { + os << Delimiters::close; + } + + return os; + } + + + // Operators + + //- Ostream Operator + inline friend Ostream& + operator<< + ( + Ostream& os, + const OutputAdaptor& adaptor + ) + { + return adaptor.write(os); + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace FlatOutput +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +//- Global flatOutput() function with specified output delimiters +template +inline FlatOutput::OutputAdaptor +flatOutput +( + const Container& obj, + Delimiters delim +) +{ + return FlatOutput::OutputAdaptor(obj); +} + + +//- Global flatOutput() function with default (parenthesis/space) delimiters +template +inline FlatOutput::OutputAdaptor +flatOutput +( + const Container& obj +) +{ + return FlatOutput::OutputAdaptor(obj); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/global/debug/debug.C b/src/OpenFOAM/global/debug/debug.C index 419b247e7f..d3e5c79f7a 100644 --- a/src/OpenFOAM/global/debug/debug.C +++ b/src/OpenFOAM/global/debug/debug.C @@ -348,10 +348,26 @@ Foam::simpleObjectRegistry& Foam::debug::dimensionedConstantObjects() namespace Foam { +// Print the switch status +static inline void printStatus +( + const char * const message, + const wordList& list +) +{ + // Use writeList with length = -1 to ensure we always have newlines, + // even for short lists + + Info<< message << nl; + list.writeList(Info, -1) << nl; +} + + // Write the switch names. // -// Use flatOutput with -1 for the length to ensure we always have newlines, +// Use writeList with -1 for the length to ensure we always have newlines, // even if the lists are short + static void listSwitches ( const wordList& debugSwitches, @@ -373,7 +389,7 @@ static void listSwitches controlDict.merge(dictionary(is)); } - // Use a HashSet to track switches that have not been set + // HashSet to track switches that have not been set wordHashSet hashed; // DebugSwitches @@ -381,9 +397,7 @@ static void listSwitches { hashed = debugSwitches; hashed.unset(controlDict.subDict("DebugSwitches").toc()); - - Info<< "Unset DebugSwitches" - << flatOutput(hashed.sortedToc(), -1) << nl; + printStatus("Unset DebugSwitches", hashed.sortedToc()); } // InfoSwitches @@ -391,9 +405,7 @@ static void listSwitches { hashed = infoSwitches; hashed.unset(controlDict.subDict("InfoSwitches").toc()); - - Info<< "Unset InfoSwitches" - << flatOutput(hashed.sortedToc(), -1) << nl; + printStatus("Unset InfoSwitches", hashed.sortedToc()); } // OptimisationSwitches @@ -401,9 +413,7 @@ static void listSwitches { hashed = optSwitches; hashed.unset(controlDict.subDict("OptimisationSwitches").toc()); - - Info<< "Unset OptimisationSwitches" - << flatOutput(hashed.sortedToc(), -1) << nl; + printStatus("Unset OptimisationSwitches", hashed.sortedToc()); } } else @@ -411,22 +421,19 @@ static void listSwitches // DebugSwitches if (notNull(debugSwitches)) { - Info<< "DebugSwitches" - << flatOutput(debugSwitches, -1) << nl; + printStatus("DebugSwitches", debugSwitches); } // InfoSwitches if (notNull(infoSwitches)) { - Info<< "InfoSwitches" - << flatOutput(infoSwitches, -1) << nl; + printStatus("InfoSwitches", infoSwitches); } // OptimisationSwitches if (notNull(optSwitches)) { - Info<< "OptimisationSwitches" - << flatOutput(optSwitches, -1) << nl; + printStatus("OptimisationSwitches", optSwitches); } } }