1 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
2 | // basic_xml_oarchive.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 | // See http://www.boost.org for updates, documentation, and revision history. |
10 | |
11 | #include <algorithm> |
12 | #include <cstddef> // NULL |
13 | #include <cstring> |
14 | #if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__) |
15 | namespace std{ |
16 | using ::strlen; |
17 | } // namespace std |
18 | #endif |
19 | |
20 | #include <boost/archive/basic_xml_archive.hpp> |
21 | #include <boost/archive/basic_xml_oarchive.hpp> |
22 | #include <boost/archive/xml_archive_exception.hpp> |
23 | #include <boost/core/no_exceptions_support.hpp> |
24 | |
25 | namespace boost { |
26 | namespace archive { |
27 | |
28 | namespace detail { |
29 | template<class CharType> |
30 | struct XML_name { |
31 | void operator()(CharType t) const{ |
32 | const unsigned char lookup_table[] = { |
33 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
34 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
35 | 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0, // -. |
36 | 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, // 0-9 |
37 | 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // A- |
38 | 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, // -Z _ |
39 | 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // a- |
40 | 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, // -z |
41 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
42 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
43 | }; |
44 | if((unsigned)t > 127) |
45 | return; |
46 | if(0 == lookup_table[(unsigned)t]) |
47 | boost::serialization::throw_exception( |
48 | e: xml_archive_exception( |
49 | xml_archive_exception::xml_archive_tag_name_error |
50 | ) |
51 | ); |
52 | } |
53 | }; |
54 | |
55 | } // namespace detail |
56 | |
57 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
58 | // implemenations of functions common to both types of xml output |
59 | |
60 | template<class Archive> |
61 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
62 | basic_xml_oarchive<Archive>::write_attribute( |
63 | const char *attribute_name, |
64 | int t, |
65 | const char *conjunction |
66 | ){ |
67 | this->This()->put(' '); |
68 | this->This()->put(attribute_name); |
69 | this->This()->put(conjunction); |
70 | this->This()->save(t); |
71 | this->This()->put('"'); |
72 | } |
73 | |
74 | template<class Archive> |
75 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
76 | basic_xml_oarchive<Archive>::write_attribute( |
77 | const char *attribute_name, |
78 | const char *key |
79 | ){ |
80 | this->This()->put(' '); |
81 | this->This()->put(attribute_name); |
82 | this->This()->put("=\"" ); |
83 | this->This()->save(key); |
84 | this->This()->put('"'); |
85 | } |
86 | |
87 | template<class Archive> |
88 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
89 | basic_xml_oarchive<Archive>::indent(){ |
90 | int i; |
91 | for(i = depth; i-- > 0;) |
92 | this->This()->put('\t'); |
93 | } |
94 | |
95 | template<class Archive> |
96 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
97 | basic_xml_oarchive<Archive>::save_start(const char *name) |
98 | { |
99 | if(NULL == name) |
100 | return; |
101 | |
102 | // be sure name has no invalid characters |
103 | std::for_each(first: name, last: name + std::strlen(s: name), f: detail::XML_name<const char>()); |
104 | |
105 | end_preamble(); |
106 | if(depth > 0){ |
107 | this->This()->put('\n'); |
108 | indent(); |
109 | } |
110 | ++depth; |
111 | this->This()->put('<'); |
112 | this->This()->save(name); |
113 | pending_preamble = true; |
114 | indent_next = false; |
115 | } |
116 | |
117 | template<class Archive> |
118 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
119 | basic_xml_oarchive<Archive>::save_end(const char *name) |
120 | { |
121 | if(NULL == name) |
122 | return; |
123 | |
124 | // be sure name has no invalid characters |
125 | std::for_each(first: name, last: name + std::strlen(s: name), f: detail::XML_name<const char>()); |
126 | |
127 | end_preamble(); |
128 | --depth; |
129 | if(indent_next){ |
130 | this->This()->put('\n'); |
131 | indent(); |
132 | } |
133 | indent_next = true; |
134 | this->This()->put("</" ); |
135 | this->This()->save(name); |
136 | this->This()->put('>'); |
137 | if(0 == depth) |
138 | this->This()->put('\n'); |
139 | } |
140 | |
141 | template<class Archive> |
142 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
143 | basic_xml_oarchive<Archive>::end_preamble(){ |
144 | if(pending_preamble){ |
145 | this->This()->put('>'); |
146 | pending_preamble = false; |
147 | } |
148 | } |
149 | #if 0 |
150 | template<class Archive> |
151 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
152 | basic_xml_oarchive<Archive>::save_override(const object_id_type & t) |
153 | { |
154 | int i = t.t; // extra .t is for borland |
155 | write_attribute(BOOST_ARCHIVE_XML_OBJECT_ID(), i, "=\"_" ); |
156 | } |
157 | template<class Archive> |
158 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
159 | basic_xml_oarchive<Archive>::save_override( |
160 | const object_reference_type & t, |
161 | int |
162 | ){ |
163 | int i = t.t; // extra .t is for borland |
164 | write_attribute(BOOST_ARCHIVE_XML_OBJECT_REFERENCE(), i, "=\"_" ); |
165 | } |
166 | template<class Archive> |
167 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
168 | basic_xml_oarchive<Archive>::save_override(const version_type & t) |
169 | { |
170 | int i = t.t; // extra .t is for borland |
171 | write_attribute(BOOST_ARCHIVE_XML_VERSION(), i); |
172 | } |
173 | #endif |
174 | |
175 | template<class Archive> |
176 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
177 | basic_xml_oarchive<Archive>::save_override(const object_id_type & t) |
178 | { |
179 | // borland doesn't do conversion of STRONG_TYPEDEFs very well |
180 | const unsigned int i = t; |
181 | write_attribute(BOOST_ARCHIVE_XML_OBJECT_ID(), i, "=\"_" ); |
182 | } |
183 | template<class Archive> |
184 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
185 | basic_xml_oarchive<Archive>::save_override( |
186 | const object_reference_type & t |
187 | ){ |
188 | const unsigned int i = t; |
189 | write_attribute(BOOST_ARCHIVE_XML_OBJECT_REFERENCE(), i, "=\"_" ); |
190 | } |
191 | template<class Archive> |
192 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
193 | basic_xml_oarchive<Archive>::save_override(const version_type & t) |
194 | { |
195 | const unsigned int i = t; |
196 | write_attribute(BOOST_ARCHIVE_XML_VERSION(), i); |
197 | } |
198 | |
199 | template<class Archive> |
200 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
201 | basic_xml_oarchive<Archive>::save_override(const class_id_type & t) |
202 | { |
203 | write_attribute(BOOST_ARCHIVE_XML_CLASS_ID(), t); |
204 | } |
205 | template<class Archive> |
206 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
207 | basic_xml_oarchive<Archive>::save_override( |
208 | const class_id_reference_type & t |
209 | ){ |
210 | write_attribute(BOOST_ARCHIVE_XML_CLASS_ID_REFERENCE(), t); |
211 | } |
212 | template<class Archive> |
213 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
214 | basic_xml_oarchive<Archive>::save_override( |
215 | const class_id_optional_type & t |
216 | ){ |
217 | write_attribute(BOOST_ARCHIVE_XML_CLASS_ID(), t); |
218 | } |
219 | template<class Archive> |
220 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
221 | basic_xml_oarchive<Archive>::save_override(const class_name_type & t) |
222 | { |
223 | const char * key = t; |
224 | if(NULL == key) |
225 | return; |
226 | write_attribute(BOOST_ARCHIVE_XML_CLASS_NAME(), key); |
227 | } |
228 | |
229 | template<class Archive> |
230 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
231 | basic_xml_oarchive<Archive>::save_override(const tracking_type & t) |
232 | { |
233 | write_attribute(BOOST_ARCHIVE_XML_TRACKING(), t.t); |
234 | } |
235 | |
236 | template<class Archive> |
237 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
238 | basic_xml_oarchive<Archive>::init(){ |
239 | // xml header |
240 | this->This()->put("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n" ); |
241 | this->This()->put("<!DOCTYPE boost_serialization>\n" ); |
242 | // xml document wrapper - outer root |
243 | this->This()->put("<boost_serialization" ); |
244 | write_attribute("signature" , BOOST_ARCHIVE_SIGNATURE()); |
245 | write_attribute("version" , BOOST_ARCHIVE_VERSION()); |
246 | this->This()->put(">\n" ); |
247 | } |
248 | |
249 | template<class Archive> |
250 | BOOST_ARCHIVE_OR_WARCHIVE_DECL void |
251 | basic_xml_oarchive<Archive>::windup(){ |
252 | // xml_trailer |
253 | this->This()->put("</boost_serialization>\n" ); |
254 | } |
255 | |
256 | template<class Archive> |
257 | BOOST_ARCHIVE_OR_WARCHIVE_DECL |
258 | basic_xml_oarchive<Archive>::basic_xml_oarchive(unsigned int flags) : |
259 | detail::common_oarchive<Archive>(flags), |
260 | depth(0), |
261 | pending_preamble(false), |
262 | indent_next(false) |
263 | { |
264 | } |
265 | |
266 | template<class Archive> |
267 | BOOST_ARCHIVE_OR_WARCHIVE_DECL |
268 | basic_xml_oarchive<Archive>::~basic_xml_oarchive(){ |
269 | } |
270 | |
271 | } // namespace archive |
272 | } // namespace boost |
273 | |