1 | // |
---|---|
2 | // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) |
3 | // Copyright (c) 2022 Alexander Grund |
4 | // |
5 | // Distributed under the Boost Software License, Version 1.0. |
6 | // https://www.boost.org/LICENSE_1_0.txt |
7 | |
8 | #ifndef BOOST_SRC_LOCALE_IOS_PROP_HPP |
9 | #define BOOST_SRC_LOCALE_IOS_PROP_HPP |
10 | |
11 | #include <boost/locale/config.hpp> |
12 | #include <boost/assert.hpp> |
13 | #include <ios> |
14 | |
15 | namespace boost { namespace locale { namespace impl { |
16 | |
17 | template<typename Property> |
18 | class BOOST_SYMBOL_VISIBLE ios_prop { |
19 | public: |
20 | static Property& get(std::ios_base& ios) |
21 | { |
22 | Property* result = get_impl(ios); |
23 | return result ? *result : create(ios); |
24 | } |
25 | |
26 | static void global_init() { get_id(); } |
27 | |
28 | private: |
29 | static Property* get_impl(std::ios_base& ios) { return static_cast<Property*>(ios.pword(ix: get_id())); } |
30 | |
31 | static Property& create(std::ios_base& ios) |
32 | { |
33 | BOOST_ASSERT_MSG(!get_impl(ios), "Called create while the property already exists"); |
34 | const int id = get_id(); |
35 | ios.register_callback(fn: callback, index: id); |
36 | Property* value = new Property(); |
37 | ios.pword(ix: id) = value; |
38 | return *value; |
39 | } |
40 | |
41 | static void callback(std::ios_base::event ev, std::ios_base& ios, int id) |
42 | { |
43 | Property* prop = get_impl(ios); |
44 | if(!prop) |
45 | return; |
46 | switch(ev) { |
47 | case std::ios_base::erase_event: |
48 | delete prop; |
49 | ios.pword(ix: id) = nullptr; |
50 | break; |
51 | case std::ios_base::copyfmt_event: ios.pword(ix: id) = new Property(*prop); break; |
52 | case std::ios_base::imbue_event: prop->on_imbue(); break; |
53 | default: break; |
54 | } |
55 | } |
56 | static int get_id() |
57 | { |
58 | static int id = std::ios_base::xalloc(); |
59 | return id; |
60 | } |
61 | }; |
62 | |
63 | }}} // namespace boost::locale::impl |
64 | |
65 | #endif |
66 |