Imported Upstream version 1.57.0
[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         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        */
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)();
187         operator bool_type() const BOOST_NOEXCEPT
188         {
189             return (get()!=0)?&ios_state_ptr::release:0;
190         }
191         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          */
199         explicit operator bool() const BOOST_NOEXCEPT
200         {
201           return get()!=0;
202         }
203 #endif
204
205       std::ios_base& getios()BOOST_NOEXCEPT
206       {
207         return ios_;
208       }
209       std::ios_base& getios() const BOOST_NOEXCEPT
210       {
211         return ios_;
212       }
213       /**
214        * Implicit conversion to the ios_base
215        */
216       operator std::ios_base&() BOOST_NOEXCEPT
217       {
218         return ios_;
219       }
220       /**
221        * Implicit conversion to the ios_base const
222        */
223       operator std::ios_base&() const BOOST_NOEXCEPT
224       {
225         return ios_;
226       }
227     private:
228       static inline bool is_registerd(std::ios_base& ios)
229       {
230         long iw = ios.iword(index());
231         return (iw == 1);
232       }
233       static inline void set_registered(std::ios_base& ios)
234       {
235         long& iw = ios.iword(index());
236         iw = 1;
237       }
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
267       static inline int index()
268       {
269         return detail::xalloc_key_holder<Final>::value;
270       }
271
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:
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       }
310       ~ios_state_not_null_ptr()
311       {
312       }
313
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        */
334       explicit ios_flags(std::ios_base& ios) :
335         ios_(ios)
336       {
337       }
338       ~ios_flags()
339       {
340       }
341       /**
342        * @Returns The format control information.
343        */
344       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        */
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        */
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        */
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        */
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        */
400       operator std::ios_base&()BOOST_NOEXCEPT
401       {
402         return ios_;
403       }
404       /**
405        * implicit conversion to the @c ios_base const
406        */
407       operator std::ios_base const&() const BOOST_NOEXCEPT
408       {
409         return ios_;
410       }
411     private:
412       long value() const BOOST_NOEXCEPT
413       {
414         return ios_.iword(index());
415       }
416       long& ref()BOOST_NOEXCEPT
417       {
418         return ios_.iword(index());
419       }
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