当前位置: 首页 > news >正文

Boost源码分析: Serialization

本文梳理Boost.Serialization代码的实现原理。

注1:限于研究水平,分析难免不当,欢迎批评指正。

注2:文章内容会不定期更新。

一、概述

二、核心组件

2.1 boost::archive::detail::interface_oarchive

// include\boost\archive\detail\interface_oarchive.hpp namespace boost { namespace archive { namespace detail { class basic_pointer_oserializer; template<class Archive> class interface_oarchive { protected: interface_oarchive() {} public: ///////////////////////////////////////////////////////// // archive public interface typedef mpl::bool_<false> is_loading; typedef mpl::bool_<true> is_saving; // return a pointer to the most derived class Archive * This(){ return static_cast<Archive*>(this); } template<class T> const basic_pointer_oserializer * register_type(const T * = NULL){ const basic_pointer_oserializer & bpos = boost::serialization::singleton< pointer_oserializer<Archive, T> >::get_const_instance(); this->This()->register_basic_serializer(bpos.get_basic_serializer()); return & bpos; } template<class Helper> Helper & get_helper(void * const id = 0){ helper_collection & hc = this->This()->get_helper_collection(); return hc.template find_helper<Helper>(id); } template<class T> Archive & operator<<(const T & t){ this->This()->save_override(t); return * this->This(); } // the & operator template<class T> Archive & operator&(const T & t){ return * this ->This() << t; } }; } // namespace detail } // namespace archive } // namespace boost

2.2 boost::archive::binary_oarchive_impl

// include\boost\archive\binary_oarchive_impl.hpp namespace boost { namespace archive { namespace detail { template<class Archive> class interface_oarchive; } // namespace detail template<class Archive, class Elem, class Tr> class BOOST_SYMBOL_VISIBLE binary_oarchive_impl : public basic_binary_oprimitive<Archive, Elem, Tr>, public basic_binary_oarchive<Archive> { #ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS public: #else protected: #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) // for some inexplicable reason insertion of "class" generates compile erro // on msvc 7.1 friend detail::interface_oarchive<Archive>; friend basic_binary_oarchive<Archive>; friend save_access; #else friend class detail::interface_oarchive<Archive>; friend class basic_binary_oarchive<Archive>; friend class save_access; #endif #endif template<class T> void save_override(T & t){ this->basic_binary_oarchive<Archive>::save_override(t); } void init(unsigned int flags) { if(0 != (flags & no_header)){ return; } #if ! defined(__MWERKS__) this->basic_binary_oarchive<Archive>::init(); this->basic_binary_oprimitive<Archive, Elem, Tr>::init(); #else basic_binary_oarchive<Archive>::init(); basic_binary_oprimitive<Archive, Elem, Tr>::init(); #endif } binary_oarchive_impl( std::basic_streambuf<Elem, Tr> & bsb, unsigned int flags ) : basic_binary_oprimitive<Archive, Elem, Tr>( bsb, 0 != (flags & no_codecvt) ), basic_binary_oarchive<Archive>(flags) {} binary_oarchive_impl( std::basic_ostream<Elem, Tr> & os, unsigned int flags ) : basic_binary_oprimitive<Archive, Elem, Tr>( * os.rdbuf(), 0 != (flags & no_codecvt) ), basic_binary_oarchive<Archive>(flags) {} }; } // namespace archive } // namespace boost

2.3 boost::archive::basic_binary_oarchive

