lmi-commits
[Top][All Lists]
Advanced

[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;
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]