1 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
---|
2 | // xml_woarchive_impl.ipp: |
---|
3 | |
---|
4 | // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . |
---|
5 | // Distributed under the Boost Software License, Version 1.0. (See |
---|
6 | // accompanying file LICENSE_1_0.txt or copy at |
---|
7 | // http://www.boost.org/LICENSE_1_0.txt) |
---|
8 | |
---|
9 | #include <boost/config.hpp> |
---|
10 | #ifndef BOOST_NO_STD_WSTREAMBUF |
---|
11 | |
---|
12 | #include <ostream> |
---|
13 | #include <string> |
---|
14 | #include <algorithm> |
---|
15 | #include <locale> |
---|
16 | |
---|
17 | #include <boost/config.hpp> // msvc 6.0 needs this to suppress warnings |
---|
18 | // for BOOST_DEDUCED_TYPENAME |
---|
19 | #include <cstring> // strlen |
---|
20 | #include <cstdlib> // mbtowc |
---|
21 | #include <cwchar> // wcslen |
---|
22 | |
---|
23 | #if defined(BOOST_NO_STDC_NAMESPACE) |
---|
24 | namespace std{ |
---|
25 | using ::strlen; |
---|
26 | #if ! defined(BOOST_NO_INTRINSIC_WCHAR_T) |
---|
27 | using ::mbtowc; |
---|
28 | using ::wcslen; |
---|
29 | #endif |
---|
30 | } // namespace std |
---|
31 | #endif |
---|
32 | |
---|
33 | #include <boost/throw_exception.hpp> |
---|
34 | #include <boost/pfto.hpp> |
---|
35 | |
---|
36 | #include <boost/archive/iterators/xml_escape.hpp> |
---|
37 | #include <boost/archive/iterators/wchar_from_mb.hpp> |
---|
38 | #include <boost/archive/iterators/ostream_iterator.hpp> |
---|
39 | #include <boost/archive/iterators/dataflow_exception.hpp> |
---|
40 | |
---|
41 | #include <boost/archive/add_facet.hpp> |
---|
42 | #include <boost/archive/detail/utf8_codecvt_facet.hpp> |
---|
43 | |
---|
44 | namespace boost { |
---|
45 | namespace archive { |
---|
46 | |
---|
47 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
---|
48 | // implemenations of functions specific to wide char archives |
---|
49 | |
---|
50 | // copy chars to output escaping to xml and widening characters as we go |
---|
51 | template<class InputIterator> |
---|
52 | void save_iterator(std::wostream &os, InputIterator begin, InputIterator end){ |
---|
53 | typedef iterators::wchar_from_mb< |
---|
54 | iterators::xml_escape<InputIterator> |
---|
55 | > xmbtows; |
---|
56 | std::copy( |
---|
57 | xmbtows(BOOST_MAKE_PFTO_WRAPPER(begin)), |
---|
58 | xmbtows(BOOST_MAKE_PFTO_WRAPPER(end)), |
---|
59 | boost::archive::iterators::ostream_iterator<wchar_t>(os) |
---|
60 | ); |
---|
61 | } |
---|
62 | |
---|
63 | template<class Archive> |
---|
64 | BOOST_WARCHIVE_DECL(void) |
---|
65 | xml_woarchive_impl<Archive>::save(const std::string & s){ |
---|
66 | // note: we don't use s.begin() and s.end() because dinkumware |
---|
67 | // doesn't have string::value_type defined. So use a wrapper |
---|
68 | // around these values to implement the definitions. |
---|
69 | const char * begin = s.data(); |
---|
70 | const char * end = begin + s.size(); |
---|
71 | save_iterator(os, begin, end); |
---|
72 | } |
---|
73 | |
---|
74 | #ifndef BOOST_NO_STD_WSTRING |
---|
75 | template<class Archive> |
---|
76 | BOOST_WARCHIVE_DECL(void) |
---|
77 | xml_woarchive_impl<Archive>::save(const std::wstring & ws){ |
---|
78 | #if 0 |
---|
79 | typedef iterators::xml_escape<std::wstring::const_iterator> xmbtows; |
---|
80 | std::copy( |
---|
81 | xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.begin())), |
---|
82 | xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.end())), |
---|
83 | boost::archive::iterators::ostream_iterator<wchar_t>(os) |
---|
84 | ); |
---|
85 | #endif |
---|
86 | typedef iterators::xml_escape<const wchar_t *> xmbtows; |
---|
87 | std::copy( |
---|
88 | xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.data())), |
---|
89 | xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.data() + ws.size())), |
---|
90 | boost::archive::iterators::ostream_iterator<wchar_t>(os) |
---|
91 | ); |
---|
92 | } |
---|
93 | #endif //BOOST_NO_STD_WSTRING |
---|
94 | |
---|
95 | template<class Archive> |
---|
96 | BOOST_WARCHIVE_DECL(void) |
---|
97 | xml_woarchive_impl<Archive>::save(const char * s){ |
---|
98 | save_iterator(os, s, s + std::strlen(s)); |
---|
99 | } |
---|
100 | |
---|
101 | #ifndef BOOST_NO_INTRINSIC_WCHAR_T |
---|
102 | template<class Archive> |
---|
103 | BOOST_WARCHIVE_DECL(void) |
---|
104 | xml_woarchive_impl<Archive>::save(const wchar_t * ws){ |
---|
105 | os << ws; |
---|
106 | typedef iterators::xml_escape<const wchar_t *> xmbtows; |
---|
107 | std::copy( |
---|
108 | xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws)), |
---|
109 | xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws + std::wcslen(ws))), |
---|
110 | boost::archive::iterators::ostream_iterator<wchar_t>(os) |
---|
111 | ); |
---|
112 | } |
---|
113 | #endif |
---|
114 | |
---|
115 | template<class Archive> |
---|
116 | BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) |
---|
117 | xml_woarchive_impl<Archive>::xml_woarchive_impl( |
---|
118 | std::wostream & os_, |
---|
119 | unsigned int flags |
---|
120 | ) : |
---|
121 | basic_text_oprimitive<std::wostream>( |
---|
122 | os_, |
---|
123 | true // don't change the codecvt - use the one below |
---|
124 | ), |
---|
125 | basic_xml_oarchive<Archive>(flags) |
---|
126 | { |
---|
127 | // Standard behavior is that imbue can be called |
---|
128 | // a) before output is invoked or |
---|
129 | // b) after flush has been called. This prevents one-to-many |
---|
130 | // transforms (such as one to many transforms from getting |
---|
131 | // mixed up. Unfortunately, STLPort doesn't respect b) above |
---|
132 | // so the restoration of the original archive locale done by |
---|
133 | // the locale_saver doesn't get processed, |
---|
134 | // before the current one is destroyed. |
---|
135 | // so the codecvt doesn't get replaced with the orginal |
---|
136 | // so closing the stream invokes codecvt::do_unshift |
---|
137 | // so it crashes because the corresponding locale that contained |
---|
138 | // the codecvt isn't around any more. |
---|
139 | // we can hack around this by using a static codecvt that never |
---|
140 | // gets destroyed. |
---|
141 | if(0 == (flags & no_codecvt)){ |
---|
142 | detail::utf8_codecvt_facet *pfacet; |
---|
143 | #if defined(__SGI_STL_PORT) |
---|
144 | static detail::utf8_codecvt_facet facet(static_cast<size_t>(1)); |
---|
145 | pfacet = & facet; |
---|
146 | #else |
---|
147 | pfacet = new detail::utf8_codecvt_facet; |
---|
148 | #endif |
---|
149 | archive_locale.reset(add_facet(std::locale::classic(), pfacet)); |
---|
150 | os.imbue(* archive_locale); |
---|
151 | } |
---|
152 | if(0 == (flags & no_header)) |
---|
153 | this->init(); |
---|
154 | } |
---|
155 | |
---|
156 | } // namespace archive |
---|
157 | } // namespace boost |
---|
158 | |
---|
159 | #endif //BOOST_NO_STD_WSTREAMBUF |
---|