// include\boost\archive\basic_binary_oarchive.hpp namespace boost { namespace archive { namespace detail { template<class Archive> class interface_oarchive; } // namespace detail ////////////////////////////////////////////////////////////////////// // class basic_binary_oarchive - write serialized objects to a binary output stream // note: this archive has no pretensions to portability. Archive format // may vary across machine architectures and compilers. About the only // guarantee is that an archive created with this code will be readable // by a program built with the same tools for the same machine. This class // does have the virtue of building the smallest archive in the minimum amount // of time. So under some circumstances it may be he right choice. template<class Archive> class BOOST_SYMBOL_VISIBLE basic_binary_oarchive : public detail::common_oarchive<Archive> { #ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS public: #else protected: #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) // for some inexplicable reason insertion of "class" generates compile erro // on msvc 7.1 friend detail::interface_oarchive<Archive>; #else friend class detail::interface_oarchive<Archive>; #endif #endif // any datatype not specified below will be handled by base class typedef detail::common_oarchive<Archive> detail_common_oarchive; template<class T> void save_override(const T & t){ this->detail_common_oarchive::save_override(t); } // include these to trap a change in binary format which // isn't specifically handled BOOST_STATIC_ASSERT(sizeof(tracking_type) == sizeof(bool)); // upto 32K classes BOOST_STATIC_ASSERT(sizeof(class_id_type) == sizeof(int_least16_t)); BOOST_STATIC_ASSERT(sizeof(class_id_reference_type) == sizeof(int_least16_t)); // upto 2G objects BOOST_STATIC_ASSERT(sizeof(object_id_type) == sizeof(uint_least32_t)); BOOST_STATIC_ASSERT(sizeof(object_reference_type) == sizeof(uint_least32_t)); // binary files don't include the optional information void save_override(const class_id_optional_type & /* t */){} // enable this if we decide to support generation of previous versions #if 0 void save_override(const boost::archive::version_type & t){ library_version_type lvt = this->get_library_version(); if(boost::serialization::library_version_type(7) < lvt){ this->detail_common_oarchive::save_override(t); } else if(boost::serialization::library_version_type(6) < lvt){ const boost::uint_least16_t x = t; * this->This() << x; } else{ const unsigned int x = t; * this->This() << x; } } void save_override(const boost::serialization::item_version_type & t){ library_version_type lvt = this->get_library_version(); if(boost::serialization::library_version_type(7) < lvt){ this->detail_common_oarchive::save_override(t); } else if(boost::serialization::library_version_type(6) < lvt){ const boost::uint_least16_t x = t; * this->This() << x; } else{ const unsigned int x = t; * this->This() << x; } } void save_override(class_id_type & t){ library_version_type lvt = this->get_library_version(); if(boost::serialization::library_version_type(7) < lvt){ this->detail_common_oarchive::save_override(t); } else if(boost::serialization::library_version_type(6) < lvt){ const boost::int_least16_t x = t; * this->This() << x; } else{ const int x = t; * this->This() << x; } } void save_override(class_id_reference_type & t){ save_override(static_cast<class_id_type &>(t)); } #endif // explicitly convert to char * to avoid compile ambiguities void save_override(const class_name_type & t){ const std::string s(t); * this->This() << s; } #if 0 void save_override(const serialization::collection_size_type & t){ if (get_library_version() < boost::serialization::library_version_type(6)){ unsigned int x=0; * this->This() >> x; t = serialization::collection_size_type(x); } else{ * this->This() >> t; } } #endif BOOST_ARCHIVE_OR_WARCHIVE_DECL void init(); basic_binary_oarchive(unsigned int flags) : detail::common_oarchive<Archive>(flags) {} }; } // namespace archive } // namespace boost

2.4 boost::archive::detail::common_oarchive

// include\boost\archive\detail\common_oarchive.hpp namespace boost { namespace archive { namespace detail { // note: referred to as Curiously Recurring Template Patter (CRTP) template<class Archive> class BOOST_SYMBOL_VISIBLE common_oarchive : public basic_oarchive, public interface_oarchive<Archive> { friend class interface_oarchive<Archive>; friend class basic_oarchive; private: void vsave(const version_type t) BOOST_OVERRIDE { * this->This() << t; } void vsave(const object_id_type t) BOOST_OVERRIDE { * this->This() << t; } void vsave(const object_reference_type t) BOOST_OVERRIDE { * this->This() << t; } void vsave(const class_id_type t) BOOST_OVERRIDE { * this->This() << t; } void vsave(const class_id_reference_type t) BOOST_OVERRIDE { * this->This() << t; } void vsave(const class_id_optional_type t) BOOST_OVERRIDE { * this->This() << t; } void vsave(const class_name_type & t) BOOST_OVERRIDE { * this->This() << t; } void vsave(const tracking_type t) BOOST_OVERRIDE { * this->This() << t; } protected: // default processing - invoke serialization library template<class T> void save_override(T & t){ archive::save(* this->This(), t); } void save_start(const char * /*name*/){} void save_end(const char * /*name*/){} common_oarchive(unsigned int flags = 0) : basic_oarchive(flags), interface_oarchive<Archive>() {} }; } // namespace detail } // namespace archive } // namespace boost

