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
29namespace 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 );
66
67 protected:
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); }
91 { return static_cast<value_type *>(m_pNext); }
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;
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>
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) {};
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:
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; }
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: */
helper class that provides Svalue_typeL-style container iteration to the ring
Definition: ring.hxx:151
value_type * m_pStart
the item in the ring where iteration starts
Definition: ring.hxx:154
void merge(RingContainer< value_type > aDestRing)
Merges two ring containers.
Definition: ring.hxx:182
std::remove_const< value_type >::type nonconst_value_type
Definition: ring.hxx:155
RingIterator< const value_type > const_iterator
Definition: ring.hxx:160
RingIterator< value_type > iterator
Definition: ring.hxx:158
iterator end()
Definition: ring.hxx:252
RingContainer(value_type *pRing)
Definition: ring.hxx:158
iterator begin()
iterator access
Definition: ring.hxx:248
size_t size() const
Definition: ring.hxx:173
bool equal(RingIterator const &other) const
Definition: ring.hxx:219
void increment()
Definition: ring.hxx:217
std::remove_const< value_type >::type nonconst_value_type
Definition: ring.hxx:201
RingIterator(nonconst_value_type *pRing, bool bStart=true)
Definition: ring.hxx:207
value_type & dereference() const
Definition: ring.hxx:226
nonconst_value_type * m_pStart
the first item of the iteration
Definition: ring.hxx:236
nonconst_value_type * m_pCurrent
value_type is:
Definition: ring.hxx:234
friend class boost::iterator_core_access
Definition: ring.hxx:216
const_value_type * GetNextInRing() const
Definition: ring.hxx:90
friend const_ring_container
Definition: ring.hxx:112
boost::intrusive::circular_list_algorithms< Ring_node_traits > algo
Definition: ring.hxx:118
virtual ~Ring() COVERITY_NOEXCEPT_FALSE
Definition: ring.hxx:44
bool unique() const
Definition: ring.hxx:96
std::add_const< value_type >::type const_value_type
Definition: ring.hxx:41
void MoveTo(value_type *pDestRing)
Removes this item from its current ring container and adds it to another ring container.
Definition: ring.hxx:135
void unlink()
algo::unlink is buggy! don't call it directly!
Definition: ring.hxx:47
RingContainer< value_type > ring_container
Definition: ring.hxx:42
Ring()
Creates a new item in a ring container all by itself.
Definition: ring.hxx:73
Ring(value_type *pRing)
Creates a new item and add it to an existing ring container.
Definition: ring.hxx:124
ring_container GetRingContainer()
Definition: ring.hxx:240
value_type * GetPrevInRing()
Definition: ring.hxx:87
friend ring_container
Definition: ring.hxx:111
Ring * m_pPrev
Definition: ring.hxx:120
RingContainer< const_value_type > const_ring_container
Definition: ring.hxx:43
const_ring_container GetRingContainer() const
Definition: ring.hxx:244
Ring * m_pNext
Definition: ring.hxx:119
const_value_type * GetPrevInRing() const
Definition: ring.hxx:93
value_type * GetNextInRing()
Definition: ring.hxx:84
sal_Int64 n
enumrange< T >::Iterator begin(enumrange< T >)
end
Dialog to specify the properties of date form field.
internal implementation class – not for external use
Definition: ring.hxx:102
static node_ptr get_previous(const_node_ptr n)
Definition: ring.hxx:108
const Ring * const_node_ptr
Definition: ring.hxx:105
static node_ptr get_next(const_node_ptr n)
Definition: ring.hxx:106
static void set_next(node_ptr n, node_ptr next)
Definition: ring.hxx:107
static void set_previous(node_ptr n, node_ptr previous)
Definition: ring.hxx:109
#define SAL_WARN_UNUSED