[io_base-utilities] Request for interest and/or comments.

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_... 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_... 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
participants (1)
-
Vicente J. Botet Escriba