2.5 boost::archive::detail::oserializer

// include\boost\archive\detail\oserializer.hpp namespace boost { namespace serialization { class extended_type_info; } // namespace serialization namespace archive { // ... template<class Archive, class T> inline void save(Archive & ar, /*const*/ T &t){ typedef typename mpl::eval_if<is_pointer< T >, mpl::identity<detail::save_pointer_type<Archive> >, //else typename mpl::eval_if<is_enum< T >, mpl::identity<detail::save_enum_type<Archive> >, //else typename mpl::eval_if<is_array< T >, mpl::identity<detail::save_array_type<Archive> >, //else mpl::identity<detail::save_non_pointer_type<Archive> > > > >::type typex; typex::invoke(ar, t); } } // namespace archive } // namespace boost

2.6 boost::archive::detail::basic_oarchive

// include\boost\archive\detail\basic_oarchive.hpp namespace boost { namespace serialization { class extended_type_info; } // namespace serialization namespace archive { namespace detail { class basic_oarchive_impl; class basic_oserializer; class basic_pointer_oserializer; ////////////////////////////////////////////////////////////////////// // class basic_oarchive - write serialized objects to an output stream class BOOST_SYMBOL_VISIBLE basic_oarchive : private boost::noncopyable, public boost::archive::detail::helper_collection { friend class basic_oarchive_impl; // hide implementation of this class to minimize header conclusion boost::scoped_ptr<basic_oarchive_impl> pimpl; // overload these to bracket object attributes. Used to implement // xml archives virtual void vsave(const version_type t) = 0; virtual void vsave(const object_id_type t) = 0; virtual void vsave(const object_reference_type t) = 0; virtual void vsave(const class_id_type t) = 0; virtual void vsave(const class_id_optional_type t) = 0; virtual void vsave(const class_id_reference_type t) = 0; virtual void vsave(const class_name_type & t) = 0; virtual void vsave(const tracking_type t) = 0; protected: BOOST_ARCHIVE_DECL basic_oarchive(unsigned int flags = 0); BOOST_ARCHIVE_DECL boost::archive::detail::helper_collection & get_helper_collection(); virtual BOOST_ARCHIVE_DECL ~basic_oarchive(); public: // note: NOT part of the public interface BOOST_ARCHIVE_DECL void register_basic_serializer( const basic_oserializer & bos ); BOOST_ARCHIVE_DECL void save_object( const void *x, const basic_oserializer & bos ); BOOST_ARCHIVE_DECL void save_pointer( const void * t, const basic_pointer_oserializer * bpos_ptr ); void save_null_pointer(){ vsave(BOOST_SERIALIZATION_NULL_POINTER_TAG); } // real public interface starts here BOOST_ARCHIVE_DECL void end_preamble(); // default implementation does nothing BOOST_ARCHIVE_DECL boost::serialization::library_version_type get_library_version() const; BOOST_ARCHIVE_DECL unsigned int get_flags() const; }; } // namespace detail } // namespace archive } // namespace boost

2.7 boost::archive::detail::asic_oarchive_impl

