tst_map.hpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. ==============================================================================*/
  6. #if !defined(BOOST_SPIRIT_TST_MAP_JUNE_03_2007_1143AM)
  7. #define BOOST_SPIRIT_TST_MAP_JUNE_03_2007_1143AM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/qi/string/detail/tst.hpp>
  12. #include <boost/unordered_map.hpp>
  13. #include <boost/pool/object_pool.hpp>
  14. namespace boost { namespace spirit { namespace qi
  15. {
  16. struct tst_pass_through; // declared in tst.hpp
  17. template <typename Char, typename T>
  18. struct tst_map
  19. {
  20. typedef Char char_type; // the character type
  21. typedef T value_type; // the value associated with each entry
  22. typedef detail::tst_node<Char, T> node;
  23. tst_map()
  24. {
  25. }
  26. ~tst_map()
  27. {
  28. // Nothing to do here.
  29. // The pools do the right thing for us
  30. }
  31. tst_map(tst_map const& rhs)
  32. {
  33. copy(rhs);
  34. }
  35. tst_map& operator=(tst_map const& rhs)
  36. {
  37. return assign(rhs);
  38. }
  39. template <typename Iterator, typename Filter>
  40. T* find(Iterator& first, Iterator last, Filter filter) const
  41. {
  42. if (first != last)
  43. {
  44. Iterator save = first;
  45. typename map_type::const_iterator
  46. i = map.find(filter(*first++));
  47. if (i == map.end())
  48. {
  49. first = save;
  50. return 0;
  51. }
  52. if (T* p = node::find(i->second.root, first, last, filter))
  53. {
  54. return p;
  55. }
  56. return i->second.data;
  57. }
  58. return 0;
  59. }
  60. template <typename Iterator>
  61. T* find(Iterator& first, Iterator last) const
  62. {
  63. return find(first, last, tst_pass_through());
  64. }
  65. template <typename Iterator>
  66. bool add(
  67. Iterator first
  68. , Iterator last
  69. , typename boost::call_traits<T>::param_type val)
  70. {
  71. if (first != last)
  72. {
  73. map_data x = {0, 0};
  74. std::pair<typename map_type::iterator, bool>
  75. r = map.insert(std::pair<Char, map_data>(*first++, x));
  76. if (first != last)
  77. {
  78. return node::add(r.first->second.root
  79. , first, last, val, this) ? true : false;
  80. }
  81. else
  82. {
  83. if (r.first->second.data)
  84. return false;
  85. r.first->second.data = this->new_data(val);
  86. }
  87. return true;
  88. }
  89. return false;
  90. }
  91. template <typename Iterator>
  92. void remove(Iterator first, Iterator last)
  93. {
  94. if (first != last)
  95. {
  96. typename map_type::iterator i = map.find(*first++);
  97. if (i != map.end())
  98. {
  99. if (first != last)
  100. {
  101. node::remove(i->second.root, first, last, this);
  102. }
  103. else if (i->second.data)
  104. {
  105. this->delete_data(i->second.data);
  106. i->second.data = 0;
  107. }
  108. if (i->second.data == 0 && i->second.root == 0)
  109. {
  110. map.erase(i);
  111. }
  112. }
  113. }
  114. }
  115. void clear()
  116. {
  117. BOOST_FOREACH(typename map_type::value_type& x, map)
  118. {
  119. node::destruct_node(x.second.root, this);
  120. if (x.second.data)
  121. this->delete_data(x.second.data);
  122. }
  123. map.clear();
  124. }
  125. template <typename F>
  126. void for_each(F f) const
  127. {
  128. BOOST_FOREACH(typename map_type::value_type const& x, map)
  129. {
  130. std::basic_string<Char> s(1, x.first);
  131. node::for_each(x.second.root, s, f);
  132. if (x.second.data)
  133. f(s, *x.second.data);
  134. }
  135. }
  136. private:
  137. friend struct detail::tst_node<Char, T>;
  138. struct map_data
  139. {
  140. node* root;
  141. T* data;
  142. };
  143. typedef unordered_map<Char, map_data> map_type;
  144. void copy(tst_map const& rhs)
  145. {
  146. BOOST_FOREACH(typename map_type::value_type const& x, rhs.map)
  147. {
  148. map_data xx = {node::clone_node(x.second.root, this), 0};
  149. if (x.second.data)
  150. xx.data = data_pool.construct(*x.second.data);
  151. map[x.first] = xx;
  152. }
  153. }
  154. tst_map& assign(tst_map const& rhs)
  155. {
  156. if (this != &rhs)
  157. {
  158. BOOST_FOREACH(typename map_type::value_type& x, map)
  159. {
  160. node::destruct_node(x.second.root, this);
  161. }
  162. map.clear();
  163. copy(rhs);
  164. }
  165. return *this;
  166. }
  167. node* new_node(Char id)
  168. {
  169. return node_pool.construct(id);
  170. }
  171. T* new_data(typename boost::call_traits<T>::param_type val)
  172. {
  173. return data_pool.construct(val);
  174. }
  175. void delete_node(node* p)
  176. {
  177. node_pool.destroy(p);
  178. }
  179. void delete_data(T* p)
  180. {
  181. data_pool.destroy(p);
  182. }
  183. map_type map;
  184. object_pool<node> node_pool;
  185. object_pool<T> data_pool;
  186. };
  187. }}}
  188. #endif