1 #ifndef BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP
2 #define BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP
3 
4 // MS compatible compilers support #pragma once
5 #if defined(_MSC_VER)
6 # pragma once
7 #endif
8 
9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
10 // xml_unescape.hpp
11 
12 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
13 // Use, modification and distribution is subject to the Boost Software
14 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
15 // http://www.boost.org/LICENSE_1_0.txt)
16 
17 //  See http://www.boost.org for updates, documentation, and revision history.
18 
19 #include <boost/config.hpp>
20 #include <boost/detail/workaround.hpp>
21 #include <boost/assert.hpp>
22 
23 #include <boost/serialization/throw_exception.hpp>
24 
25 #include <boost/archive/iterators/unescape.hpp>
26 #include <boost/archive/iterators/dataflow_exception.hpp>
27 
28 namespace boost {
29 namespace archive {
30 namespace iterators {
31 
32 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
33 // replace &??? xml escape sequences with the corresponding characters
34 template<class Base>
35 class xml_unescape
36     : public unescape<xml_unescape<Base>, Base>
37 {
38     friend class boost::iterator_core_access;
39     typedef xml_unescape<Base> this_t;
40     typedef unescape<this_t, Base> super_t;
41     typedef typename boost::iterator_reference<this_t> reference_type;
42 
dereference() const43     reference_type dereference() const {
44         return unescape<xml_unescape<Base>, Base>::dereference();
45     }
46 public:
47     // msvc versions prior to 14.0 crash with and ICE
48     #if BOOST_WORKAROUND(BOOST_MSVC, < 1900)
49         typedef int value_type;
50     #else
51         typedef typename super_t::value_type value_type;
52     #endif
53 
54     void drain_residue(const char *literal);
55     value_type drain();
56 
57     template<class T>
xml_unescape(T start)58     xml_unescape(T start) :
59         super_t(Base(static_cast< T >(start)))
60     {}
61     // intel 7.1 doesn't like default copy constructor
xml_unescape(const xml_unescape & rhs)62     xml_unescape(const xml_unescape & rhs) :
63         super_t(rhs.base_reference())
64     {}
65 };
66 
67 template<class Base>
drain_residue(const char * literal)68 void xml_unescape<Base>::drain_residue(const char * literal){
69     do{
70         if(* literal != * ++(this->base_reference()))
71             boost::serialization::throw_exception(
72                 dataflow_exception(
73                     dataflow_exception::invalid_xml_escape_sequence
74                 )
75             );
76     }
77     while('\0' != * ++literal);
78 }
79 
80 // note key constraint on this function is that can't "look ahead" any
81 // more than necessary into base iterator.  Doing so would alter the base
82 // iterator refenence which would make subsequent iterator comparisons
83 // incorrect and thereby break the composiblity of iterators.
84 template<class Base>
85 typename xml_unescape<Base>::value_type
86 //int
drain()87 xml_unescape<Base>::drain(){
88     value_type retval = * this->base_reference();
89     if('&' != retval){
90         return retval;
91     }
92     retval = * ++(this->base_reference());
93     switch(retval){
94     case 'l': // &lt;
95         drain_residue("t;");
96         retval = '<';
97         break;
98     case 'g': // &gt;
99         drain_residue("t;");
100         retval = '>';
101         break;
102     case 'a':
103         retval = * ++(this->base_reference());
104         switch(retval){
105         case 'p': // &apos;
106             drain_residue("os;");
107             retval = '\'';
108             break;
109         case 'm': // &amp;
110             drain_residue("p;");
111             retval = '&';
112             break;
113         }
114         break;
115     case 'q':
116         drain_residue("uot;");
117         retval = '"';
118         break;
119     }
120     return retval;
121 }
122 
123 } // namespace iterators
124 } // namespace archive
125 } // namespace boost
126 
127 #endif // BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP
128