1 // boost/chrono/utility/ios_base_pword_ptr.hpp ------------------------------------------------------------// 2 3 // Copyright 2011 Vicente J. Botet Escriba 4 5 // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8 // See http://www.boost.org/libs/chrono for documentation. 9 10 #ifndef BOOST_CHRONO_UTILITY_IOS_BASE_STATE_PTR_HPP 11 #define BOOST_CHRONO_UTILITY_IOS_BASE_STATE_PTR_HPP 12 13 #include <ios> 14 #include <boost/assert.hpp> 15 16 /** 17 * 18 19 20 */ 21 namespace boost 22 { 23 namespace chrono 24 { 25 namespace detail 26 { 27 28 /** 29 * xalloc key holder. 30 */ 31 template <typename T> 32 struct xalloc_key_holder 33 { 34 static int value; //< the xalloc value associated to T. 35 static bool initialized; //< whether the value has been initialized or not. 36 }; 37 38 template <typename T> 39 int xalloc_key_holder<T>::value = 0; 40 41 template <typename T> 42 bool xalloc_key_holder<T>::initialized = false; 43 44 } 45 46 /** 47 * xalloc key initialiazer. 48 * 49 * Declare a static variable of this type to ensure that the xalloc_key_holder<T> is initialized correctly. 50 */ 51 template <typename T> 52 struct xalloc_key_initializer 53 { xalloc_key_initializerboost::chrono::xalloc_key_initializer54 xalloc_key_initializer() 55 { 56 if (!detail::xalloc_key_holder<T>::initialized) 57 { 58 detail::xalloc_key_holder<T>::value = std::ios_base::xalloc(); 59 detail::xalloc_key_holder<T>::initialized = true; 60 } 61 } 62 }; 63 /** 64 * @c ios_state_ptr is a smart pointer to a ios_base specific state. 65 */ 66 template <typename Final, typename T> 67 class ios_state_ptr 68 { 69 ios_state_ptr& operator=(ios_state_ptr const& rhs) ; 70 71 public: 72 /** 73 * The pointee type 74 */ 75 typedef T element_type; 76 /** 77 * Explicit constructor. 78 * @param ios the ios 79 * @Effects Constructs a @c ios_state_ptr by storing the associated @c ios. 80 */ ios_state_ptr(std::ios_base & ios)81 explicit ios_state_ptr(std::ios_base& ios) : 82 ios_(ios) 83 { 84 85 } 86 /** 87 * Nothing to do as xalloc index can not be removed. 88 */ ~ios_state_ptr()89 ~ios_state_ptr() 90 { 91 } 92 93 /** 94 * @Effects Allocates the index if not already done. 95 * Registers the callback responsible of maintaining the state pointer coherency, if not already done. 96 * Retrieves the associated ios pointer 97 * @return the retrieved pointer statically casted to const. 98 */ get() const99 T const* get() const BOOST_NOEXCEPT 100 { 101 register_once(index(), ios_); 102 void* &pw = ios_.pword(index()); 103 if (pw == 0) 104 { 105 return 0; 106 } 107 return static_cast<const T*> (pw); 108 } 109 /** 110 * @Effects Allocates the index if not already done. 111 * Registers the callback responsible of maintaining the state pointer coherency, if not already done. 112 * Retrieves the associated ios pointer 113 * @return the retrieved pointer. 114 */ get()115 T * get() BOOST_NOEXCEPT 116 { 117 register_once(index(), ios_); 118 void* &pw = ios_.pword(index()); 119 if (pw == 0) 120 { 121 return 0; 122 } 123 return static_cast<T*> (pw); 124 } 125 /** 126 * @Effects as if @c return get(); 127 * @return the retrieved pointer. 128 */ operator ->()129 T * operator->()BOOST_NOEXCEPT 130 { 131 return get(); 132 } 133 /** 134 * @Effects as if @c return get(); 135 * @return the retrieved pointer. 136 */ operator ->() const137 T const * operator->() const BOOST_NOEXCEPT 138 { 139 return get(); 140 } 141 142 /** 143 * @Effects as if @c return *get(); 144 * @return a reference to the retrieved state. 145 * @Remark The behavior is undefined if @c get()==0. 146 */ operator *()147 T & operator*() BOOST_NOEXCEPT 148 { 149 return *get(); 150 } 151 /** 152 * @Effects as if @c return *get(); 153 * @return a reference to the retrieved state. 154 * @Remark The behavior is undefined if @c get()==0. 155 */ operator *() const156 T const & operator *() const BOOST_NOEXCEPT 157 { 158 return *get(); 159 } 160 161 /** 162 * @Effects reset the current pointer after storing in a temporary variable the pointer to the current state. 163 * @return the stored state pointer. 164 */ release()165 T * release() BOOST_NOEXCEPT 166 { 167 T const* f = get(); 168 reset(); 169 return f; 170 } 171 172 /** 173 * 174 * @param new_ptr the new pointer. 175 * @Effects deletes the current state and replace it with the new one. 176 */ reset(T * new_ptr=0)177 void reset(T* new_ptr = 0)BOOST_NOEXCEPT 178 { 179 register_once(index(), ios_); 180 void*& pw = ios_.pword(index()); 181 delete static_cast<T*> (pw); 182 pw = new_ptr; 183 } 184 185 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) 186 typedef T* (ios_state_ptr::*bool_type)(); operator bool_type() const187 operator bool_type() const BOOST_NOEXCEPT 188 { 189 return (get()!=0)?&ios_state_ptr::release:0; 190 } operator !() const191 bool operator!() const BOOST_NOEXCEPT 192 { 193 return (get()==0)?&ios_state_ptr::release:0; 194 } 195 #else 196 /** 197 * Explicit conversion to bool. 198 */ operator bool() const199 explicit operator bool() const BOOST_NOEXCEPT 200 { 201 return get()!=0; 202 } 203 #endif 204 getios()205 std::ios_base& getios()BOOST_NOEXCEPT 206 { 207 return ios_; 208 } getios() const209 std::ios_base& getios() const BOOST_NOEXCEPT 210 { 211 return ios_; 212 } 213 /** 214 * Implicit conversion to the ios_base 215 */ operator std::ios_base&()216 operator std::ios_base&() BOOST_NOEXCEPT 217 { 218 return ios_; 219 } 220 /** 221 * Implicit conversion to the ios_base const 222 */ operator std::ios_base&() const223 operator std::ios_base&() const BOOST_NOEXCEPT 224 { 225 return ios_; 226 } 227 private: is_registerd(std::ios_base & ios)228 static inline bool is_registerd(std::ios_base& ios) 229 { 230 long iw = ios.iword(index()); 231 return (iw == 1); 232 } set_registered(std::ios_base & ios)233 static inline void set_registered(std::ios_base& ios) 234 { 235 long& iw = ios.iword(index()); 236 iw = 1; 237 } callback(std::ios_base::event evt,std::ios_base & ios,int index)238 static inline void callback(std::ios_base::event evt, std::ios_base& ios, int index) 239 { 240 switch (evt) 241 { 242 case std::ios_base::erase_event: 243 { 244 void*& pw = ios.pword(index); 245 if (pw != 0) 246 { 247 T* ptr = static_cast<T*> (pw); 248 delete ptr; 249 pw = 0; 250 } 251 break; 252 } 253 case std::ios_base::copyfmt_event: 254 { 255 void*& pw = ios.pword(index); 256 if (pw != 0) 257 { 258 pw = new T(*static_cast<T*> (pw)); 259 } 260 break; 261 } 262 default: 263 break; 264 } 265 } 266 index()267 static inline int index() 268 { 269 return detail::xalloc_key_holder<Final>::value; 270 } 271 register_once(int indx,std::ios_base & ios)272 static inline void register_once(int indx, std::ios_base& ios) 273 { 274 // needs a mask registered 275 if (!is_registerd(ios)) 276 { 277 set_registered(ios); 278 ios.register_callback(callback, indx); 279 } 280 } 281 282 283 protected: 284 std::ios_base& ios_; 285 //static detail::xalloc_key_initializer<Final> xalloc_key_initializer_; 286 287 }; 288 //template <typename Final, typename T> 289 //detail::xalloc_key_initializer<Final> ios_state_ptr<Final,T>::xalloc_key_initializer_; 290 291 292 /** 293 * @c ios_state_not_null_ptr is a non null variant of @c ios_state_ptr. 294 * @tparm T 295 * @Requires @c T must be @c DefaultConstructible and @c HeapAllocatable 296 */ 297 template <typename Final, typename T> 298 class ios_state_not_null_ptr: public ios_state_ptr<Final, T> 299 { 300 typedef ios_state_ptr<Final, T> base_type; 301 public: ios_state_not_null_ptr(std::ios_base & ios)302 explicit ios_state_not_null_ptr(std::ios_base& ios) : 303 base_type(ios) 304 { 305 if (this->get() == 0) 306 { 307 this->base_type::reset(new T()); 308 } 309 } ~ios_state_not_null_ptr()310 ~ios_state_not_null_ptr() 311 { 312 } 313 reset(T * new_value)314 void reset(T* new_value) BOOST_NOEXCEPT 315 { 316 BOOST_ASSERT(new_value!=0); 317 this->base_type::reset(new_value); 318 } 319 320 }; 321 322 /** 323 * This class is useful to associate some flags to an std::ios_base. 324 */ 325 template <typename Final> 326 class ios_flags 327 { 328 public: 329 /** 330 * 331 * @param ios the associated std::ios_base. 332 * @Postcondition <c>flags()==0</c> 333 */ ios_flags(std::ios_base & ios)334 explicit ios_flags(std::ios_base& ios) : 335 ios_(ios) 336 { 337 } ~ios_flags()338 ~ios_flags() 339 { 340 } 341 /** 342 * @Returns The format control information. 343 */ flags() const344 long flags() const BOOST_NOEXCEPT 345 { 346 return value(); 347 } 348 349 /** 350 * @param v the new bit mask. 351 * @Postcondition <c>v == flags()</c>. 352 * @Returns The previous value of @c flags(). 353 */ flags(long v)354 long flags(long v)BOOST_NOEXCEPT 355 { 356 long tmp = flags(); 357 ref() = v; 358 return tmp; 359 } 360 361 /** 362 * @param v the new value 363 * @Effects: Sets @c v in @c flags(). 364 * @Returns: The previous value of @c flags(). 365 */ setf(long v)366 long setf(long v) 367 { 368 long tmp = value(); 369 ref() |= v; 370 return tmp; 371 } 372 373 /** 374 * @param mask the bit mask to clear. 375 * @Effects: Clears @c mask in @c flags(). 376 */ unsetf(long mask)377 void unsetf(long mask) 378 { 379 ref() &= ~mask; 380 } 381 382 /** 383 * 384 * @param v 385 * @param mask 386 * @Effects: Clears @c mask in @c flags(), sets <c>v & mask</c> in @c flags(). 387 * @Returns: The previous value of flags(). 388 */ setf(long v,long mask)389 long setf(long v, long mask) 390 { 391 long tmp = value(); 392 unsetf(mask); 393 ref() |= v & mask; 394 return tmp; 395 } 396 397 /** 398 * implicit conversion to the @c ios_base 399 */ operator std::ios_base&()400 operator std::ios_base&()BOOST_NOEXCEPT 401 { 402 return ios_; 403 } 404 /** 405 * implicit conversion to the @c ios_base const 406 */ operator std::ios_base const&() const407 operator std::ios_base const&() const BOOST_NOEXCEPT 408 { 409 return ios_; 410 } 411 private: value() const412 long value() const BOOST_NOEXCEPT 413 { 414 return ios_.iword(index()); 415 } ref()416 long& ref()BOOST_NOEXCEPT 417 { 418 return ios_.iword(index()); 419 } index()420 static inline int index() 421 { 422 return detail::xalloc_key_holder<Final>::value; 423 } 424 ios_flags& operator=(ios_flags const& rhs) ; 425 426 std::ios_base& ios_; 427 //static detail::xalloc_key_initializer<Final> xalloc_key_initializer_; 428 429 }; 430 //template <typename Final> 431 //detail::xalloc_key_initializer<Final> ios_flags<Final>::xalloc_key_initializer_; 432 433 } // namespace chrono 434 } // namespace boost 435 436 #endif // header 437