// boost/chrono/utility/ios_base_pword_ptr.hpp ------------------------------------------------------------// // Copyright 2011 Vicente J. Botet Escriba // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/chrono for documentation. #ifndef BOOST_CHRONO_UTILITY_IOS_BASE_STATE_PTR_HPP #define BOOST_CHRONO_UTILITY_IOS_BASE_STATE_PTR_HPP #include #include /** * */ namespace boost { namespace chrono { namespace detail { /** * xalloc key holder. */ template struct xalloc_key_holder { static int value; //< the xalloc value associated to T. static bool initialized; //< whether the value has been initialized or not. }; template int xalloc_key_holder::value = 0; template bool xalloc_key_holder::initialized = false; } /** * xalloc key initialiazer. * * Declare a static variable of this type to ensure that the xalloc_key_holder is initialized correctly. */ template struct xalloc_key_initializer { xalloc_key_initializer() { if (!detail::xalloc_key_holder::initialized) { detail::xalloc_key_holder::value = std::ios_base::xalloc(); detail::xalloc_key_holder::initialized = true; } } }; /** * @c ios_state_ptr is a smart pointer to a ios_base specific state. */ template class ios_state_ptr { ios_state_ptr& operator=(ios_state_ptr const& rhs) ; public: /** * The pointee type */ typedef T element_type; /** * Explicit constructor. * @param ios the ios * @Effects Constructs a @c ios_state_ptr by storing the associated @c ios. */ explicit ios_state_ptr(std::ios_base& ios) : ios_(ios) { } /** * Nothing to do as xalloc index can not be removed. */ ~ios_state_ptr() { } /** * @Effects Allocates the index if not already done. * Registers the callback responsible of maintaining the state pointer coherency, if not already done. * Retrieves the associated ios pointer * @return the retrieved pointer statically casted to const. */ T const* get() const BOOST_NOEXCEPT { register_once(index(), ios_); void* &pw = ios_.pword(index()); if (pw == 0) { return 0; } return static_cast (pw); } /** * @Effects Allocates the index if not already done. * Registers the callback responsible of maintaining the state pointer coherency, if not already done. * Retrieves the associated ios pointer * @return the retrieved pointer. */ T * get() BOOST_NOEXCEPT { register_once(index(), ios_); void* &pw = ios_.pword(index()); if (pw == 0) { return 0; } return static_cast (pw); } /** * @Effects as if @c return get(); * @return the retrieved pointer. */ T * operator->()BOOST_NOEXCEPT { return get(); } /** * @Effects as if @c return get(); * @return the retrieved pointer. */ T const * operator->() const BOOST_NOEXCEPT { return get(); } /** * @Effects as if @c return *get(); * @return a reference to the retrieved state. * @Remark The behavior is undefined if @c get()==0. */ T & operator*() BOOST_NOEXCEPT { return *get(); } /** * @Effects as if @c return *get(); * @return a reference to the retrieved state. * @Remark The behavior is undefined if @c get()==0. */ T const & operator *() const BOOST_NOEXCEPT { return *get(); } /** * @Effects reset the current pointer after storing in a temporary variable the pointer to the current state. * @return the stored state pointer. */ T * release() BOOST_NOEXCEPT { void*& pw = ios_.pword(index()); T* ptr = static_cast (pw); pw = 0; return ptr; } /** * * @param new_ptr the new pointer. * @Effects deletes the current state and replace it with the new one. */ void reset(T* new_ptr = 0)BOOST_NOEXCEPT { register_once(index(), ios_); void*& pw = ios_.pword(index()); delete static_cast (pw); pw = new_ptr; } #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) typedef T* (ios_state_ptr::*bool_type)(); operator bool_type() const BOOST_NOEXCEPT { return (get()!=0)?&ios_state_ptr::release:0; } bool operator!() const BOOST_NOEXCEPT { return (get()==0)?&ios_state_ptr::release:0; } #else /** * Explicit conversion to bool. */ explicit operator bool() const BOOST_NOEXCEPT { return get()!=0; } #endif std::ios_base& getios()BOOST_NOEXCEPT { return ios_; } std::ios_base& getios() const BOOST_NOEXCEPT { return ios_; } /** * Implicit conversion to the ios_base */ operator std::ios_base&() BOOST_NOEXCEPT { return ios_; } /** * Implicit conversion to the ios_base const */ operator std::ios_base&() const BOOST_NOEXCEPT { return ios_; } private: static inline bool is_registerd(std::ios_base& ios) { long iw = ios.iword(index()); return (iw == 1); } static inline void set_registered(std::ios_base& ios) { long& iw = ios.iword(index()); iw = 1; } static inline void callback(std::ios_base::event evt, std::ios_base& ios, int index) { switch (evt) { case std::ios_base::erase_event: { void*& pw = ios.pword(index); if (pw != 0) { T* ptr = static_cast (pw); delete ptr; pw = 0; } break; } case std::ios_base::copyfmt_event: { void*& pw = ios.pword(index); if (pw != 0) { pw = new T(*static_cast (pw)); } break; } default: break; } } static inline int index() { return detail::xalloc_key_holder::value; } static inline void register_once(int indx, std::ios_base& ios) { // needs a mask registered if (!is_registerd(ios)) { set_registered(ios); ios.register_callback(callback, indx); } } protected: std::ios_base& ios_; //static detail::xalloc_key_initializer xalloc_key_initializer_; }; //template //detail::xalloc_key_initializer ios_state_ptr::xalloc_key_initializer_; /** * @c ios_state_not_null_ptr is a non null variant of @c ios_state_ptr. * @tparm T * @Requires @c T must be @c DefaultConstructible and @c HeapAllocatable */ template class ios_state_not_null_ptr: public ios_state_ptr { typedef ios_state_ptr base_type; public: explicit ios_state_not_null_ptr(std::ios_base& ios) : base_type(ios) { if (this->get() == 0) { this->base_type::reset(new T()); } } ~ios_state_not_null_ptr() { } void reset(T* new_value) BOOST_NOEXCEPT { BOOST_ASSERT(new_value!=0); this->base_type::reset(new_value); } }; /** * This class is useful to associate some flags to an std::ios_base. */ template class ios_flags { public: /** * * @param ios the associated std::ios_base. * @Postcondition flags()==0 */ explicit ios_flags(std::ios_base& ios) : ios_(ios) { } ~ios_flags() { } /** * @Returns The format control information. */ long flags() const BOOST_NOEXCEPT { return value(); } /** * @param v the new bit mask. * @Postcondition v == flags(). * @Returns The previous value of @c flags(). */ long flags(long v)BOOST_NOEXCEPT { long tmp = flags(); ref() = v; return tmp; } /** * @param v the new value * @Effects: Sets @c v in @c flags(). * @Returns: The previous value of @c flags(). */ long setf(long v) { long tmp = value(); ref() |= v; return tmp; } /** * @param mask the bit mask to clear. * @Effects: Clears @c mask in @c flags(). */ void unsetf(long mask) { ref() &= ~mask; } /** * * @param v * @param mask * @Effects: Clears @c mask in @c flags(), sets v & mask in @c flags(). * @Returns: The previous value of flags(). */ long setf(long v, long mask) { long tmp = value(); unsetf(mask); ref() |= v & mask; return tmp; } /** * implicit conversion to the @c ios_base */ operator std::ios_base&()BOOST_NOEXCEPT { return ios_; } /** * implicit conversion to the @c ios_base const */ operator std::ios_base const&() const BOOST_NOEXCEPT { return ios_; } private: long value() const BOOST_NOEXCEPT { return ios_.iword(index()); } long& ref()BOOST_NOEXCEPT { return ios_.iword(index()); } static inline int index() { return detail::xalloc_key_holder::value; } ios_flags& operator=(ios_flags const& rhs) ; std::ios_base& ios_; //static detail::xalloc_key_initializer xalloc_key_initializer_; }; //template //detail::xalloc_key_initializer ios_flags::xalloc_key_initializer_; } // namespace chrono } // namespace boost #endif // header