Boost logo

Boost :

Subject: [boost] [io_base-utilities] Request for interest and/or comments.
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2012-05-28 09:51:36


Hi,

While refactoring the Boost.Chrono IO (version 2) I've created some
utilities that could be of general use.

* Manipulator Mixin

It is is based on
http://www.angelikalanger.com/Articles/Cuj/05.Manipulators/Manipulators.html.

http://svn.boost.org/svn/boost/trunk/boost/chrono/io/utility/manip_base.hpp
defines a class manip that can be used as follows

     class mendl: public manip<mendl>
     {
     public:
       explicit mendl(size_t how_many) :
         count(how_many) {}
       template <typename out_stream>
       void operator()(out_stream &out) const
       {
         for (size_t line = 0; line < count; ++line)
         {
           out.put(out.widen('\n'));
         }
         out.flush();
       }
     private:
       size_t count;
     };

* std::ios_base Specific Pointers

std::ios_base allows to create specific pointers indexed by xalloc() and
retrieved by pword().

http://svn.boost.org/svn/boost/trunk/boost/chrono/io/utility/ios_base_state_ptr.hpp
defines a class ios_state_ptr class that provides the same interface
that a smart ptr with some minor adaptations to a std::ios_base.

     template <typename Tag, typename T>
     class ios_state_ptr;

The type T must be CopyConstructible. This class must be used as follows

      struct mytag {}
      struct myT {
        int i;
      };

       ios_state_ptr<mytag, myT > ptr(ios);
       if (! ptr) {
         ptr.reset(new myT);
       }
       ptr->i =0;

This class is not thread_safe and should be protected as other io
functions if the user needs to use them in a multi-threaded environment;

The user can use also ios_state_ptr for classes T that are
DefaultConstructible, so that the type is created implicitly if not
already created.

       ios_state_not_null_ptr<mytag, myT > ptr(ios);
       ptr->i =0;

This class is not thread_safe.

Boost.Chrono use it as follows

   namespace chrono {
     namespace detail {
       template<typename CharT>
       struct ios_base_data_aux
       {
         std::basic_string<CharT> time_fmt;
         std::basic_string<CharT> duration_fmt;
       public:

         ios_base_data_aux() :
           time_fmt(""),
           duration_fmt("")
         {}
       };
       template<typename CharT>
       struct ios_base_data {};
     } // namespace detail

     template<typename CharT>
     static inline std::basic_string<CharT> get_time_fmt(std::ios_base &
ios)
     {
       ios_state_not_null_ptr<detail::ios_base_data<CharT>,
detail::ios_base_data_aux<CharT> > ptr(ios);
       return ptr->time_fmt;
     }
     template<typename CharT>
     static inline void set_time_fmt(std::ios_base& ios, std::basic_string<
         CharT> const& fmt)
     {
       ios_state_not_null_ptr<detail::ios_base_data<CharT>,
detail::ios_base_data_aux<CharT> > ptr(ios);
       ptr->time_fmt = fmt;
     }
   }

The internal single call to xalloc should be done before main() to be
thread safe. The library provide a initializer class
xalloc_key_initializer that takes as parameter a tag class.

   namespace chrono { namespace detail {
       namespace /**/ {
         xalloc_key_initializer<detail::ios_base_data<char> >
ios_base_data_aux_xalloc_key_initializer;
         xalloc_key_initializer<detail::ios_base_data<wchar_t> >
wios_base_data_aux_xalloc_key_initializer;
#if BOOST_CHRONO_HAS_UNICODE_SUPPORT
         xalloc_key_initializer<detail::ios_base_data<char16_t> >
u16ios_base_data_aux_xalloc_key_initializer;
         xalloc_key_initializer<detail::ios_base_data<char32_t> >
u32ios_base_data_aux_xalloc_key_initializer;
#endif
       } // namespace
     } }

* ios_flags

ios_base allows also to create specific pointers indexed by xalloc() and
retrieved by iword().

http://svn.boost.org/svn/boost/trunk/boost/chrono/io/utility/ios_base_state_ptr.hpp
defines a class

     template <typename Final>
     class ios_flags;

providing an interface similar to "27.5.3.2 ios_base state functions
[fmtflags.state]

fmtflags flags() const;

Returns: The format control information for both input and output.

fmtflags flags(fmtflags fmtfl);

Postcondition: fmtfl == flags().

Returns: The previous value of flags().

fmtflags setf(fmtflags fmtfl);

Effects: Sets fmtfl in flags().

Returns: The previous value of flags().

fmtflags setf(fmtflags fmtfl, fmtflags mask);

Effects: Clears mask in flags(), sets fmtfl & mask in flags().

Returns: The previous value of flags().

void unsetf(fmtflags mask);

Effects: Clears mask in flags()
"

and that creates implicitly the index of the ios_base::iword() function
once for a specific ios_flags<Final>.

For example, Boost.Chrono use it as follows to store the use_symbol and
use_local flags.

     class fmt_masks : public ios_flags<fmt_masks>
     {
       typedef ios_flags<fmt_masks> base_type;
     public:
       fmt_masks(std::ios_base& ios): base_type(ios) {}
       enum type
       {
         uses_symbol = 1 << 0,
         uses_local = 1 << 1
       };
       duration_style get_duration_style()
       {
         return (flags() & uses_symbol) ? duration_style::symbol :
duration_style::prefix;
       }
       void set_duration_style(duration_style style)
       {
         if (style == duration_style::symbol)
           setf(uses_symbol);
         else
           unsetf(uses_symbol);
       }
       timezone get_timezone()
       {
         return (flags() & uses_local) ? timezone::local : timezone::utc;
       }
       void set_timezone(timezone tz)
       {
         if (tz == timezone::local)
           setf(uses_local);
         else
           unsetf(uses_local);
       }
     };

The internal single call to xalloc should be done before main() to be
thread safe. The library provide a initializer class
     namespace detail
     {
       namespace /**/ {
         xalloc_key_initializer<fmt_masks >
fmt_masks_xalloc_key_initializer;
       } // namespace
     } // namespace detail

Do you see a design flaw on the design of these classes?
Is there an interest to include them in Boost? Could these classes be
associated iostreams?

Best,
Vicente


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk