From b7d6668e81e282b242571ca0eb2b22f96631b8a5 Mon Sep 17 00:00:00 2001 From: Robert Ramey Date: Sun, 11 Jul 2004 00:30:45 +0000 Subject: [PATCH] *** empty log message *** [SVN r23430] --- .gitattributes | 96 ++++++ src/basic_archive.cpp | 56 ++++ src/basic_iarchive.cpp | 439 ++++++++++++++++++++++++++++ src/basic_oarchive.cpp | 395 +++++++++++++++++++++++++ src/basic_serializer_map.cpp | 51 ++++ src/basic_xml_archive.cpp | 24 ++ src/binary_iarchive.cpp | 26 ++ src/binary_oarchive.cpp | 26 ++ src/binary_wiarchive.cpp | 35 +++ src/binary_woarchive.cpp | 34 +++ src/codecvt_null.cpp | 87 ++++++ src/extended_type_info.cpp | 179 ++++++++++++ src/extended_type_info_no_rtti.cpp | 21 ++ src/extended_type_info_typeid.cpp | 23 ++ src/polymorphic_iarchive.cpp | 28 ++ src/polymorphic_oarchive.cpp | 28 ++ src/text_iarchive.cpp | 30 ++ src/text_oarchive.cpp | 32 ++ src/text_wiarchive.cpp | 40 +++ src/text_woarchive.cpp | 37 +++ src/utf8_codecvt_facet.cpp | 344 ++++++++++++++++++++++ src/void_cast.cpp | 194 ++++++++++++ src/xbasic_iarchive.cpp | 454 +++++++++++++++++++++++++++++ src/xbasic_oarchive.cpp | 391 +++++++++++++++++++++++++ src/xml_grammar.cpp | 71 +++++ src/xml_iarchive.cpp | 45 +++ src/xml_oarchive.cpp | 34 +++ src/xml_wgrammar.cpp | 253 ++++++++++++++++ src/xml_wiarchive.cpp | 49 ++++ src/xml_woarchive.cpp | 36 +++ 30 files changed, 3558 insertions(+) create mode 100644 .gitattributes create mode 100644 src/basic_archive.cpp create mode 100644 src/basic_iarchive.cpp create mode 100644 src/basic_oarchive.cpp create mode 100644 src/basic_serializer_map.cpp create mode 100644 src/basic_xml_archive.cpp create mode 100644 src/binary_iarchive.cpp create mode 100644 src/binary_oarchive.cpp create mode 100644 src/binary_wiarchive.cpp create mode 100644 src/binary_woarchive.cpp create mode 100644 src/codecvt_null.cpp create mode 100644 src/extended_type_info.cpp create mode 100644 src/extended_type_info_no_rtti.cpp create mode 100644 src/extended_type_info_typeid.cpp create mode 100644 src/polymorphic_iarchive.cpp create mode 100644 src/polymorphic_oarchive.cpp create mode 100644 src/text_iarchive.cpp create mode 100644 src/text_oarchive.cpp create mode 100644 src/text_wiarchive.cpp create mode 100644 src/text_woarchive.cpp create mode 100644 src/utf8_codecvt_facet.cpp create mode 100644 src/void_cast.cpp create mode 100644 src/xbasic_iarchive.cpp create mode 100644 src/xbasic_oarchive.cpp create mode 100644 src/xml_grammar.cpp create mode 100644 src/xml_iarchive.cpp create mode 100644 src/xml_oarchive.cpp create mode 100644 src/xml_wgrammar.cpp create mode 100644 src/xml_wiarchive.cpp create mode 100644 src/xml_woarchive.cpp diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..3e84d7c7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/src/basic_archive.cpp b/src/basic_archive.cpp new file mode 100644 index 00000000..9b920ac7 --- /dev/null +++ b/src/basic_archive.cpp @@ -0,0 +1,56 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_archive.cpp: + +// (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. + +////////////////////////////////////////////////////////////////////// +// +// objects are stored as +// +// class_id* // -1 for a null pointer +// if a new class id +// [ +// exported key - class name* +// tracking level - always/never +// file version +// ] +// +// if tracking +// [ +// object_id +// ] +// +// [ // if a new object id +// data... +// ] +// +// * required only for pointers - optional for objects + +#include + +namespace boost { +namespace archive { + +/////////////////////////////////////////////////////////////////////// +// constants used in archive signature +//This should never ever change. note that is not an std::string +// string. +const char * ARCHIVE_SIGNATURE = "serialization::archive"; + +// this should change if the capabilities are added to the library +// such that archives can be created which can't be read by previous +// versions of this library +// 1 - initial version +// 2 - made address tracking optional +// 3 - numerous changes - can't guarentee compatibility with previous versions +const version_type ARCHIVE_VERSION(3); + +const class_id_type null_pointer_tag(-1); + +} // namespace archive +} // namespace boost diff --git a/src/basic_iarchive.cpp b/src/basic_iarchive.cpp new file mode 100644 index 00000000..bb5b37df --- /dev/null +++ b/src/basic_iarchive.cpp @@ -0,0 +1,439 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_archive.cpp: + +// (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 // msvc 6.0 needs this to suppress warnings + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +using namespace boost::serialization; + +namespace boost { +namespace archive { +namespace detail { + +class basic_iserializer; +class basic_pointer_iserializer; + +class basic_iarchive_impl +{ + friend class basic_iarchive; + ////////////////////////////////////////////////////////////////////// + // information about each serialized object loaded + // indexed on object_id + struct aobject + { + void * address; + class_id_type class_id; + aobject( + void *a, + class_id_type class_id_ + ) : + address(a), + class_id(class_id_) + {} + aobject() : address(NULL), class_id(-2) {} + }; + typedef std::vector object_id_vector_type; + object_id_vector_type object_id_vector; + + ////////////////////////////////////////////////////////////////////// + // used by load object to look up class id given basic_serializer + struct cobject_type + { + const basic_iserializer * bis; + const class_id_type class_id; + cobject_type( + size_t class_id_, + const basic_iserializer & bis_ + ) : + bis(& bis_), + class_id(class_id_) + {} + cobject_type(const cobject_type & rhs) : + bis(rhs.bis), + class_id(rhs.class_id) + {} + // the following cannot be defined because of the const + // member. This will generate a link error if an attempt + // is made to assign. This should never be necessary + cobject_type & operator=(const cobject_type & rhs); + bool operator<(const cobject_type &rhs) const + { + return *bis < *(rhs.bis); + } + }; + typedef std::set cobject_info_set_type; + cobject_info_set_type cobject_info_set; + + ////////////////////////////////////////////////////////////////////// + // information about each serialized class indexed on class_id + class cobject_id + { + public: + cobject_id & operator=(const cobject_id & rhs){ + bis_ptr = rhs.bis_ptr; + bpis_ptr = rhs.bpis_ptr; + file_version = rhs.file_version; + tracking_level = rhs.tracking_level; + initialized = rhs.initialized; + return *this; + } + const basic_iserializer * bis_ptr; + const basic_pointer_iserializer * bpis_ptr; + version_type file_version; + tracking_type tracking_level; + bool initialized; + + cobject_id(const basic_iserializer & bis_) : + bis_ptr(& bis_), + bpis_ptr(NULL), + file_version(0), + tracking_level(track_never), + initialized(false) + {} + cobject_id(const cobject_id &rhs): + bis_ptr(rhs.bis_ptr), + bpis_ptr(rhs.bpis_ptr), + file_version(rhs.file_version), + tracking_level(rhs.tracking_level), + initialized(rhs.initialized) + {} + }; + typedef std::vector cobject_id_vector_type; + cobject_id_vector_type cobject_id_vector; + + // list of objects created by de-serialization. Used to implement + // clean up after exceptions. + class created_pointer_type + { + public: + created_pointer_type( + class_id_type class_id_, + void * address_ + ) : + class_id(class_id_), + address(address_) + {} + created_pointer_type(const created_pointer_type &rhs) : + class_id(rhs.class_id), + address(rhs.address) + {} + created_pointer_type & operator=(const created_pointer_type &){ + assert(false); + return *this; + } + void * get_address() const { + return address; + } + // object to which this item refers + const class_id_type class_id; + private: + void * address; + }; + + std::list created_pointers; + + bool is_object; // pass forward indicater that we're saving an object + // directly rather than result of a pointer + + basic_iarchive_impl() + : is_object(true) + {} + bool + track( + basic_iarchive & ar, + void * & t + ); + void + load_preamble( + basic_iarchive & ar, + cobject_id & co + ); + class_id_type register_type( + const basic_iserializer & bis + ); + + // redirect through virtual functions to load functions for this archive + template + void load(basic_iarchive & ar, T & t){ + ar.vload(t); + } + +public: + void delete_created_pointers(); + class_id_type register_type( + const basic_pointer_iserializer & bpis + ); + void load_object( + basic_iarchive & ar, + void * & t, + const basic_iserializer & bis + ); + const basic_pointer_iserializer * load_pointer( + basic_iarchive & ar, + void * & t, + const basic_pointer_iserializer * bpis, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type + ) + ); +}; + +inline void +basic_iarchive_impl::delete_created_pointers() +{ + while(created_pointers.size() > 0){ + const created_pointer_type & cp = created_pointers.front(); + + // figure out the class of the object to be deleted + // note: extra line used to evand borland issue + const int id = cp.class_id; + const cobject_id & co = cobject_id_vector[id]; + // with the appropriate input serializer, + // delete the indicated object + co.bis_ptr->destroy(cp.get_address()); + created_pointers.pop_front(); + } +} + +inline class_id_type +basic_iarchive_impl::register_type( + const basic_iserializer & bis +){ + cobject_type co(cobject_info_set.size(), bis); + std::pair + result = cobject_info_set.insert(co); + + if(result.second){ + cobject_id_vector.push_back(cobject_id(bis)); + assert(cobject_info_set.size() == cobject_id_vector.size()); + } + const int id = result.first->class_id; + cobject_id & coid = cobject_id_vector[id]; + coid.bpis_ptr = bis.get_bpis_ptr(); + return result.first->class_id; +} + +void +basic_iarchive_impl::load_preamble( + basic_iarchive & ar, + cobject_id & co +){ + if(! co.initialized){ + if(co.bis_ptr->class_info()){ + class_id_optional_type cid; + load(ar, cid); // to be thrown away + load(ar, co.tracking_level); + load(ar, co.file_version); + } + else{ + // override tracking with indicator from class information + co.tracking_level = co.bis_ptr->tracking(); + co.file_version = version_type( + co.bis_ptr->version() + ); + } + co.initialized = true; + } +} + +bool +basic_iarchive_impl::track( + basic_iarchive & ar, + void * & t +){ + object_id_type oid; + load(ar, oid); + + // if its a reference to a old object + if(object_id_type(object_id_vector.size()) > oid){ + // we're done + t = object_id_vector[oid].address; + return false; + } + return true; +} + +inline void +basic_iarchive_impl::load_object( + basic_iarchive & ar, + void * & t, + const basic_iserializer & bis +){ + bool result = true; + const class_id_type cid = register_type(bis); + // note: extra line used to evand borland issue + const int id = cid; + cobject_id & co = cobject_id_vector[id]; + if(is_object){ + load_preamble(ar, co); + // note: extra line used to evand borland issue + const bool b = co.tracking_level; + if(b){ + result = track(ar, t); + if(! result) + return; + object_id_vector.push_back(aobject(t, cid)); + } + } + + // read data if required + state_saver x(is_object); + is_object = true; + (bis.load_object_data)(ar, t, co.file_version); +} + +inline const basic_pointer_iserializer * +basic_iarchive_impl::load_pointer( + basic_iarchive &ar, + void * & t, + const basic_pointer_iserializer * bpis_ptr, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type_ + ) +){ + class_id_type cid; + load(ar, cid); + + if(null_pointer_tag == cid){ + t = NULL; + return bpis_ptr; + } + + // if its a new class type - i.e. never been registered + if(class_id_type(cobject_info_set.size()) <= cid){ + // if its either abstract + if(NULL == bpis_ptr + // or polymorphic + || bpis_ptr->get_basic_serializer().is_polymorphic()){ + // is must have been exported + char key[BOOST_SERIALIZATION_MAX_KEY_SIZE]; + class_name_type class_name(key); + load(ar, class_name); + // if it has a class name + const serialization::extended_type_info *eti = NULL; + if(0 != key[0]) + eti = serialization::extended_type_info::find(key); + if(NULL == eti) + boost::throw_exception( + archive_exception(archive_exception::unregistered_class) + ); + bpis_ptr = (*finder)(*eti); + } + assert(NULL != bpis_ptr); + class_id_type new_cid = register_type(bpis_ptr->get_basic_serializer()); + int i = cid; + cobject_id_vector[i].bpis_ptr = bpis_ptr; + assert(new_cid == cid); + } + int i = cid; + cobject_id & co = cobject_id_vector[i]; + const basic_iserializer * bis_ptr = co.bis_ptr; + bpis_ptr = co.bpis_ptr; + + load_preamble(ar, co); + + bool track_object = true; + // extra line to evade borland issue + const bool b = co.tracking_level; + if(b) + track_object = track(ar, t); + + // if required + if(track_object){ + // read data + state_saver x(is_object); + is_object = false; + + if(bis_ptr->tracking()){ + // predict next object id to be created + const unsigned int i = object_id_vector.size(); + + // because the following operation could move the items + // don't use co after this + object_id_vector.push_back(aobject(t, cid)); + bpis_ptr->load_object_ptr( + ar, + object_id_vector[i].address, + co.file_version + ); + t = object_id_vector[i].address; + // and add to list of created pointers + created_pointers.push_back(created_pointer_type(cid, t)); + } + else{ + bpis_ptr->load_object_ptr(ar, t, co.file_version); + } + assert(NULL != t); + } + + return bpis_ptr; +} + +////////////////////////////////////////////////////////////////////// +// implementation of basic_iarchive functions + +basic_iarchive::basic_iarchive() : + pimpl(new basic_iarchive_impl), + archive_library_version(ARCHIVE_VERSION) +{} + +basic_iarchive::~basic_iarchive() +{ + delete pimpl; +} + +void basic_iarchive::load_object( + void *t, + const basic_iserializer & bis +){ + pimpl->load_object(*this, t, bis); +} + +// load a pointer object +const basic_pointer_iserializer * +basic_iarchive::load_pointer( + void * &t, + const basic_pointer_iserializer * bpis_ptr, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type_ + ) +){ + return pimpl->load_pointer(*this, t, bpis_ptr, finder); +} + +void basic_iarchive::register_basic_serializer(const basic_iserializer & bis){ + pimpl->register_type(bis); +} + +void basic_iarchive::delete_created_pointers() +{ + pimpl->delete_created_pointers(); +} + +} // namespace detail +} // namespace archive +} // namespace boost diff --git a/src/basic_oarchive.cpp b/src/basic_oarchive.cpp new file mode 100644 index 00000000..d9d475d4 --- /dev/null +++ b/src/basic_oarchive.cpp @@ -0,0 +1,395 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_oarchive.cpp: + +// (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 // msvc 6.0 needs this for warning suppression + +#include +#include + +#include +#include +#include + +// including this here to work around an ICC in intel 7.0 +// normally this would be part of basic_oarchive.hpp below. +#include + +#include +#include +#include + +#include +#include + +using namespace boost::serialization; + +namespace boost { +namespace archive { +namespace detail { + +class basic_oserializer; +class basic_pointer_oserializer; + +class basic_oarchive_impl +{ + friend class basic_oarchive; + ////////////////////////////////////////////////////////////////////// + // information about each serialized object saved + // keyed on address, class_id + struct aobject + { + const void * address; + class_id_type class_id; + object_id_type object_id; + + bool operator<(const aobject &rhs) const + { + assert(NULL != address); + assert(NULL != rhs.address); + if( address < rhs.address ) + return true; + if( address > rhs.address ) + return false; + return class_id < rhs.class_id; + } + aobject & operator=(const aobject & rhs) + { + address = rhs.address; + class_id = rhs.class_id; + object_id = rhs.object_id; + return *this; + } + aobject( + const void *a, + class_id_type class_id_, + object_id_type object_id_ + ) : + address(a), + class_id(class_id_), + object_id(object_id_) + {} + aobject() : address(NULL){} + }; + // keyed on class_id, address + typedef std::set object_set_type; + object_set_type object_set; + + ////////////////////////////////////////////////////////////////////// + // information about each serialized class saved + // keyed on type_info + struct cobject_type + { + const basic_oserializer * bos_ptr; + const class_id_type class_id; + bool initialized; + cobject_type( + size_t class_id_, + const basic_oserializer & bos_ + ) : + bos_ptr(& bos_), + class_id(class_id_), + initialized(false) + {} + cobject_type(const basic_oserializer & bos_) + : bos_ptr(& bos_) + {} + cobject_type( + const cobject_type & rhs + ) : + bos_ptr(rhs.bos_ptr), + class_id(rhs.class_id), + initialized(rhs.initialized) + {} + // the following cannot be defined because of the const + // member. This will generate a link error if an attempt + // is made to assign. This should never be necessary + // use this only for lookup argument + cobject_type & operator=(const cobject_type &rhs); + bool operator<(const cobject_type &rhs) const { + return *bos_ptr < *(rhs.bos_ptr); + } + }; + // keyed on type_info + typedef std::set cobject_info_set_type; + cobject_info_set_type cobject_info_set; + + // list of objects initially stored as pointers - used to detect errors + // keyed on object id + std::set stored_pointers; + + bool is_object; // pass forward indicater that we're saving an object + // directly rather than result of a pointer + basic_oarchive_impl() + : is_object(true) + {} + + const cobject_type & + find(const basic_oserializer & bos); + const basic_oserializer * + find(const serialization::extended_type_info &ti) const; + void + save_preamble( + basic_oarchive & ar, + const unsigned int file_version, + bool tracking + ); + bool + track( + basic_oarchive & ar, + const void *t, + const basic_oserializer & bos, + const class_id_type cid, + bool is_object + ); +public: + const cobject_type & + register_type(const basic_oserializer & bos); + void save_object( + basic_oarchive & ar, + const void *t, + const basic_oserializer & bos + ); + void save_pointer( + basic_oarchive & ar, + const void * t, + const basic_pointer_oserializer * bpos + ); + +}; + +////////////////////////////////////////////////////////////////////// +// implementation of basic_oarchive implementation functions + +// given a type_info - find its bos +// return NULL if not found +inline const basic_oserializer * +basic_oarchive_impl::find(const serialization::extended_type_info & ti) const { + class bosarg : public basic_oserializer + { + bool class_info() const { + assert(false); + return false; + } + // returns true if objects should be tracked + bool tracking() const { + assert(false); + return false; + } + // returns class version + unsigned int version() const { + assert(false); + return 0; + } + // returns true if this class is polymorphic + bool is_polymorphic() const{ + assert(false); + return false; + } + void save_object_data( + basic_oarchive & ar, const void * x + ) const { + assert(false); + } + public: + bosarg(const serialization::extended_type_info & type_) : + boost::archive::detail::basic_oserializer(type_) + {} + }; + bosarg bos(ti); + cobject_info_set_type::const_iterator cit + = cobject_info_set.find(cobject_type(bos)); + // it should already have been "registered" - see below + if(cit == cobject_info_set.end()){ + // if an entry is not found in the table it is because a pointer + // of a derived class has been serialized through its base class + // but the derived class hasn't been "registered" + return NULL; + } + // return pointer to the real class + return cit->bos_ptr; +} + +inline const basic_oarchive_impl::cobject_type & +basic_oarchive_impl::find(const basic_oserializer & bos) +{ + std::pair cresult = + cobject_info_set.insert(cobject_type(cobject_info_set.size(), bos)); + return *(cresult.first); +} + +inline const basic_oarchive_impl::cobject_type & +basic_oarchive_impl::register_type( + const basic_oserializer & bos +){ + cobject_type co(cobject_info_set.size(), bos); + std::pair + result = cobject_info_set.insert(co); + return *(result.first); +} + +void +basic_oarchive_impl::save_preamble( + basic_oarchive & ar, + const unsigned int file_version, + bool tracking +){ + ar.vsave(tracking_type(tracking)); + ar.vsave(version_type(file_version)); +} + +// return true if this is a new object and should be serialized +// false if it can be skipped. +bool +basic_oarchive_impl::track( + basic_oarchive & ar, + const void *t, + const basic_oserializer & bos, + const class_id_type cid, + bool is_object +){ + object_id_type oid(object_set.size()); + // lookup to see if this object has already been written to the archive + basic_oarchive_impl::aobject ao(t, cid, oid); + std::pair + aresult = object_set.insert(ao); + oid = aresult.first->object_id; + // if its aready there + if(! aresult.second){ + ar.vsave(object_reference_type(oid)); + // and its an object + if(is_object + // but it was originally stored through a pointer + && stored_pointers.end() != stored_pointers.find(oid)){ + // this has to be a user error. loading such an archive + // would create duplicate objects + boost::throw_exception( + archive_exception(archive_exception::pointer_conflict) + ); + } + return false; + } + ar.vsave(oid); + if(! is_object) + // add to the set of object initially stored through pointers + stored_pointers.insert(oid); + return true; +} + +inline void +basic_oarchive_impl::save_object( + basic_oarchive & ar, + const void *t, + const basic_oserializer & bos +){ + bool new_object = true; + if(is_object){ + const cobject_type & co = register_type(bos); + if(bos.class_info()){ + if( ! co.initialized){ + ar.vsave(class_id_optional_type(co.class_id)); + save_preamble(ar, bos.version(), bos.tracking()); + (const_cast(co)).initialized = true; + } + } + if(bos.tracking()) + new_object = track(ar, t, bos, co.class_id, true); + ar.end_preamble(); + } + if(new_object){ + state_saver x(is_object); + is_object = true; + (bos.save_object_data)(ar, t); + } +} + +// save a pointer to an object instance +inline void +basic_oarchive_impl::save_pointer( + basic_oarchive & ar, + const void * t, + const basic_pointer_oserializer * bpos_ptr +){ + const basic_oserializer & bos = bpos_ptr->get_basic_serializer(); + unsigned int original_count = cobject_info_set.size(); + const cobject_type & co = register_type(bos); + if(! co.initialized){ + ar.vsave(co.class_id); + // if its a previously unregistered class + if((cobject_info_set.size() > original_count)){ + if(bos.is_polymorphic()){ + const serialization::extended_type_info *eti = & bos.type; + const char * key = NULL; + if(NULL != eti) + key = eti->key; + if(NULL != key) + // write out the external class identifier + ar.vsave(class_name_type(key)); + else + // without an external class name + // we won't be able to de-serialize it so bail now + boost::throw_exception( + archive_exception(archive_exception::unregistered_class) + ); + } + } + if(bos.class_info()) + save_preamble(ar, bos.version(), bos.tracking()); + (const_cast(co)).initialized = true; + } + else{ + ar.vsave(class_id_reference_type(co.class_id)); + } + + bool result = true; + if(bos.tracking()) + result = track(ar, t, bos, co.class_id, false); + + ar.end_preamble(); + + if(result){ + state_saver x(is_object); + is_object = false; + bpos_ptr->save_object_ptr(ar, t); + } +} + +////////////////////////////////////////////////////////////////////// +// implementation of basic_oarchive functions + +basic_oarchive::basic_oarchive() + : pimpl(new basic_oarchive_impl) +{} + +basic_oarchive::~basic_oarchive() +{ + delete pimpl; +} + +void basic_oarchive::save_object( + const void *x, + const basic_oserializer & bos +){ + pimpl->save_object(*this, x, bos); +} + +void basic_oarchive::save_pointer( + const void * t, + const basic_pointer_oserializer * bpos_ptr +){ + pimpl->save_pointer(*this, t, bpos_ptr); +} + +void basic_oarchive::register_basic_serializer(const basic_oserializer & bos){ + pimpl->register_type(bos); +} + +} // namespace detail +} // namespace archive +} // namespace boost diff --git a/src/basic_serializer_map.cpp b/src/basic_serializer_map.cpp new file mode 100644 index 00000000..9fdc8342 --- /dev/null +++ b/src/basic_serializer_map.cpp @@ -0,0 +1,51 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// serializer_map.cpp: + +// (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. + +#if (defined _MSC_VER) && (_MSC_VER == 1200) +# pragma warning (disable : 4786) // too long name, harmless warning +#endif + +#include + +#include +#include + +namespace boost { + namespace serialization { + class extended_type_info; + } +namespace archive { +namespace detail { + +bool basic_serializer_map::insert(const basic_serializer * bs){ + return map.insert(bs).second; +} + +class basic_serializer_arg : public basic_serializer { +public: + basic_serializer_arg(const serialization::extended_type_info & eti) : + basic_serializer(eti) + {} +}; + +const basic_serializer * basic_serializer_map::tfind( + const boost::serialization::extended_type_info & type_ +) const { + const basic_serializer_arg bs(type_); + map_type::const_iterator it; + it = map.find(& bs); + if(it == map.end()) + return NULL; + return *it; +} + +} // namespace detail +} // namespace archive +} // namespace boost diff --git a/src/basic_xml_archive.cpp b/src/basic_xml_archive.cpp new file mode 100644 index 00000000..e7f1d305 --- /dev/null +++ b/src/basic_xml_archive.cpp @@ -0,0 +1,24 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_archive.cpp: + +// (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. + +namespace boost { +namespace archive { + +const char * OBJECT_ID = "object_id"; +const char * OBJECT_REFERENCE = "object_id_reference"; +const char * CLASS_ID = "class_id"; +const char * CLASS_ID_REFERENCE = "class_id_reference"; +const char * CLASS_NAME = "class_name"; +const char * TRACKING = "tracking_level"; +const char * VERSION = "version"; +const char * SIGNATURE = "signature"; + +}// namespace archive +}// namespace boost diff --git a/src/binary_iarchive.cpp b/src/binary_iarchive.cpp new file mode 100644 index 00000000..8896fc05 --- /dev/null +++ b/src/binary_iarchive.cpp @@ -0,0 +1,26 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_iarchive.cpp: + +// (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 +#include +#include + +// explicitly instantiate for this type of text stream +#include + +namespace boost { +namespace archive { + +template class basic_binary_iprimitive ; +template class binary_iarchive_impl ; +template class detail::archive_pointer_iserializer ; + +} // namespace archive +} // namespace boost diff --git a/src/binary_oarchive.cpp b/src/binary_oarchive.cpp new file mode 100644 index 00000000..7cd99bab --- /dev/null +++ b/src/binary_oarchive.cpp @@ -0,0 +1,26 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_oarchive.cpp: + +// (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 +#include + +#include +#include + +namespace boost { +namespace archive { + +// explicitly instantiate for this type of binary stream +template class basic_binary_oprimitive ; +template class binary_oarchive_impl ; +template class detail::archive_pointer_oserializer ; + +} // namespace archive +} // namespace boost diff --git a/src/binary_wiarchive.cpp b/src/binary_wiarchive.cpp new file mode 100644 index 00000000..a6ca1a80 --- /dev/null +++ b/src/binary_wiarchive.cpp @@ -0,0 +1,35 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_wiarchive.cpp: + +// (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 + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +BOOST_STATIC_ASSERT(false); +#else + +#include + +#include +#include + +namespace boost { +namespace archive { + +// explicitly instantiate for this type of text stream +template class basic_binary_iprimitive ; +template class binary_wiarchive_impl ; +template class detail::archive_pointer_iserializer ; + +} // namespace archive +} // namespace boost + +#endif // BOOST_NO_STD_WSTREAMBUF + diff --git a/src/binary_woarchive.cpp b/src/binary_woarchive.cpp new file mode 100644 index 00000000..ce4654a8 --- /dev/null +++ b/src/binary_woarchive.cpp @@ -0,0 +1,34 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_woarchive.cpp: + +// (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 + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +BOOST_STATIC_ASSERT(false); +#else + +#include + +#include +#include + +namespace boost { +namespace archive { + +// explicitly instantiate for this type of text stream +template class basic_binary_oprimitive ; +template class binary_woarchive_impl ; +template class detail::archive_pointer_oserializer ; + +} // namespace archive +} // namespace boost + +#endif // BOOST_NO_STD_WSTREAMBUF diff --git a/src/codecvt_null.cpp b/src/codecvt_null.cpp new file mode 100644 index 00000000..f63a1a1b --- /dev/null +++ b/src/codecvt_null.cpp @@ -0,0 +1,87 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// codecvt_null.cpp + +// Copyright © 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). +// 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) + +#include + +// codecvt implementation for passing wchar_t objects to char output +// without any translation whatever. Used to implement binary output +// of wchar_t objects. + +namespace boost { +namespace archive { + +std::codecvt_base::result +codecvt_null::do_out( + mbstate_t & state, + const wchar_t * first1, + const wchar_t * last1, + const wchar_t * & next1, + char * first2, + char * last2, + char * & next2 +) const { + for(;first1 != last1; ++first1){ + // Per std::22.2.1.5.2/2, we can store no more that + // last2-first2 characters. If we need to more encode + // next internal char type, return 'partial'. + if(static_cast(sizeof(wchar_t)) > (last2 - first2)){ + next1 = first1; + next2 = first2; + return std::codecvt_base::partial; + } + unsigned int i; + for(i = sizeof(wchar_t); i > 0;) + *first2++ = (* first1 >> (8 * --i)) & 0xff; + } + next1 = first1; + next2 = first2; + return std::codecvt_base::ok; +} + +std::codecvt_base::result +codecvt_null::do_in( + mbstate_t & state, + const char * first1, + const char * last1, + const char * & next1, + wchar_t * first2, + wchar_t * last2, + wchar_t * & next2 +) const { + // Process input characters until we've run of them, + // or the number of remaining characters is not + // enough to construct another output character, + // or we've run out of place for output characters. + while(first2 != last2){ + // Have we converted all input characters? + // Return with 'ok', if so. + if (first1 == last1) + break; + // Do we have less input characters than needed + // for a single output character? + if(static_cast(sizeof(wchar_t)) > (last1 - first1)){ + next1 = first1; + next2 = first2; + return std::codecvt_base::partial; + } + *first2 = static_cast(*first1++); + int i = sizeof(wchar_t) - 1; + do{ + *first2 <<= 8; + *first2 |= static_cast(*first1++); + }while(--i > 0); + ++first2; + } + next1 = first1; + next2 = first2; + return std::codecvt_base::ok; +} + +} // namespace archive +} // namespace boost diff --git a/src/extended_type_info.cpp b/src/extended_type_info.cpp new file mode 100644 index 00000000..00dfeb6e --- /dev/null +++ b/src/extended_type_info.cpp @@ -0,0 +1,179 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// extended_type_info.cpp: implementation for portable version of type_info + +// (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 // msvc needs this to suppress warning + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ using ::strcmp; } +#endif + +#include +#include + +#include + +namespace boost { +namespace serialization { + +namespace { // anonymous + +struct type_info_compare +{ + bool + operator()(const extended_type_info * lhs, const extended_type_info * rhs) const + { + return *lhs < *rhs; + } +}; +struct key_compare +{ + bool + operator()(const extended_type_info * lhs, const extended_type_info * rhs) const + { + // shortcut to exploit string pooling + if(lhs->key == rhs->key) + return false; + if(NULL == lhs->key) + return true; + if(NULL == rhs->key) + return false; + return std::strcmp(lhs->key, rhs->key) < 0; + } +}; + +// use static local variables to ensure that collections are +// initialized before being used. +typedef std::set tkmap_type; +static tkmap_type & +tkmap(){ + static tkmap_type map; + return map; +} + +typedef std::set ktmap_type; +static ktmap_type & +ktmap(){ + static ktmap_type map; + return map; +} + +} // anonymous + +void extended_type_info::self_register() +{ + tkmap().insert(this); +} + +void extended_type_info::key_register(const char *key_) { + if(NULL == key_) + return; + key = key_; + ktmap().insert(this); +} + +namespace { + +class extended_type_info_arg : public extended_type_info +{ +public: + extended_type_info_arg(const char * search_key_) + : extended_type_info(NULL) + { + key = search_key_; + } + virtual bool + less_than(const extended_type_info &rhs) const + { + assert(false); + return false; // to prevent a syntax error + } + virtual bool + equal_to(const extended_type_info &rhs) const{ + assert(false); + return false; // to prevent a syntax error + } + virtual bool + not_equal_to(const extended_type_info &rhs) const{ + assert(false); + return false; // to prevent a syntax error + } +}; +} // anonymous + +const extended_type_info * extended_type_info::find(const char *key) +{ + + extended_type_info_arg arg(key); + ktmap_type::const_iterator it; + it = ktmap().find(&arg); + if(it == ktmap().end()) + return NULL; + + return *it; +} + +const extended_type_info * extended_type_info::find(const extended_type_info * t) +{ + tkmap_type::const_iterator it; + it = tkmap().find(t); + if(it == tkmap().end()) + return NULL; + return *it; +} + +namespace { // anonymous +int type_info_key_cmp( + const extended_type_info & lhs, + const extended_type_info & rhs +) { + if(lhs.type_info_key == rhs.type_info_key) + return 0; + //return strcmp(lhs.type_info_key, rhs.type_info_key); + // all we require is that the type_info_key be unique + // so just compare the addresses + return lhs.type_info_key < rhs.type_info_key ? -1 : 1; +} +} // anonymous + +bool operator<( + const extended_type_info &lhs, + const extended_type_info &rhs +){ + int i = type_info_key_cmp(lhs, rhs); + if(i < 0) + return true; + if(i > 0) + return false; + return lhs.less_than(rhs); +} + +bool operator==( + const extended_type_info &lhs, + const extended_type_info &rhs +){ + int i = type_info_key_cmp(lhs, rhs); + if(i != 0) + return false; + return lhs.equal_to(rhs); +} + +bool operator!=( + const extended_type_info &lhs, + const extended_type_info &rhs +){ + int i = type_info_key_cmp(lhs, rhs); + if(i != 0) + return true; + return lhs.not_equal_to(rhs); +} + +} // namespace serialization +} // namespace boost diff --git a/src/extended_type_info_no_rtti.cpp b/src/extended_type_info_no_rtti.cpp new file mode 100644 index 00000000..a7b5a025 --- /dev/null +++ b/src/extended_type_info_no_rtti.cpp @@ -0,0 +1,21 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// extended_type_info_no_rtti.cpp: specific implementation of type info +// that is NOT based on typeid + +// (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 + +namespace boost { +namespace serialization { + +const char * extended_type_info_no_rtti_base::type_info_key + = "extended_type_info_no_rtti"; + +} // namespace serialization +} // namespace boost diff --git a/src/extended_type_info_typeid.cpp b/src/extended_type_info_typeid.cpp new file mode 100644 index 00000000..33a0a6eb --- /dev/null +++ b/src/extended_type_info_typeid.cpp @@ -0,0 +1,23 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// extended_type_info_typeid.cpp: specific implementation of type info +// that is based on typeid + +// (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 + +namespace boost { +namespace serialization { +namespace detail { + +const char * extended_type_info_typeid_0::type_info_key + = "extended_type_info_typeid"; + +} // namespace detail +} // namespace serialization +} // namespace boost diff --git a/src/polymorphic_iarchive.cpp b/src/polymorphic_iarchive.cpp new file mode 100644 index 00000000..968ae19f --- /dev/null +++ b/src/polymorphic_iarchive.cpp @@ -0,0 +1,28 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_text_iarchive.cpp: + +// (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. + +#if (defined _MSC_VER) && (_MSC_VER == 1200) +# pragma warning (disable : 4786) // too long name, harmless warning +#endif + +#include + +#include + +// explicitly instantiate for this type of text stream +#include + +namespace boost { +namespace archive { + +template class detail::archive_pointer_iserializer ; + +} // namespace serialization +} // namespace boost diff --git a/src/polymorphic_oarchive.cpp b/src/polymorphic_oarchive.cpp new file mode 100644 index 00000000..958d3f42 --- /dev/null +++ b/src/polymorphic_oarchive.cpp @@ -0,0 +1,28 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_text_oarchive.cpp: + +// (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. + +#if (defined _MSC_VER) && (_MSC_VER == 1200) +# pragma warning (disable : 4786) // too long name, harmless warning +#endif + +#include + +#include + +// explicitly instantiate for this type of text stream +#include + +namespace boost { +namespace archive { + +template class detail::archive_pointer_oserializer ; + +} // namespace serialization +} // namespace boost diff --git a/src/text_iarchive.cpp b/src/text_iarchive.cpp new file mode 100644 index 00000000..3612727f --- /dev/null +++ b/src/text_iarchive.cpp @@ -0,0 +1,30 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_iarchive.cpp: + +// (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 + +#include + +// explicitly instantiate for this type of text stream +#include +#include +#include +#include + +namespace boost { +namespace archive { + +template class basic_text_iprimitive ; +template class basic_text_iarchive ; +template class text_iarchive_impl ; +template class detail::archive_pointer_iserializer ; + +} // namespace archive +} // namespace boost diff --git a/src/text_oarchive.cpp b/src/text_oarchive.cpp new file mode 100644 index 00000000..4264b5ee --- /dev/null +++ b/src/text_oarchive.cpp @@ -0,0 +1,32 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_oarchive.cpp: + +// (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. + +#if (defined _MSC_VER) && (_MSC_VER == 1200) +# pragma warning (disable : 4786) // too long name, harmless warning +#endif + +#include + +#include + +// explicitly instantiate for this type of text stream +#include +#include +#include + +namespace boost { +namespace archive { + +template class basic_text_oprimitive ; +template class text_oarchive_impl ; +template class detail::archive_pointer_oserializer ; + +} // namespace serialization +} // namespace boost diff --git a/src/text_wiarchive.cpp b/src/text_wiarchive.cpp new file mode 100644 index 00000000..fafff70d --- /dev/null +++ b/src/text_wiarchive.cpp @@ -0,0 +1,40 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_wiarchive.cpp: + +// (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 + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +BOOST_STATIC_ASSERT(false); +#else + +#include +#include + +// explicitly instantiate for this type of text stream +#include +#include +#include +#include + +namespace boost { +namespace archive { + +template class basic_text_iprimitive ; +template class basic_text_iarchive ; +template class text_wiarchive_impl ; +template class detail::archive_pointer_iserializer ; + +} // namespace archive +} // namespace boost + +#endif // BOOST_NO_STD_WSTREAMBUF + + diff --git a/src/text_woarchive.cpp b/src/text_woarchive.cpp new file mode 100644 index 00000000..142e7645 --- /dev/null +++ b/src/text_woarchive.cpp @@ -0,0 +1,37 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_woarchive.cpp: + +// (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 + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +BOOST_STATIC_ASSERT(false); +#else + +#include + +#include + +// explicitly instantiate for this type of text stream +#include +#include +#include + +namespace boost { +namespace archive { + +template class basic_text_oprimitive ; +template class text_woarchive_impl ; +template class detail::archive_pointer_oserializer ; + +} // namespace archive +} // namespace boost + +#endif // BOOST_NO_STD_WSTREAMBUF diff --git a/src/utf8_codecvt_facet.cpp b/src/utf8_codecvt_facet.cpp new file mode 100644 index 00000000..db4dc502 --- /dev/null +++ b/src/utf8_codecvt_facet.cpp @@ -0,0 +1,344 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// utf8_codecvt_facet.cpp + +// Copyright © 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). +// 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) + +//#include // for multi-byte converson routines + +#include +#include +#include + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation for wchar_t + +// Translate incoming UTF-8 into UCS-4 +std::codecvt_base::result utf8_codecvt_facet_wchar_t::do_in( + mbstate_t& state, + const char * from, + const char * from_end, + const char * & from_next, + wchar_t * to, + wchar_t * to_end, + wchar_t * & to_next +) const { + // Basic algorithm: The first octet determines how many + // octets total make up the UCS-4 character. The remaining + // "continuing octets" all begin with "10". To convert, subtract + // the amount that specifies the number of octets from the first + // octet. Subtract 0x80 (1000 0000) from each continuing octet, + // then mash the whole lot together. Note that each continuing + // octet only uses 6 bits as unique values, so only shift by + // multiples of 6 to combine. + while (from != from_end && to != to_end) { + + // Error checking on the first octet + if (invalid_leading_octet(*from)){ + from_next = from; + to_next = to; + return std::codecvt_base::error; + } + + // The first octet is adjusted by a value dependent upon + // the number of "continuing octets" encoding the character + const int cont_octet_count = get_cont_octet_count(*from); + const wchar_t octet1_modifier_table[] = { + 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc + }; + + // The unsigned char conversion is necessary in case char is + // signed (I learned this the hard way) + wchar_t ucs_result = + (unsigned char)(*from++) - octet1_modifier_table[cont_octet_count]; + + // Invariants : + // 1) At the start of the loop, 'i' continuing characters have been + // processed + // 2) *from points to the next continuing character to be processed. + int i = 0; + while(i != cont_octet_count && from != from_end) { + + // Error checking on continuing characters + if (invalid_continuing_octet(*from)) { + from_next = from; + to_next = to; + return std::codecvt_base::error; + } + + ucs_result *= (1 << 6); + + // each continuing character has an extra (10xxxxxx)b attached to + // it that must be removed. + ucs_result += (unsigned char)(*from++) - 0x80; + ++i; + } + + // If the buffer ends with an incomplete unicode character... + if (from == from_end && i != cont_octet_count) { + // rewind "from" to before the current character translation + from_next = from - (i+1); + to_next = to; + return std::codecvt_base::partial; + } + *to++ = ucs_result; + } + from_next = from; + to_next = to; + + // Were we done converting or did we run out of destination space? + if(from == from_end) return std::codecvt_base::ok; + else return std::codecvt_base::partial; +} + +std::codecvt_base::result utf8_codecvt_facet_wchar_t::do_out( + mbstate_t & state, + const wchar_t * from, + const wchar_t * from_end, + const wchar_t * & from_next, + char * to, + char * to_end, + char * & to_next +) const +{ + // RG - consider merging this table with the other one + const wchar_t octet1_modifier_table[] = { + 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc + }; + + while (from != from_end && to != to_end) { + + // Check for invalid UCS-4 character + if (*from > std::numeric_limits::max()) { + from_next = from; + to_next = to; + return std::codecvt_base::error; + } + + int cont_octet_count = get_cont_octet_out_count(*from); + + // RG - comment this formula better + int shift_exponent = (cont_octet_count) * 6; + + // Process the first character + *to++ = octet1_modifier_table[cont_octet_count] + + (unsigned char)(*from / (1 << shift_exponent)); + + // Process the continuation characters + // Invariants: At the start of the loop: + // 1) 'i' continuing octets have been generated + // 2) '*to' points to the next location to place an octet + // 3) shift_exponent is 6 more than needed for the next octet + int i = 0; + while (i != cont_octet_count && to != to_end) { + shift_exponent -= 6; + *to++ = 0x80 + ((*from / (1 << shift_exponent)) % (1 << 6)); + ++i; + } + // If we filled up the out buffer before encoding the character + if(to == to_end && i != cont_octet_count) { + from_next = from; + to_next = to - (i+1); + return std::codecvt_base::partial; + } + *from++; + } + from_next = from; + to_next = to; + // Were we done or did we run out of destination space + if(from == from_end) return std::codecvt_base::ok; + else return std::codecvt_base::partial; +} + +// How many char objects can I process to get <= max_limit +// wchar_t objects? +int utf8_codecvt_facet_wchar_t::do_length( + const mbstate_t &, + const char * from, + const char * from_end, + size_t max_limit +) const throw() +{ + // RG - this code is confusing! I need a better way to express it. + // and test cases. + + // Invariants: + // 1) last_octet_count has the size of the last measured character + // 2) char_count holds the number of characters shown to fit + // within the bounds so far (no greater than max_limit) + // 3) from_next points to the octet 'last_octet_count' before the + // last measured character. + int last_octet_count=0; + size_t char_count = 0; + const char* from_next = from; + // Use "<" because the buffer may represent incomplete characters + while (from_next+last_octet_count <= from_end && char_count <= max_limit) { + from_next += last_octet_count; + last_octet_count = (get_octet_count(*from_next)); + ++char_count; + } + return from_next-from_end; +} + +unsigned int utf8_codecvt_facet_wchar_t::get_octet_count( + unsigned char lead_octet +){ + // if the 0-bit (MSB) is 0, then 1 character + if (lead_octet <= 0x7f) return 1; + + // Otherwise the count number of consecutive 1 bits starting at MSB + assert(0xc0 <= lead_octet && lead_octet <= 0xfd); + + if (0xc0 <= lead_octet && lead_octet <= 0xdf) return 2; + else if (0xe0 <= lead_octet && lead_octet <= 0xef) return 3; + else if (0xf0 <= lead_octet && lead_octet <= 0xf7) return 4; + else if (0xf8 <= lead_octet && lead_octet <= 0xfb) return 5; + else return 6; +} + +namespace { +template +int get_cont_octet_out_count_impl(wchar_t word){ + if (word < 0x80) { + return 0; + } + if (word < 0x800) { + return 1; + } + return 2; +} + +// note the following code will generate on some platforms where +// wchar_t is defined as UCS2. The warnings are superfluous as +// the specialization is never instantitiated with such compilers. +template<> +int get_cont_octet_out_count_impl<4>(wchar_t word){ + if (word < 0x80) { + return 0; + } + if (word < 0x800) { + return 1; + } + if (word < 0x10000) { + return 2; + } + if (word < 0x200000) { + return 3; + } + if (word < 0x4000000) { + return 4; + } + return 5; +} + +} // namespace anonymous + +// How many "continuing octets" will be needed for this word +// == total octets - 1. +int utf8_codecvt_facet_wchar_t::get_cont_octet_out_count( + wchar_t word +) const { + return get_cont_octet_out_count_impl(word); +} + +#if 0 // not used? +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation for char + +std::codecvt_base::result utf8_codecvt_facet_char::do_in( + mbstate_t & state, + const char * from, + const char * from_end, + const char * & from_next, + char * to, + char * to_end, + char * & to_next +) const +{ + while(from_next < from_end){ + wchar_t w; + wchar_t *wnext = & w; + utf8_codecvt_facet_wchar_t::result ucs4_result; + ucs4_result = base_class::do_in( + state, + from, from_end, from_next, + wnext, wnext + 1, wnext + ); + if(codecvt_base::ok != ucs4_result) + return ucs4_result; + // if the conversion succeeds. + int length = std::wctomb(to_next, w); + assert(-1 != length); + to_next += length; + } + return codecvt_base::ok; +} + +std::codecvt_base::result utf8_codecvt_facet_char::do_out( + mbstate_t & state, + const char * from, + const char * from_end, + const char * & from_next, + char * to, + char * to_end, + char * & to_next +) const +{ + while(from_next < from_end){ + wchar_t w; + int result = std::mbtowc(&w, from_next, MB_LENGTH_MAX); + assert(-1 != result); + from_next += result; + utf8_codecvt_facet_wchar_t::result ucs4_result; + + const wchar_t *wptr = & w; + ucs4_result = base_class::do_out( + state, + wptr, wptr+1, wptr, + to_next, to_end, to_next + ); + if(codecvt_base::ok != ucs4_result) + return ucs4_result; + } + return codecvt_base::ok; +} + +// How many bytes objects can I process to get <= max_limit +// char objects? +int utf8_codecvt_facet_char::do_length( + const utf8_codecvt_facet_wchar_t::mbstate_t & initial_state, + const char * from_next, + const char * from_end, + size_t max_limit +) const +{ + int total_length = 0; + const char *from = from_next; + mbstate_t state = initial_state; + while(from_next < from_end){ + wchar_t w; + wchar_t *wnext = & w; + utf8_codecvt_facet_wchar_t::result ucs4_result; + ucs4_result = base_class::do_in( + state, + from_next, from_end, from_next, + wnext, wnext + 1, wnext + ); + + if(codecvt_base::ok != ucs4_result) + break; + + char carray[MB_LENGTH_MAX]; + size_t count = wctomb(carray, w); + if(count > max_limit) + break; + + max_limit -= count; + total_length = from_next - from; + } + return total_length; +} +#endif diff --git a/src/void_cast.cpp b/src/void_cast.cpp new file mode 100644 index 00000000..0db0c52a --- /dev/null +++ b/src/void_cast.cpp @@ -0,0 +1,194 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// void_cast.cpp: implementation of run-time casting of void pointers + +// (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 // msvc needs this to suppress warning + +// STL +#include +#include +#include +#include + +// BOOST +#include +#include + +namespace boost { +namespace serialization { + +namespace void_cast_detail { + +struct void_caster_compare +{ + bool + operator()( void_caster const* lhs, void_caster const* rhs ) const + { + if( lhs->m_derived_type < rhs->m_derived_type ) + return true; + + if( rhs->m_derived_type < lhs->m_derived_type) + return false; + + if( lhs->m_base_type < rhs->m_base_type ) + return true; + + return false; + } +}; + +struct void_caster_registry +{ + typedef std::set set_type; + typedef set_type::iterator iterator; + set_type m_set; +}; + +// note: using accessing through this singleton guarentees that the +// constructor for the set is invoked before any entries are added to it. +void_caster_registry & +global_registry() +{ + static void_caster_registry instance; + return instance; +} + +void +void_caster::self_register() +{ + // from/to pairs are registered when created + // and there should only be one instance of each pair + if(! global_registry().m_set.insert(this).second) + assert(false); +} + +} // void_cast_detail + +// Given a void *, assume that it really points to an instance of one type +// and alter it so that it would point to an instance of a related type. +// Return the altered pointer. If there exists no sequence of casts that +// can transform from_type to to_type, return a NULL. +const void * +void_upcast( + const extended_type_info & derived_type, + const extended_type_info & base_type, + const void * t, + bool top +){ + // same types - trivial case + if (derived_type == base_type) + return t; + + // check to see if base/derived pair is found in the registry + void_cast_detail::void_caster ca(derived_type, base_type ); + void_cast_detail::void_caster_registry::iterator it; + it = void_cast_detail::global_registry().m_set.find( &ca ); + + // if so + if (it != void_cast_detail::global_registry().m_set.end()) + // we're done + return (*it)->upcast(t); + + const void * t_new = NULL; + // try to find a chain that gives us what we want + for( + it = void_cast_detail::global_registry().m_set.begin(); + it != void_cast_detail::global_registry().m_set.end(); + ++it + ){ + // if the current candidate doesn't cast to the desired target type + if ((*it)->m_base_type == base_type){ + // if the current candidate casts from the desired source type + if ((*it)->m_derived_type == derived_type){ + // we have a base/derived match - we're done + // cast to the intermediate type + t_new = (*it)->upcast(t); + break; + } + t_new = void_upcast(derived_type, (*it)->m_derived_type, t, false); + if (NULL != t_new){ + t_new = (*it)->upcast(t_new); + if(top){ + // register the this pair so we will have to go through + // keep this expensive search process more than once. + new void_cast_detail::void_caster_derived( + derived_type, + base_type, + static_cast(t_new) - static_cast(t) + ); + } + break; + } + } + } + return t_new; +} + +const void * +void_downcast( + const extended_type_info & derived_type, + const extended_type_info & base_type, + const void * t, + bool top +){ + // same types - trivial case + if (derived_type == base_type) + return t; + + // check to see if base/derived pair is found in the registry + void_cast_detail::void_caster ca(derived_type, base_type ); + void_cast_detail::void_caster_registry::iterator it; + it = void_cast_detail::global_registry().m_set.find( &ca ); + + // if so + if (it != void_cast_detail::global_registry().m_set.end()) + // we're done + return (*it)->downcast(t); + + const void * t_new = NULL; + // try to find a chain that gives us what we want + for( + it = void_cast_detail::global_registry().m_set.begin(); + it != void_cast_detail::global_registry().m_set.end(); + ++it + ){ + // if the current candidate doesn't cast from the desired target type + if ((*it)->m_base_type == base_type){ + // if the current candidate casts to the desired source type + if ((*it)->m_derived_type == derived_type){ + // we have a base/derived match - we're done + // cast to the intermediate type + t_new = (*it)->downcast(t); + break; + } + t_new = void_downcast(derived_type, (*it)->m_derived_type, t, false); + if (NULL != t_new){ + t_new = (*it)->downcast(t_new); + if(top){ + // register the this pair so we will have to go through + // keep this expensive search process more than once. + new void_cast_detail::void_caster_derived( + derived_type, + base_type, + static_cast(t) - static_cast(t_new) + ); + } + break; + } + } + } + return t_new; +} + + +} // namespace serialization +} // namespace boost + +// EOF diff --git a/src/xbasic_iarchive.cpp b/src/xbasic_iarchive.cpp new file mode 100644 index 00000000..860e35c1 --- /dev/null +++ b/src/xbasic_iarchive.cpp @@ -0,0 +1,454 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_archive.cpp: + +// (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 // msvc 6.0 needs this to suppress warnings + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +using namespace boost::serialization; + +namespace boost { +namespace archive { +namespace detail { + +class basic_iarchive_impl +{ + friend class basic_iarchive; + ////////////////////////////////////////////////////////////////////// + // information about each serialized object loaded + // indexed on object_id + struct aobject + { + void * address; + class_id_type class_id; + aobject( + void *a, + class_id_type class_id_ + ) : + address(a), + class_id(class_id_) + {} + aobject() : address(NULL), class_id(-2) {} + }; + typedef std::vector object_id_vector_type; + object_id_vector_type object_id_vector; + + ////////////////////////////////////////////////////////////////////// + // used by load object to look up class id given basic_serializer + class cobject_type + { + private: + friend class basic_iarchive; + const basic_iserializer * bis; + public: + const class_id_type class_id; + cobject_type( + size_t class_id_, + const basic_iserializer & bis_ + ) : + bis(& bis_), + class_id(class_id_) + {} + cobject_type(const cobject_type & rhs) : + bis(rhs.bis), + class_id(rhs.class_id) + {} + // the following cannot be defined because of the const + // member. This will generate a link error if an attempt + // is made to assign. This should never be necessary + cobject_type & operator=(const cobject_type & rhs); + bool operator<(const cobject_type &rhs) const + { + return *bis < *(rhs.bis); + } + }; + typedef std::set cobject_info_set_type; + cobject_info_set_type cobject_info_set; + + ////////////////////////////////////////////////////////////////////// + // information about each serialized class indexed on class_id + class cobject_id + { + public: + cobject_id & operator=(const cobject_id & rhs){ + bis_ptr = rhs.bis_ptr; + bpis_ptr = rhs.bpis_ptr; + file_version = rhs.file_version; + tracking_level = rhs.tracking_level; + initialized = rhs.initialized; + return *this; + } + const basic_iserializer * bis_ptr; +// const basic_pointer_iserializer * bpis_ptr; + version_type file_version; + tracking_type tracking_level; + bool initialized; + + cobject_id(const basic_iserializer & bis_) : + bis_ptr(& bis_), +// bpis_ptr(NULL), + file_version(0), + tracking_level(track_never), + initialized(false) + {} + cobject_id(const cobject_id &rhs): + bis_ptr(rhs.bis_ptr), + // bpis_ptr(rhs.bpis_ptr), + file_version(rhs.file_version), + tracking_level(rhs.tracking_level), + initialized(rhs.initialized) + {} + }; + typedef std::vector cobject_id_vector_type; + cobject_id_vector_type cobject_id_vector; + + // list of objects created by de-serialization. Used to implement + // clean up after exceptions. + class created_pointer_type + { + public: + created_pointer_type( + class_id_type class_id_, + void * address_ + ) : + class_id(class_id_), + address(address_) + {} + created_pointer_type(const created_pointer_type &rhs) : + class_id(rhs.class_id), + address(rhs.address) + {} + created_pointer_type & operator=(const created_pointer_type &){ + assert(false); + return *this; + } + void * get_address() const { + return address; + } + // object to which this item refers + const class_id_type class_id; + private: + void * address; + }; + + std::list created_pointers; + + bool is_object; // pass forward indicater that we're saving an object + // directly rather than result of a pointer + + basic_iarchive_impl() + : is_object(true) + {} + bool + track( + basic_iarchive & ar, + void * & t + ); + void + load_preamble( + basic_iarchive & ar, + cobject_id & co, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type_ + ) = NULL + ); + class_id_type register_type( + const basic_iserializer & bis + ); + + // redirect through virtual functions to load functions for this archive + template + void load(basic_iarchive & ar, T & t){ + ar.vload(t); + } + +public: + void delete_created_pointers(); + class_id_type register_type( + const basic_pointer_iserializer & bpis + ); + void load_object( + basic_iarchive & ar, + void * & t, + const basic_iserializer & bis + ); + const basic_pointer_iserializer * load_pointer( + basic_iarchive & ar, + void * & t, + const basic_pointer_iserializer * bpis, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type + ) + ); +}; + +inline void +basic_iarchive_impl::delete_created_pointers() +{ + while(created_pointers.size() > 0){ + const created_pointer_type & cp = created_pointers.front(); + + // figure out the class of the object to be deleted + // note: extra line used to evand borland issue + const int id = cp.class_id; + const cobject_id & co = cobject_id_vector[id]; + // with the appropriate input serializer, + // delete the indicated object + co.bis_ptr->destroy(cp.get_address()); + created_pointers.pop_front(); + } +} + +inline class_id_type +basic_iarchive_impl::register_type( + const basic_iserializer & bis +){ + cobject_type co(cobject_info_set.size(), bis); + std::pair + result = cobject_info_set.insert(co); + + if(result.second){ + cobject_id_vector.push_back(cobject_id(bis)); + assert(cobject_info_set.size() == cobject_id_vector.size()); + } + return result.first->class_id; +} + +inline class_id_type +basic_iarchive_impl::register_type( + const basic_pointer_iserializer & bpis +){ + const basic_iserializer & bis = bpis.get_basic_serializer(); + class_id_type cid = register_type(bis); + // note: extra line used to evade borland issue + const int id = cid; + cobject_id & co = cobject_id_vector[id]; + co.bpis_ptr = & bpis; + return cid; +} + +void +basic_iarchive_impl::load_preamble( + basic_iarchive & ar, + cobject_id & co, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type_ + ) +){ + if(! co.initialized){ + const basic_iserializer & bis = * co.bis_ptr; + if(NULL == co.bpis_ptr){ + if(bis.serialized_as_pointer()){ + // is must have been exported + char key[BOOST_SERIALIZATION_MAX_KEY_SIZE]; + class_name_type class_name(key); + load(ar, class_name); + // if it has a class name + const serialization::extended_type_info *eti = NULL; + if(0 != key[0]) + eti = serialization::extended_type_info::find(key); + if(NULL == eti) + boost::throw_exception( + archive_exception(archive_exception::unregistered_class) + ); + co.bpis_ptr = (*finder)(*eti); + } + } + if(bis.class_info()){ + class_id_optional_type cid; + load(ar, cid); // to be thrown away + load(ar, co.tracking_level); + load(ar, co.file_version); + } + else{ + // override tracking with indicator from class information + co.tracking_level = bis.tracking(); + co.file_version = version_type(bis.version()); + } + co.initialized = true; + } +} + +bool +basic_iarchive_impl::track( + basic_iarchive & ar, + void * & t +){ + object_id_type oid; + load(ar, oid); + + // if its a reference to a old object + if(object_id_type(object_id_vector.size()) > oid){ + // we're done + t = object_id_vector[oid].address; + return false; + } + return true; +} + +inline void +basic_iarchive_impl::load_object( + basic_iarchive & ar, + void * & t, + const basic_iserializer & bis +){ + bool result = true; + const class_id_type cid = register_type(bis); + // note: extra line used to evand borland issue + const int id = cid; + cobject_id & co = cobject_id_vector[id]; + if(is_object){ + load_preamble(ar, co); + // note: extra line used to evand borland issue + const bool b = co.tracking_level; + if(b){ + result = track(ar, t); + if(! result) + return; + object_id_vector.push_back(aobject(t, cid)); + } + } + + // read data if required + state_saver x(is_object); + is_object = true; + (bis.load_object_data)(ar, t, co.file_version); +} + +inline const basic_pointer_iserializer * +basic_iarchive_impl::load_pointer( + basic_iarchive &ar, + void * & t, + const basic_pointer_iserializer * bpis_ptr, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type_ + ) +){ + class_id_type cid; + load(ar, cid); + + if(null_pointer_tag == cid){ + t = NULL; + return bpis_ptr; + } + + // if its a new class type - i.e. never been registered + if(class_id_type(cobject_info_set.size()) <= cid){ + class_id_type new_cid = register_type(bpis_ptr->get_basic_serializer()); + assert(new_cid == cid); + } + + // borland won't find class_id_type->int->unsigned int so use a cast + int icid = cid; + cobject_id & co = cobject_id_vector[icid]; + load_preamble(ar, co, finder); + + bool new_object = true; + // extra line to evade borland issue + const bool b = co.tracking_level; + if(b) + new_object = track(ar, t); + + // we update this because its going to be returned and it has to + // reflect that TRUE type recovered rather than the base type + bpis_ptr = co.bpis_ptr; + // if required + if(new_object){ + // read data + state_saver x(is_object); + is_object = false; + + if(co.bis_ptr->tracking()){ + // predict next object id to be created + const unsigned int i = object_id_vector.size(); + + // because the following operation could move the items + // don't use co after this + object_id_vector.push_back(aobject(t, cid)); + bpis_ptr->load_object_ptr( + ar, + object_id_vector[i].address, + co.file_version + ); + t = object_id_vector[i].address; + // and add to list of created pointers + created_pointers.push_back(created_pointer_type(cid, t)); + } + else{ + bpis_ptr->load_object_ptr(ar, t, co.file_version); + } + assert(NULL != t); + } + + return bpis_ptr; +} + +////////////////////////////////////////////////////////////////////// +// implementation of basic_iarchive functions + +basic_iarchive::basic_iarchive() : + pimpl(new basic_iarchive_impl), + archive_library_version(ARCHIVE_VERSION) +{} + +basic_iarchive::~basic_iarchive() +{ + delete pimpl; +} + +void basic_iarchive::delete_created_pointers() +{ + pimpl->delete_created_pointers(); +} + +void basic_iarchive::register_pointer_iserializer( + const basic_pointer_iserializer & bpis +){ + pimpl->register_type(bpis); +} + +void basic_iarchive::load_object( + void *t, + const basic_iserializer &bis +){ + pimpl->load_object(*this, t, bis); +} + +// load a pointer object +const basic_pointer_iserializer * +basic_iarchive::load_pointer( + void * &t, + const basic_pointer_iserializer * bpis_ptr, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type_ + ) +){ + return pimpl->load_pointer(*this, t, bpis_ptr, finder); +} + +} // namespace detail +} // namespace archive +} // namespace boost diff --git a/src/xbasic_oarchive.cpp b/src/xbasic_oarchive.cpp new file mode 100644 index 00000000..c974f6ee --- /dev/null +++ b/src/xbasic_oarchive.cpp @@ -0,0 +1,391 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_oarchive.cpp: + +// (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 // msvc 6.0 needs this for warning suppression + +#include +#include + +#include +#include +#include + +// including this here to work around an ICC in intel 7.0 +// normally this would be part of basic_oarchive.hpp below. +#include + +#include +#include +#include + +#include +#include + +using namespace boost::serialization; + +namespace boost { +namespace archive { +namespace detail { + +class basic_oarchive_impl +{ + friend class basic_oarchive; + ////////////////////////////////////////////////////////////////////// + // information about each serialized object saved + // keyed on address, class_id + struct aobject + { + const void * address; + class_id_type class_id; + object_id_type object_id; + + bool operator<(const aobject &rhs) const + { + assert(NULL != address); + assert(NULL != rhs.address); + if( address < rhs.address ) + return true; + if( address > rhs.address ) + return false; + return class_id < rhs.class_id; + } + aobject & operator=(const aobject & rhs) + { + address = rhs.address; + class_id = rhs.class_id; + object_id = rhs.object_id; + return *this; + } + aobject( + const void *a, + class_id_type class_id_, + object_id_type object_id_ + ) : + address(a), + class_id(class_id_), + object_id(object_id_) + {} + aobject() : address(NULL){} + }; + // keyed on class_id, address + typedef std::set object_set_type; + object_set_type object_set; + + ////////////////////////////////////////////////////////////////////// + // information about each serialized class saved + // keyed on type_info + struct cobject_type + { + const basic_oserializer * bos_ptr; + const class_id_type class_id; + bool initialized; + cobject_type( + size_t class_id_, + const basic_oserializer & bos_ + ) : + bos_ptr(& bos_), + class_id(class_id_), + initialized(false) + {} + cobject_type(const basic_oserializer & bos_) + : bos_ptr(& bos_) + {} + cobject_type( + const cobject_type & rhs + ) : + bos_ptr(rhs.bos_ptr), + class_id(rhs.class_id), + initialized(rhs.initialized) + {} + // the following cannot be defined because of the const + // member. This will generate a link error if an attempt + // is made to assign. This should never be necessary + // use this only for lookup argument + cobject_type & operator=(const cobject_type &rhs); + bool operator<(const cobject_type &rhs) const { + return *bos_ptr < *(rhs.bos_ptr); + } + }; + // keyed on type_info + typedef std::set cobject_info_set_type; + cobject_info_set_type cobject_info_set; + + // list of objects initially stored as pointers - used to detect errors + // keyed on object id + std::set stored_pointers; + + bool is_object; // pass forward indicater that we're saving an object + // directly rather than result of a pointer + basic_oarchive_impl() + : is_object(true) + {} + + const cobject_type & + find(const basic_oserializer & bos); + const basic_oserializer * + find(const serialization::extended_type_info &ti) const; + void + save_preamble( + basic_oarchive & ar, + cobject_type & co + ); + bool + track( + basic_oarchive & ar, + const void *t, + const class_id_type cid, + bool is_object + ); +public: + cobject_type & + register_type(const basic_oserializer & bos); + void save_object( + basic_oarchive & ar, + const void *t, + const basic_oserializer & bos + ); + void save_pointer( + basic_oarchive & ar, + const void * t, + const basic_pointer_oserializer & bpos + ); + +}; + +////////////////////////////////////////////////////////////////////// +// implementation of basic_oarchive implementation functions + +// given a type_info - find its bos +// return NULL if not found +inline const basic_oserializer * +basic_oarchive_impl::find(const serialization::extended_type_info & ti) const { + class bosarg : public boost::archive::detail::basic_oserializer + { + bool class_info() const { + assert(false); + return false; + } + // returns true if objects should be tracked + bool tracking() const { + assert(false); + return false; + } + // returns class version + unsigned int version() const { + assert(false); + return 0; + } + // returns true if this class is polymorphic + bool is_polymorphic() const{ + assert(false); + return false; + } + void save_object_data( + basic_oarchive & ar, const void * x + ) const { + assert(false); + } + public: + bosarg(const serialization::extended_type_info & type_) : + boost::archive::detail::basic_oserializer(type_) + {} + }; + bosarg bos(ti); + cobject_info_set_type::const_iterator cit + = cobject_info_set.find(cobject_type(bos)); + // it should already have been "registered" - see below + if(cit == cobject_info_set.end()){ + // if an entry is not found in the table it is because a pointer + // of a derived class has been serialized through its base class + // but the derived class hasn't been "registered" + return NULL; + } + // return pointer to the real class + return cit->bos_ptr; +} + +inline const basic_oarchive_impl::cobject_type & +basic_oarchive_impl::find(const basic_oserializer & bos) +{ + std::pair cresult = + cobject_info_set.insert(cobject_type(cobject_info_set.size(), bos)); + return *(cresult.first); +} + +inline basic_oarchive_impl::cobject_type & +basic_oarchive_impl::register_type( + const basic_oserializer & bos +){ + cobject_type co(cobject_info_set.size(), bos); + std::pair + result = cobject_info_set.insert(co); + return const_cast(*(result.first)); +} + +void +basic_oarchive_impl::save_preamble( + basic_oarchive & ar, + cobject_type & co +){ + if(! co.initialized){ + if(is_object) + ar.vsave(class_id_optional_type(co.class_id)); + else + ar.vsave(co.class_id); + const basic_oserializer & bos = * co.bos_ptr; + if(bos.serialized_as_pointer + && bos.is_polymorphic()){ + if(bos.is_polymorphic()){ + const serialization::extended_type_info *eti = & bos.type; + const char * key = NULL; + if(NULL != eti) + key = eti->key; + if(NULL != key) + // write out the external class identifier + ar.vsave(class_name_type(key)); + else + // without an external class name + // we won't be able to de-serialize it so bail now + boost::throw_exception( + archive_exception(archive_exception::unregistered_class) + ); + } + } + if(bos.class_info()){ + ar.vsave(tracking_type(bos.tracking())); + ar.vsave(version_type(bos.version())); + } + (const_cast(co)).initialized = true; + } + else{ + ar.vsave(class_id_reference_type(co.class_id)); + } + + ar.end_preamble(); + +} + +// return true if this is a new object and should be serialized +// false if it can be skipped. +bool +basic_oarchive_impl::track( + basic_oarchive & ar, + const void *t, + const class_id_type cid, + bool is_object +){ + object_id_type oid(object_set.size()); + // lookup to see if this object has already been written to the archive + basic_oarchive_impl::aobject ao(t, cid, oid); + std::pair + aresult = object_set.insert(ao); + oid = aresult.first->object_id; + // if its aready there + if(! aresult.second){ + ar.vsave(object_reference_type(oid)); + // and its an object + if(is_object + // but it was originally stored through a pointer + && stored_pointers.end() != stored_pointers.find(oid)){ + // this has to be a user error. loading such an archive + // would create duplicate objects + boost::throw_exception( + archive_exception(archive_exception::pointer_conflict) + ); + } + return false; + } + ar.vsave(oid); + if(! is_object) + // add to the set of object initially stored through pointers + stored_pointers.insert(oid); + return true; +} + +inline void +basic_oarchive_impl::save_object( + basic_oarchive & ar, + const void *t, + const basic_oserializer & bos +){ + bool new_object = true; + if(is_object){ + cobject_type & co = register_type(bos); + save_preamble(ar, co); + if(bos.tracking()) + new_object = track(ar, t, co.class_id, true); + ar.end_preamble(); + } + if(new_object){ + state_saver x(is_object); + is_object = true; + (bos.save_object_data)(ar, t); + } +} + +// save a pointer to an object instance +inline void +basic_oarchive_impl::save_pointer( + basic_oarchive & ar, + const void * t, + const basic_pointer_oserializer & bpos +){ + const basic_oserializer & bos = bpos.get_basic_serializer(); + unsigned int original_count = cobject_info_set.size(); + cobject_type & co = register_type(bos); + + is_object = false; + save_preamble(ar, co); + + bool new_object = true; + if(bos.tracking()) + new_object = track(ar, t, co.class_id, false); + + if(new_object){ + state_saver x(is_object); + bpos.save_object_ptr(ar, t); + } +} + +////////////////////////////////////////////////////////////////////// +// implementation of basic_oarchive functions + +basic_oarchive::basic_oarchive() + : pimpl(new basic_oarchive_impl) +{} + +basic_oarchive::~basic_oarchive() +{ + delete pimpl; +} + +void basic_oarchive::register_pointer_oserializer( + const basic_pointer_oserializer & bosp +){ + pimpl->register_type(bosp.get_basic_serializer()); +} + +void basic_oarchive::save_object( + const void *x, + const basic_oserializer & bos +){ + pimpl->save_object(*this, x, bos); +} + +void basic_oarchive::save_pointer( + const void * t, + const basic_pointer_oserializer & bpos +){ + pimpl->save_pointer(*this, t, bpos); +} + +} // namespace detail +} // namespace archive +} // namespace boost diff --git a/src/xml_grammar.cpp b/src/xml_grammar.cpp new file mode 100644 index 00000000..7e125abd --- /dev/null +++ b/src/xml_grammar.cpp @@ -0,0 +1,71 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_grammar.cpp: + +// (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. + +#if (defined _MSC_VER) && (_MSC_VER == 1200) +# pragma warning (disable : 4786) // too long name, harmless warning +#endif + +#include + +using namespace boost::spirit; + +#include + +// fixup for borland +// The following code will be put into Boost.Config in a later revision +#if defined(_RWSTD_VER) && ! defined(__SGI_STL_PORT) +#include +namespace std { + template<> + inline string & + string::replace ( + char * first1, + char * last1, + const char * first2, + const char * last2 + ){ + replace(first1-begin(),last1-first1,first2,last2-first2,0,last2-first2); + return *this; + } +} // namespace std +#endif + +namespace boost { +namespace archive { + +typedef basic_xml_grammar xml_grammar; + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// specific definitions for char based XML + +template<> +void xml_grammar::init_chset(){ + Char = chset_t("\x9\xA\xD\x20-\xFF"); + Letter = chset_t("\x41-\x5A\x61-\x7A\xC0-\xD6\xD8-\xF6\xF8-\xFF"); + Digit = chset_t("0-9"); + Extender = chset_t('\xB7'); + Sch = chset_t("\x20\x9\xD\xA"); + NameChar = Letter | Digit | chset_p("._:-") | Extender ; +} + +} // namespace archive +} // namespace boost + +#include "basic_xml_grammar.ipp" + +namespace boost { +namespace archive { + +// explicit instantiation of xml for 8 bit characters +template class basic_xml_grammar; + +} // namespace archive +} // namespace boost + diff --git a/src/xml_iarchive.cpp b/src/xml_iarchive.cpp new file mode 100644 index 00000000..4c2431ef --- /dev/null +++ b/src/xml_iarchive.cpp @@ -0,0 +1,45 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_iarchive.cpp: + +// (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. + +#if (defined _MSC_VER) && (_MSC_VER == 1200) +# pragma warning (disable : 4786) // too long name, harmless warning +#endif + +#include + +#include +#include + +// the following works around an issue between spirit 1.61 and borland. +// it turns out the the certain spirit stuff must be defined before +// certain parts of mpl. including this here makes sure that happens +#if BOOST_WORKAROUND(__BORLANDC__, <= 0x564 ) +#include +#endif + +#include + +// explicitly instantiate for this type of xml stream +#include +#include +#include +#include + +namespace boost { +namespace archive { + +template class basic_text_iprimitive ; +template class basic_xml_iarchive ; +template class xml_iarchive_impl ; +template class detail::archive_pointer_iserializer ; + +} // namespace archive +} // namespace boost + diff --git a/src/xml_oarchive.cpp b/src/xml_oarchive.cpp new file mode 100644 index 00000000..7b648d74 --- /dev/null +++ b/src/xml_oarchive.cpp @@ -0,0 +1,34 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_oarchive.cpp: + +// (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. + +#if (defined _MSC_VER) && (_MSC_VER == 1200) +# pragma warning (disable : 4786) // too long name, harmless warning +#endif + +#include + +#include + +#include +#include +#include +#include + +namespace boost { +namespace archive { + +// explicitly instantiate for this type of xml stream +template class basic_text_oprimitive ; +template class basic_xml_oarchive ; +template class xml_oarchive_impl ; +template class detail::archive_pointer_oserializer ; + +} // namespace archive +} // namespace boost diff --git a/src/xml_wgrammar.cpp b/src/xml_wgrammar.cpp new file mode 100644 index 00000000..e22c1306 --- /dev/null +++ b/src/xml_wgrammar.cpp @@ -0,0 +1,253 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_wgrammar.cpp: + +// (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 + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +BOOST_STATIC_ASSERT(false); +#else + +#include + +using namespace boost::spirit; + +// fixup for RogueWave +#include +#if defined(_RWSTD_VER) && ! defined(__SGI_STL_PORT) +#include +namespace std { + template<> + inline wstring & + wstring::replace ( + wchar_t * first1, + wchar_t * last1, + const wchar_t * first2, + const wchar_t * last2 + ){ + replace(first1-begin(),last1-first1,first2,last2-first2,0,last2-first2); + return *this; + } +} // namespace std +#endif + +namespace boost { +namespace archive { + +typedef basic_xml_grammar xml_wgrammar; + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// specific definitions for wchar_t based XML + +#if 0 +template<> +const xml_wgrammar::chset_t xml_wgrammar:: + #if defined(__GNUC__) && defined(linux) + Char(L"\x9\xA\xD\x20-\xD7FF\xE000-\xFFFD\x10000-\x10FFFF"); + #else + Char(L"\x9\xA\xD\x20-\xD7FF\xE000-\xFFFD"); + #endif + +template<> +const xml_wgrammar::chset_t xml_wgrammar::Sch(L"\x20\x9\xD\xA"); + +template<> +const xml_wgrammar::chset_t xml_wgrammar::BaseChar ( + L"\x41-\x5A\x61-\x7A\xC0-\xD6\xD8-\xF6\xF8-\xFF\x100-\x131\x134-\x13E" + L"\x141-\x148\x14A-\x17E\x180-\x1C3\x1CD-\x1F0\x1F4-\x1F5\x1FA-\x217" + L"\x250-\x2A8\x2BB-\x2C1\x386\x388-\x38A\x38C\x38E-\x3A1\x3A3-\x3CE" + L"\x3D0-\x3D6\x3DA\x3DC\x3DE\x3E0\x3E2-\x3F3\x401-\x40C\x40E-\x44F" + L"\x451-\x45C\x45E-\x481\x490-\x4C4\x4C7-\x4C8\x4CB-\x4CC\x4D0-\x4EB" + L"\x4EE-\x4F5\x4F8-\x4F9\x531-\x556\x559\x561-\x586\x5D0-\x5EA" + L"\x5F0-\x5F2\x621-\x63A\x641-\x64A\x671-\x6B7\x6BA-\x6BE\x6C0-\x6CE" + L"\x6D0-\x6D3\x6D5\x6E5-\x6E6\x905-\x939\x93D\x958-\x961\x985-\x98C" + L"\x98F-\x990\x993-\x9A8\x9AA-\x9B0\x9B2\x9B6-\x9B9\x9DC-\x9DD" + L"\x9DF-\x9E1\x9F0-\x9F1\xA05-\xA0A\xA0F-\xA10\xA13-\xA28\xA2A-\xA30" + L"\xA32-\xA33\xA35-\xA36\xA38-\xA39\xA59-\xA5C\xA5E\xA72-\xA74" + L"\xA85-\xA8B\xA8D\xA8F-\xA91\xA93-\xAA8\xAAA-\xAB0\xAB2-\xAB3" + L"\xAB5-\xAB9\xABD\xAE0\xB05-\xB0C\xB0F-\xB10\xB13-\xB28\xB2A-\xB30" + L"\xB32-\xB33\xB36-\xB39\xB3D\xB5C-\xB5D\xB5F-\xB61\xB85-\xB8A" + L"\xB8E-\xB90\xB92-\xB95\xB99-\xB9A\xB9C\xB9E-\xB9F\xBA3-\xBA4" + L"\xBA8-\xBAA\xBAE-\xBB5\xBB7-\xBB9\xC05-\xC0C\xC0E-\xC10\xC12-\xC28" + L"\xC2A-\xC33\xC35-\xC39\xC60-\xC61\xC85-\xC8C\xC8E-\xC90\xC92-\xCA8" + L"\xCAA-\xCB3\xCB5-\xCB9\xCDE\xCE0-\xCE1\xD05-\xD0C\xD0E-\xD10" + L"\xD12-\xD28\xD2A-\xD39\xD60-\xD61\xE01-\xE2E\xE30\xE32-\xE33" + L"\xE40-\xE45\xE81-\xE82\xE84\xE87-\xE88\xE8A\xE8D\xE94-\xE97" + L"\xE99-\xE9F\xEA1-\xEA3\xEA5\xEA7\xEAA-\xEAB\xEAD-\xEAE\xEB0" + L"\xEB2-\xEB3\xEBD\xEC0-\xEC4\xF40-\xF47\xF49-\xF69\x10A0-\x10C5" + L"\x10D0-\x10F6\x1100\x1102-\x1103\x1105-\x1107\x1109\x110B-\x110C" + L"\x110E-\x1112\x113C\x113E\x1140\x114C\x114E\x1150\x1154-\x1155" + L"\x1159\x115F-\x1161\x1163\x1165\x1167\x1169\x116D-\x116E" + L"\x1172-\x1173\x1175\x119E\x11A8\x11AB\x11AE-\x11AF\x11B7-\x11B8" + L"\x11BA\x11BC-\x11C2\x11EB\x11F0\x11F9\x1E00-\x1E9B\x1EA0-\x1EF9" + L"\x1F00-\x1F15\x1F18-\x1F1D\x1F20-\x1F45\x1F48-\x1F4D\x1F50-\x1F57" + L"\x1F59\x1F5B\x1F5D\x1F5F-\x1F7D\x1F80-\x1FB4\x1FB6-\x1FBC\x1FBE" + L"\x1FC2-\x1FC4\x1FC6-\x1FCC\x1FD0-\x1FD3\x1FD6-\x1FDB\x1FE0-\x1FEC" + L"\x1FF2-\x1FF4\x1FF6-\x1FFC\x2126\x212A-\x212B\x212E\x2180-\x2182" + L"\x3041-\x3094\x30A1-\x30FA\x3105-\x312C\xAC00-\xD7A3"); + +template<> +const xml_wgrammar::chset_t xml_wgrammar::Ideographic( + L"\x4E00-\x9FA5\x3007\x3021-\x3029"); + +template<> +const xml_wgrammar::chset_t xml_wgrammar::Letter = BaseChar | Ideographic; + +template<> +const xml_wgrammar::chset_t xml_wgrammar::CombiningChar( + L"\x0300-\x0345\x0360-\x0361\x0483-\x0486\x0591-\x05A1\x05A3-\x05B9" + L"\x05BB-\x05BD\x05BF\x05C1-\x05C2\x05C4\x064B-\x0652\x0670" + L"\x06D6-\x06DC\x06DD-\x06DF\x06E0-\x06E4\x06E7-\x06E8\x06EA-\x06ED" + L"\x0901-\x0903\x093C\x093E-\x094C\x094D\x0951-\x0954\x0962-\x0963" + L"\x0981-\x0983\x09BC\x09BE\x09BF\x09C0-\x09C4\x09C7-\x09C8" + L"\x09CB-\x09CD\x09D7\x09E2-\x09E3\x0A02\x0A3C\x0A3E\x0A3F" + L"\x0A40-\x0A42\x0A47-\x0A48\x0A4B-\x0A4D\x0A70-\x0A71\x0A81-\x0A83" + L"\x0ABC\x0ABE-\x0AC5\x0AC7-\x0AC9\x0ACB-\x0ACD\x0B01-\x0B03\x0B3C" + L"\x0B3E-\x0B43\x0B47-\x0B48\x0B4B-\x0B4D\x0B56-\x0B57\x0B82-\x0B83" + L"\x0BBE-\x0BC2\x0BC6-\x0BC8\x0BCA-\x0BCD\x0BD7\x0C01-\x0C03" + L"\x0C3E-\x0C44\x0C46-\x0C48\x0C4A-\x0C4D\x0C55-\x0C56\x0C82-\x0C83" + L"\x0CBE-\x0CC4\x0CC6-\x0CC8\x0CCA-\x0CCD\x0CD5-\x0CD6\x0D02-\x0D03" + L"\x0D3E-\x0D43\x0D46-\x0D48\x0D4A-\x0D4D\x0D57\x0E31\x0E34-\x0E3A" + L"\x0E47-\x0E4E\x0EB1\x0EB4-\x0EB9\x0EBB-\x0EBC\x0EC8-\x0ECD" + L"\x0F18-\x0F19\x0F35\x0F37\x0F39\x0F3E\x0F3F\x0F71-\x0F84" + L"\x0F86-\x0F8B\x0F90-\x0F95\x0F97\x0F99-\x0FAD\x0FB1-\x0FB7\x0FB9" + L"\x20D0-\x20DC\x20E1\x302A-\x302F\x3099\x309A"); + +template<> +const xml_wgrammar::chset_t xml_wgrammar::Digit( + L"\x0030-\x0039\x0660-\x0669\x06F0-\x06F9\x0966-\x096F\x09E6-\x09EF" + L"\x0A66-\x0A6F\x0AE6-\x0AEF\x0B66-\x0B6F\x0BE7-\x0BEF\x0C66-\x0C6F" + L"\x0CE6-\x0CEF\x0D66-\x0D6F\x0E50-\x0E59\x0ED0-\x0ED9\x0F20-\x0F29"); + +template<> +const xml_wgrammar::chset_t xml_wgrammar::Extender( + L"\x00B7\x02D0\x02D1\x0387\x0640\x0E46\x0EC6\x3005\x3031-\x3035" + L"\x309D-\x309E\x30FC-\x30FE"); + +template<> +const xml_wgrammar::chset_t xml_wgrammar::NameChar = + Letter + | Digit + | L'.' + | L'-' + | L'_' + | L':' + | CombiningChar + | Extender; +#endif + +template<> +void xml_wgrammar::init_chset(){ + Char = chset_t( + #if defined(__GNUC__) && defined(linux) + L"\x9\xA\xD\x20-\xD7FF\xE000-\xFFFD\x10000-\x10FFFF" + #else + L"\x9\xA\xD\x20-\xD7FF\xE000-\xFFFD" + #endif + ); + + Sch = chset_t(L"\x20\x9\xD\xA"); + + BaseChar = chset_t( + L"\x41-\x5A\x61-\x7A\xC0-\xD6\xD8-\xF6\xF8-\xFF\x100-\x131\x134-\x13E" + L"\x141-\x148\x14A-\x17E\x180-\x1C3\x1CD-\x1F0\x1F4-\x1F5\x1FA-\x217" + L"\x250-\x2A8\x2BB-\x2C1\x386\x388-\x38A\x38C\x38E-\x3A1\x3A3-\x3CE" + L"\x3D0-\x3D6\x3DA\x3DC\x3DE\x3E0\x3E2-\x3F3\x401-\x40C\x40E-\x44F" + L"\x451-\x45C\x45E-\x481\x490-\x4C4\x4C7-\x4C8\x4CB-\x4CC\x4D0-\x4EB" + L"\x4EE-\x4F5\x4F8-\x4F9\x531-\x556\x559\x561-\x586\x5D0-\x5EA" + L"\x5F0-\x5F2\x621-\x63A\x641-\x64A\x671-\x6B7\x6BA-\x6BE\x6C0-\x6CE" + L"\x6D0-\x6D3\x6D5\x6E5-\x6E6\x905-\x939\x93D\x958-\x961\x985-\x98C" + L"\x98F-\x990\x993-\x9A8\x9AA-\x9B0\x9B2\x9B6-\x9B9\x9DC-\x9DD" + L"\x9DF-\x9E1\x9F0-\x9F1\xA05-\xA0A\xA0F-\xA10\xA13-\xA28\xA2A-\xA30" + L"\xA32-\xA33\xA35-\xA36\xA38-\xA39\xA59-\xA5C\xA5E\xA72-\xA74" + L"\xA85-\xA8B\xA8D\xA8F-\xA91\xA93-\xAA8\xAAA-\xAB0\xAB2-\xAB3" + L"\xAB5-\xAB9\xABD\xAE0\xB05-\xB0C\xB0F-\xB10\xB13-\xB28\xB2A-\xB30" + L"\xB32-\xB33\xB36-\xB39\xB3D\xB5C-\xB5D\xB5F-\xB61\xB85-\xB8A" + L"\xB8E-\xB90\xB92-\xB95\xB99-\xB9A\xB9C\xB9E-\xB9F\xBA3-\xBA4" + L"\xBA8-\xBAA\xBAE-\xBB5\xBB7-\xBB9\xC05-\xC0C\xC0E-\xC10\xC12-\xC28" + L"\xC2A-\xC33\xC35-\xC39\xC60-\xC61\xC85-\xC8C\xC8E-\xC90\xC92-\xCA8" + L"\xCAA-\xCB3\xCB5-\xCB9\xCDE\xCE0-\xCE1\xD05-\xD0C\xD0E-\xD10" + L"\xD12-\xD28\xD2A-\xD39\xD60-\xD61\xE01-\xE2E\xE30\xE32-\xE33" + L"\xE40-\xE45\xE81-\xE82\xE84\xE87-\xE88\xE8A\xE8D\xE94-\xE97" + L"\xE99-\xE9F\xEA1-\xEA3\xEA5\xEA7\xEAA-\xEAB\xEAD-\xEAE\xEB0" + L"\xEB2-\xEB3\xEBD\xEC0-\xEC4\xF40-\xF47\xF49-\xF69\x10A0-\x10C5" + L"\x10D0-\x10F6\x1100\x1102-\x1103\x1105-\x1107\x1109\x110B-\x110C" + L"\x110E-\x1112\x113C\x113E\x1140\x114C\x114E\x1150\x1154-\x1155" + L"\x1159\x115F-\x1161\x1163\x1165\x1167\x1169\x116D-\x116E" + L"\x1172-\x1173\x1175\x119E\x11A8\x11AB\x11AE-\x11AF\x11B7-\x11B8" + L"\x11BA\x11BC-\x11C2\x11EB\x11F0\x11F9\x1E00-\x1E9B\x1EA0-\x1EF9" + L"\x1F00-\x1F15\x1F18-\x1F1D\x1F20-\x1F45\x1F48-\x1F4D\x1F50-\x1F57" + L"\x1F59\x1F5B\x1F5D\x1F5F-\x1F7D\x1F80-\x1FB4\x1FB6-\x1FBC\x1FBE" + L"\x1FC2-\x1FC4\x1FC6-\x1FCC\x1FD0-\x1FD3\x1FD6-\x1FDB\x1FE0-\x1FEC" + L"\x1FF2-\x1FF4\x1FF6-\x1FFC\x2126\x212A-\x212B\x212E\x2180-\x2182" + L"\x3041-\x3094\x30A1-\x30FA\x3105-\x312C\xAC00-\xD7A3" + ); + + Ideographic = chset_t(L"\x4E00-\x9FA5\x3007\x3021-\x3029"); + + Letter = BaseChar | Ideographic; + + CombiningChar = chset_t( + L"\x0300-\x0345\x0360-\x0361\x0483-\x0486\x0591-\x05A1\x05A3-\x05B9" + L"\x05BB-\x05BD\x05BF\x05C1-\x05C2\x05C4\x064B-\x0652\x0670" + L"\x06D6-\x06DC\x06DD-\x06DF\x06E0-\x06E4\x06E7-\x06E8\x06EA-\x06ED" + L"\x0901-\x0903\x093C\x093E-\x094C\x094D\x0951-\x0954\x0962-\x0963" + L"\x0981-\x0983\x09BC\x09BE\x09BF\x09C0-\x09C4\x09C7-\x09C8" + L"\x09CB-\x09CD\x09D7\x09E2-\x09E3\x0A02\x0A3C\x0A3E\x0A3F" + L"\x0A40-\x0A42\x0A47-\x0A48\x0A4B-\x0A4D\x0A70-\x0A71\x0A81-\x0A83" + L"\x0ABC\x0ABE-\x0AC5\x0AC7-\x0AC9\x0ACB-\x0ACD\x0B01-\x0B03\x0B3C" + L"\x0B3E-\x0B43\x0B47-\x0B48\x0B4B-\x0B4D\x0B56-\x0B57\x0B82-\x0B83" + L"\x0BBE-\x0BC2\x0BC6-\x0BC8\x0BCA-\x0BCD\x0BD7\x0C01-\x0C03" + L"\x0C3E-\x0C44\x0C46-\x0C48\x0C4A-\x0C4D\x0C55-\x0C56\x0C82-\x0C83" + L"\x0CBE-\x0CC4\x0CC6-\x0CC8\x0CCA-\x0CCD\x0CD5-\x0CD6\x0D02-\x0D03" + L"\x0D3E-\x0D43\x0D46-\x0D48\x0D4A-\x0D4D\x0D57\x0E31\x0E34-\x0E3A" + L"\x0E47-\x0E4E\x0EB1\x0EB4-\x0EB9\x0EBB-\x0EBC\x0EC8-\x0ECD" + L"\x0F18-\x0F19\x0F35\x0F37\x0F39\x0F3E\x0F3F\x0F71-\x0F84" + L"\x0F86-\x0F8B\x0F90-\x0F95\x0F97\x0F99-\x0FAD\x0FB1-\x0FB7\x0FB9" + L"\x20D0-\x20DC\x20E1\x302A-\x302F\x3099\x309A" + ); + + Digit = chset_t( + L"\x0030-\x0039\x0660-\x0669\x06F0-\x06F9\x0966-\x096F\x09E6-\x09EF" + L"\x0A66-\x0A6F\x0AE6-\x0AEF\x0B66-\x0B6F\x0BE7-\x0BEF\x0C66-\x0C6F" + L"\x0CE6-\x0CEF\x0D66-\x0D6F\x0E50-\x0E59\x0ED0-\x0ED9\x0F20-\x0F29" + ); + + Extender = chset_t( + L"\x00B7\x02D0\x02D1\x0387\x0640\x0E46\x0EC6\x3005\x3031-\x3035" + L"\x309D-\x309E\x30FC-\x30FE" + ); + + NameChar = + Letter + | Digit + | L'.' + | L'-' + | L'_' + | L':' + | CombiningChar + | Extender + ; +} +} // namespace archive +} // namespace boost + +#include "basic_xml_grammar.ipp" + +namespace boost { +namespace archive { + +// explicit instantiation of xml for wide characters +template class basic_xml_grammar; + +} // namespace archive +} // namespace boost + +#endif diff --git a/src/xml_wiarchive.cpp b/src/xml_wiarchive.cpp new file mode 100644 index 00000000..ca8b0288 --- /dev/null +++ b/src/xml_wiarchive.cpp @@ -0,0 +1,49 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_wiarchive.cpp: + +// (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 +#ifdef BOOST_NO_STD_WSTREAMBUF +BOOST_STATIC_ASSERT(false); +#else + +#include +#include + +#if (defined _MSC_VER) && (_MSC_VER == 1200) +# pragma warning (disable : 4786) // too long name, harmless warning +#endif + +// the following works around an issue between spirit 1.61 and borland. +// it turns out the the certain spirit stuff must be defined before +// certain parts of mpl. including this here makes sure that happens +#if BOOST_WORKAROUND(__BORLANDC__, <= 0x564 ) +#include +#endif + +#include + +// explicitly instantiate for this type of xml stream +#include +#include +#include +#include + +namespace boost { +namespace archive { + +template class basic_text_iprimitive ; +template class basic_xml_iarchive ; +template class xml_wiarchive_impl ; +template class detail::archive_pointer_iserializer ; + +} // namespace archive +} // namespace boost + +#endif // BOOST_NO_STD_WSTREAMBUF diff --git a/src/xml_woarchive.cpp b/src/xml_woarchive.cpp new file mode 100644 index 00000000..bbc08ac9 --- /dev/null +++ b/src/xml_woarchive.cpp @@ -0,0 +1,36 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_woarchive.cpp: + +// (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 +#ifdef BOOST_NO_STD_WSTREAMBUF +BOOST_STATIC_ASSERT(false); +#else + +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace archive { + +// explicitly instantiate for this type of xml stream +template class basic_text_oprimitive ; +template class basic_xml_oarchive ; +template class xml_woarchive_impl ; +template class detail::archive_pointer_oserializer ; + +} // namespace archive +} // namespace boost + +#endif // BOOST_NO_STD_WSTREAMBUF