Skip to content

Commit

Permalink
IOFormatSaver
Browse files Browse the repository at this point in the history
Add a class that can be used to save and restore IO stream format in a RAII
way. Below is an example.

    auto& os = amrex::OutStream();
    auto old_fill = os.fill();
    auto old_flags = os.flags();
    auto old_precision = os.precision();
    auto old_width = os.width();

    {
        IOFormatSaver iofmtsaver(os);

        os << std::setfill('x');
        os << std::left;
        os << std::setprecision(4);
        os << std::setw(111);
    }

    AMREX_ALWAYS_ASSERT(old_fill == os.fill());
    AMREX_ALWAYS_ASSERT(old_flags == os.flags());
    AMREX_ALWAYS_ASSERT(old_precision == os.precision());
    AMREX_ALWAYS_ASSERT(old_width == os.width());
  • Loading branch information
WeiqunZhang committed Sep 1, 2024
1 parent ebd9a11 commit cd1b0e1
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 8 deletions.
51 changes: 51 additions & 0 deletions Src/Base/AMReX_IOFormat.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#ifndef AMREX_IO_FORMAT_H_
#define AMREX_IO_FORMAT_H_

#include <ios>

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 CharT, class Traits>
class IOFormatSaver
{
public:
using BasicIos = std::basic_ios<CharT, Traits>;

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
10 changes: 7 additions & 3 deletions Src/Base/AMReX_TinyProfiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <AMReX_GpuDevice.H>
#endif
#include <AMReX_Print.H>
#include <AMReX_IOFormat.H>

#ifdef AMREX_USE_OMP
#include <omp.h>
Expand Down Expand Up @@ -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());
Expand All @@ -399,6 +399,8 @@ TinyProfiler::Finalize (bool bFlushing) noexcept
}
}

IOFormatSaver iofmtsaver(amrex::OutStream());

if (os)
{
os->precision(4);
Expand Down Expand Up @@ -438,8 +440,6 @@ TinyProfiler::Finalize (bool bFlushing) noexcept
}
}
}

if(os) { os->precision(oldprec); }
}

void
Expand Down Expand Up @@ -593,6 +593,8 @@ TinyProfiler::PrintStats (std::map<std::string,Stats>& regstats, double dt_max,

if (ParallelDescriptor::IOProcessor() && os)
{
IOFormatSaver iofmtsaver(*os);

*os << std::setfill(' ') << std::setprecision(4);
int wt = 9;

Expand Down Expand Up @@ -876,6 +878,8 @@ TinyProfiler::PrintMemStats (std::map<std::string, MemStat>& memstats,

if (allstatsstr.size() == 1 || !os) { return; }

IOFormatSaver iofmtsaver(*os);

int lenhline = 0;
for (auto i : maxlen) {
lenhline += i;
Expand Down
8 changes: 3 additions & 5 deletions Src/Base/AMReX_VisMF.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

#include <AMReX_FabArrayUtility.H>
#include <AMReX_FPC.H>
#include <AMReX_IOFormat.H>
#include <AMReX_ParmParse.H>
#include <AMReX_Utility.H>
#include <AMReX_VisMF.H>
Expand Down Expand Up @@ -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<int>(os.precision(16));
os.precision(17);

os << hd.m_vers << '\n';
os << int(hd.m_how) << '\n';
Expand Down Expand Up @@ -327,9 +328,6 @@ operator<< (std::ostream &os,
}
}

os.flags(oflags);
os.precision(oldPrec);

if( ! os.good()) {
amrex::Error("Write of VisMF::Header failed");
}
Expand Down
1 change: 1 addition & 0 deletions Src/Base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions Src/Base/Make.package
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit cd1b0e1

Please sign in to comment.