diff --git a/Src/Base/AMReX_IOFormat.H b/Src/Base/AMReX_IOFormat.H new file mode 100644 index 0000000000..e9a5597cb0 --- /dev/null +++ b/Src/Base/AMReX_IOFormat.H @@ -0,0 +1,51 @@ +#ifndef AMREX_IO_FORMAT_H_ +#define AMREX_IO_FORMAT_H_ + +#include + +namespace amrex { + +/* + * \brief I/O stream format saver + * + * This class can be used to save and restore I/O stream format in a RAII + * way. It handles fill, fmtflag, precision, and width. + */ +template +class IOFormatSaver +{ +public: + using BasicIos = std::basic_ios; + + explicit IOFormatSaver (BasicIos& ios) + : m_ios(&ios), + m_fill(ios.fill()), + m_flags(ios.flags()), + m_precision(ios.precision()), + m_width(ios.width()) + {} + + ~IOFormatSaver () + { + m_ios->fill(m_fill); + m_ios->flags(m_flags); + m_ios->precision(m_precision); + m_ios->width(m_width); + } + + IOFormatSaver (IOFormatSaver const&) = delete; + IOFormatSaver (IOFormatSaver &&) noexcept = delete; + IOFormatSaver& operator= (IOFormatSaver const&) = delete; + IOFormatSaver& operator= (IOFormatSaver &&) noexcept = delete; + +private: + BasicIos* m_ios; + CharT m_fill; + typename BasicIos::fmtflags m_flags; + std::streamsize m_precision; + std::streamsize m_width; +}; + +} + +#endif diff --git a/Src/Base/AMReX_TinyProfiler.cpp b/Src/Base/AMReX_TinyProfiler.cpp index db92274578..4360cf7671 100644 --- a/Src/Base/AMReX_TinyProfiler.cpp +++ b/Src/Base/AMReX_TinyProfiler.cpp @@ -10,6 +10,7 @@ #include #endif #include +#include #ifdef AMREX_USE_OMP #include @@ -386,7 +387,6 @@ TinyProfiler::Finalize (bool bFlushing) noexcept std::ofstream ofs; std::ostream* os = nullptr; - std::streamsize oldprec = 0; if (ParallelDescriptor::IOProcessor()) { if (output_file.empty()) { os = &(amrex::OutStream()); @@ -399,6 +399,8 @@ TinyProfiler::Finalize (bool bFlushing) noexcept } } + IOFormatSaver iofmtsaver(amrex::OutStream()); + if (os) { os->precision(4); @@ -438,8 +440,6 @@ TinyProfiler::Finalize (bool bFlushing) noexcept } } } - - if(os) { os->precision(oldprec); } } void @@ -593,6 +593,8 @@ TinyProfiler::PrintStats (std::map& regstats, double dt_max, if (ParallelDescriptor::IOProcessor() && os) { + IOFormatSaver iofmtsaver(*os); + *os << std::setfill(' ') << std::setprecision(4); int wt = 9; @@ -876,6 +878,8 @@ TinyProfiler::PrintMemStats (std::map& memstats, if (allstatsstr.size() == 1 || !os) { return; } + IOFormatSaver iofmtsaver(*os); + int lenhline = 0; for (auto i : maxlen) { lenhline += i; diff --git a/Src/Base/AMReX_VisMF.cpp b/Src/Base/AMReX_VisMF.cpp index 2b0ac6716d..f5f1430d59 100644 --- a/Src/Base/AMReX_VisMF.cpp +++ b/Src/Base/AMReX_VisMF.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -277,9 +278,9 @@ operator<< (std::ostream &os, // Up the precision for the Reals in m_min and m_max. // Force it to be written in scientific notation to match fParallel code. // - std::ios::fmtflags oflags = os.flags(); + IOFormatSaver iofmtsaver(os); os.setf(std::ios::floatfield, std::ios::scientific); - int oldPrec = static_cast(os.precision(16)); + os.precision(17); os << hd.m_vers << '\n'; os << int(hd.m_how) << '\n'; @@ -327,9 +328,6 @@ operator<< (std::ostream &os, } } - os.flags(oflags); - os.precision(oldPrec); - if( ! os.good()) { amrex::Error("Write of VisMF::Header failed"); } diff --git a/Src/Base/CMakeLists.txt b/Src/Base/CMakeLists.txt index 0436ad032e..1ee0b23612 100644 --- a/Src/Base/CMakeLists.txt +++ b/Src/Base/CMakeLists.txt @@ -97,6 +97,7 @@ foreach(D IN LISTS AMReX_SPACEDIM) AMReX_Print.H AMReX_IntConv.H AMReX_IntConv.cpp + AMReX_IOFormat.H # Index space ------------------------------------------------------------- AMReX_Box.H AMReX_Box.cpp diff --git a/Src/Base/Make.package b/Src/Base/Make.package index b009ebf7d6..a8c1d0faaa 100644 --- a/Src/Base/Make.package +++ b/Src/Base/Make.package @@ -121,6 +121,7 @@ C$(AMREX_BASE)_headers += AMReX_ParReduce.H # C${AMREX_BASE}_headers += AMReX_ANSIEscCode.H AMReX_FabConv.H AMReX_FPC.H AMReX_Print.H AMReX_IntConv.H AMReX_VectorIO.H C${AMREX_BASE}_sources += AMReX_FabConv.cpp AMReX_FPC.cpp AMReX_IntConv.cpp AMReX_VectorIO.cpp +C${AMREX_BASE}_headers += AMReX_IOFormat.H # # Index space.