1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // basic_xml_grammar.ipp:
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)
9 // See http://www.boost.org for updates, documentation, and revision history.
11 #if (defined _MSC_VER) && (_MSC_VER == 1200)
12 # pragma warning (disable : 4786) // too long name, harmless warning
17 #include <boost/config.hpp> // typename
20 # pragma warning(push)
21 # pragma warning(disable : 4244 4511 4512)
25 #include <boost/spirit/include/classic_operators.hpp>
26 #include <boost/spirit/include/classic_actions.hpp>
27 #include <boost/spirit/include/classic_numerics.hpp>
33 // for head_iterator test
34 //#include <boost/bind.hpp>
35 #include <boost/function.hpp>
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>
44 using namespace boost::spirit::classic;
49 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
50 // template code for basic_xml_grammar of both wchar_t and char types
52 namespace xml { // anonymous
55 # pragma warning(push)
56 # pragma warning(disable : 4511 4512)
62 void operator()(const T t_) const {
71 struct assign_impl<std::string> {
74 std::string::const_iterator b,
75 std::string::const_iterator e
83 assign_impl<std::string> & operator=(
84 assign_impl<std::string> & rhs
86 assign_impl(std::string & t_)
91 #ifndef BOOST_NO_STD_WSTRING
93 struct assign_impl<std::wstring> {
96 std::wstring::const_iterator b,
97 std::wstring::const_iterator e
105 assign_impl(std::wstring & t_)
112 assign_impl<T> assign_object(T &t){
113 return assign_impl<T>(t);
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;
121 assign_level(tracking_type & tracking_level_)
122 : tracking_level(tracking_level_)
126 template<class String, class Iterator>
127 struct append_string {
129 void operator()(Iterator start, Iterator end) const {
131 typedef boost::archive::iterators::xml_unescape<Iterator> translator;
133 translator(BOOST_MAKE_PFTO_WRAPPER(start)),
134 translator(BOOST_MAKE_PFTO_WRAPPER(end))
137 contents.append(start, end);
139 append_string(String & contents_)
140 : contents(contents_)
144 template<class String>
147 void operator()(const unsigned int char_value) const {
148 const typename String::value_type z = char_value;
151 append_char(String & contents_)
152 : contents(contents_)
156 template<class String, unsigned int c>
159 template<class X, class Y>
160 void operator()(const X & /*x*/, const Y & /*y*/) const {
161 const typename String::value_type z = c;
164 append_lit(String & contents_)
165 : contents(contents_)
173 } // namespace anonymous
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_,
185 boost::io::ios_flags_saver ifs(is);
188 std::basic_string<CharType> arg;
192 typename basic_xml_grammar<CharType>::IStream::int_type
196 val = static_cast<CharType>(result);
199 while(val != delimiter);
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.
206 parse_info<typename std::basic_string<CharType>::iterator>
207 result = boost::spirit::classic::parse(arg.begin(), arg.end(), rule_);
211 template<class CharType>
212 bool basic_xml_grammar<CharType>::parse_start_tag(
213 typename basic_xml_grammar<CharType>::IStream & is
215 rv.class_name.resize(0);
216 return my_parse(is, STag);
219 template<class CharType>
220 bool basic_xml_grammar<CharType>::parse_end_tag(IStream & is) const {
221 return my_parse(is, ETag);
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
230 // putback another dilimiter instead
237 template<class CharType>
238 basic_xml_grammar<CharType>::basic_xml_grammar(){
245 // refactoring to workaround template depth on darwin
246 NameHead = (Letter | '_' | ':');
247 NameTail = *NameChar ;
263 >> Name [xml::assign_object(rv.object_name)]
272 >> Name [xml::assign_object(rv.object_name)]
277 // refactoring to workaround template depth on darwin
278 CharDataChars = +(anychar_p - chset_p(L"&<"));
283 typename std::basic_string<CharType>::const_iterator
288 // slight factoring works around ICE in msvc 6.0
290 str_p(L"&#") >> uint_p [xml::append_char<StringType>(rv.contents)] >> L';'
293 str_p(L"&#x") >> hex_p [xml::append_char<StringType>(rv.contents)] >> L';'
295 CharRef = CharRef1 | CharRef2 ;
297 AmpRef = str_p(L"&")[xml::append_lit<StringType, L'&'>(rv.contents)];
298 LTRef = str_p(L"<")[xml::append_lit<StringType, L'<'>(rv.contents)];
299 GTRef = str_p(L">")[xml::append_lit<StringType, L'>'>(rv.contents)];
300 AposRef = str_p(L"'")[xml::append_lit<StringType, L'\''>(rv.contents)];
301 QuoteRef = str_p(L""")[xml::append_lit<StringType, L'"'>(rv.contents)];
313 L"<" // should be end_p
314 | +(Reference | CharData) >> L"<"
318 str_p(BOOST_ARCHIVE_XML_CLASS_ID()) >> NameTail
321 >> int_p [xml::assign_object(rv.class_id)]
325 ObjectIDAttribute = (
326 str_p(BOOST_ARCHIVE_XML_OBJECT_ID())
328 str_p(BOOST_ARCHIVE_XML_OBJECT_REFERENCE())
334 >> uint_p [xml::assign_object(rv.object_id)]
338 AmpName = str_p(L"&")[xml::append_lit<StringType, L'&'>(rv.class_name)];
339 LTName = str_p(L"<")[xml::append_lit<StringType, L'<'>(rv.class_name)];
340 GTName = str_p(L">")[xml::append_lit<StringType, L'>'>(rv.class_name)];
345 | (anychar_p - chset_p(L"\"")) [xml::append_char<StringType>(rv.class_name)]
353 str_p(BOOST_ARCHIVE_XML_CLASS_NAME())
361 str_p(BOOST_ARCHIVE_XML_TRACKING())
364 >> uint_p [xml::assign_level(rv.tracking_level)]
369 str_p(BOOST_ARCHIVE_XML_VERSION())
372 >> uint_p [xml::assign_object(rv.version)]
393 XMLDeclChars = *(anychar_p - chset_p(L"?>"));
406 DocTypeDeclChars = *(anychar_p - chset_p(L">"));
409 >> str_p(L"<!DOCTYPE")
418 >> Name [xml::assign_object(rv.class_name)]
422 SerializationWrapper =
424 >> str_p(L"<boost_serialization")
426 >> ( (SignatureAttribute >> S >> VersionAttribute)
427 | (VersionAttribute >> S >> SignatureAttribute)
434 template<class CharType>
435 void basic_xml_grammar<CharType>::init(IStream & is){
437 if(! my_parse(is, XMLDecl))
438 boost::serialization::throw_exception(
439 xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
441 if(! my_parse(is, DocTypeDecl))
442 boost::serialization::throw_exception(
443 xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
445 if(! my_parse(is, SerializationWrapper))
446 boost::serialization::throw_exception(
447 xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
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)
455 template<class CharType>
456 bool basic_xml_grammar<CharType>::windup(IStream & is) {
457 return my_parse(is, ETag);
460 } // namespace archive