| 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 |
