[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master 67531b2 4/5: Add io stream scope guards
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master 67531b2 4/5: Add io stream scope guards |
Date: |
Mon, 2 Aug 2021 18:25:15 -0400 (EDT) |
branch: master
commit 67531b222701534015e5625df0a1cca64d8c725e
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Add io stream scope guards
---
miscellany.hpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++
miscellany_test.cpp | 29 +++++++++++++++++++++++
2 files changed, 95 insertions(+)
diff --git a/miscellany.hpp b/miscellany.hpp
index b72439f..5fd12ea 100644
--- a/miscellany.hpp
+++ b/miscellany.hpp
@@ -168,6 +168,72 @@ LMI_SO void ltrim(std::string& s, char const* superfluous);
LMI_SO void rtrim(std::string& s, char const* superfluous);
+/// Restore std::ios state on scope exit.
+///
+/// This is a blunt and simple tool that saves and restores many
+/// things that are not often wanted, and may be unwanted, such as
+/// tied streams and the exception mask.
+///
+/// If no use is found for this, it may be expunged someday.
+///
+/// Cannot be implemented in terms of std::ios_base, which lacks
+/// copyfmt(). Could be templated if std::wios support is wanted.
+
+class scoped_ios_fmt
+{
+ public:
+ explicit scoped_ios_fmt(std::ios& ios)
+ :ios_ {ios}
+ ,saved_ (nullptr)
+ {
+ saved_.copyfmt(ios_);
+ }
+
+ ~scoped_ios_fmt()
+ {
+ ios_.copyfmt(saved_);
+ }
+
+ private:
+ std::ios& ios_;
+ std::ios saved_;
+};
+
+/// Restore std::ios formatting state on scope exit.
+///
+/// Restores only formatting members, not the full stream state
+/// (which includes tied streams and the exception mask, e.g.).
+///
+/// Cannot be implemented in terms of std::ios_base, which lacks
+/// fill(). Could be templated if std::wios support is wanted.
+
+class scoped_ios_format
+{
+ public:
+ explicit scoped_ios_format(std::ios& ios)
+ :ios_ {ios}
+ ,old_fill_ {ios.fill()}
+ ,old_flags_ {ios.flags()}
+ ,old_precision_ {ios.precision()}
+ ,old_width_ {ios.width()}
+ {}
+
+ ~scoped_ios_format()
+ {
+ ios_.fill (old_fill_);
+ ios_.flags (old_flags_);
+ ios_.precision(old_precision_);
+ ios_.width (old_width_);
+ }
+
+ private:
+ std::ios& ios_;
+ std::ios::char_type const old_fill_;
+ std::ios::fmtflags const old_flags_;
+ std::streamsize const old_precision_;
+ std::streamsize const old_width_;
+};
+
inline std::ios_base::openmode ios_in_binary()
{
return
diff --git a/miscellany_test.cpp b/miscellany_test.cpp
index 83d68d5..9a0506f 100644
--- a/miscellany_test.cpp
+++ b/miscellany_test.cpp
@@ -29,7 +29,9 @@
#include <cmath> // HUGE_VAL
#include <cstdio> // remove()
#include <fstream>
+#include <iomanip>
#include <limits>
+#include <sstream>
void test_each_equal()
{
@@ -421,6 +423,32 @@ void test_trimming()
LMI_TEST_EQUAL(s, "a ; a");
}
+void test_scoped_ios_format()
+{
+ std::ostringstream oss;
+ oss << -2.71828 << ' ' << 3.14159 << std::endl;
+ std::string const s(oss.str());
+
+ {
+ scoped_ios_format meaningless_name(oss);
+ oss << std::setfill('0');
+ oss << std::setprecision(3);
+ oss << std::setw(12);
+ oss << std::fixed;
+ oss << std::hex;
+ oss << std::hexfloat;
+ oss << std::left;
+ oss << std::showpos;
+ oss << -2.71828 << ' ' << 3.14159 << std::endl;
+ }
+
+ oss.str("");
+ oss.clear();
+
+ oss << -2.71828 << ' ' << 3.14159 << std::endl;
+ LMI_TEST_EQUAL(oss.str(), s);
+}
+
int test_main(int, char*[])
{
test_each_equal();
@@ -430,6 +458,7 @@ int test_main(int, char*[])
test_prefix_and_suffix();
test_scale_power();
test_trimming();
+ test_scoped_ios_format();
return 0;
}