LibreOffice Module sw (master)  1
ring.hxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 #ifndef INCLUDED_SW_INC_RING_HXX
20 #define INCLUDED_SW_INC_RING_HXX
21 
22 #include <utility>
23 #include <sal/types.h>
24 #include <iterator>
25 #include <type_traits>
26 #include <boost/iterator/iterator_facade.hpp>
27 #include <boost/intrusive/circular_list_algorithms.hpp>
28 
29 namespace sw
30 {
31  template <typename value_type> class RingContainer;
32  template <typename value_type> class RingIterator;
37  template <typename value_type>
39  {
40  public:
41  typedef typename std::add_const<value_type>::type const_value_type;
44  virtual ~Ring() COVERITY_NOEXCEPT_FALSE
45  { unlink(); };
47  void unlink()
48  {
49  algo::unlink(this);
50  m_pNext = this; // don't leave pointers to old list behind!
51  m_pPrev = this;
52  }
61  void MoveTo( value_type* pDestRing );
63  ring_container GetRingContainer();
65  const_ring_container GetRingContainer() const;
66 
67  protected:
73  Ring()
74  : m_pNext(this)
75  , m_pPrev(this)
76  { }
82  Ring( value_type* pRing );
84  value_type* GetNextInRing()
85  { return static_cast<value_type *>(m_pNext); }
87  value_type* GetPrevInRing()
88  { return static_cast<value_type *>(m_pPrev); }
90  const_value_type* GetNextInRing() const
91  { return static_cast<value_type *>(m_pNext); }
93  const_value_type* GetPrevInRing() const
94  { return static_cast<value_type *>(m_pPrev); }
96  bool unique() const
97  { return algo::unique(static_cast< const_value_type* >(this)); }
98 
99  private:
102  {
103  typedef Ring node;
104  typedef Ring* node_ptr;
105  typedef const Ring* const_node_ptr;
106  static node_ptr get_next(const_node_ptr n) { return const_cast<node_ptr>(n)->m_pNext; };
107  static void set_next(node_ptr n, node_ptr next) { n->m_pNext = next; };
108  static node_ptr get_previous(const_node_ptr n) { return const_cast<node_ptr>(n)->m_pPrev; };
109  static void set_previous(node_ptr n, node_ptr previous) { n->m_pPrev = previous; };
110  };
113  friend typename ring_container::iterator;
114  friend typename ring_container::const_iterator;
115  friend typename const_ring_container::iterator;
116  friend typename const_ring_container::const_iterator;
117  friend class boost::iterator_core_access;
118  typedef boost::intrusive::circular_list_algorithms<Ring_node_traits> algo;
121  };
122 
123  template <typename value_type>
124  inline Ring<value_type>::Ring( value_type* pObj )
125  : m_pNext(this)
126  , m_pPrev(this)
127  {
128  if( pObj )
129  {
130  algo::link_before(pObj, this);
131  }
132  }
133 
134  template <typename value_type>
135  inline void Ring<value_type>::MoveTo(value_type* pDestRing)
136  {
137  value_type* pThis = static_cast< value_type* >(this);
138  unlink();
139  // insert into "new"
140  if (pDestRing)
141  {
142  algo::link_before(pDestRing, pThis);
143  }
144  }
145 
149  template <typename value_type>
150  class SAL_WARN_UNUSED RingContainer final
151  {
152  private:
154  value_type* m_pStart;
155  typedef typename std::remove_const<value_type>::type nonconst_value_type;
156 
157  public:
158  RingContainer( value_type* pRing ) : m_pStart(pRing) {};
159  typedef RingIterator<value_type> iterator;
168  iterator begin();
169  iterator end();
170  const_iterator begin() const;
171  const_iterator end() const;
173  size_t size() const
174  { return std::distance(begin(), end()); }
183  {
184  // first check that we aren't merged already, swapping would
185  // actually un-merge in this case!
186  assert(m_pStart->m_pPrev != aDestRing.m_pStart);
187  assert(m_pStart != aDestRing.m_pStart->m_pPrev);
188  std::swap(m_pStart->m_pPrev->m_pNext, aDestRing.m_pStart->m_pPrev->m_pNext);
189  std::swap(m_pStart->m_pPrev, aDestRing.m_pStart->m_pPrev);
190  }
191  };
192 
193  template <typename value_type>
194  class RingIterator final : public boost::iterator_facade<
195  RingIterator<value_type>
196  , value_type
197  , boost::forward_traversal_tag
198  >
199  {
200  private:
201  typedef typename std::remove_const<value_type>::type nonconst_value_type;
202  public:
204  : m_pCurrent(nullptr)
205  , m_pStart(nullptr)
206  {}
207  explicit RingIterator(nonconst_value_type* pRing, bool bStart = true)
208  : m_pCurrent(nullptr)
209  , m_pStart(pRing)
210  {
211  if(!bStart)
213  }
214 
215  private:
217  void increment()
218  { m_pCurrent = m_pCurrent ? m_pCurrent->GetNextInRing() : m_pStart->GetNextInRing(); }
219  bool equal(RingIterator const& other) const
220  {
221  // we never want to compare iterators from
222  // different rings or starting points
223  assert(m_pStart == other.m_pStart);
224  return m_pCurrent == other.m_pCurrent;
225  }
226  value_type& dereference() const
227  { return m_pCurrent ? *m_pCurrent : * m_pStart; }
234  nonconst_value_type* m_pCurrent;
236  nonconst_value_type* m_pStart;
237  };
238 
239  template <typename value_type>
241  { return Ring<value_type>::ring_container(static_cast< value_type* >(this)); };
242 
243  template <typename value_type>
245  { return Ring<value_type>::const_ring_container(static_cast< const_value_type* >(this)); };
246 
247  template <typename value_type>
249  { return RingContainer<value_type>::iterator(const_cast< nonconst_value_type* >(m_pStart)); };
250 
251  template <typename value_type>
253  { return RingContainer<value_type>::iterator(const_cast< nonconst_value_type* >(m_pStart), false); };
254 
255  template <typename value_type>
257  { return RingContainer<value_type>::const_iterator(const_cast< nonconst_value_type* >(m_pStart)); };
258 
259  template <typename value_type>
261  { return RingContainer<value_type>::const_iterator(const_cast< nonconst_value_type* >(m_pStart), false); };
262 }
263 #endif
264 
265 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void merge(RingContainer< value_type > aDestRing)
Merges two ring containers.
Definition: ring.hxx:182
value_type & dereference() const
Definition: ring.hxx:226
iterator end()
Definition: ring.hxx:252
friend const_ring_container
Definition: ring.hxx:112
nonconst_value_type * m_pStart
the first item of the iteration
Definition: ring.hxx:236
std::remove_const< value_type >::type nonconst_value_type
Definition: ring.hxx:201
helper class that provides Svalue_typeL-style container iteration to the ring
Definition: ring.hxx:31
RingContainer< value_type > ring_container
Definition: ring.hxx:42
Dialog to specify the properties of drop-down form field.
Definition: accframe.hxx:34
internal implementation class – not for external use
Definition: ring.hxx:101
friend ring_container
Definition: ring.hxx:111
void MoveTo(value_type *pDestRing)
Removes this item from its current ring container and adds it to another ring container.
Definition: ring.hxx:135
boost::intrusive::circular_list_algorithms< Ring_node_traits > algo
Definition: ring.hxx:118
enumrange< T >::Iterator begin(enumrange< T >)
RingIterator(nonconst_value_type *pRing, bool bStart=true)
Definition: ring.hxx:207
value_type * GetPrevInRing()
Definition: ring.hxx:87
const Ring * const_node_ptr
Definition: ring.hxx:105
Ring * m_pNext
Definition: ring.hxx:119
static node_ptr get_previous(const_node_ptr n)
Definition: ring.hxx:108
RingContainer(value_type *pRing)
Definition: ring.hxx:158
size_t size() const
Definition: ring.hxx:173
bool unique() const
Definition: ring.hxx:96
friend class boost::iterator_core_access
Definition: ring.hxx:216
value_type * GetNextInRing()
Definition: ring.hxx:84
RingContainer< const_value_type > const_ring_container
Definition: ring.hxx:43
void increment()
Definition: ring.hxx:217
iterator begin()
iterator access
Definition: ring.hxx:248
static void set_previous(node_ptr n, node_ptr previous)
Definition: ring.hxx:109
ring_container GetRingContainer()
Definition: ring.hxx:240
const_value_type * GetPrevInRing() const
Definition: ring.hxx:93
enumrange< T >::Iterator end(enumrange< T >)
const_value_type * GetNextInRing() const
Definition: ring.hxx:90
virtual ~Ring() COVERITY_NOEXCEPT_FALSE
Definition: ring.hxx:44
RingIterator< const value_type > const_iterator
Definition: ring.hxx:160
#define SAL_WARN_UNUSED
std::remove_const< value_type >::type nonconst_value_type
Definition: ring.hxx:155
static node_ptr get_next(const_node_ptr n)
Definition: ring.hxx:106
bool equal(RingIterator const &other) const
Definition: ring.hxx:219
static void set_next(node_ptr n, node_ptr next)
Definition: ring.hxx:107
nonconst_value_type * m_pCurrent
value_type is:
Definition: ring.hxx:234
std::add_const< value_type >::type const_value_type
Definition: ring.hxx:41
void unlink()
algo::unlink is buggy! don't call it directly!
Definition: ring.hxx:47
Ring()
Creates a new item in a ring container all by itself.
Definition: ring.hxx:73
RingIterator< value_type > iterator
Definition: ring.hxx:158
value_type * m_pStart
the item in the ring where iteration starts
Definition: ring.hxx:154
Ring * m_pPrev
Definition: ring.hxx:120