Crazy Eddie's GUI System  ${CEGUI_VERSION}
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
container_proxy.hpp
1 // This file has been generated by Py++.
2 
3 // Copyright (c) 2003 Raoul M. Gough
4 //
5 // Use, modification and distribution is subject to the Boost Software
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
7 // at http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // Header file container_proxy.hpp
10 //
11 // A container-wrapper that provides Python-style reference semantics
12 // for values stored in vector-like containers via element proxies.
13 //
14 // Class invariant:
15 // size() == m_proxies.size()
16 // for 0 <= i < size()
17 // m_proxies[i].get() != 0
18 // m_proxies[i]->owner() == this
19 // m_proxies[i]->index() == i
20 // m_proxies[i]->m_element_ptr.get() == 0
21 //
22 // History
23 // =======
24 // 2003/ 8/26 rmg File creation
25 // 2003/10/23 rmg Change pointer container from map to sequence
26 // 2008/12/08 Roman Change indexing suite layout
27 //
28 // $Id: container_proxy.hpp,v 1.1.2.28 2004/02/08 18:57:42 raoulgough Exp $
29 //
30 
31 #ifndef BOOST_PYTHON_INDEXING_CONTAINER_PROXY_HPP
32 #define BOOST_PYTHON_INDEXING_CONTAINER_PROXY_HPP
33 
34 #include <indexing_suite/proxy_iterator.hpp>
35 #include <indexing_suite/shared_proxy_impl.hpp>
36 #include <indexing_suite/element_proxy.hpp>
37 #include <indexing_suite/element_proxy_traits.hpp>
38 #include <indexing_suite/workaround.hpp>
39 #include <indexing_suite/methods.hpp>
40 
41 #include <vector>
42 #include <cassert>
43 #include <boost/shared_ptr.hpp>
44 #include <boost/mpl/apply.hpp>
45 #include <boost/iterator/iterator_traits.hpp>
46 #include <indexing_suite/container_traits.hpp>
47 #include <indexing_suite/container_suite.hpp>
48 #include <indexing_suite/algorithms.hpp>
49 
50 namespace boost { namespace python { namespace indexing {
51 
52  template<typename T> struct identity {
53  typedef T held_type;
54 
55  static T & get(T & obj) { return obj; }
56  static T const & get(T const & obj) { return obj; }
57 
58  static T create () { return T(); }
59  static T copy (T const &copy) { return copy; }
60  static void assign (T &to, T const &from) { to = from; }
61  static void pre_destruction (T &) { }
62  static void swap (T &one, T &two) { std::swap (one, two); }
63  };
64 
65  template<typename P> struct deref {
66  typedef P held_type;
67 
68  typedef typename boost::iterator_value<P>::type value;
69 
70  static value & get (P & ptr) { return *ptr; }
71  static value const & get (P const & ptr) { return *ptr; }
72 
73  static P create () { return P(); }
74  static P copy (P const &copy) { return copy; }
75  static void assign (P &to, P const &from) { to = from; }
76  static void pre_destruction (P &) { }
77  static void swap (P &one, P &two) { std::swap (one, two); }
78  };
79 
81  // Generates vector type for any element type with default allocator
82  template<typename Element> struct apply {
83  typedef std::vector<Element> type;
84  };
85  };
86 
87 #if BOOST_WORKAROUND (BOOST_MSVC, == 1200)
88  // Early template instantiation (ETI) workaround
89  namespace detail {
90  template<typename Container> struct msvc6_iterator {
91  typedef Container::iterator type;
92  };
93 
94  template<> struct msvc6_iterator<int> {
95  typedef int *type;
96  };
97  }
98 #endif
99 
100  template<class Container,
101  class Holder = identity<Container>,
102  class Generator = vector_generator>
104  {
106  typedef typename Container::iterator raw_iterator;
107  typedef ::boost::detail::iterator_traits<raw_iterator> raw_iterator_traits;
108 
109 #if !defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
110  template<class C> friend class shared_proxy_impl;
111  template<class C, typename E, typename T, typename S, typename I>
112  friend class proxy_iterator;
113 #endif
114 
115  public:
116  typedef typename Holder::held_type held_type;
117 
118  typedef typename Container::size_type size_type;
119  typedef typename Container::difference_type difference_type;
120 
122 
123  typedef typename Container::value_type raw_value_type;
124 
126  typedef value_type reference; // Already has ref. semantics
127 
129  typedef const_value_type const_reference; // Ref. semantics
130 
131  typedef proxy_iterator <self_type, value_type, raw_iterator_traits,
132  size_type, raw_iterator> iterator;
133  typedef iterator const_iterator; // No const_iterator yet implemented
134 
135  public:
136  // Constructors
137  template<typename Iter> container_proxy (Iter start, Iter finish)
138  // Define inline for MSVC6 compatibility
139  : m_held_obj (Holder::create()),
140  m_proxies ()
141  {
142  insert (begin(), start, finish);
143  }
144 
145  container_proxy ();
146  explicit container_proxy (held_type const &h);
147 
149  container_proxy &operator= (container_proxy const &);
150  ~container_proxy ();
151 
152  Container const &raw_container() const; // OK to expose const reference
153 
154  reference at (size_type index);
155  const_reference at (size_type index) const;
156 
157  reference operator[] (size_type index) { return at(index); }
158  const_reference operator[] (size_type index) const { return at(index); }
159 
160  size_type size () const { return raw_container().size(); }
161  size_type capacity () const { return raw_container().capacity(); }
162  void reserve (size_type s);
163 
164  public:
165  iterator begin() { return iterator (this, static_cast<size_type>(0)); }
166  iterator end() { return iterator (this, raw_container().size()); }
167 
168  iterator erase (iterator);
169  iterator erase (iterator, iterator);
170  iterator insert (iterator, raw_value_type const &);
171 
172  template<typename Iter> void insert (iterator iter, Iter from, Iter to)
173  // Define here for MSVC6 compatibility
174  {
175  // Forward insertion to the right overloaded version
176  typedef typename BOOST_ITERATOR_CATEGORY<Iter>::type category;
177  insert (iter, from, to, category());
178  }
179 
180  void push_back (raw_value_type const &copy) { insert (end(), copy); }
181 
182  value_type pop_back () {
183  value_type result = at (size() - 1);
184  erase (end() - 1);
185  return result;
186  }
187 
188  public:
189  // These functions are useful only when client code has direct
190  // non-const acccess to the raw container (e.g. via an indirect
191  // holder supplied to our constructor). Any code that directly
192  // modifies the contents of the raw container (by replacing,
193  // inserting or erasing elements) must notify the container_proxy.
194 
195  void detach_proxy (size_type index);
196  void detach_proxies (size_type from, size_type to);
197  // Call before overwriting element(s) in the raw container
198 
199  void prepare_erase (size_type from, size_type to);
200  // Call before erasing elements directly from the raw container
201 
202  void notify_insertion (size_type from, size_type to);
203  // Call after inserting elements directly into the raw container
204 
205  public:
206  // Convenient replacement of elements (automatic proxy detachment)
207  void replace (size_type index, raw_value_type const &);
208  // template<typename Iter> void replace (size_type index, Iter, Iter);
209 
210  void swap_elements (size_type index1, size_type index2);
211 
212  bool is_valid () const; // Check the class invariant (for testing purposes)
213 
214  private:
215  // Overloads for insertions with/without useful std::distance
216  template<typename Iter>
217  void insert (iterator iter, Iter from, Iter to, std::forward_iterator_tag)
218  // Define here for MSVC6 compatibility
219  {
220  assert (iter.ptr == this);
221  size_type count = std::distance (from, to);
222 
223  // Add empty proxy pointers for the new value(s) (could throw)
224  m_proxies.insert (m_proxies.begin() + iter.index, count, pointer_impl());
225 
226  try
227  {
228  // Insert the new element(s) into the real container (could throw)
229  raw_container().insert(
230  raw_container().begin() + iter.index,
231  from,
232  to);
233 
234  try
235  {
236  // Create new proxies for the new elements (could throw)
237  write_proxies (iter.index, iter.index + count);
238  }
239 
240  catch (...)
241  {
242  raw_container().erase(
243  raw_container().begin() + iter.index,
244  raw_container().begin() + iter.index + count);
245 
246  throw;
247  }
248  }
249 
250  catch (...)
251  {
252  m_proxies.erase(
253  m_proxies.begin() + iter.index,
254  m_proxies.begin() + iter.index + count);
255 
256  throw;
257  }
258 
259  // Adjust any proxies after the inserted elements (nothrow)
260  adjust_proxies(
261  m_proxies.begin() + iter.index + count,
262  m_proxies.end(),
263  static_cast<difference_type> (count));
264  }
265 
266  template<typename Iter>
267  void insert (iterator iter, Iter from, Iter to, std::input_iterator_tag)
268  // Define here for MSVC6 compatibility
269  {
270  // insert overload for iterators where we *can't* get distance()
271  // so just insert elements one at a time
272  while (from != to)
273  {
274  iter = insert (iter, *from++) + 1;
275  }
276  }
277 
278  private:
279  typedef boost::shared_ptr<shared_proxy> pointer_impl;
280 
281  typedef typename mpl::apply1<Generator, pointer_impl>::type
282  pointer_container;
283 
284 #if BOOST_WORKAROUND (BOOST_MSVC, == 1200)
285  typedef detail::msvc6_iterator<pointer_container>::type pointer_iterator;
286 #else
287  typedef typename pointer_container::iterator pointer_iterator;
288 #endif
289 
290 #if defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
291  // Proxies need mutable access, and can't be friends with MSVC6
292  public:
293 #endif
294  Container &raw_container();
295 
296  private:
297  void adjust_proxies (pointer_iterator, pointer_iterator, difference_type);
298  void write_proxies (size_type, size_type);
299  bool clear_proxy (pointer_impl &); // detach and do not reset
300  void clear_proxies (size_type, size_type); // detach and do not reset
301  void claim_all_proxies (); // Makes all proxies point at this object
302 
303  private:
304  held_type m_held_obj;
305  pointer_container m_proxies;
306  };
307 
308  template<class Container, class Holder, class Generator>
311  : m_held_obj (Holder::create()),
312  m_proxies ()
313  {
314  // Container is empty - no further processing
315  }
316 
317  template<class Container, class Holder, class Generator>
318  container_proxy<Container, Holder, Generator>
319  ::container_proxy (held_type const &held)
320  : m_held_obj (Holder::copy (held)),
321  m_proxies (size())
322  {
323  write_proxies (0, size());
324  }
325 
326  template<class Container, class Holder, class Generator>
327  container_proxy<Container, Holder, Generator>
328  ::container_proxy (container_proxy const &copy)
329  : m_held_obj (Holder::copy (copy.m_held_obj)),
330  m_proxies (size())
331  {
332  write_proxies (0, size()); // Create our own proxies for the copied values
333  }
334 
335  template<class Container, class Holder, class Generator>
336  container_proxy<Container, Holder, Generator> &
337  container_proxy<Container, Holder, Generator>
338  ::operator= (container_proxy const &copy)
339  {
340  container_proxy<Container, Holder, Generator> temp (copy);
341  // This could throw, but none of the remaining operations can
342 
343  Holder::swap (m_held_obj, temp.m_held_obj);
344  std::swap (m_proxies, temp.m_proxies);
345 
346  claim_all_proxies ();
347  temp.claim_all_proxies (); // Prepare for detach
348 
349  return *this;
350  // temp destruction detaches any proxies that used to belong to us
351  }
352 
353  template<class Container, class Holder, class Generator>
354  container_proxy<Container, Holder, Generator>
355  ::~container_proxy ()
356  {
357  // Copy original values into any proxies being shared by external pointers
358  clear_proxies (0, size());
359  Holder::pre_destruction (m_held_obj);
360  }
361 
362  template<class Container, class Holder, class Generator>
363  Container &
364  container_proxy<Container, Holder, Generator>
365  ::raw_container ()
366  {
367  return Holder::get (m_held_obj);
368  }
369 
370  template<class Container, class Holder, class Generator>
371  Container const &
372  container_proxy<Container, Holder, Generator>
373  ::raw_container () const
374  {
375  return Holder::get (m_held_obj);
376  }
377 
378  template<class Container, class Holder, class Generator>
379  void container_proxy<Container, Holder, Generator>::reserve (size_type size)
380  {
381  raw_container().reserve (size);
382  m_proxies.reserve (size);
383  }
384 
385  template<class Container, class Holder, class Generator>
386  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::reference
387  container_proxy<Container, Holder, Generator>
388  ::at (size_type index)
389  {
390  pointer_impl const &ptr = m_proxies.BOOST_PYTHON_INDEXING_AT (index);
391  assert (ptr->owner() == this);
392  assert (ptr->index() == index);
393  return reference (ptr);
394  }
395 
396  template<class Container, class Holder, class Generator>
397  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::const_reference
398  container_proxy<Container, Holder, Generator>
399  ::at (size_type index) const
400  {
401  pointer_impl const &ptr = m_proxies.BOOST_PYTHON_INDEXING_AT (index);
402  assert (ptr->owner() == this);
403  assert (ptr->index() == index);
404  return const_reference (ptr);
405  }
406 
407  template<class Container, class Holder, class Generator>
408  void
409  container_proxy<Container, Holder, Generator>
410  ::replace (size_type index, raw_value_type const &copy)
411  {
412  detach_proxy (index);
413  raw_container().BOOST_PYTHON_INDEXING_AT (index) = copy;
414  write_proxies (index, index + 1);
415  }
416 
417  template<class Container, class Holder, class Generator>
418  void
419  container_proxy<Container, Holder, Generator>
420  ::swap_elements (size_type index1, size_type index2)
421  {
422  pointer_impl &ptr1 = m_proxies[index1];
423  pointer_impl &ptr2 = m_proxies[index2];
424 
425  assert (ptr1->owner() == this);
426  assert (ptr2->owner() == this);
427  assert (ptr1->index() == index1);
428  assert (ptr2->index() == index2);
429 
430  // Swap produces the diagrammed transformation. Any external
431  // pointers that refer to proxy1 or proxy2 will end up still
432  // pointing to their original (now relocated) values.
433  //
434  // .. ptr1 .. ptr2 .. .. ptr1 .. ptr2 .. (m_proxies)
435  // | | \ /
436  // | | \/
437  // | | /\.
438  // V V / \.
439  // proxy1 proxy2 --> proxy1 proxy2
440  // | | \ /
441  // | | \/
442  // | | /\.
443  // V V / \.
444  // .. v1 ... v2 .. .. v2 .. v1 .. (raw_container)
445 
446  std::swap (ptr1->m_index, ptr2->m_index);
447  std::swap (ptr1, ptr2);
448  std::swap (raw_container()[index1], raw_container()[index2]);
449 
450  assert (m_proxies[index1]->index() == index1);
451  assert (m_proxies[index2]->index() == index2);
452  }
453 
454  template<class Container, class Holder, class Generator>
455  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
456  container_proxy<Container, Holder, Generator>::erase (iterator iter)
457  {
458  return erase (iter, iter + 1);
459  }
460 
461  template<class Container, class Holder, class Generator>
462  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
463  container_proxy<Container, Holder, Generator>::erase(
464  iterator from, iterator to)
465  {
466  assert (from.ptr == this);
467  assert (to.ptr == this);
468 
469  // Detach and remove the proxies for the about-to-be-erased elements
470  prepare_erase (from.index, to.index);
471 
472  // Erase the elements from the real container
473  raw_iterator result
474  = raw_container().erase(
475  raw_container().begin() + from.index,
476  raw_container().begin() + to.index);
477 
478  return iterator (this, result);
479  }
480 
481  template<class Container, class Holder, class Generator>
482  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
483  container_proxy<Container, Holder, Generator>::insert(
484  iterator iter, raw_value_type const &copy)
485  {
486  // Use the iterator-based version by treating the value as an
487  // array of size one (see section 5.7/4 of the C++98 standard)
488  insert (iter, &copy, (&copy) + 1, std::random_access_iterator_tag());
489 
490  return iter;
491  }
492 
493  template<class Container, class Holder, class Generator>
494  bool container_proxy<Container, Holder, Generator>::clear_proxy(
495  pointer_impl &ptr)
496  {
497  // Warning - this can break the class invariant. Use only when the
498  // pointer is about to be overwritten or removed from m_proxies
499 
500  assert (ptr->owner() == this);
501 
502  if (!ptr.unique())
503  {
504  ptr->detach (); // Cause proxy to copy element value
505  return true;
506  }
507 
508  else
509  {
510  // If the pointer isn't shared, don't bother causing a copy of
511  // the container element, since the proxy is about to be
512  // deleted or reused.
513  return false;
514  }
515  }
516 
517  template<class Container, class Holder, class Generator>
518  void container_proxy<Container, Holder, Generator>::clear_proxies(
519  size_type from_index, size_type to_index)
520  {
521  while (from_index != to_index)
522  {
523  clear_proxy (m_proxies[from_index]);
524  ++from_index;
525  }
526  }
527 
528  template<class Container, class Holder, class Generator>
529  void container_proxy<Container, Holder, Generator>
530  ::detach_proxy (size_type index)
531  {
532  pointer_impl &ptr = m_proxies[index];
533 
534  assert (ptr->index() == index);
535 
536  if (clear_proxy (ptr))
537  {
538  // To maintain class invariant
539  ptr.reset (new shared_proxy (this, index));
540  }
541  }
542 
543  template<class Container, class Holder, class Generator>
544  void container_proxy<Container, Holder, Generator>::detach_proxies(
545  size_type from_index, size_type to_index)
546  {
547  while (from_index != to_index)
548  {
549  detach_proxy (from_index);
550  ++from_index;
551  }
552  }
553 
554  template<class Container, class Holder, class Generator>
555  void container_proxy<Container, Holder, Generator>
556  ::prepare_erase (size_type from_index, size_type to_index)
557  {
558  difference_type deleting = to_index - from_index;
559  pointer_iterator erase_begin = m_proxies.begin() + from_index;
560  pointer_iterator erase_end = m_proxies.begin() + to_index;
561 
562  // Adjust the indexes of any trailing proxies
563  adjust_proxies (erase_end, m_proxies.end(), -deleting);
564 
565  // Detach any proxies without updating our pointers to them
566  clear_proxies (from_index, to_index);
567 
568  // Remove the pointers
569  m_proxies.erase (erase_begin, erase_end);
570  }
571 
572  template<class Container, class Holder, class Generator>
573  void container_proxy<Container, Holder, Generator>::notify_insertion(
574  size_type from_index, size_type to_index)
575  {
576  size_type count = to_index - from_index;
577 
578  m_proxies.insert(
579  m_proxies.begin() + from_index, count, pointer_impl());
580 
581  try
582  {
583  write_proxies (from_index, to_index); // Could throw
584  }
585 
586  catch (...)
587  {
588  m_proxies.erase(
589  m_proxies.begin() + from_index,
590  m_proxies.begin() + to_index);
591 
592  throw;
593  }
594 
595  // Adjust any proxies after the inserted elements (nothrow)
596  adjust_proxies(
597  m_proxies.begin() + to_index,
598  m_proxies.end(),
599  static_cast<difference_type> (count));
600  }
601 
602  template<class Container, class Holder, class Generator>
603  void container_proxy<Container, Holder, Generator>::adjust_proxies(
604  pointer_iterator from,
605  pointer_iterator to,
606  difference_type offset)
607  {
608  while (from != to)
609  {
610  (*from)->m_index += offset;
611  ++from;
612  }
613  }
614 
615  template<class Container, class Holder, class Generator>
616  void container_proxy<Container, Holder, Generator>::write_proxies(
617  size_type from, size_type to)
618  {
619  // (over)write proxy pointers in the given range. Re-uses existing
620  // shared_proxy objects where possible. Does not call detach_proxy
621  // since it is assumed that the original values could have already
622  // been modified and copying them now would be wrong.
623 
624  while (from != to)
625  {
626  pointer_impl &ptr = m_proxies[from];
627 
628  if ((ptr.get() == 0) || (!ptr.unique()))
629  {
630  // Either no proxy yet allocated here, or there is one
631  // but it is being shared by an external pointer.
632  ptr.reset (new shared_proxy (this, from));
633  }
634 
635  else
636  {
637  // Re-use the existing object since we have the only pointer to it
638  assert (ptr->owner() == this);
639  ptr->m_index = from;
640  }
641 
642  ++from;
643  }
644  }
645 
646  template<class Container, class Holder, class Generator>
647  void container_proxy<Container, Holder, Generator>::claim_all_proxies ()
648  {
649  for (pointer_iterator iter = m_proxies.begin();
650  iter != m_proxies.end();
651  ++iter)
652  {
653  (*iter)->m_owner_ptr = this;
654  }
655  }
656 
657  template<class Container, class Holder, class Generator>
658  bool container_proxy<Container, Holder, Generator>::is_valid () const
659  {
660  bool ok = size() == m_proxies.size(); // Sizes must match
661 
662  for (size_type count = 0; ok && (count < size()); ++count)
663  {
664  pointer_impl const &ptr = m_proxies[count];
665 
666  ok = ptr.get() && (ptr->owner() == this) && (ptr->index() == count)
667  && !ptr->m_element_ptr.get();
668  }
669 
670  return ok;
671  }
672 
674  // ContainerTraits implementation for container_proxy instances
676 
677  template<typename Container>
679  {
680  typedef Container container;
681  typedef typename container::raw_value_type value_type; // insert, ...
682  typedef typename container::raw_value_type key_type; // find, count, ...
683  typedef typename container::reference reference; // return values
684 
685  typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <value_type>::param_type
686  value_param;
687  typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <key_type>::param_type
688  key_param;
689 
690 #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
691  // value_traits for the reference type (i.e. our element_proxy
692  // instance) supplies a custom visit_container_class. Compilers
693  // without partial specialization need help here.
694 
695  typedef element_proxy_traits<Container> value_traits_type;
696 
697  // Hide base class visit_container_class, which would call the
698  // unspecialized value_traits version
699  template<typename PythonClass, typename Policy>
700  static void visit_container_class(
701  PythonClass &pyClass, Policy const &policy)
702  {
703  value_traits_type::visit_container_class (pyClass, policy);
704  }
705 #endif
706  };
707 
708 #if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
709  namespace detail {
711  // algorithms support for container_proxy instances
713 
714  template <typename RawContainer, typename Holder, typename Generator>
715  class algorithms_selector<container_proxy<RawContainer, Holder, Generator> >
716  {
718 
721 
722  public:
725  };
726  }
727 #endif
728  template<
729  class Container,
730  method_set_type MethodMask = all_methods,
731  class Traits = container_proxy_traits<Container>
732  >
734  : container_suite<Container, MethodMask, default_algorithms<Traits> >
735  {
736  };
737 
738 } } }
739 
740 #endif // BOOST_PYTHON_INDEXING_CONTAINER_PROXY_HPP
741 
742 
743 
Definition: container_proxy.hpp:65
Definition: algorithms.hpp:42
Definition: container_traits.hpp:113
Definition: python_CEGUI.h:11
Definition: container_proxy.hpp:80
Definition: proxy_iterator.hpp:32
Definition: container_suite.hpp:42
Definition: container_proxy.hpp:103
Definition: element_proxy_traits.hpp:37
Definition: element_proxy.hpp:33
Definition: container_proxy.hpp:82
Definition: container_proxy.hpp:733
Definition: container_proxy.hpp:52
Definition: shared_proxy_impl.hpp:34
Definition: element_proxy.hpp:117
Definition: container_proxy.hpp:678