| #ifndef BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP |
| #define BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP |
| |
| // MS compatible compilers support #pragma once |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| # pragma once |
| #endif |
| |
| /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
| // xml_unescape.hpp |
| |
| // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . |
| // Use, modification and distribution is subject to the Boost Software |
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| // See http://www.boost.org for updates, documentation, and revision history. |
| |
| #include <cassert> |
| |
| #include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME |
| #include <boost/serialization/throw_exception.hpp> |
| #include <boost/serialization/pfto.hpp> |
| |
| #include <boost/archive/iterators/unescape.hpp> |
| #include <boost/archive/iterators/dataflow_exception.hpp> |
| |
| namespace boost { |
| namespace archive { |
| namespace iterators { |
| |
| /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
| // replace &??? xml escape sequences with the corresponding characters |
| template<class Base> |
| class xml_unescape |
| : public unescape<xml_unescape<Base>, Base> |
| { |
| friend class boost::iterator_core_access; |
| typedef xml_unescape<Base> this_t; |
| typedef unescape<this_t, Base> super_t; |
| typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<this_t> reference_type; |
| |
| reference_type dereference() const { |
| return unescape<xml_unescape<Base>, Base>::dereference(); |
| } |
| public: |
| void drain_residue(const char *literal); |
| int drain(); |
| |
| template<class T> |
| xml_unescape(BOOST_PFTO_WRAPPER(T) start) : |
| super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast<T>(start)))) |
| {} |
| // intel 7.1 doesn't like default copy constructor |
| xml_unescape(const xml_unescape & rhs) : |
| super_t(rhs.base_reference()) |
| {} |
| }; |
| |
| template<class Base> |
| void xml_unescape<Base>::drain_residue(const char * literal){ |
| do{ |
| if(* literal != * ++(this->base_reference())) |
| boost::serialization::throw_exception( |
| dataflow_exception( |
| dataflow_exception::invalid_xml_escape_sequence |
| ) |
| ); |
| } |
| while('\0' != * ++literal); |
| } |
| |
| // note key constraint on this function is that can't "look ahead" any |
| // more than necessary into base iterator. Doing so would alter the base |
| // iterator refenence which would make subsequent iterator comparisons |
| // incorrect and thereby break the composiblity of iterators. |
| template<class Base> |
| int xml_unescape<Base>::drain(){ |
| int retval = * this->base_reference(); |
| if('&' != retval){ |
| return retval; |
| } |
| retval = * ++(this->base_reference()); |
| switch(retval){ |
| case 'l': // < |
| drain_residue("t;"); |
| retval = '<'; |
| break; |
| case 'g': // > |
| drain_residue("t;"); |
| retval = '>'; |
| break; |
| case 'a': |
| retval = * ++(this->base_reference()); |
| switch(retval){ |
| case 'p': // ' |
| drain_residue("os;"); |
| retval = '\''; |
| break; |
| case 'm': // & |
| drain_residue("p;"); |
| retval = '&'; |
| break; |
| } |
| break; |
| case 'q': |
| drain_residue("uot;"); |
| retval = '"'; |
| break; |
| } |
| return retval; |
| } |
| |
| } // namespace iterators |
| } // namespace archive |
| } // namespace boost |
| |
| #endif // BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP |