change support python version
[platform/upstream/boost.git] / boost / chrono / io / utility / ios_base_state_ptr.hpp
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     {
54       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        */
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        */
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        */
99       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        */
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        */
129       T * operator->()BOOST_NOEXCEPT
130       {
131         return get();
132       }
133       /**
134        * @Effects as if @c return get();
135        * @return the retrieved pointer.
136        */
137       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        */
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        */
156       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        */
165       T * release() BOOST_NOEXCEPT
166       {
167         void*& pw = ios_.pword(index());
168         T* ptr = static_cast<T*> (pw);
169         pw = 0;
170         return ptr;
171       }
172
173       /**
174        *
175        * @param new_ptr the new pointer.
176        * @Effects deletes the current state and replace it with the new one.
177        */
178       void reset(T* new_ptr = 0)BOOST_NOEXCEPT
179       {
180         register_once(index(), ios_);
181         void*& pw = ios_.pword(index());
182         delete static_cast<T*> (pw);
183         pw = new_ptr;
184       }
185
186 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
187         typedef T* (ios_state_ptr::*bool_type)();
188         operator bool_type() const BOOST_NOEXCEPT
189         {
190             return (get()!=0)?&ios_state_ptr::release:0;
191         }
192         bool operator!() const BOOST_NOEXCEPT
193         {
194           return (get()==0)?&ios_state_ptr::release:0;
195         }
196 #else
197         /**
198          * Explicit conversion to bool.
199          */
200         explicit operator bool() const BOOST_NOEXCEPT
201         {
202           return get()!=0;
203         }
204 #endif
205
206       std::ios_base& getios()BOOST_NOEXCEPT
207       {
208         return ios_;
209       }
210       std::ios_base& getios() const BOOST_NOEXCEPT
211       {
212         return ios_;
213       }
214       /**
215        * Implicit conversion to the ios_base
216        */
217       operator std::ios_base&() BOOST_NOEXCEPT
218       {
219         return ios_;
220       }
221       /**
222        * Implicit conversion to the ios_base const
223        */
224       operator std::ios_base&() const BOOST_NOEXCEPT
225       {
226         return ios_;
227       }
228     private:
229       static inline bool is_registerd(std::ios_base& ios)
230       {
231         long iw = ios.iword(index());
232         return (iw == 1);
233       }
234       static inline void set_registered(std::ios_base& ios)
235       {
236         long& iw = ios.iword(index());
237         iw = 1;
238       }
239       static inline void callback(std::ios_base::event evt, std::ios_base& ios, int index)
240       {
241         switch (evt)
242         {
243         case std::ios_base::erase_event:
244         {
245           void*& pw = ios.pword(index);
246           if (pw != 0)
247           {
248             T* ptr = static_cast<T*> (pw);
249             delete ptr;
250             pw = 0;
251           }
252           break;
253         }
254         case std::ios_base::copyfmt_event:
255         {
256           void*& pw = ios.pword(index);
257           if (pw != 0)
258           {
259             pw = new T(*static_cast<T*> (pw));
260           }
261           break;
262         }
263         default:
264           break;
265         }
266       }
267
268       static inline int index()
269       {
270         return detail::xalloc_key_holder<Final>::value;
271       }
272
273       static inline void register_once(int indx, std::ios_base& ios)
274       {
275         // needs a mask registered
276         if (!is_registerd(ios))
277         {
278           set_registered(ios);
279           ios.register_callback(callback, indx);
280         }
281       }
282
283
284     protected:
285       std::ios_base& ios_;
286       //static detail::xalloc_key_initializer<Final> xalloc_key_initializer_;
287
288     };
289     //template <typename Final, typename T>
290     //detail::xalloc_key_initializer<Final> ios_state_ptr<Final,T>::xalloc_key_initializer_;
291
292
293     /**
294      * @c ios_state_not_null_ptr is a non null variant of @c ios_state_ptr.
295      * @tparm T
296      * @Requires @c T must be @c DefaultConstructible and @c HeapAllocatable
297      */
298     template <typename Final, typename T>
299     class ios_state_not_null_ptr: public ios_state_ptr<Final, T>
300     {
301       typedef ios_state_ptr<Final, T> base_type;
302     public:
303       explicit ios_state_not_null_ptr(std::ios_base& ios) :
304       base_type(ios)
305       {
306         if (this->get() == 0)
307         {
308           this->base_type::reset(new T());
309         }
310       }
311       ~ios_state_not_null_ptr()
312       {
313       }
314
315       void reset(T* new_value) BOOST_NOEXCEPT
316       {
317         BOOST_ASSERT(new_value!=0);
318         this->base_type::reset(new_value);
319       }
320
321     };
322
323     /**
324      * This class is useful to associate some flags to an std::ios_base.
325      */
326     template <typename Final>
327     class ios_flags
328     {
329     public:
330       /**
331        *
332        * @param ios the associated std::ios_base.
333        * @Postcondition <c>flags()==0</c>
334        */
335       explicit ios_flags(std::ios_base& ios) :
336         ios_(ios)
337       {
338       }
339       ~ios_flags()
340       {
341       }
342       /**
343        * @Returns The format control information.
344        */
345       long flags() const BOOST_NOEXCEPT
346       {
347         return value();
348       }
349
350       /**
351        * @param v the new bit mask.
352        * @Postcondition <c>v == flags()</c>.
353        * @Returns The previous value of @c flags().
354        */
355       long flags(long v)BOOST_NOEXCEPT
356       {
357         long tmp = flags();
358         ref() = v;
359         return tmp;
360       }
361
362       /**
363        * @param v the new value
364        * @Effects: Sets @c v in @c flags().
365        * @Returns: The previous value of @c flags().
366        */
367       long setf(long v)
368       {
369         long tmp = value();
370         ref() |= v;
371         return tmp;
372       }
373
374       /**
375        * @param mask the bit mask to clear.
376        * @Effects: Clears @c mask in @c flags().
377        */
378       void unsetf(long mask)
379       {
380         ref() &= ~mask;
381       }
382
383       /**
384        *
385        * @param v
386        * @param mask
387        * @Effects: Clears @c mask in @c flags(), sets <c>v & mask</c> in @c flags().
388        * @Returns: The previous value of flags().
389        */
390       long setf(long v, long mask)
391       {
392         long tmp = value();
393         unsetf(mask);
394         ref() |= v & mask;
395         return tmp;
396       }
397
398       /**
399        * implicit conversion to the @c ios_base
400        */
401       operator std::ios_base&()BOOST_NOEXCEPT
402       {
403         return ios_;
404       }
405       /**
406        * implicit conversion to the @c ios_base const
407        */
408       operator std::ios_base const&() const BOOST_NOEXCEPT
409       {
410         return ios_;
411       }
412     private:
413       long value() const BOOST_NOEXCEPT
414       {
415         return ios_.iword(index());
416       }
417       long& ref()BOOST_NOEXCEPT
418       {
419         return ios_.iword(index());
420       }
421       static inline int index()
422       {
423         return detail::xalloc_key_holder<Final>::value;
424       }
425       ios_flags& operator=(ios_flags const& rhs) ;
426
427       std::ios_base& ios_;
428       //static detail::xalloc_key_initializer<Final> xalloc_key_initializer_;
429
430     };
431     //template <typename Final>
432     //detail::xalloc_key_initializer<Final> ios_flags<Final>::xalloc_key_initializer_;
433
434   } // namespace chrono
435 } // namespace boost
436
437 #endif // header