Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/serialization/src/basic_xml_grammar.ipp @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

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