void save(const T &t){ if(os.fail()) boost::serialization::throw_exception( archive_exception(archive_exception::stream_error) ); os << t; }
void save_impl(const T &t, autoboost::mpl::bool_<false> &){ if(os.fail()) autoboost::serialization::throw_exception( archive_exception(archive_exception::output_stream_error) ); os << t; }
void save(const double t) { if(os.fail()) boost::throw_exception(archive_exception(archive_exception::stream_error)); os << std::setprecision(std::numeric_limits<double>::digits10 + 2); os << t; }
void save(const wchar_t t) { if(os.fail()) boost::serialization::throw_exception( archive_exception(archive_exception::stream_error) ); os << static_cast<int>(t); }
void save(const unsigned char t) { if(os.fail()) boost::serialization::throw_exception( archive_exception(archive_exception::stream_error) ); os << static_cast<short unsigned int>(t); }
void load(T & t) { if(is >> t) return; boost::serialization::throw_exception( archive_exception(archive_exception::input_stream_error) ); }
void save(const double t) { // must be a user mistake - can't serialize un-initialized data if(os.fail()) boost::throw_exception(archive_exception(archive_exception::stream_error)); os << std::setprecision(std::numeric_limits<double>::digits10 + 2); os << t; }
///////////////////////////////////////////////////////// // fundamental types that need special treatment void save(const bool t){ // trap usage of invalid uninitialized boolean which would // otherwise crash on load. int i = t; assert(0 == i || 1 == i); if(os.fail()) boost::throw_exception(archive_exception(archive_exception::stream_error)); os << t; }
///////////////////////////////////////////////////////// // fundamental types that need special treatment void save(const bool t){ // trap usage of invalid uninitialized boolean which would // otherwise crash on load. AUTOBOOST_ASSERT(0 == static_cast<int>(t) || 1 == static_cast<int>(t)); if(os.fail()) autoboost::serialization::throw_exception( archive_exception(archive_exception::output_stream_error) ); os << t; }
void save(const float t) { // must be a user mistake - can't serialize un-initialized data if(os.fail()) pdalboost::serialization::throw_exception( archive_exception(archive_exception::output_stream_error) ); os << std::setprecision(std::numeric_limits<float>::digits10 + 2); os << t; }
inline void reverse_bytes(signed char size, char *address){ if (size <= 0) throw archive_exception(archive_exception::other_exception); char * first = address; char * last = first + size - 1; for(;first < last;++first, --last){ char x = *last; *last = *first; *first = x; } }
void save_impl(const T &t, autoboost::mpl::bool_<true> &){ // must be a user mistake - can't serialize un-initialized data if(os.fail()) autoboost::serialization::throw_exception( archive_exception(archive_exception::output_stream_error) ); // The formulae for the number of decimla digits required is given in // http://www2.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1822.pdf // which is derived from Kahan's paper: // www.eecs.berkeley.edu/~wkahan/ieee754status/ieee754.ps // const unsigned int digits = (std::numeric_limits<T>::digits * 3010) / 10000; // note: I've commented out the above because I didn't get good results. e.g. // in one case I got a difference of 19 units. #ifndef AUTOBOOST_NO_CXX11_NUMERIC_LIMITS const unsigned int digits = std::numeric_limits<T>::max_digits10; #else const unsigned int digits = std::numeric_limits<T>::digits10 + 2; #endif os << std::setprecision(digits) << std::scientific << t; }
inline void basic_binary_oprimitive<Archive, OStream>::save_binary( const void *address, std::size_t count ){ assert( static_cast<std::size_t>(std::numeric_limits<std::streamsize>::max()) >= count ); // note: if the following assertions fail // a likely cause is that the output stream is set to "text" // mode where by cr characters recieve special treatment. // be sure that the output stream is opened with ios::binary if(os.fail()) boost::throw_exception(archive_exception(archive_exception::stream_error)); // figure number of elements to output - round up count = ( count + sizeof(BOOST_DEDUCED_TYPENAME OStream::char_type) - 1) / sizeof(BOOST_DEDUCED_TYPENAME OStream::char_type); os.write( static_cast<const BOOST_DEDUCED_TYPENAME OStream::char_type *>(address), count ); assert(os.good()); }
// unformatted append of null terminated string void put(const char * s){ if(os.fail()) boost::throw_exception(archive_exception(archive_exception::stream_error)); while('\0' != *s) os.put(*s++); }
// 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(); std::size_t original_count = cobject_info_set.size(); const cobject_type & co = register_type(bos); if(! co.m_initialized){ ar.vsave(co.m_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.get_eti(); const char * key = NULL; if(NULL != eti) key = eti->get_key(); if(NULL != key){ // the following is required by IBM C++ compiler which // makes a copy when passing a non-const to a const. This // is permitted by the standard but rarely seen in practice const class_name_type cn(key); // write out the external class identifier ar.vsave(cn); } else // without an external class name // we won't be able to de-serialize it so bail now boost::serialization::throw_exception( archive_exception(archive_exception::unregistered_class) ); } } if(bos.class_info()){ ar.vsave(tracking_type(bos.tracking(m_flags))); ar.vsave(version_type(bos.version())); } (const_cast<cobject_type &>(co)).m_initialized = true; } else{ ar.vsave(class_id_reference_type(co.m_class_id)); } // if we're not tracking if(! bos.tracking(m_flags)){ // just save the data itself ar.end_preamble(); serialization::state_saver<const void *> x(pending_object); serialization::state_saver<const basic_oserializer *> y(pending_bos); pending_object = t; pending_bos = & bpos_ptr->get_basic_serializer(); bpos_ptr->save_object_ptr(ar, t); return; } 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, co.m_class_id, oid); std::pair<basic_oarchive_impl::object_set_type::const_iterator, bool> aresult = object_set.insert(ao); oid = aresult.first->object_id; // if the saved object already exists if(! aresult.second){ // append the object id to he preamble ar.vsave(object_reference_type(oid)); // and windup. ar.end_preamble(); return; } // append id of this object to preamble ar.vsave(oid); ar.end_preamble(); // and save the object itself serialization::state_saver<const void *> x(pending_object); serialization::state_saver<const basic_oserializer *> y(pending_bos); pending_object = t; pending_bos = & bpos_ptr->get_basic_serializer(); bpos_ptr->save_object_ptr(ar, t); // add to the set of object initially stored through pointers stored_pointers.insert(oid); }
inline void basic_oarchive_impl::save_object( basic_oarchive & ar, const void *t, const basic_oserializer & bos ){ // if its been serialized through a pointer and the preamble's been done if(t == pending_object && pending_bos == & bos){ // just save the object data ar.end_preamble(); (bos.save_object_data)(ar, t); return; } // get class information for this object const cobject_type & co = register_type(bos); if(bos.class_info()){ if( ! co.m_initialized){ ar.vsave(class_id_optional_type(co.m_class_id)); ar.vsave(tracking_type(bos.tracking(m_flags))); ar.vsave(version_type(bos.version())); (const_cast<cobject_type &>(co)).m_initialized = true; } } // we're not tracking this type of object if(! bos.tracking(m_flags)){ // just windup the preamble - no object id to write ar.end_preamble(); // and save the data (bos.save_object_data)(ar, t); return; } // look for an existing object id 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, co.m_class_id, oid); std::pair<basic_oarchive_impl::object_set_type::const_iterator, bool> aresult = object_set.insert(ao); oid = aresult.first->object_id; // if its a new object if(aresult.second){ // write out the object id ar.vsave(oid); ar.end_preamble(); // and data (bos.save_object_data)(ar, t); return; } // check that it wasn't originally stored through a pointer if(stored_pointers.end() != stored_pointers.find(oid)){ // this has to be a user error. loading such an archive // would create duplicate objects boost::serialization::throw_exception( archive_exception(archive_exception::pointer_conflict) ); } // just save the object id ar.vsave(object_reference_type(oid)); ar.end_preamble(); return; }
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_ ) ){ m_moveable_objects.is_pointer = true; serialization::state_saver<bool> w(m_moveable_objects.is_pointer); 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::serialization::throw_exception( archive_exception(archive_exception::unregistered_class) ); bpis_ptr = (*finder)(*eti); } BOOST_ASSERT(NULL != bpis_ptr); // class_id_type new_cid = register_type(bpis_ptr->get_basic_serializer()); BOOST_VERIFY(register_type(bpis_ptr->get_basic_serializer()) == cid); int i = cid; cobject_id_vector[i].bpis_ptr = bpis_ptr; } int i = cid; cobject_id & co = cobject_id_vector[i]; bpis_ptr = co.bpis_ptr; load_preamble(ar, co); // extra line to evade borland issue const bool tracking = co.tracking_level; // if we're tracking and the pointer has already been read if(tracking && ! track(ar, t)) // we're done return bpis_ptr; // save state serialization::state_saver<object_id_type> w_start(m_moveable_objects.start); // allocate space on the heap for the object - to be constructed later t = bpis_ptr->heap_allocation(); BOOST_ASSERT(NULL != t); if(! tracking){ bpis_ptr->load_object_ptr(ar, t, co.file_version); } else{ serialization::state_saver<void *> x(m_pending.object); serialization::state_saver<const basic_iserializer *> y(m_pending.bis); serialization::state_saver<version_type> z(m_pending.version); m_pending.bis = & bpis_ptr->get_basic_serializer(); m_pending.version = co.file_version; // predict next object id to be created const unsigned int ui = object_id_vector.size(); serialization::state_saver<object_id_type> w_end(m_moveable_objects.end); // add to list of serialized objects so that we can properly handle // cyclic strucures object_id_vector.push_back(aobject(t, cid)); // remember that that the address of these elements could change // when we make another call so don't use the address bpis_ptr->load_object_ptr( ar, t, m_pending.version ); object_id_vector[ui].loaded_as_pointer = true; } return bpis_ptr; }
// unformatted append of one character void put(int c){ if(os.fail()) boost::throw_exception(archive_exception(archive_exception::stream_error)); os.put(c); }