// src\basic_oarchive.cpp namespace boost { namespace archive { namespace detail { class basic_oarchive_impl { friend class basic_oarchive; unsigned int m_flags; ////////////////////////////////////////////////////////////////////// // 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 { BOOST_ASSERT(NULL != address); BOOST_ASSERT(NULL != rhs.address); if( address < rhs.address ) return true; if( address > rhs.address ) return false; return class_id < rhs.class_id; } 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<aobject> object_set_type; object_set_type object_set; ////////////////////////////////////////////////////////////////////// // information about each serialized class saved // keyed on type_info struct cobject_type { const basic_oserializer * m_bos_ptr; const class_id_type m_class_id; bool m_initialized; cobject_type( std::size_t class_id, const basic_oserializer & bos ) : m_bos_ptr(& bos), m_class_id(class_id), m_initialized(false) {} cobject_type(const basic_oserializer & bos) : m_bos_ptr(& bos), m_initialized(false) {} cobject_type( const cobject_type & rhs ) : m_bos_ptr(rhs.m_bos_ptr), m_class_id(rhs.m_class_id), m_initialized(rhs.m_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 *m_bos_ptr < *(rhs.m_bos_ptr); } }; // keyed on type_info typedef std::set<cobject_type> 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<object_id_type> stored_pointers; // address of the most recent object serialized as a pointer // whose data itself is now pending serialization const void * pending_object; const basic_oserializer * pending_bos; basic_oarchive_impl(unsigned int flags) : m_flags(flags), pending_object(NULL), pending_bos(NULL) {} const cobject_type & find(const basic_oserializer & bos); const basic_oserializer * find(const serialization::extended_type_info &ti) const; //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 ); }; } // namespace detail } // namespace archive } // namespace boost

三、关键流程

网络

Boost.Serializationhttps://www.boost.org/doc/libs/latest/libs/serialization/doc/index.html

Github: Boost.Serializationhttps://github.com/boostorg/serialization/tree/develop

http://www.jsqmd.com/news/472814/

相关文章:

  • 国产化解决方案!鼎讯信通 射频信号源模块 DXSL系列
  • 哺乳动物为什么不长绿毛
  • next-dbm:审批可控、部署高效,解锁数据构建更新新范式
  • 广西选物业律师实践经验分享,效果看得见!
  • 计算机毕业设计springboot基于Java的校园问题反馈系统 基于Spring Boot框架的高校师生诉求处理与服务平台的设计与实现 基于Java Web的校园意见收集与问题跟踪管理系统开发与应用
  • 鱼眼相机标定矫正详细步骤
  • 参观幼儿园前要做哪些准备?
  • 如何封装一个vue组件为hook函数
  • 皮皮宋渗透日记 09|业务逻辑漏洞全总结:登录 / 验证码 / 支付 / 找回密码 / 越权一网打尽
  • OpenClaw 使用指南:指令大集合
  • 数据结构:合并两个有序链表约瑟夫问题详解(C语言实现 + 图解思路)
  • 开源OpenClaw部署指南
  • openClaw实用Skill
  • master 节点 Java 环境安装操作总结
  • 【企业形象】优秀公司介绍PPT,远不止幻灯片!
  • 关于DeepSeek的详细介绍
  • OpenClaw数据安全深度分析:守护AI执行全流程,优选OPE本地部署
  • Flutter 三方库 dnsolve 的鸿蒙化适配指南 - 让网络寻址回归“高确定性”,打造鸿蒙应用专家级的 DNS 解析与全局网络调度底座
  • java深度学习【AI Infra】Pytorch ON Java 简介 学真算法 用真框架 做认真的人 掌握真本领
  • 【求助】穷学生想进linux do论坛
  • 奥尔特云智慧安保解决方案,安全运营“稳定器”
  • 714. 买卖股票的最佳时机含手续费
  • 现象级爆火:一只 “龙虾” 引发的全民狂欢
  • 2026年三防布行业TOP10厂商盘点:谁将引领市场新趋势?
  • Oracle 拒绝放权 MySQL,社区版发展何去何从?
  • pytorch使用笔记、hugging face等
  • 代码随想录算法训练营第三十八天|198.打家劫舍、213.打家劫舍II、337.打家劫舍III。
  • Flutter 三方库 df_collection 的鸿蒙化适配指南 - 强大的集合操作增强工具,优化鸿蒙应用数据处理流
  • 种植保险场景解决方案:遥感技术护航农险高质量发展
  • 第 6 篇 RK 平台开发核心:设备树(DTS)详解,小白也能看懂的保姆级教程