summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/multi_index/example
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/multi_index/example')
-rw-r--r--src/boost/libs/multi_index/example/Jamfile.v269
-rw-r--r--src/boost/libs/multi_index/example/basic.cpp119
-rw-r--r--src/boost/libs/multi_index/example/bimap.cpp149
-rw-r--r--src/boost/libs/multi_index/example/complex_structs.cpp315
-rw-r--r--src/boost/libs/multi_index/example/composite_keys.cpp285
-rw-r--r--src/boost/libs/multi_index/example/fun_key.cpp100
-rw-r--r--src/boost/libs/multi_index/example/hashed.cpp124
-rw-r--r--src/boost/libs/multi_index/example/ip_allocator.cpp293
-rw-r--r--src/boost/libs/multi_index/example/non_default_ctor.cpp96
-rw-r--r--src/boost/libs/multi_index/example/random_access.cpp102
-rw-r--r--src/boost/libs/multi_index/example/rearrange.cpp265
-rw-r--r--src/boost/libs/multi_index/example/sequenced.cpp100
-rw-r--r--src/boost/libs/multi_index/example/serialization.cpp144
13 files changed, 2161 insertions, 0 deletions
diff --git a/src/boost/libs/multi_index/example/Jamfile.v2 b/src/boost/libs/multi_index/example/Jamfile.v2
new file mode 100644
index 000000000..a4dc9c318
--- /dev/null
+++ b/src/boost/libs/multi_index/example/Jamfile.v2
@@ -0,0 +1,69 @@
+# Boost.MultiIndex examples Jamfile
+#
+# Copyright 2003-2007 Joaquín M López Muñoz.
+# Distributed under 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/libs/multi_index for library home page.
+
+exe basic
+ : basic.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
+exe bimap
+ : bimap.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
+exe complex_structs
+ : complex_structs.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
+exe composite_keys
+ : composite_keys.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
+exe fun_key
+ : fun_key.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
+exe hashed
+ : hashed.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
+exe ip_allocator
+ : ip_allocator.cpp
+ : <include>$(BOOST_ROOT) <threading>multi
+ ;
+
+exe non_default_ctor
+ : non_default_ctor.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
+exe random_access
+ : random_access.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
+exe rearrange
+ : rearrange.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
+exe sequenced
+ : sequenced.cpp
+ : <include>$(BOOST_ROOT)
+ ;
+
+exe serialization
+ : serialization.cpp
+ /boost/serialization//boost_serialization
+ : <include>$(BOOST_ROOT)
+ ;
diff --git a/src/boost/libs/multi_index/example/basic.cpp b/src/boost/libs/multi_index/example/basic.cpp
new file mode 100644
index 000000000..f7c46ced0
--- /dev/null
+++ b/src/boost/libs/multi_index/example/basic.cpp
@@ -0,0 +1,119 @@
+/* Boost.MultiIndex basic example.
+ *
+ * Copyright 2003-2013 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <string>
+
+using boost::multi_index_container;
+using namespace boost::multi_index;
+
+/* an employee record holds its ID, name and age */
+
+struct employee
+{
+ int id;
+ std::string name;
+ int age;
+
+ employee(int id_,std::string name_,int age_):id(id_),name(name_),age(age_){}
+
+ friend std::ostream& operator<<(std::ostream& os,const employee& e)
+ {
+ os<<e.id<<" "<<e.name<<" "<<e.age<<std::endl;
+ return os;
+ }
+};
+
+/* tags for accessing the corresponding indices of employee_set */
+
+struct id{};
+struct name{};
+struct age{};
+
+/* see Compiler specifics: Use of member_offset for info on
+ * BOOST_MULTI_INDEX_MEMBER
+ */
+
+/* Define a multi_index_container of employees with following indices:
+ * - a unique index sorted by employee::int,
+ * - a non-unique index sorted by employee::name,
+ * - a non-unique index sorted by employee::age.
+ */
+
+typedef multi_index_container<
+ employee,
+ indexed_by<
+ ordered_unique<
+ tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
+ ordered_non_unique<
+ tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,std::string,name)>,
+ ordered_non_unique<
+ tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >
+> employee_set;
+
+template<typename Tag,typename MultiIndexContainer>
+void print_out_by(const MultiIndexContainer& s)
+{
+ /* obtain a reference to the index tagged by Tag */
+
+ const typename boost::multi_index::index<MultiIndexContainer,Tag>::type& i=
+ get<Tag>(s);
+
+ typedef typename MultiIndexContainer::value_type value_type;
+
+ /* dump the elements of the index to cout */
+
+ std::copy(i.begin(),i.end(),std::ostream_iterator<value_type>(std::cout));
+}
+
+
+int main()
+{
+ employee_set es;
+
+ es.insert(employee(0,"Joe",31));
+ es.insert(employee(1,"Robert",27));
+ es.insert(employee(2,"John",40));
+
+ /* next insertion will fail, as there is an employee with
+ * the same ID
+ */
+
+ es.insert(employee(2,"Aristotle",2387));
+
+ es.insert(employee(3,"Albert",20));
+ es.insert(employee(4,"John",57));
+
+ /* list the employees sorted by ID, name and age */
+
+ std::cout<<"by ID"<<std::endl;
+ print_out_by<id>(es);
+ std::cout<<std::endl;
+
+ std::cout<<"by name"<<std::endl;
+ print_out_by<name>(es);
+ std::cout<<std::endl;
+
+ std::cout<<"by age"<<std::endl;
+ print_out_by<age>(es);
+ std::cout<<std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/bimap.cpp b/src/boost/libs/multi_index/example/bimap.cpp
new file mode 100644
index 000000000..aac99d06c
--- /dev/null
+++ b/src/boost/libs/multi_index/example/bimap.cpp
@@ -0,0 +1,149 @@
+/* Boost.MultiIndex example of a bidirectional map.
+ *
+ * Copyright 2003-2009 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <iostream>
+#include <string>
+
+using boost::multi_index_container;
+using namespace boost::multi_index;
+
+/* tags for accessing both sides of a bidirectional map */
+
+struct from{};
+struct to{};
+
+/* The class template bidirectional_map wraps the specification
+ * of a bidirectional map based on multi_index_container.
+ */
+
+template<typename FromType,typename ToType>
+struct bidirectional_map
+{
+ struct value_type
+ {
+ value_type(const FromType& first_,const ToType& second_):
+ first(first_),second(second_)
+ {}
+
+ FromType first;
+ ToType second;
+ };
+
+#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) ||\
+ defined(BOOST_MSVC)&&(BOOST_MSVC<1300) ||\
+ defined(BOOST_INTEL_CXX_VERSION)&&defined(_MSC_VER)&&\
+ (BOOST_INTEL_CXX_VERSION<=700)
+
+/* see Compiler specifics: Use of member_offset for info on member<> and
+ * member_offset<>
+ */
+
+ BOOST_STATIC_CONSTANT(unsigned,from_offset=offsetof(value_type,first));
+ BOOST_STATIC_CONSTANT(unsigned,to_offset =offsetof(value_type,second));
+
+ typedef multi_index_container<
+ value_type,
+ indexed_by<
+ ordered_unique<
+ tag<from>,member_offset<value_type,FromType,from_offset> >,
+ ordered_unique<
+ tag<to>, member_offset<value_type,ToType,to_offset> >
+ >
+ > type;
+
+#else
+
+ /* A bidirectional map can be simulated as a multi_index_container
+ * of pairs of (FromType,ToType) with two unique indices, one
+ * for each member of the pair.
+ */
+
+ typedef multi_index_container<
+ value_type,
+ indexed_by<
+ ordered_unique<
+ tag<from>,member<value_type,FromType,&value_type::first> >,
+ ordered_unique<
+ tag<to>, member<value_type,ToType,&value_type::second> >
+ >
+ > type;
+
+#endif
+};
+
+/* a dictionary is a bidirectional map from strings to strings */
+
+typedef bidirectional_map<std::string,std::string>::type dictionary;
+
+int main()
+{
+ dictionary d;
+
+ /* Fill up our microdictionary. first members Spanish, second members
+ * English.
+ */
+
+ d.insert(dictionary::value_type("hola","hello"));
+ d.insert(dictionary::value_type("adios","goodbye"));
+ d.insert(dictionary::value_type("rosa","rose"));
+ d.insert(dictionary::value_type("mesa","table"));
+
+
+ std::cout<<"enter a word"<<std::endl;
+ std::string word;
+ std::getline(std::cin,word);
+
+#if defined(BOOST_NO_MEMBER_TEMPLATES) /* use global get<> and family instead */
+
+ dictionary::iterator it=get<from>(d).find(word);
+ if(it!=d.end()){
+ std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl;
+ }
+ else{
+ nth_index<dictionary,1>::type::iterator it2=get<1>(d).find(word);
+ if(it2!=get<1>(d).end()){
+ std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl;
+ }
+ else std::cout<<"No such word in the dictionary"<<std::endl;
+ }
+
+#else
+
+ /* search the queried word on the from index (Spanish) */
+
+ dictionary::iterator it=d.get<from>().find(word);
+ if(it!=d.end()){ /* found */
+
+ /* the second part of the element is the equivalent in English */
+
+ std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl;
+ }
+ else{
+ /* word not found in Spanish, try our luck in English */
+
+ dictionary::index<to>::type::iterator it2=d.get<to>().find(word);
+ if(it2!=d.get<to>().end()){
+ std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl;
+ }
+ else std::cout<<"No such word in the dictionary"<<std::endl;
+ }
+
+#endif
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/complex_structs.cpp b/src/boost/libs/multi_index/example/complex_structs.cpp
new file mode 100644
index 000000000..70eb78bcd
--- /dev/null
+++ b/src/boost/libs/multi_index/example/complex_structs.cpp
@@ -0,0 +1,315 @@
+/* Boost.MultiIndex example: complex searches and foreign keys.
+ *
+ * Copyright 2003-2008 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <iostream>
+#include <string>
+
+using boost::multi_index_container;
+using namespace boost::multi_index;
+
+/* This small utility that cascades two key extractors will be
+ * used througout the example.
+ */
+
+template<class KeyExtractor1,class KeyExtractor2>
+struct key_from_key
+{
+public:
+ typedef typename KeyExtractor1::result_type result_type;
+
+ key_from_key(
+ const KeyExtractor1& key1_=KeyExtractor1(),
+ const KeyExtractor2& key2_=KeyExtractor2()):
+ key1(key1_),key2(key2_)
+ {}
+
+ template<typename Arg>
+ result_type operator()(Arg& arg)const
+ {
+ return key1(key2(arg));
+ }
+
+private:
+ KeyExtractor1 key1;
+ KeyExtractor2 key2;
+};
+
+/* tags for accessing several indices defined below */
+
+struct model{};
+struct manufacturer{};
+struct price{};
+
+/* a manufacturer struct just holds the name of the manufacturer */
+
+struct car_manufacturer
+{
+ std::string name;
+
+ car_manufacturer(const std::string& name_):name(name_){}
+};
+
+/* car_model holds the model of car, its price and a pointer to the
+ * manufacturer. The pointer thing eliminates duplication of the same
+ * data among cars of the same manufacturer.
+ */
+
+struct car_model
+{
+ std::string model;
+ const car_manufacturer* manufacturer;
+ int price;
+
+ car_model(
+ const std::string& model_,const car_manufacturer* manufacturer_,int price_):
+ model(model_),manufacturer(manufacturer_),price(price_)
+ {}
+
+ friend std::ostream& operator<<(std::ostream& os,const car_model& c)
+ {
+ os<<c.manufacturer->name<<" "<<c.model<<" $"<<c.price<<std::endl;
+ return os;
+ }
+};
+
+/* see Compiler specifics: Use of member_offset for info on
+ * BOOST_MULTI_INDEX_MEMBER
+ */
+
+/* Car manufacturers are stored in a multi_index_container with one single
+ * index on the name member. This is functionally equivalent to an std::set,
+ * though in this latter case we woud have to define a non-default comparison
+ * predicate (with multi_index_container, member<> does the work for us.)
+ */
+
+typedef multi_index_container<
+ car_manufacturer,
+ indexed_by<
+ ordered_unique<
+ BOOST_MULTI_INDEX_MEMBER(car_manufacturer,std::string,name)
+ >
+ >
+> car_manufacturer_table;
+
+/* Define a multi_index_container of car_models with following indices:
+ * - a unique index sorted by car_model::model,
+ * - a non-unique index sorted by car_model::manufacturer; note the
+ * non-standard manufacturer_extractor used.
+ * - a non-unique index sorted by car_model::price.
+ */
+
+typedef multi_index_container<
+ car_model,
+ indexed_by<
+ ordered_unique<
+ tag<model>,BOOST_MULTI_INDEX_MEMBER(car_model,std::string,model)
+ >,
+ ordered_non_unique<
+ tag<manufacturer>,
+ key_from_key<
+ BOOST_MULTI_INDEX_MEMBER(car_manufacturer,const std::string,name),
+ BOOST_MULTI_INDEX_MEMBER(
+ car_model,const car_manufacturer *,manufacturer)
+ >
+ >,
+ ordered_non_unique<
+ tag<price>,BOOST_MULTI_INDEX_MEMBER(car_model,int,price)
+ >
+ >
+> car_table;
+
+/* We call a *view* to a multi_index_container storing pointers instead of
+ * actual objects. These views are used in the complex search performed
+ * in the program. Resorting to multi_index of pointers eliminates
+ * unnecessary copying of objects, and provides us with an opportunity
+ * to show how BOOST_MULTI_INDEX_MEMBER can be used with pointer
+ * type elements.
+ * car_table_price_view indexes (pointers to) car_models by price.
+ */
+
+typedef multi_index_container<
+ const car_model*,
+ indexed_by<
+ ordered_non_unique<BOOST_MULTI_INDEX_MEMBER(car_model,const int,price)>
+ >
+> car_table_price_view;
+
+/* car_table_manufacturer_view indexes (pointers to) car_models by
+ * manufacturer
+ */
+
+typedef multi_index_container<
+ const car_model*,
+ indexed_by<
+ ordered_non_unique<
+ key_from_key<
+ BOOST_MULTI_INDEX_MEMBER(car_manufacturer,const std::string,name),
+ BOOST_MULTI_INDEX_MEMBER(
+ car_model,const car_manufacturer * const,manufacturer)
+ >
+ >
+ >
+> car_table_manufacturer_view;
+
+int main()
+{
+ car_manufacturer_table cmt;
+
+ /* Fill the car_manufacturer table and keep pointers to the
+ * elements inserted.
+ */
+
+ const car_manufacturer * cadillac=
+ &*(cmt.insert(car_manufacturer("Cadillac")).first);
+ const car_manufacturer * ford =
+ &*(cmt.insert(car_manufacturer("Ford")).first);
+ const car_manufacturer * bmw =
+ &*(cmt.insert(car_manufacturer("BMW")).first);
+ const car_manufacturer * audi =
+ &*(cmt.insert(car_manufacturer("Audi")).first);
+
+ car_table ct;
+
+ /* Fill the car_model_table. We use the previously initialized
+ * pointers to the elements of cmt.
+ */
+
+ ct.insert(car_model("XLR",cadillac,76200));
+ ct.insert(car_model("SRX",cadillac,38690));
+ ct.insert(car_model("CTS",cadillac,30695));
+ ct.insert(car_model("Escalade",cadillac,54770));
+ ct.insert(car_model("ESV",cadillac,57195));
+ ct.insert(car_model("EXT",cadillac,52045));
+ ct.insert(car_model("Deville",cadillac,45195));
+ ct.insert(car_model("Seville",cadillac,46330));
+
+ ct.insert(car_model("ZX2",ford,15355));
+ ct.insert(car_model("Thunderbird",ford,43995));
+ ct.insert(car_model("Windstar",ford,35510));
+ ct.insert(car_model("Focus",ford,19630));
+ ct.insert(car_model("Taurus",ford,24290));
+ ct.insert(car_model("Mustang",ford,39900));
+ ct.insert(car_model("Crown Victoria",ford,30370));
+
+ ct.insert(car_model("325i",bmw,27800));
+ ct.insert(car_model("545i",bmw,54300));
+ ct.insert(car_model("745i",bmw,68500));
+ ct.insert(car_model("M3 coupe",bmw,46500));
+ ct.insert(car_model("Z4 roadster 3.0i",bmw,40250));
+ ct.insert(car_model("X5 4.4i",bmw,49950));
+
+ ct.insert(car_model("A4 1.8T",audi,25940));
+ ct.insert(car_model("TT Coupe",audi,33940));
+ ct.insert(car_model("A6 3.0",audi,36640));
+ ct.insert(car_model("Allroad quattro 2.7T",audi,40640));
+ ct.insert(car_model("A8 L",audi,69190));
+
+ std::cout<<"enter a car manufacturer"<<std::endl;
+ std::string cm;
+ std::getline(std::cin,cm);
+
+ /* check for manufacturer */
+
+ car_manufacturer_table::iterator icm=cmt.find(cm);
+
+ if(icm==cmt.end()){
+ std::cout<<"no such manufacturer in the table"<<std::endl;
+ return 0;
+ }
+
+ std::cout<<"enter a minimum price"<<std::endl;
+ int min_price;
+ std::cin>>min_price;
+ std::cout<<"enter a maximum price"<<std::endl;
+ int max_price;
+ std::cin>>max_price;
+
+ {
+ /* method 1 */
+
+ /* find all the cars for the manufacturer given */
+
+ boost::multi_index::index<car_table,manufacturer>::type::iterator ic0,ic1;
+ boost::tuples::tie(ic0,ic1)=get<manufacturer>(ct).equal_range(cm);
+
+ /* construct a view (indexed by price) with these */
+
+ car_table_price_view ctpv;
+ while(ic0!=ic1){
+ ctpv.insert(&*ic0);
+ ++ic0;
+ }
+
+ /* select the cars in the range given */
+
+ car_table_price_view::iterator ictpv0=ctpv.lower_bound(min_price);
+ car_table_price_view::iterator ictpv1=ctpv.upper_bound(max_price);
+ if(ictpv0==ictpv1){
+ std::cout<<"no cars in the range given"<<std::endl;
+ return 0;
+ }
+
+ /* list them */
+
+ std::cout<<"listing by method 1"<<std::endl;
+ while(ictpv0!=ictpv1){
+ std::cout<<**ictpv0;
+ ++ictpv0;
+ }
+ std::cout<<std::endl;
+ }
+
+ {
+ /* method 2 will give the same results */
+
+ /* find the cars in the range given */
+
+ boost::multi_index::index<car_table,price>::type::iterator ic0,ic1;
+ ic0=get<price>(ct).lower_bound(min_price);
+ ic1=get<price>(ct).upper_bound(max_price);
+
+ /* construct a view with these */
+
+ car_table_manufacturer_view ctmv;
+ while(ic0!=ic1){
+ ctmv.insert(&*ic0);
+ ++ic0;
+ }
+
+ /* select the cars with given manufacturer */
+
+ car_table_manufacturer_view::iterator ictmv0,ictmv1;
+ boost::tuples::tie(ictmv0,ictmv1)=ctmv.equal_range(cm);
+ if(ictmv0==ictmv1){
+ std::cout<<"no cars in the range given"<<std::endl;
+ return 0;
+ }
+
+ /* list them */
+
+ std::cout<<"listing by method 2"<<std::endl;
+ while(ictmv0!=ictmv1){
+ std::cout<<**ictmv0;
+ ++ictmv0;
+ }
+ std::cout<<std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/composite_keys.cpp b/src/boost/libs/multi_index/example/composite_keys.cpp
new file mode 100644
index 000000000..e9da2affa
--- /dev/null
+++ b/src/boost/libs/multi_index/example/composite_keys.cpp
@@ -0,0 +1,285 @@
+/* Boost.MultiIndex example of composite keys.
+ *
+ * Copyright 2003-2008 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/call_traits.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/composite_key.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/next_prior.hpp>
+#include <boost/tokenizer.hpp>
+#include <functional>
+#include <iostream>
+#include <iterator>
+#include <map>
+#include <string>
+
+using namespace boost::multi_index;
+
+/* A file record maintains some info on name and size as well
+ * as a pointer to the directory it belongs (null meaning the root
+ * directory.)
+ */
+
+struct file_entry
+{
+ file_entry(
+ std::string name_,unsigned size_,bool is_dir_,const file_entry* dir_):
+ name(name_),size(size_),is_dir(is_dir_),dir(dir_)
+ {}
+
+ std::string name;
+ unsigned size;
+ bool is_dir;
+ const file_entry* dir;
+
+ friend std::ostream& operator<<(std::ostream& os,const file_entry& f)
+ {
+ os<<f.name<<"\t"<<f.size;
+ if(f.is_dir)os<<"\t <dir>";
+ return os;
+ }
+};
+
+/* A file system is just a multi_index_container of entries with indices on
+ * file and size. These indices are firstly ordered by directory, as commands
+ * work on a current directory basis. Composite keys are just fine to model
+ * this.
+ * NB: The use of derivation here instead of simple typedef is explained in
+ * Compiler specifics: type hiding.
+ */
+
+struct name_key:composite_key<
+ file_entry,
+ BOOST_MULTI_INDEX_MEMBER(file_entry,const file_entry*,dir),
+ BOOST_MULTI_INDEX_MEMBER(file_entry,std::string,name)
+>{};
+
+struct size_key:composite_key<
+ file_entry,
+ BOOST_MULTI_INDEX_MEMBER(file_entry,const file_entry* const,dir),
+ BOOST_MULTI_INDEX_MEMBER(file_entry,unsigned,size)
+>{};
+
+/* see Compiler specifics: composite_key in compilers without partial
+ * template specialization, for info on composite_key_result_less
+ */
+
+typedef multi_index_container<
+ file_entry,
+ indexed_by<
+ /* primary index sorted by name (inside the same directory) */
+ ordered_unique<name_key>,
+ /* secondary index sorted by size (inside the same directory) */
+ ordered_non_unique<size_key>
+ >
+> file_system;
+
+/* typedef's of the two indices of file_system */
+
+typedef nth_index<file_system,0>::type file_system_by_name;
+typedef nth_index<file_system,1>::type file_system_by_size;
+
+/* We build a rudimentary file system simulation out of some global
+ * info and a map of commands provided to the user.
+ */
+
+static file_system fs; /* the one and only file system */
+static file_system_by_name& fs_by_name=fs; /* name index to fs */
+static file_system_by_size& fs_by_size=get<1>(fs); /* size index to fs */
+static const file_entry* current_dir=0; /* root directory */
+
+/* command framework */
+
+/* A command provides an execute memfun fed with the corresponding params
+ * (first param is stripped off as it serves to identify the command
+ * currently being used.)
+ */
+
+typedef boost::tokenizer<boost::char_separator<char> > command_tokenizer;
+
+class command
+{
+public:
+ virtual ~command(){}
+ virtual void execute(
+ command_tokenizer::iterator tok1,command_tokenizer::iterator tok2)=0;
+};
+
+/* available commands */
+
+/* cd: syntax cd [.|..|<directory>] */
+
+class command_cd:public command
+{
+public:
+ virtual void execute(
+ command_tokenizer::iterator tok1,command_tokenizer::iterator tok2)
+ {
+ if(tok1==tok2)return;
+ std::string dir=*tok1++;
+
+ if(dir==".")return;
+ if(dir==".."){
+ if(current_dir)current_dir=current_dir->dir;
+ return;
+ }
+
+ file_system_by_name::iterator it=fs.find(
+ boost::make_tuple(current_dir,dir));
+ if(it==fs.end()){
+ std::cout<<"non-existent directory"<<std::endl;
+ return;
+ }
+ if(!it->is_dir){
+ std::cout<<dir<<" is not a directory"<<std::endl;
+ return;
+ }
+ current_dir=&*it;
+ }
+};
+static command_cd cd;
+
+/* ls: syntax ls [-s] */
+
+class command_ls:public command
+{
+public:
+ virtual void execute(
+ command_tokenizer::iterator tok1,command_tokenizer::iterator tok2)
+ {
+ std::string option;
+ if(tok1!=tok2)option=*tok1++;
+
+ if(!option.empty()){
+ if(option!="-s"){
+ std::cout<<"incorrect parameter"<<std::endl;
+ return;
+ }
+
+ /* list by size */
+
+ file_system_by_size::iterator it0,it1;
+ boost::tie(it0,it1)=fs_by_size.equal_range(
+ boost::make_tuple(current_dir));
+ std::copy(it0,it1,std::ostream_iterator<file_entry>(std::cout,"\n"));
+
+ return;
+ }
+
+ /* list by name */
+
+ file_system_by_name::iterator it0,it1;
+ boost::tie(it0,it1)=fs.equal_range(boost::make_tuple(current_dir));
+ std::copy(it0,it1,std::ostream_iterator<file_entry>(std::cout,"\n"));
+ }
+};
+static command_ls ls;
+
+/* mkdir: syntax mkdir <directory> */
+
+class command_mkdir:public command
+{
+public:
+ virtual void execute(
+ command_tokenizer::iterator tok1,command_tokenizer::iterator tok2)
+ {
+ std::string dir;
+ if(tok1!=tok2)dir=*tok1++;
+
+ if(dir.empty()){
+ std::cout<<"missing parameter"<<std::endl;
+ return;
+ }
+
+ if(dir=="."||dir==".."){
+ std::cout<<"incorrect parameter"<<std::endl;
+ return;
+ }
+
+ if(!fs.insert(file_entry(dir,0,true,current_dir)).second){
+ std::cout<<"directory already exists"<<std::endl;
+ return;
+ }
+ }
+};
+static command_mkdir mkdir;
+
+/* table of commands, a map from command names to class command pointers */
+
+typedef std::map<std::string,command*> command_table;
+static command_table cmt;
+
+int main()
+{
+ /* fill the file system with some data */
+
+ file_system::iterator it0,it1;
+
+ fs.insert(file_entry("usr.cfg",240,false,0));
+ fs.insert(file_entry("memo.txt",2430,false,0));
+ it0=fs.insert(file_entry("dev",0,true,0)).first;
+ fs.insert(file_entry("tty0",128,false,&*it0));
+ fs.insert(file_entry("tty1",128,false,&*it0));
+ it0=fs.insert(file_entry("usr",0,true,0)).first;
+ it1=fs.insert(file_entry("bin",0,true,&*it0)).first;
+ fs.insert(file_entry("bjam",172032,false,&*it1));
+ it0=fs.insert(file_entry("home",0,true,0)).first;
+ it1=fs.insert(file_entry("andy",0,true,&*it0)).first;
+ fs.insert(file_entry("logo.jpg",5345,false,&*it1)).first;
+ fs.insert(file_entry("foo.cpp",890,false,&*it1)).first;
+ fs.insert(file_entry("foo.hpp",93,false,&*it1)).first;
+ fs.insert(file_entry("foo.html",750,false,&*it1)).first;
+ fs.insert(file_entry("a.obj",12302,false,&*it1)).first;
+ fs.insert(file_entry(".bash_history",8780,false,&*it1)).first;
+ it1=fs.insert(file_entry("rachel",0,true,&*it0)).first;
+ fs.insert(file_entry("test.py",650,false,&*it1)).first;
+ fs.insert(file_entry("todo.txt",241,false,&*it1)).first;
+ fs.insert(file_entry(".bash_history",9510,false,&*it1)).first;
+
+ /* fill the command table */
+
+ cmt["cd"] =&cd;
+ cmt["ls"] =&ls;
+ cmt["mkdir"]=&mkdir;
+
+ /* main looop */
+
+ for(;;){
+ /* print out the current directory and the prompt symbol */
+
+ if(current_dir)std::cout<<current_dir->name;
+ std::cout<<">";
+
+ /* get an input line from the user: if empty, exit the program */
+
+ std::string com;
+ std::getline(std::cin,com);
+ command_tokenizer tok(com,boost::char_separator<char>(" \t\n"));
+ if(tok.begin()==tok.end())break; /* null command, exit */
+
+ /* select the corresponding command and execute it */
+
+ command_table::iterator it=cmt.find(*tok.begin());
+ if(it==cmt.end()){
+ std::cout<<"invalid command"<<std::endl;
+ continue;
+ }
+
+ it->second->execute(boost::next(tok.begin()),tok.end());
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/fun_key.cpp b/src/boost/libs/multi_index/example/fun_key.cpp
new file mode 100644
index 000000000..769d7bf6c
--- /dev/null
+++ b/src/boost/libs/multi_index/example/fun_key.cpp
@@ -0,0 +1,100 @@
+/* Boost.MultiIndex example of functions used as key extractors.
+ *
+ * Copyright 2003-2008 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/global_fun.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <iostream>
+#include <string>
+
+using namespace boost::multi_index;
+
+/* A name record consists of the given name (e.g. "Charlie")
+ * and the family name (e.g. "Brown"). The full name, calculated
+ * by name_record::name() is laid out in the "phonebook order"
+ * family name + given_name.
+ */
+
+struct name_record
+{
+ name_record(std::string given_name_,std::string family_name_):
+ given_name(given_name_),family_name(family_name_)
+ {}
+
+ std::string name()const
+ {
+ std::string str=family_name;
+ str+=" ";
+ str+=given_name;
+ return str;
+ }
+
+private:
+ std::string given_name;
+ std::string family_name;
+};
+
+std::string::size_type name_record_length(const name_record& r)
+{
+ return r.name().size();
+}
+
+/* multi_index_container with indices based on name_record::name()
+ * and name_record_length().
+ * See Compiler specifics: Use of const_mem_fun_explicit and
+ * mem_fun_explicit for info on BOOST_MULTI_INDEX_CONST_MEM_FUN.
+ */
+
+typedef multi_index_container<
+ name_record,
+ indexed_by<
+ ordered_unique<
+ BOOST_MULTI_INDEX_CONST_MEM_FUN(name_record,std::string,name)
+ >,
+ ordered_non_unique<
+ global_fun<const name_record&,std::string::size_type,name_record_length>
+ >
+ >
+> name_record_set;
+
+int main()
+{
+ name_record_set ns;
+
+ ns.insert(name_record("Joe","Smith"));
+ ns.insert(name_record("Robert","Nightingale"));
+ ns.insert(name_record("Robert","Brown"));
+ ns.insert(name_record("Marc","Tuxedo"));
+
+ /* list the names in ns in phonebook order */
+
+ std::cout<<"Phonenook order\n"
+ <<"---------------"<<std::endl;
+ for(name_record_set::iterator it=ns.begin();it!=ns.end();++it){
+ std::cout<<it->name()<<std::endl;
+ }
+
+ /* list the names in ns according to their length*/
+
+ std::cout<<"\nLength order\n"
+ << "------------"<<std::endl;
+ for(nth_index<name_record_set,1>::type::iterator it1=get<1>(ns).begin();
+ it1!=get<1>(ns).end();++it1){
+ std::cout<<it1->name()<<std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/hashed.cpp b/src/boost/libs/multi_index/example/hashed.cpp
new file mode 100644
index 000000000..98228ea25
--- /dev/null
+++ b/src/boost/libs/multi_index/example/hashed.cpp
@@ -0,0 +1,124 @@
+/* Boost.MultiIndex example of use of hashed indices.
+ *
+ * Copyright 2003-2008 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/tokenizer.hpp>
+#include <iomanip>
+#include <iostream>
+#include <string>
+
+using boost::multi_index_container;
+using namespace boost::multi_index;
+
+/* word_counter keeps the ocurrences of words inserted. A hashed
+ * index allows for fast checking of preexisting entries.
+ */
+
+struct word_counter_entry
+{
+ std::string word;
+ unsigned int occurrences;
+
+ word_counter_entry(std::string word_):word(word_),occurrences(0){}
+};
+
+/* see Compiler specifics: Use of member_offset for info on
+ * BOOST_MULTI_INDEX_MEMBER
+ */
+
+typedef multi_index_container<
+ word_counter_entry,
+ indexed_by<
+ ordered_non_unique<
+ BOOST_MULTI_INDEX_MEMBER(word_counter_entry,unsigned int,occurrences),
+ std::greater<unsigned int> /* sorted beginning with most frequent */
+ >,
+ hashed_unique<
+ BOOST_MULTI_INDEX_MEMBER(word_counter_entry,std::string,word)
+ >
+ >
+> word_counter;
+
+/* utilities */
+
+template<typename T>
+struct increment
+{
+ void operator()(T& x)const{++x;}
+};
+
+typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
+
+int main()
+{
+ /* boostinspect:noascii */
+
+ std::string text=
+ "En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha "
+ "mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga "
+ "antigua, rocín flaco y galgo corredor. Una olla de algo más vaca que "
+ "carnero, salpicón las más noches, duelos y quebrantos los sábados, "
+ "lantejas los viernes, algún palomino de añadidura los domingos, "
+ "consumían las tres partes de su hacienda. El resto della concluían sayo "
+ "de velarte, calzas de velludo para las fiestas, con sus pantuflos de lo "
+ "mesmo, y los días de entresemana se honraba con su vellorí de lo más "
+ "fino. Tenía en su casa una ama que pasaba de los cuarenta, y una "
+ "sobrina que no llegaba a los veinte, y un mozo de campo y plaza, que "
+ "así ensillaba el rocín como tomaba la podadera. Frisaba la edad de "
+ "nuestro hidalgo con los cincuenta años; era de complexión recia, seco "
+ "de carnes, enjuto de rostro, gran madrugador y amigo de la caza. "
+ "Quieren decir que tenía el sobrenombre de Quijada, o Quesada, que en "
+ "esto hay alguna diferencia en los autores que deste caso escriben; "
+ "aunque, por conjeturas verosímiles, se deja entender que se llamaba "
+ "Quejana. Pero esto importa poco a nuestro cuento; basta que en la "
+ "narración dél no se salga un punto de la verdad.";
+
+ /* feed the text into the container */
+
+ word_counter wc;
+ text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
+ unsigned int total_occurrences=0;
+ for(text_tokenizer::iterator it=tok.begin(),it_end=tok.end();
+ it!=it_end;++it){
+ /* Insert the word into the container. If duplicate, wit will point to
+ * the preexistent entry.
+ */
+
+ ++total_occurrences;
+ word_counter::iterator wit=wc.insert(*it).first;
+
+ /* Increment occurrences.
+ * In a lambda-capable compiler, this can be written as:
+ * wc.modify_key(wit,++_1);
+ */
+
+ wc.modify_key(wit,increment<unsigned int>());
+ }
+
+ /* list words by frequency of appearance */
+
+ std::cout<<std::fixed<<std::setprecision(2);
+ for(word_counter::iterator wit=wc.begin(),wit_end=wc.end();
+ wit!=wit_end;++wit){
+ std::cout<<std::setw(11)<<wit->word<<": "
+ <<std::setw(5) <<100.0*wit->occurrences/total_occurrences<<"%"
+ <<std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/ip_allocator.cpp b/src/boost/libs/multi_index/example/ip_allocator.cpp
new file mode 100644
index 000000000..f2c6d677d
--- /dev/null
+++ b/src/boost/libs/multi_index/example/ip_allocator.cpp
@@ -0,0 +1,293 @@
+/* Boost.MultiIndex example of use of Boost.Interprocess allocators.
+ *
+ * Copyright 2003-2008 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <algorithm>
+#include <boost/interprocess/allocators/allocator.hpp>
+#include <boost/interprocess/containers/string.hpp>
+#include <boost/interprocess/managed_mapped_file.hpp>
+#include <boost/interprocess/sync/named_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/member.hpp>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+#include <string>
+
+using boost::multi_index_container;
+using namespace boost::multi_index;
+namespace bip=boost::interprocess;
+
+/* shared_string is a string type placeable in shared memory,
+ * courtesy of Boost.Interprocess.
+ */
+
+typedef bip::basic_string<
+ char,std::char_traits<char>,
+ bip::allocator<char,bip::managed_mapped_file::segment_manager>
+> shared_string;
+
+/* Book record. All its members can be placed in shared memory,
+ * hence the structure itself can too.
+ */
+
+struct book
+{
+ shared_string name;
+ shared_string author;
+ unsigned pages;
+ unsigned prize;
+
+ book(const shared_string::allocator_type& al):
+ name(al),author(al),pages(0),prize(0)
+ {}
+
+ friend std::ostream& operator<<(std::ostream& os,const book& b)
+ {
+ os<<b.author<<": \""<<b.name<<"\", $"<<b.prize<<", "<<b.pages<<" pages\n";
+ return os;
+ }
+};
+
+/* partial_str_less allows for partial searches taking into account
+ * only the first n chars of the strings compared against. See
+ * Tutorial: Basics: Special lookup operations for more info on this
+ * type of comparison functors.
+ */
+
+/* partial_string is a mere string holder used to differentiate from
+ * a plain string.
+ */
+
+struct partial_string
+{
+ partial_string(const shared_string& str):str(str){}
+ shared_string str;
+};
+
+struct partial_str_less
+{
+ bool operator()(const shared_string& x,const shared_string& y)const
+ {
+ return x<y;
+ }
+
+ bool operator()(const shared_string& x,const partial_string& y)const
+ {
+ return x.substr(0,y.str.size())<y.str;
+ }
+
+ bool operator()(const partial_string& x,const shared_string& y)const
+ {
+ return x.str<y.substr(0,x.str.size());
+ }
+};
+
+/* Define a multi_index_container of book records with indices on
+ * author, name and prize. The index on names allows for partial
+ * searches. This container can be placed in shared memory because:
+ * * book can be placed in shared memory.
+ * * We are using a Boost.Interprocess specific allocator.
+ */
+
+/* see Compiler specifics: Use of member_offset for info on
+ * BOOST_MULTI_INDEX_MEMBER
+ */
+
+typedef multi_index_container<
+ book,
+ indexed_by<
+ ordered_non_unique<
+ BOOST_MULTI_INDEX_MEMBER(book,shared_string,author)
+ >,
+ ordered_non_unique<
+ BOOST_MULTI_INDEX_MEMBER(book,shared_string,name),
+ partial_str_less
+ >,
+ ordered_non_unique<
+ BOOST_MULTI_INDEX_MEMBER(book,unsigned,prize)
+ >
+ >,
+ bip::allocator<book,bip::managed_mapped_file::segment_manager>
+> book_container;
+
+/* A small utility to get data entered via std::cin */
+
+template<typename T>
+void enter(const char* msg,T& t)
+{
+ std::cout<<msg;
+ std::string str;
+ std::getline(std::cin,str);
+ std::istringstream iss(str);
+ iss>>t;
+}
+
+void enter(const char* msg,std::string& str)
+{
+ std::cout<<msg;
+ std::getline(std::cin,str);
+}
+
+void enter(const char* msg,shared_string& str)
+{
+ std::cout<<msg;
+ std::string stdstr;
+ std::getline(std::cin,stdstr);
+ str=stdstr.c_str();
+}
+
+int main()
+{
+ /* Create (or open) the memory mapped file where the book container
+ * is stored, along with a mutex for synchronized access.
+ */
+
+ bip::managed_mapped_file seg(
+ bip::open_or_create,"./book_container.db",
+ 65536);
+ bip::named_mutex mutex(
+ bip::open_or_create,"7FD6D7E8-320B-11DC-82CF-F0B655D89593");
+
+ /* create or open the book container in shared memory */
+
+ book_container* pbc=seg.find_or_construct<book_container>("book container")(
+ book_container::ctor_args_list(),
+ book_container::allocator_type(seg.get_segment_manager()));
+
+ std::string command_info=
+ "1. list books by author\n"
+ "2. list all books by prize\n"
+ "3. insert a book\n"
+ "4. delete a book\n"
+ "0. exit\n";
+
+ std::cout<<command_info;
+
+ /* main loop */
+
+ for(bool exit=false;!exit;){
+ int command=-1;
+ enter("command: ",command);
+
+ switch(command){
+ case 0:{ /* exit */
+ exit=true;
+ break;
+ }
+ case 1:{ /* list books by author */
+ std::string author;
+ enter("author (empty=all authors): ",author);
+
+ /* operations with the container must be mutex protected */
+
+ bip::scoped_lock<bip::named_mutex> lock(mutex);
+
+ std::pair<book_container::iterator,book_container::iterator> rng;
+ if(author.empty()){
+ rng=std::make_pair(pbc->begin(),pbc->end());
+ }
+ else{
+ rng=pbc->equal_range(
+ shared_string(
+ author.c_str(),
+ shared_string::allocator_type(seg.get_segment_manager())));
+ }
+
+ if(rng.first==rng.second){
+ std::cout<<"no entries\n";
+ }
+ else{
+ std::copy(
+ rng.first,rng.second,std::ostream_iterator<book>(std::cout));
+ }
+ break;
+ }
+ case 2:{ /* list all books by prize */
+ bip::scoped_lock<bip::named_mutex> lock(mutex);
+
+ std::copy(
+ get<2>(*pbc).begin(),get<2>(*pbc).end(),
+ std::ostream_iterator<book>(std::cout));
+ break;
+ }
+ case 3:{ /* insert a book */
+ book b(shared_string::allocator_type(seg.get_segment_manager()));
+
+ enter("author: ",b.author);
+ enter("name: " ,b.name);
+ enter("prize: " ,b.prize);
+ enter("pages: " ,b.pages);
+
+ std::cout<<"insert the following?\n"<<b<<"(y/n): ";
+ char yn='n';
+ enter("",yn);
+ if(yn=='y'||yn=='Y'){
+ bip::scoped_lock<bip::named_mutex> lock(mutex);
+ pbc->insert(b);
+ }
+
+ break;
+ }
+ case 4:{ /* delete a book */
+ shared_string name(
+ shared_string::allocator_type(seg.get_segment_manager()));
+ enter(
+ "name of the book (you can enter\nonly the first few characters): ",
+ name);
+
+ typedef nth_index<book_container,1>::type index_by_name;
+ index_by_name& idx=get<1>(*pbc);
+ index_by_name::iterator it;
+ book b(shared_string::allocator_type(seg.get_segment_manager()));
+
+ {
+ /* Look for a book whose title begins with name. Note that we
+ * are unlocking after doing the search so as to not leave the
+ * container blocked during user prompting. That is also why a
+ * local copy of the book is done.
+ */
+
+ bip::scoped_lock<bip::named_mutex> lock(mutex);
+
+ it=idx.find(partial_string(name));
+ if(it==idx.end()){
+ std::cout<<"no such book found\n";
+ break;
+ }
+ b=*it;
+ }
+
+ std::cout<<"delete the following?\n"<<b<<"(y/n): ";
+ char yn='n';
+ enter("",yn);
+ if(yn=='y'||yn=='Y'){
+ bip::scoped_lock<bip::named_mutex> lock(mutex);
+ idx.erase(it);
+ }
+
+ break;
+ }
+ default:{
+ std::cout<<"select one option:\n"<<command_info;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/non_default_ctor.cpp b/src/boost/libs/multi_index/example/non_default_ctor.cpp
new file mode 100644
index 000000000..afdbd5133
--- /dev/null
+++ b/src/boost/libs/multi_index/example/non_default_ctor.cpp
@@ -0,0 +1,96 @@
+/* Boost.MultiIndex example of use of multi_index_container::ctor_args_list.
+ *
+ * Copyright 2003-2008 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/identity.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+
+using boost::multi_index_container;
+using namespace boost::multi_index;
+
+/* modulo_less order numbers according to their division residual.
+ * For instance, if modulo==10 then 22 is less than 15 as 22%10==2 and
+ * 15%10==5.
+ */
+
+template<typename IntegralType>
+struct modulo_less
+{
+ modulo_less(IntegralType m):modulo(m){}
+
+ bool operator()(IntegralType x,IntegralType y)const
+ {
+ return (x%modulo)<(y%modulo);
+ }
+
+private:
+ IntegralType modulo;
+};
+
+/* multi_index_container of unsigned ints holding a "natural" index plus
+ * an ordering based on modulo_less.
+ */
+
+typedef multi_index_container<
+ unsigned int,
+ indexed_by<
+ ordered_unique<identity<unsigned int> >,
+ ordered_non_unique<identity<unsigned int>, modulo_less<unsigned int> >
+ >
+> modulo_indexed_set;
+
+int main()
+{
+ /* define a modulo_indexed_set with modulo==10 */
+
+ modulo_indexed_set::ctor_args_list args_list=
+ boost::make_tuple(
+ /* ctor_args for index #0 is default constructible */
+ nth_index<modulo_indexed_set,0>::type::ctor_args(),
+
+ /* first parm is key_from_value, second is our sought for key_compare */
+ boost::make_tuple(identity<unsigned int>(),modulo_less<unsigned int>(10))
+ );
+
+ modulo_indexed_set m(args_list);
+ /* this could have be written online without the args_list variable,
+ * left as it is for explanatory purposes. */
+
+ /* insert some numbers */
+
+ unsigned int numbers[]={0,1,20,40,33,68,11,101,60,34,88,230,21,4,7,17};
+ const std::size_t numbers_length(sizeof(numbers)/sizeof(numbers[0]));
+
+ m.insert(&numbers[0],&numbers[numbers_length]);
+
+ /* lists all numbers in order, along with their "equivalence class", that is,
+ * the equivalent numbers under modulo_less
+ */
+
+ for(modulo_indexed_set::iterator it=m.begin();it!=m.end();++it){
+ std::cout<<*it<<" -> ( ";
+
+ nth_index<modulo_indexed_set,1>::type::iterator it0,it1;
+ boost::tie(it0,it1)=get<1>(m).equal_range(*it);
+ std::copy(it0,it1,std::ostream_iterator<unsigned int>(std::cout," "));
+
+ std::cout<<")"<<std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/random_access.cpp b/src/boost/libs/multi_index/example/random_access.cpp
new file mode 100644
index 000000000..7532c6d9d
--- /dev/null
+++ b/src/boost/libs/multi_index/example/random_access.cpp
@@ -0,0 +1,102 @@
+/* Boost.MultiIndex example of use of random access indices.
+ *
+ * Copyright 2003-2008 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/identity.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/random_access_index.hpp>
+#include <boost/tokenizer.hpp>
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <string>
+
+using boost::multi_index_container;
+using namespace boost::multi_index;
+
+/* text_container holds words as inserted and also keep them indexed
+ * by dictionary order.
+ */
+
+typedef multi_index_container<
+ std::string,
+ indexed_by<
+ random_access<>,
+ ordered_non_unique<identity<std::string> >
+ >
+> text_container;
+
+/* ordered index */
+
+typedef nth_index<text_container,1>::type ordered_text;
+
+/* Helper function for obtaining the position of an element in the
+ * container.
+ */
+
+template<typename IndexIterator>
+text_container::size_type text_position(
+ const text_container& tc,IndexIterator it)
+{
+ /* project to the base index and calculate offset from begin() */
+
+ return project<0>(tc,it)-tc.begin();
+}
+
+typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
+
+int main()
+{
+ std::string text=
+ "'Oh, you wicked little thing!' cried Alice, catching up the kitten, "
+ "and giving it a little kiss to make it understand that it was in "
+ "disgrace. 'Really, Dinah ought to have taught you better manners! You "
+ "ought, Dinah, you know you ought!' she added, looking reproachfully at "
+ "the old cat, and speaking in as cross a voice as she could manage "
+ "-- and then she scrambled back into the armchair, taking the kitten and "
+ "the worsted with her, and began winding up the ball again. But she "
+ "didn't get on very fast, as she was talking all the time, sometimes to "
+ "the kitten, and sometimes to herself. Kitty sat very demurely on her "
+ "knee, pretending to watch the progress of the winding, and now and then "
+ "putting out one paw and gently touching the ball, as if it would be glad "
+ "to help, if it might.";
+
+ /* feed the text into the container */
+
+ text_container tc;
+ tc.reserve(text.size()); /* makes insertion faster */
+ text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
+ std::copy(tok.begin(),tok.end(),std::back_inserter(tc));
+
+ std::cout<<"enter a position (0-"<<tc.size()-1<<"):";
+ text_container::size_type pos=tc.size();
+ std::cin>>pos;
+ if(pos>=tc.size()){
+ std::cout<<"out of bounds"<<std::endl;
+ }
+ else{
+ std::cout<<"the word \""<<tc[pos]<<"\" appears at position(s): ";
+
+ std::pair<ordered_text::iterator,ordered_text::iterator> p=
+ get<1>(tc).equal_range(tc[pos]);
+ while(p.first!=p.second){
+ std::cout<<text_position(tc,p.first++)<<" ";
+ }
+
+ std::cout<<std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/rearrange.cpp b/src/boost/libs/multi_index/example/rearrange.cpp
new file mode 100644
index 000000000..31388513d
--- /dev/null
+++ b/src/boost/libs/multi_index/example/rearrange.cpp
@@ -0,0 +1,265 @@
+/* Boost.MultiIndex example of use of rearrange facilities.
+ *
+ * Copyright 2003-2015 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/config.hpp>
+#include <boost/detail/iterator.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/random_access_index.hpp>
+#include <boost/random/binomial_distribution.hpp>
+#include <boost/random/uniform_real.hpp>
+#include <boost/random/mersenne_twister.hpp>
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <vector>
+
+#if !defined(BOOST_NO_CXX11_HDR_RANDOM)
+#include <random>
+#endif
+
+using boost::multi_index_container;
+using namespace boost::multi_index;
+
+/* We model a card deck with a random access array containing
+ * card numbers (from 0 to 51), supplemented with an additional
+ * index which retains the start ordering.
+ */
+
+class deck
+{
+ BOOST_STATIC_CONSTANT(std::size_t,num_cards=52);
+
+ typedef multi_index_container<
+ int,
+ indexed_by<
+ random_access<>, /* base index */
+ random_access<> /* "start" index */
+ >
+ > container_type;
+ container_type cont;
+
+public:
+ deck()
+ {
+ cont.reserve(num_cards);
+ get<1>(cont).reserve(num_cards);
+ for(std::size_t i=0;i<num_cards;++i)cont.push_back(i);
+ }
+
+ typedef container_type::iterator iterator;
+ typedef container_type::size_type size_type;
+
+ iterator begin()const{return cont.begin();}
+ iterator end()const{return cont.end();}
+ size_type size()const{return cont.size();}
+
+ template<typename InputIterator>
+ void rearrange(InputIterator it)
+ {
+ cont.rearrange(it);
+ }
+
+ void reset()
+ {
+ /* simply rearrange the base index like the start index */
+
+ cont.rearrange(get<1>(cont).begin());
+ }
+
+ std::size_t position(int i)const
+ {
+ /* The position of a card in the deck is calculated by locating
+ * the card through the start index (which is ordered), projecting
+ * to the base index and diffing with the begin position.
+ * Resulting complexity: constant.
+ */
+
+ return project<0>(cont,get<1>(cont).begin()+i)-cont.begin();
+ }
+
+ std::size_t rising_sequences()const
+ {
+ /* Iterate through all cards and increment the sequence count
+ * when the current position is left to the previous.
+ * Resulting complexity: O(n), n=num_cards.
+ */
+
+ std::size_t s=1;
+ std::size_t last_pos=0;
+
+ for(std::size_t i=0;i<num_cards;++i){
+ std::size_t pos=position(i);
+ if(pos<last_pos)++s;
+ last_pos=pos;
+ }
+
+ return s;
+ }
+};
+
+/* A vector of reference_wrappers to deck elements can be used
+ * as a view to the deck container.
+ * We use a special implicit_reference_wrapper having implicit
+ * ctor from its base type, as this simplifies the use of generic
+ * techniques on the resulting data structures.
+ */
+
+template<typename T>
+class implicit_reference_wrapper:public boost::reference_wrapper<T>
+{
+private:
+ typedef boost::reference_wrapper<T> super;
+public:
+ implicit_reference_wrapper(T& t):super(t){}
+};
+
+typedef std::vector<implicit_reference_wrapper<const int> > deck_view;
+
+/* Riffle shuffle is modeled like this: A cut is selected in the deck
+ * following a binomial distribution. Then, cards are randomly selected
+ * from one packet or the other with probability proportional to
+ * packet size.
+ */
+
+template<typename RandomAccessIterator,typename OutputIterator>
+void riffle_shuffle(
+ RandomAccessIterator first,RandomAccessIterator last,
+ OutputIterator out)
+{
+ static boost::mt19937 rnd_gen;
+
+ typedef typename boost::detail::iterator_traits<
+ RandomAccessIterator>::difference_type difference_type;
+ typedef boost::binomial_distribution<
+ difference_type> rnd_cut_select_type;
+ typedef boost::uniform_real<> rnd_deck_select_type;
+
+ rnd_cut_select_type cut_select(last-first);
+ RandomAccessIterator middle=first+cut_select(rnd_gen);
+ difference_type s0=middle-first;
+ difference_type s1=last-middle;
+ rnd_deck_select_type deck_select;
+
+ while(s0!=0&&s1!=0){
+ if(deck_select(rnd_gen)<(double)s0/(s0+s1)){
+ *out++=*first++;
+ --s0;
+ }
+ else{
+ *out++=*middle++;
+ --s1;
+ }
+ }
+ std::copy(first,first+s0,out);
+ std::copy(middle,middle+s1,out);
+}
+
+struct riffle_shuffler
+{
+ void operator()(deck& d)const
+ {
+ dv.clear();
+ dv.reserve(d.size());
+ riffle_shuffle(
+ d.begin(),d.end(),std::back_inserter(dv)); /* do the shuffling */
+ d.rearrange(dv.begin()); /* apply to the deck */
+ }
+
+private:
+ mutable deck_view dv;
+};
+
+/* A truly random shuffle (up to stdlib implementation quality) using
+ * std::shuffle.
+ */
+
+struct random_shuffler
+{
+ void operator()(deck& d)
+ {
+ dv.clear();
+ dv.reserve(d.size());
+ std::copy(d.begin(),d.end(),std::back_inserter(dv));
+ shuffle_view();
+ d.rearrange(dv.begin()); /* apply to the deck */
+ }
+
+private:
+ deck_view dv;
+
+#if !defined(BOOST_NO_CXX11_HDR_RANDOM)
+ std::mt19937 e;
+
+ void shuffle_view()
+ {
+ std::shuffle(dv.begin(),dv.end(),e);
+ }
+#else
+ /* for pre-C++11 compilers we use std::random_shuffle */
+
+ void shuffle_view()
+ {
+ std::random_shuffle(dv.begin(),dv.end());
+ }
+#endif
+};
+
+/* Repeat a given shuffling algorithm repeats_num times
+ * and obtain the resulting rising sequences number. Average
+ * for tests_num trials.
+ */
+
+template<typename Shuffler>
+double shuffle_test(
+ unsigned int repeats_num,unsigned int tests_num
+ BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Shuffler))
+{
+ deck d;
+ Shuffler sh;
+ unsigned long total=0;
+
+ for(unsigned int n=0;n<tests_num;++n){
+ for(unsigned m=0;m<repeats_num;++m)sh(d);
+ total+=d.rising_sequences();
+ d.reset();
+ }
+
+ return (double)total/tests_num;
+}
+
+int main()
+{
+ unsigned rifs_num=0;
+ unsigned tests_num=0;
+
+ std::cout<<"number of riffle shuffles (vg 5):";
+ std::cin>>rifs_num;
+ std::cout<<"number of tests (vg 1000):";
+ std::cin>>tests_num;
+
+ std::cout<<"shuffling..."<<std::endl;
+
+ std::cout<<"riffle shuffling\n"
+ " avg number of rising sequences: "
+ <<shuffle_test<riffle_shuffler>(rifs_num,tests_num)
+ <<std::endl;
+
+ std::cout<<"random shuffling\n"
+ " avg number of rising sequences: "
+ <<shuffle_test<random_shuffler>(1,tests_num)
+ <<std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/sequenced.cpp b/src/boost/libs/multi_index/example/sequenced.cpp
new file mode 100644
index 000000000..14651da4f
--- /dev/null
+++ b/src/boost/libs/multi_index/example/sequenced.cpp
@@ -0,0 +1,100 @@
+/* Boost.MultiIndex example of use of sequenced indices.
+ *
+ * Copyright 2003-2008 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/identity.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+#include <boost/tokenizer.hpp>
+#include <algorithm>
+#include <iomanip>
+#include <iostream>
+#include <iterator>
+#include <string>
+
+using boost::multi_index_container;
+using namespace boost::multi_index;
+
+/* text_container holds words as inserted and also keep them indexed
+ * by dictionary order.
+ */
+
+typedef multi_index_container<
+ std::string,
+ indexed_by<
+ sequenced<>,
+ ordered_non_unique<identity<std::string> >
+ >
+> text_container;
+
+/* ordered index */
+
+typedef nth_index<text_container,1>::type ordered_text;
+
+typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
+
+int main()
+{
+ std::string text=
+ "Alice was beginning to get very tired of sitting by her sister on the "
+ "bank, and of having nothing to do: once or twice she had peeped into the "
+ "book her sister was reading, but it had no pictures or conversations in "
+ "it, 'and what is the use of a book,' thought Alice 'without pictures or "
+ "conversation?'";
+
+ /* feed the text into the container */
+
+ text_container tc;
+ text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
+ std::copy(tok.begin(),tok.end(),std::back_inserter(tc));
+
+ /* list all words in alphabetical order along with their number
+ * of occurrences
+ */
+
+ ordered_text& ot=get<1>(tc);
+ for(ordered_text::iterator it=ot.begin();it!=ot.end();){
+ std::cout<<std::left<<std::setw(14)<<*it<<":"; /* print the word */
+ ordered_text::iterator it2=ot.upper_bound(*it); /* jump to next */
+ std::cout<<std::right<<std::setw(3) /* and compute the distance */
+ <<std::distance(it,it2)<<" times"<<std::endl;
+ it=it2;
+ }
+
+ /* reverse the text and print it out */
+
+ tc.reverse();
+ std::cout<<std::endl;
+ std::copy(
+ tc.begin(),tc.end(),std::ostream_iterator<std::string>(std::cout," "));
+ std::cout<<std::endl;
+ tc.reverse(); /* undo */
+
+ /* delete most common English words and print the result */
+
+ std::string common_words[]=
+ {"the","of","and","a","to","in","is","you","that","it",
+ "he","for","was","on","are","as","with","his","they","at"};
+
+ for(std::size_t n=0;n<sizeof(common_words)/sizeof(common_words[0]);++n){
+ ot.erase(common_words[n]);
+ }
+ std::cout<<std::endl;
+ std::copy(
+ tc.begin(),tc.end(),std::ostream_iterator<std::string>(std::cout," "));
+ std::cout<<std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/multi_index/example/serialization.cpp b/src/boost/libs/multi_index/example/serialization.cpp
new file mode 100644
index 000000000..46ccf508e
--- /dev/null
+++ b/src/boost/libs/multi_index/example/serialization.cpp
@@ -0,0 +1,144 @@
+/* Boost.MultiIndex example of serialization of a MRU list.
+ *
+ * Copyright 2003-2008 Joaquin M Lopez Munoz.
+ * Distributed under 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/libs/multi_index for library home page.
+ */
+
+#if !defined(NDEBUG)
+#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
+#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
+#endif
+
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <algorithm>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/identity.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+#include <fstream>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+#include <string>
+
+using namespace boost::multi_index;
+
+/* An MRU (most recently used) list keeps record of the last n
+ * inserted items, listing first the newer ones. Care has to be
+ * taken when a duplicate item is inserted: instead of letting it
+ * appear twice, the MRU list relocates it to the first position.
+ */
+
+template <typename Item>
+class mru_list
+{
+ typedef multi_index_container<
+ Item,
+ indexed_by<
+ sequenced<>,
+ hashed_unique<identity<Item> >
+ >
+ > item_list;
+
+public:
+ typedef Item item_type;
+ typedef typename item_list::iterator iterator;
+
+ mru_list(std::size_t max_num_items_):max_num_items(max_num_items_){}
+
+ void insert(const item_type& item)
+ {
+ std::pair<iterator,bool> p=il.push_front(item);
+
+ if(!p.second){ /* duplicate item */
+ il.relocate(il.begin(),p.first); /* put in front */
+ }
+ else if(il.size()>max_num_items){ /* keep the length <= max_num_items */
+ il.pop_back();
+ }
+ }
+
+ iterator begin(){return il.begin();}
+ iterator end(){return il.end();}
+
+ /* Utilities to save and load the MRU list, internally
+ * based on Boost.Serialization.
+ */
+
+ void save_to_file(const char* file_name)const
+ {
+ std::ofstream ofs(file_name);
+ boost::archive::text_oarchive oa(ofs);
+ oa<<boost::serialization::make_nvp("mru",*this);
+ }
+
+ void load_from_file(const char* file_name)
+ {
+ std::ifstream ifs(file_name);
+ if(ifs){
+ boost::archive::text_iarchive ia(ifs);
+ ia>>boost::serialization::make_nvp("mru",*this);
+ }
+ }
+
+private:
+ item_list il;
+ std::size_t max_num_items;
+
+ /* serialization support */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar,const unsigned int)
+ {
+ ar&BOOST_SERIALIZATION_NVP(il);
+ ar&BOOST_SERIALIZATION_NVP(max_num_items);
+ }
+};
+
+int main()
+{
+ const char* mru_store="mru_store";
+
+ /* Construct a MRU limited to 10 items and retrieve its
+ * previous contents.
+ */
+
+ mru_list<std::string> mru(10);
+ mru.load_from_file(mru_store);
+
+ /* main loop */
+
+ for(;;){
+ std::cout<<"enter a term: ";
+
+ std::string line;
+ std::getline(std::cin,line);
+ if(line.empty())break;
+
+ std::string term;
+ std::istringstream iss(line);
+ iss>>term;
+ if(term.empty())break;
+
+ mru.insert(term);
+
+ std::cout<<"most recently entered terms:"<<std::endl;
+ std::copy(
+ mru.begin(),mru.end(),
+ std::ostream_iterator<std::string>(std::cout,"\n"));
+ }
+
+ /* persist the MRU list */
+
+ mru.save_to_file(mru_store);
+
+ return 0;
+}