// bslim_formatguard.h -*-C++-*- #ifndef INCLUDED_BSLIM_FORMATGUARD #define INCLUDED_BSLIM_FORMATGUARD #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a guard for saving the state of a stream object. // //@CLASSES: // bslim::FormatGuard: format guard for stream types. // //@DESCRIPTION: The 'bslim::FormatGuard' type saves the configuration of a // 'basic_ostream' type, when the guard is created. When the guard is // destroyed, the stream is restored to the state it was in when the guard was // created. // // The state that is saved is //: o The 'fmtflags' state //: o The floating-point precision //: o The fill char // // Note that the 'width' field is not saved, because it does not normally // persist among multiple items output, but automatically resets to 0 after a // single item is ouput. // ///Usage ///----- // In the following example we illustrate the usage of 'FormatGuard'. // ///Example 1: Saving Stream State to be Restored Later: ///- - - - - - - - - - - - - - - - - - - - - - - - - - // Suppose we want to do some output to a stream for which we must change the // state of the stream. // // First, we declare our stream: //.. // bsl::ostringstream oss; //.. // Then, we use a 'FormatGuard' to save the state of 'oss' before we // reconfigure it, so that when the 'FormatGuard' is destroyed it will resotre // 'oss' to its original state. //.. // { // bslim::FormatGuard guard(&oss); //.. // Then, we reconfigure out stream and do some output: //.. // oss << "First line in hex: " << bsl::showbase << bsl::hex << 80 << // endl; //.. // Next, we leave the block and the destructor of 'guard' will restore 'oss' // to its original configuration: //.. // } //.. // Now, we do another line of output: //.. // oss << "Second line in decimal: " << 123 << endl; //.. // Finally, we observe that our guarded output was in hex, as desired, and the // output afterward was in decimal, as desired: //.. // assert(oss.str() == "First line in hex: 0x50\n" // "Second line in decimal: 123\n"); //.. #include <bslscm_version.h> #include <bslmf_assert.h> #include <bslmf_isintegral.h> #include <bsls_keyword.h> #include <bsls_types.h> #include <bsl_ios.h> #include <bsl_ostream.h> namespace BloombergLP { namespace bslim { // ================= // class FormatGuard // ================= class FormatGuard { // This class implements a guard that saves the state of a 'basic_ostream' // and restores that state upon destruction of the guard. // PRIVATE TYPES typedef void (FormatGuard::*DestructorImpl_p)(); // DATA bsl::ios_base * const d_iosBase_p; // base class of stream const bsl::ios_base::fmtflags d_flags; // stream format flags const bsl::streamsize d_precision; // precision of ostream const bsls::Types::Int64 d_fillChar; // fill char of ostream const DestructorImpl_p d_destructorImpl_p; // method pointer to // implementation of // destructor private: // NOT IMPLEMENTED FormatGuard(const FormatGuard&) BSLS_KEYWORD_DELETED; FormatGuard operator=(const FormatGuard&) BSLS_KEYWORD_DELETED; private: // PRIVATE MANIPULATORS template <class CHAR_TYPE, class CHAR_TRAITS> void ostreamDestructorImpl(); // Restore the format flags, precision, and fill character to the // stream that was passed to the constructor. public: // CREATORS template <class CHAR_TYPE, class CHAR_TRAITS> explicit FormatGuard(bsl::basic_ostream<CHAR_TYPE, CHAR_TRAITS> *stream); // Create a 'FormatGuard' object saving the state of the specified // 'stream'. ~FormatGuard(); // Restore all the saved state to the stream that was passed to the // constructor. }; // ----------------- // class FormatGuard // ----------------- // PRIVATE MANIPULATORS template <class CHAR_TYPE, class CHAR_TRAITS> void FormatGuard::ostreamDestructorImpl() { // Note that 'basic_ostream' inherits from 'basic_ios' through virtual // inheritance, so we cannot cast from an 'ios_base *' to a // 'basic_ostream *'. However, we can restore 100% of the state that we // intend to using a 'basic_ios *', which inherits non-virtually from // 'ios_base *'. typedef bsl::basic_ios<CHAR_TYPE, CHAR_TRAITS> BasicIos; BasicIos *basicIos_p = static_cast<BasicIos *>(d_iosBase_p); basicIos_p->flags(d_flags); basicIos_p->precision(d_precision); basicIos_p->fill(static_cast<CHAR_TYPE>(d_fillChar)); } // CREATORS template <class CHAR_TYPE, class CHAR_TRAITS> inline FormatGuard::FormatGuard(bsl::basic_ostream<CHAR_TYPE, CHAR_TRAITS> *stream) : d_iosBase_p(stream) , d_flags(stream->flags()) , d_precision(stream->precision()) , d_fillChar(stream->fill()) , d_destructorImpl_p( &FormatGuard::ostreamDestructorImpl<CHAR_TYPE, CHAR_TRAITS>) { BSLMF_ASSERT(bsl::is_integral<CHAR_TYPE>::value); BSLMF_ASSERT(sizeof(CHAR_TYPE) <= sizeof(bsls::Types::Int64)); // 'd_fillChar' } inline FormatGuard::~FormatGuard() { (this->*d_destructorImpl_p)(); } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2021 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------