6.4 Case Studies - A Simple Logging Archive Class

下面这段内容介绍了一个示例,目的是帮助澄清"归档概念(Archive Concept)"的用法,以便用户可以实现自己的归档类。simple_log_archive.hpp 实现了一个简单但实用的归档类,用于将任何可序列化类型以可读的格式发送到输出文本流中。使用这个归档类非常简单,示例如下:

#include "simple_log_archive.hpp"
...
// 显示完整的时间表
simple_log_archive log(std::cout);
log << schedule;

上述代码将时间表 schedule 以可读的格式输出到标准输出流,并且产生了以下输出:

schedule 
 count 6
 item 
  first 
   driver bob
   hour 6
   minute 24
  second -> 
   stops 
    count 3
    item -> 
     latitude 
      degrees 34
      minutes 135
      seconds 52.56
     longitude 
      degrees 134
      minutes 22
      seconds 78.3
...

这个示例的完整代码可以在 demo_simple_log.cpp 中找到。要更好地理解它的工作原理,可以查看 “Trivial Archive”。此外,请注意以下内容:

  • 仅包含了160行代码。
  • 仅包含头文件 - 无需链接到序列化库。
  • 能够显示所有可序列化类型。
  • 缺少一些功能。例如,它不会显示作为二进制数据序列化的信息。
  • 当给定指向多态基类的指针时,它不会显示派生类型的数据,仅显示基类的信息。
  • 如果需要添加这种功能,可以查看下一个示例。

simple_log_archive.hpp

#ifndef BOOST_SIMPLE_LOG_ARCHIVE_HPP
#define BOOST_SIMPLE_LOG_ARCHIVE_HPP

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif

/1/2/3/4/5/6/7/8
// simple_log_archive.hpp

// (C) Copyright 2010 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 <ostream>
#include <cstddef> // std::size_t

#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{ 
    using ::size_t; 
} // namespace std
#endif

#include <boost/type_traits/is_enum.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/access.hpp>

/
// log data to an output stream.  This illustrates a simpler implemenation
// of text output which is useful for getting a formatted display of
// any serializable class.  Intended to be useful as a debugging aid.
class simple_log_archive {
    std::ostream & m_os;
    unsigned int m_depth;

    template<class Archive>
    struct save_enum_type {
        template<class T>
        static void invoke(Archive &ar, const T &t){
            ar.m_os << static_cast<int>(t);
        }
    };
    template<class Archive>
    struct save_primitive {
        template<class T>
        static void invoke(Archive & ar, const T & t){
            ar.m_os << t;
        }
    };
    template<class Archive>
    struct save_only {
        template<class T>
        static void invoke(Archive & ar, const T & t){
            // make sure call is routed through the highest interface that might
            // be specialized by the user.
            boost::serialization::serialize_adl(
                ar, 
                const_cast<T &>(t), 
                ::boost::serialization::version< T >::value
            );
        }
    };
    template<class T>
    void save(const T &t){
        typedef 
            BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<boost::is_enum< T >,
                boost::mpl::identity<save_enum_type<simple_log_archive> >,
            //else
            BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<
                // if its primitive
                    boost::mpl::equal_to<
                        boost::serialization::implementation_level< T >,
                        boost::mpl::int_<boost::serialization::primitive_type>
                    >,
                    boost::mpl::identity<save_primitive<simple_log_archive> >,
            // else
                boost::mpl::identity<save_only<simple_log_archive> >
            > >::type typex;
        typex::invoke(*this, t);
    }    
    #ifndef BOOST_NO_STD_WSTRING
    void save(const std::wstring &ws){
        m_os << "wide string types not suported in log archive";
    }
    #endif

public:
    ///
    // Implement requirements for archive concept

    typedef boost::mpl::bool_<false> is_loading;
    typedef boost::mpl::bool_<true> is_saving;

    // this can be a no-op since we ignore pointer polymorphism
    template<class T>
    void register_type(const T * = NULL){}

    unsigned int get_library_version(){
        return 0;
    }

    void 
    save_binary(const void *address, std::size_t count){
        m_os << "save_binary not implemented";
    }

    // the << operators 
    template<class T>
    simple_log_archive & operator<<(T const & t){
        m_os << ' ';
        save(t);
        return * this;
    }
    template<class T>
    simple_log_archive & operator<<(T * const t){
        m_os << " ->";
        if(NULL == t)
            m_os << " null";
        else
            *this << * t;
        return * this;
    }
    template<class T, int N>
    simple_log_archive & operator<<(const T (&t)[N]){
        return *this << boost::serialization::make_array(
            static_cast<const T *>(&t[0]),
            N
        );
    }
    template<class T>
    simple_log_archive & operator<<(const boost::serialization::nvp< T > & t){
        m_os << '\n'; // start line with each named object
        // indent according to object depth
        for(unsigned int i = 0; i < m_depth; ++i)
            m_os << ' ';
        ++m_depth;
        m_os << t.name(); // output the name of the object
        * this << t.const_value();
        --m_depth;
        return * this;
    }

    // the & operator 
    template<class T>
    simple_log_archive & operator&(const T & t){
            return * this << t;
    }
    ///

    simple_log_archive(std::ostream & os) :
        m_os(os),
        m_depth(0)
    {}
};

#endif // BOOST_SIMPLE_LOG_ARCHIVE_HPP

demo_log.cpp

/1/2/3/4/5/6/7/8
//
// demo_log.cpp
//
// (C) Copyright 2009 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)

#include <iostream>
#include <cstdio>

#include "demo_gps.hpp"
#include "simple_log_archive.hpp"

int main(int argc, char *argv[])
{   
    // make the schedule
    bus_schedule schedule;

    // fill in the data
    // make a few stops
    bus_stop *bs0 = new bus_stop_corner(
        gps_position(34, 135, 52.560f),
        gps_position(134, 22, 78.30f),
        "24th Street", "10th Avenue"
    );
    bus_stop *bs1 = new bus_stop_corner(
        gps_position(35, 137, 23.456f),
        gps_position(133, 35, 54.12f),
        "State street", "Cathedral Vista Lane"
    );
    bus_stop *bs2 = new bus_stop_destination(
        gps_position(35, 136, 15.456f),
        gps_position(133, 32, 15.300f),
        "White House"
    );
    bus_stop *bs3 = new bus_stop_destination(
        gps_position(35, 134, 48.789f),
        gps_position(133, 32, 16.230f),
        "Lincoln Memorial"
    );

    // make a  routes
    bus_route route0;
    route0.append(bs0);
    route0.append(bs1);
    route0.append(bs2);

    // add trips to schedule
    schedule.append("bob", 6, 24, &route0);
    schedule.append("bob", 9, 57, &route0);
    schedule.append("alice", 11, 02, &route0);

    // make aother routes
    bus_route route1;
    route1.append(bs3);
    route1.append(bs2);
    route1.append(bs1);

    // add trips to schedule
    schedule.append("ted", 7, 17, &route1);
    schedule.append("ted", 9, 38, &route1);
    schedule.append("alice", 11, 47, &route1);

    // display the complete schedule
    simple_log_archive log(std::cout);
    log << schedule;

    delete bs0;
    delete bs1;
    delete bs2;
    delete bs3;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值