1/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 2// xml_iarchive_impl.cpp: 3 4// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 5// Distributed under the Boost Software License, Version 1.0. (See 6// 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#include <boost/config.hpp> 12#include <cstring> // memcpy 13#include <cstddef> // NULL 14 15#if defined(BOOST_NO_STDC_NAMESPACE) 16namespace std{ 17 using ::memcpy; 18} // namespace std 19#endif 20 21#ifndef BOOST_NO_CWCHAR 22#include <cwchar> // mbstate_t and mbrtowc 23#if defined(BOOST_NO_STDC_NAMESPACE) 24namespace std{ 25 using ::mbstate_t; 26 using ::mbrtowc; 27 } // namespace std 28#endif 29#endif // BOOST_NO_CWCHAR 30 31#include <boost/detail/workaround.hpp> // RogueWave and Dinkumware 32#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) 33#include <boost/archive/dinkumware.hpp> 34#endif 35 36#include <boost/core/uncaught_exceptions.hpp> 37#include <boost/core/no_exceptions_support.hpp> 38 39#include <boost/archive/xml_archive_exception.hpp> 40#include <boost/archive/iterators/dataflow_exception.hpp> 41#include <boost/archive/basic_xml_archive.hpp> 42#include <boost/archive/xml_iarchive.hpp> 43 44#include "basic_xml_grammar.hpp" 45 46namespace boost { 47namespace archive { 48 49/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 50// implemenations of functions specific to char archives 51 52// wide char stuff used by char archives 53 54#ifndef BOOST_NO_CWCHAR 55#ifndef BOOST_NO_STD_WSTRING 56template<class Archive> 57BOOST_ARCHIVE_DECL void 58xml_iarchive_impl<Archive>::load(std::wstring &ws){ 59 std::string s; 60 bool result = gimpl->parse_string(is, s); 61 if(! result) 62 boost::serialization::throw_exception( 63 xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) 64 ); 65 66 #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) 67 if(NULL != ws.data()) 68 #endif 69 ws.resize(0); 70 std::mbstate_t mbs = std::mbstate_t(); 71 const char * start = s.data(); 72 const char * end = start + s.size(); 73 while(start < end){ 74 wchar_t wc; 75 std::size_t count = std::mbrtowc(&wc, start, end - start, &mbs); 76 if(count == static_cast<std::size_t>(-1)) 77 boost::serialization::throw_exception( 78 iterators::dataflow_exception( 79 iterators::dataflow_exception::invalid_conversion 80 ) 81 ); 82 if(count == static_cast<std::size_t>(-2)) 83 continue; 84 start += count; 85 ws += wc; 86 } 87} 88#endif // BOOST_NO_STD_WSTRING 89 90#ifndef BOOST_NO_INTRINSIC_WCHAR_T 91template<class Archive> 92BOOST_ARCHIVE_DECL void 93xml_iarchive_impl<Archive>::load(wchar_t * ws){ 94 std::string s; 95 bool result = gimpl->parse_string(is, s); 96 if(! result) 97 boost::serialization::throw_exception( 98 xml_archive_exception( 99 xml_archive_exception::xml_archive_parsing_error 100 ) 101 ); 102 103 std::mbstate_t mbs = std::mbstate_t(); 104 const char * start = s.data(); 105 const char * end = start + s.size(); 106 while(start < end){ 107 wchar_t wc; 108 std::size_t length = std::mbrtowc(&wc, start, end - start, &mbs); 109 if(static_cast<std::size_t>(-1) == length) 110 boost::serialization::throw_exception( 111 iterators::dataflow_exception( 112 iterators::dataflow_exception::invalid_conversion 113 ) 114 ); 115 if(static_cast<std::size_t>(-2) == length) 116 continue; 117 118 start += length; 119 *ws++ = wc; 120 } 121 *ws = L'\0'; 122} 123#endif // BOOST_NO_INTRINSIC_WCHAR_T 124 125#endif // BOOST_NO_CWCHAR 126 127template<class Archive> 128BOOST_ARCHIVE_DECL void 129xml_iarchive_impl<Archive>::load(std::string &s){ 130 bool result = gimpl->parse_string(is, s); 131 if(! result) 132 boost::serialization::throw_exception( 133 xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) 134 ); 135} 136 137template<class Archive> 138BOOST_ARCHIVE_DECL void 139xml_iarchive_impl<Archive>::load(char * s){ 140 std::string tstring; 141 bool result = gimpl->parse_string(is, tstring); 142 if(! result) 143 boost::serialization::throw_exception( 144 xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) 145 ); 146 std::memcpy(s, tstring.data(), tstring.size()); 147 s[tstring.size()] = 0; 148} 149 150template<class Archive> 151BOOST_ARCHIVE_DECL void 152xml_iarchive_impl<Archive>::load_override(class_name_type & t){ 153 const std::string & s = gimpl->rv.class_name; 154 if(s.size() > BOOST_SERIALIZATION_MAX_KEY_SIZE - 1) 155 boost::serialization::throw_exception( 156 archive_exception(archive_exception::invalid_class_name) 157 ); 158 char * tptr = t; 159 std::memcpy(tptr, s.data(), s.size()); 160 tptr[s.size()] = '\0'; 161} 162 163template<class Archive> 164BOOST_ARCHIVE_DECL void 165xml_iarchive_impl<Archive>::init(){ 166 gimpl->init(is); 167 this->set_library_version( 168 boost::serialization::library_version_type(gimpl->rv.version) 169 ); 170} 171 172template<class Archive> 173BOOST_ARCHIVE_DECL 174xml_iarchive_impl<Archive>::xml_iarchive_impl( 175 std::istream &is_, 176 unsigned int flags 177) : 178 basic_text_iprimitive<std::istream>( 179 is_, 180 0 != (flags & no_codecvt) 181 ), 182 basic_xml_iarchive<Archive>(flags), 183 gimpl(new xml_grammar()) 184{} 185 186template<class Archive> 187BOOST_ARCHIVE_DECL 188xml_iarchive_impl<Archive>::~xml_iarchive_impl(){ 189 if(boost::core::uncaught_exceptions() > 0) 190 return; 191 if(0 == (this->get_flags() & no_header)){ 192 gimpl->windup(is); 193 } 194} 195} // namespace archive 196} // namespace boost 197