]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |