]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/serialization/src/basic_xml_grammar.ipp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / serialization / src / basic_xml_grammar.ipp
1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // basic_xml_grammar.ipp:
3
4 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
5 // Use, modification and distribution is subject to the Boost Software
6 // License, Version 1.0. (See 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 #if (defined _MSC_VER) && (_MSC_VER == 1200)
12 # pragma warning (disable : 4786) // too long name, harmless warning
13 #endif
14
15 #include <istream>
16 #include <algorithm>
17 #include <boost/config.hpp> // typename
18
19 #ifdef BOOST_MSVC
20 # pragma warning(push)
21 # pragma warning(disable : 4244 4511 4512)
22 #endif
23
24 // spirit stuff
25 #include <boost/spirit/include/classic_operators.hpp>
26 #include <boost/spirit/include/classic_actions.hpp>
27 #include <boost/spirit/include/classic_numerics.hpp>
28
29 #ifdef BOOST_MSVC
30 #pragma warning(pop)
31 #endif
32
33 // for head_iterator test
34 //#include <boost/bind.hpp>
35 #include <boost/function.hpp>
36
37 #include <boost/io/ios_state.hpp>
38 #include <boost/serialization/throw_exception.hpp>
39 #include <boost/archive/impl/basic_xml_grammar.hpp>
40 #include <boost/archive/xml_archive_exception.hpp>
41 #include <boost/archive/basic_xml_archive.hpp>
42 #include <boost/archive/iterators/xml_unescape.hpp>
43
44 using namespace boost::spirit::classic;
45
46 namespace boost {
47 namespace archive {
48
49 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
50 // template code for basic_xml_grammar of both wchar_t and char types
51
52 namespace xml { // anonymous
53
54 #ifdef BOOST_MSVC
55 # pragma warning(push)
56 # pragma warning(disable : 4511 4512)
57 #endif
58
59 template<class T>
60 struct assign_impl {
61 T & t;
62 void operator()(const T t_) const {
63 t = t_;
64 }
65 assign_impl(T & t_)
66 : t(t_)
67 {}
68 };
69
70 template<>
71 struct assign_impl<std::string> {
72 std::string & t;
73 void operator()(
74 std::string::const_iterator b,
75 std::string::const_iterator e
76 ) const {
77 t.resize(0);
78 while(b != e){
79 t += * b;
80 ++b;
81 }
82 }
83 assign_impl<std::string> & operator=(
84 assign_impl<std::string> & rhs
85 );
86 assign_impl(std::string & t_)
87 : t(t_)
88 {}
89 };
90
91 #ifndef BOOST_NO_STD_WSTRING
92 template<>
93 struct assign_impl<std::wstring> {
94 std::wstring & t;
95 void operator()(
96 std::wstring::const_iterator b,
97 std::wstring::const_iterator e
98 ) const {
99 t.resize(0);
100 while(b != e){
101 t += * b;
102 ++b;
103 }
104 }
105 assign_impl(std::wstring & t_)
106 : t(t_)
107 {}
108 };
109 #endif
110
111 template<class T>
112 assign_impl<T> assign_object(T &t){
113 return assign_impl<T>(t);
114 }
115
116 struct assign_level {
117 tracking_type & tracking_level;
118 void operator()(const unsigned int tracking_level_) const {
119 tracking_level = (0 == tracking_level_) ? false : true;
120 }
121 assign_level(tracking_type & tracking_level_)
122 : tracking_level(tracking_level_)
123 {}
124 };
125
126 template<class String, class Iterator>
127 struct append_string {
128 String & contents;
129 void operator()(Iterator start, Iterator end) const {
130 #if 0
131 typedef boost::archive::iterators::xml_unescape<Iterator> translator;
132 contents.append(
133 translator(BOOST_MAKE_PFTO_WRAPPER(start)),
134 translator(BOOST_MAKE_PFTO_WRAPPER(end))
135 );
136 #endif
137 contents.append(start, end);
138 }
139 append_string(String & contents_)
140 : contents(contents_)
141 {}
142 };
143
144 template<class String>
145 struct append_char {
146 String & contents;
147 void operator()(const unsigned int char_value) const {
148 const typename String::value_type z = char_value;
149 contents += z;
150 }
151 append_char(String & contents_)
152 : contents(contents_)
153 {}
154 };
155
156 template<class String, unsigned int c>
157 struct append_lit {
158 String & contents;
159 template<class X, class Y>
160 void operator()(const X & /*x*/, const Y & /*y*/) const {
161 const typename String::value_type z = c;
162 contents += z;
163 }
164 append_lit(String & contents_)
165 : contents(contents_)
166 {}
167 };
168
169 #ifdef BOOST_MSVC
170 #pragma warning(pop)
171 #endif
172
173 } // namespace anonymous
174
175 template<class CharType>
176 bool basic_xml_grammar<CharType>::my_parse(
177 typename basic_xml_grammar<CharType>::IStream & is,
178 const rule_t & rule_,
179 CharType delimiter
180 ) const {
181 if(is.fail()){
182 return false;
183 }
184
185 boost::io::ios_flags_saver ifs(is);
186 is >> std::noskipws;
187
188 std::basic_string<CharType> arg;
189
190 CharType val;
191 do{
192 typename basic_xml_grammar<CharType>::IStream::int_type
193 result = is.get();
194 if(is.fail())
195 return false;
196 val = static_cast<CharType>(result);
197 arg += val;
198 }
199 while(val != delimiter);
200
201 // read just one more character. This will be the newline after the tag
202 // this is so that the next operation will return fail if the archive
203 // is terminated. This will permit the archive to be used for debug
204 // and transaction data logging in the standard way.
205
206 parse_info<typename std::basic_string<CharType>::iterator>
207 result = boost::spirit::classic::parse(arg.begin(), arg.end(), rule_);
208 return result.hit;
209 }
210
211 template<class CharType>
212 bool basic_xml_grammar<CharType>::parse_start_tag(
213 typename basic_xml_grammar<CharType>::IStream & is
214 ){
215 rv.class_name.resize(0);
216 return my_parse(is, STag);
217 }
218
219 template<class CharType>
220 bool basic_xml_grammar<CharType>::parse_end_tag(IStream & is) const {
221 return my_parse(is, ETag);
222 }
223
224 template<class CharType>
225 bool basic_xml_grammar<CharType>::parse_string(IStream & is, StringType & s){
226 rv.contents.resize(0);
227 bool result = my_parse(is, content, '<');
228 // note: unget caused a problem with dinkumware. replace with
229 // is.unget();
230 // putback another dilimiter instead
231 is.putback('<');
232 if(result)
233 s = rv.contents;
234 return result;
235 }
236
237 template<class CharType>
238 basic_xml_grammar<CharType>::basic_xml_grammar(){
239 init_chset();
240
241 S =
242 +(Sch)
243 ;
244
245 // refactoring to workaround template depth on darwin
246 NameHead = (Letter | '_' | ':');
247 NameTail = *NameChar ;
248 Name =
249 NameHead >> NameTail
250 ;
251
252 Eq =
253 !S >> '=' >> !S
254 ;
255
256 AttributeList =
257 *(S >> Attribute)
258 ;
259
260 STag =
261 !S
262 >> '<'
263 >> Name [xml::assign_object(rv.object_name)]
264 >> AttributeList
265 >> !S
266 >> '>'
267 ;
268
269 ETag =
270 !S
271 >> "</"
272 >> Name [xml::assign_object(rv.object_name)]
273 >> !S
274 >> '>'
275 ;
276
277 // refactoring to workaround template depth on darwin
278 CharDataChars = +(anychar_p - chset_p(L"&<"));
279 CharData =
280 CharDataChars [
281 xml::append_string<
282 StringType,
283 typename std::basic_string<CharType>::const_iterator
284 >(rv.contents)
285 ]
286 ;
287
288 // slight factoring works around ICE in msvc 6.0
289 CharRef1 =
290 str_p(L"&#") >> uint_p [xml::append_char<StringType>(rv.contents)] >> L';'
291 ;
292 CharRef2 =
293 str_p(L"&#x") >> hex_p [xml::append_char<StringType>(rv.contents)] >> L';'
294 ;
295 CharRef = CharRef1 | CharRef2 ;
296
297 AmpRef = str_p(L"&amp;")[xml::append_lit<StringType, L'&'>(rv.contents)];
298 LTRef = str_p(L"&lt;")[xml::append_lit<StringType, L'<'>(rv.contents)];
299 GTRef = str_p(L"&gt;")[xml::append_lit<StringType, L'>'>(rv.contents)];
300 AposRef = str_p(L"&apos;")[xml::append_lit<StringType, L'\''>(rv.contents)];
301 QuoteRef = str_p(L"&quot;")[xml::append_lit<StringType, L'"'>(rv.contents)];
302
303 Reference =
304 AmpRef
305 | LTRef
306 | GTRef
307 | AposRef
308 | QuoteRef
309 | CharRef
310 ;
311
312 content =
313 L"<" // should be end_p
314 | +(Reference | CharData) >> L"<"
315 ;
316
317 ClassIDAttribute =
318 str_p(BOOST_ARCHIVE_XML_CLASS_ID()) >> NameTail
319 >> Eq
320 >> L'"'
321 >> int_p [xml::assign_object(rv.class_id)]
322 >> L'"'
323 ;
324
325 ObjectIDAttribute = (
326 str_p(BOOST_ARCHIVE_XML_OBJECT_ID())
327 |
328 str_p(BOOST_ARCHIVE_XML_OBJECT_REFERENCE())
329 )
330 >> NameTail
331 >> Eq
332 >> L'"'
333 >> L'_'
334 >> uint_p [xml::assign_object(rv.object_id)]
335 >> L'"'
336 ;
337
338 AmpName = str_p(L"&amp;")[xml::append_lit<StringType, L'&'>(rv.class_name)];
339 LTName = str_p(L"&lt;")[xml::append_lit<StringType, L'<'>(rv.class_name)];
340 GTName = str_p(L"&gt;")[xml::append_lit<StringType, L'>'>(rv.class_name)];
341 ClassNameChar =
342 AmpName
343 | LTName
344 | GTName
345 | (anychar_p - chset_p(L"\"")) [xml::append_char<StringType>(rv.class_name)]
346 ;
347
348 ClassName =
349 * ClassNameChar
350 ;
351
352 ClassNameAttribute =
353 str_p(BOOST_ARCHIVE_XML_CLASS_NAME())
354 >> Eq
355 >> L'"'
356 >> ClassName
357 >> L'"'
358 ;
359
360 TrackingAttribute =
361 str_p(BOOST_ARCHIVE_XML_TRACKING())
362 >> Eq
363 >> L'"'
364 >> uint_p [xml::assign_level(rv.tracking_level)]
365 >> L'"'
366 ;
367
368 VersionAttribute =
369 str_p(BOOST_ARCHIVE_XML_VERSION())
370 >> Eq
371 >> L'"'
372 >> uint_p [xml::assign_object(rv.version)]
373 >> L'"'
374 ;
375
376 UnusedAttribute =
377 Name
378 >> Eq
379 >> L'"'
380 >> !CharData
381 >> L'"'
382 ;
383
384 Attribute =
385 ClassIDAttribute
386 | ObjectIDAttribute
387 | ClassNameAttribute
388 | TrackingAttribute
389 | VersionAttribute
390 | UnusedAttribute
391 ;
392
393 XMLDeclChars = *(anychar_p - chset_p(L"?>"));
394 XMLDecl =
395 !S
396 >> str_p(L"<?xml")
397 >> S
398 >> str_p(L"version")
399 >> Eq
400 >> str_p(L"\"1.0\"")
401 >> XMLDeclChars
402 >> !S
403 >> str_p(L"?>")
404 ;
405
406 DocTypeDeclChars = *(anychar_p - chset_p(L">"));
407 DocTypeDecl =
408 !S
409 >> str_p(L"<!DOCTYPE")
410 >> DocTypeDeclChars
411 >> L'>'
412 ;
413
414 SignatureAttribute =
415 str_p(L"signature")
416 >> Eq
417 >> L'"'
418 >> Name [xml::assign_object(rv.class_name)]
419 >> L'"'
420 ;
421
422 SerializationWrapper =
423 !S
424 >> str_p(L"<boost_serialization")
425 >> S
426 >> ( (SignatureAttribute >> S >> VersionAttribute)
427 | (VersionAttribute >> S >> SignatureAttribute)
428 )
429 >> !S
430 >> L'>'
431 ;
432 }
433
434 template<class CharType>
435 void basic_xml_grammar<CharType>::init(IStream & is){
436 init_chset();
437 if(! my_parse(is, XMLDecl))
438 boost::serialization::throw_exception(
439 xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
440 );
441 if(! my_parse(is, DocTypeDecl))
442 boost::serialization::throw_exception(
443 xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
444 );
445 if(! my_parse(is, SerializationWrapper))
446 boost::serialization::throw_exception(
447 xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
448 );
449 if(! std::equal(rv.class_name.begin(), rv.class_name.end(), BOOST_ARCHIVE_SIGNATURE()))
450 boost::serialization::throw_exception(
451 archive_exception(archive_exception::invalid_signature)
452 );
453 }
454
455 template<class CharType>
456 bool basic_xml_grammar<CharType>::windup(IStream & is) {
457 return my_parse(is, ETag);
458 }
459
460 } // namespace archive
461 } // namespace boost