Brian Silverman | 3cbbaca | 2018-08-04 23:38:07 -0700 | [diff] [blame^] | 1 | /* Boost.MultiIndex example of serialization of a MRU list. |
| 2 | * |
| 3 | * Copyright 2003-2008 Joaquin M Lopez Munoz. |
| 4 | * Distributed under the Boost Software License, Version 1.0. |
| 5 | * (See accompanying file LICENSE_1_0.txt or copy at |
| 6 | * http://www.boost.org/LICENSE_1_0.txt) |
| 7 | * |
| 8 | * See http://www.boost.org/libs/multi_index for library home page. |
| 9 | */ |
| 10 | |
| 11 | #if !defined(NDEBUG) |
| 12 | #define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING |
| 13 | #define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE |
| 14 | #endif |
| 15 | |
| 16 | #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
| 17 | #include <algorithm> |
| 18 | #include <boost/archive/text_oarchive.hpp> |
| 19 | #include <boost/archive/text_iarchive.hpp> |
| 20 | #include <boost/multi_index_container.hpp> |
| 21 | #include <boost/multi_index/hashed_index.hpp> |
| 22 | #include <boost/multi_index/identity.hpp> |
| 23 | #include <boost/multi_index/sequenced_index.hpp> |
| 24 | #include <fstream> |
| 25 | #include <iostream> |
| 26 | #include <iterator> |
| 27 | #include <sstream> |
| 28 | #include <string> |
| 29 | |
| 30 | using namespace boost::multi_index; |
| 31 | |
| 32 | /* An MRU (most recently used) list keeps record of the last n |
| 33 | * inserted items, listing first the newer ones. Care has to be |
| 34 | * taken when a duplicate item is inserted: instead of letting it |
| 35 | * appear twice, the MRU list relocates it to the first position. |
| 36 | */ |
| 37 | |
| 38 | template <typename Item> |
| 39 | class mru_list |
| 40 | { |
| 41 | typedef multi_index_container< |
| 42 | Item, |
| 43 | indexed_by< |
| 44 | sequenced<>, |
| 45 | hashed_unique<identity<Item> > |
| 46 | > |
| 47 | > item_list; |
| 48 | |
| 49 | public: |
| 50 | typedef Item item_type; |
| 51 | typedef typename item_list::iterator iterator; |
| 52 | |
| 53 | mru_list(std::size_t max_num_items_):max_num_items(max_num_items_){} |
| 54 | |
| 55 | void insert(const item_type& item) |
| 56 | { |
| 57 | std::pair<iterator,bool> p=il.push_front(item); |
| 58 | |
| 59 | if(!p.second){ /* duplicate item */ |
| 60 | il.relocate(il.begin(),p.first); /* put in front */ |
| 61 | } |
| 62 | else if(il.size()>max_num_items){ /* keep the length <= max_num_items */ |
| 63 | il.pop_back(); |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | iterator begin(){return il.begin();} |
| 68 | iterator end(){return il.end();} |
| 69 | |
| 70 | /* Utilities to save and load the MRU list, internally |
| 71 | * based on Boost.Serialization. |
| 72 | */ |
| 73 | |
| 74 | void save_to_file(const char* file_name)const |
| 75 | { |
| 76 | std::ofstream ofs(file_name); |
| 77 | boost::archive::text_oarchive oa(ofs); |
| 78 | oa<<boost::serialization::make_nvp("mru",*this); |
| 79 | } |
| 80 | |
| 81 | void load_from_file(const char* file_name) |
| 82 | { |
| 83 | std::ifstream ifs(file_name); |
| 84 | if(ifs){ |
| 85 | boost::archive::text_iarchive ia(ifs); |
| 86 | ia>>boost::serialization::make_nvp("mru",*this); |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | private: |
| 91 | item_list il; |
| 92 | std::size_t max_num_items; |
| 93 | |
| 94 | /* serialization support */ |
| 95 | |
| 96 | friend class boost::serialization::access; |
| 97 | |
| 98 | template<class Archive> |
| 99 | void serialize(Archive& ar,const unsigned int) |
| 100 | { |
| 101 | ar&BOOST_SERIALIZATION_NVP(il); |
| 102 | ar&BOOST_SERIALIZATION_NVP(max_num_items); |
| 103 | } |
| 104 | }; |
| 105 | |
| 106 | int main() |
| 107 | { |
| 108 | const char* mru_store="mru_store"; |
| 109 | |
| 110 | /* Construct a MRU limited to 10 items and retrieve its |
| 111 | * previous contents. |
| 112 | */ |
| 113 | |
| 114 | mru_list<std::string> mru(10); |
| 115 | mru.load_from_file(mru_store); |
| 116 | |
| 117 | /* main loop */ |
| 118 | |
| 119 | for(;;){ |
| 120 | std::cout<<"enter a term: "; |
| 121 | |
| 122 | std::string line; |
| 123 | std::getline(std::cin,line); |
| 124 | if(line.empty())break; |
| 125 | |
| 126 | std::string term; |
| 127 | std::istringstream iss(line); |
| 128 | iss>>term; |
| 129 | if(term.empty())break; |
| 130 | |
| 131 | mru.insert(term); |
| 132 | |
| 133 | std::cout<<"most recently entered terms:"<<std::endl; |
| 134 | std::copy( |
| 135 | mru.begin(),mru.end(), |
| 136 | std::ostream_iterator<std::string>(std::cout,"\n")); |
| 137 | } |
| 138 | |
| 139 | /* persist the MRU list */ |
| 140 | |
| 141 | mru.save_to_file(mru_store); |
| 142 | |
| 143 | return 0; |
| 144 | } |