1 #ifndef LINKEDSET__HPP
2 #define LINKEDSET__HPP
3 
4 /*  $Id: linkedset.hpp 354590 2012-02-28 16:30:13Z ucko $
5 * ===========================================================================
6 *
7 *                            PUBLIC DOMAIN NOTICE
8 *               National Center for Biotechnology Information
9 *
10 *  This software/database is a "United States Government Work" under the
11 *  terms of the United States Copyright Act.  It was written as part of
12 *  the author's official duties as a United States Government employee and
13 *  thus cannot be copyrighted.  This software/database is freely available
14 *  to the public for use. The National Library of Medicine and the U.S.
15 *  Government have not placed any restriction on its use or reproduction.
16 *
17 *  Although all reasonable efforts have been taken to ensure the accuracy
18 *  and reliability of the software and data, the NLM and the U.S.
19 *  Government do not and cannot warrant the performance or results that
20 *  may be obtained by using this software or data. The NLM and the U.S.
21 *  Government disclaim all warranties, express or implied, including
22 *  warranties of performance, merchantability or fitness for any particular
23 *  purpose.
24 *
25 *  Please cite the author in any work or product based on this material.
26 *
27 * ===========================================================================
28 *
29 * Author: Eugene Vasilchenko
30 *
31 * File Description:
32 *   !!! PUT YOUR DESCRIPTION HERE !!!
33 */
34 
35 #include <corelib/ncbistd.hpp>
36 #include <set>
37 
38 
39 /** @addtogroup LinkedSet
40  *
41  * @{
42  */
43 
44 
45 BEGIN_NCBI_SCOPE
46 
47 template<typename Key> struct SLinkedSetValue;
48 template<typename Key> class CLinkedMultisetBase;
49 
50 template<typename Key>
51 struct SLinkedSetValue
52 {
53     typedef Key key_type;
54     typedef SLinkedSetValue<Key> value_type;
55 
SLinkedSetValueSLinkedSetValue56     SLinkedSetValue(const key_type& key, value_type* next = 0)
57         : m_Key(key), m_Next(next)
58         {
59         }
60 
GetKeySLinkedSetValue61     const key_type& GetKey(void) const
62         {
63             return m_Key;
64         }
GetNextSLinkedSetValue65     value_type* GetNext(void)
66         {
67             return m_Next;
68         }
GetNextSLinkedSetValue69     const value_type* GetNext(void) const
70         {
71             return m_Next;
72         }
73 
operator <SLinkedSetValue74     bool operator<(const value_type& value) const
75         {
76             return GetKey() < value.GetKey();
77         }
78 private:
79     friend class CLinkedMultisetBase<key_type>;
80 
81     const key_type m_Key;
82     value_type* m_Next;
83 };
84 
85 #if 0
86 template<typename Value, typename Compare>
87 class CLinkedSetBase
88 {
89 public:
90     struct SValue
91     {
92         typedef Value value_type;
93 
94         Value value;
95 
96         SValue* Next(void) const
97             {
98                 return m_Next;
99             }
100     private:
101         friend class CLinkedSetBase<Value, Compare>;
102 
103         SValue* m_Next;
104     };
105     typedef set<Value, Compare> TSet;
106 
107     typedef typename TSet::iterator iterator;
108     typedef typename TSet::const_iterator const_iterator;
109     typedef SValue* TForwardIterator;
110 
111     CLinkedSetBase(void)
112         : m_Start(0)
113         {
114         }
115     CLinkedSetBase(Compare comp)
116         : m_Set(comp), m_Start(0)
117         {
118         }
119 
120     bool empty(void) const
121         {
122             return m_Start == 0;
123         }
124 
125     TForwardIterator ForwardBegin(void) const
126         {
127             return m_Start;
128         }
129     TForwardIterator ForwardEnd(void) const
130         {
131             return 0;
132         }
133 
134     iterator begin(void)
135         {
136             return m_Set.begin();
137         }
138     iterator end(void)
139         {
140             return m_Set.end();
141         }
142     iterator find(const Value& value)
143         {
144             return m_Set.find(value);
145         }
146     iterator lower_bound(const Value& value)
147         {
148             return m_Set.lower_bound(value);
149         }
150 
151     const_iterator begin(void) const
152         {
153             return m_Set.begin();
154         }
155     const_iterator end(void) const
156         {
157             return m_Set.end();
158         }
159     const_iterator find(const Value& value) const
160         {
161             return m_Set.find(value);
162         }
163     const_iterator lower_bound(const Value& value) const
164         {
165             return m_Set.lower_bound(value);
166         }
167 
168 protected:
169     void clear(void)
170         {
171             m_Start = 0;
172         }
173 
174     void insertAfter(const SValue& prevValue, const SValue& newValue)
175         {
176             _ASSERT(!newValue.m_Next);
177             newValue.m_Next = prevValue.m_Next;
178             prevValue.m_Next = &newValue;
179         }
180     void insertToStart(const SValue& newValue)
181         {
182             _ASSERT(!newValue.m_Next);
183             newValue.m_Next = m_Start;
184             m_Start = &newValue;
185         }
186 
187     void removeAfter(const SValue& prevValue, const SValue& value)
188         {
189             prevValue.m_Next = value.m_Next;
190 
191         }
192     void removeFromStart(const SValue& value)
193         {
194             m_Start = value.m_Next;
195         }
196 
197 private:
198     TSet m_Set;
199     SValue* m_Start;
200 };
201 
202 template<typename Mapped>
203 class CLinkedSet : public CLinkedSetBase<typename Mapped::key_type>
204 {
205     typedef CLinkedSetBase<typename Mapped::key_type> TParent;
206 public:
207     typedef set<Mapped> TContainer;
208     typedef typename TContainer::size_type size_type;
209     typedef typename TContainer::value_type value_type;
210     typedef typename TContainer::iterator iterator;
211     typedef typename TContainer::const_iterator const_iterator;
212 
213     size_type size(void) const
214         {
215             return m_Container.size();
216         }
217 
218     void clear(void)
219         {
220             m_Container.clear();
221             TParent::clear();
222         }
223 
224     const_iterator begin(void) const
225         {
226             return m_Container.begin();
227         }
228     const_iterator end(void) const
229         {
230             return m_Container.end();
231         }
232     const_iterator find(const value_type& value) const
233         {
234             return m_Container.find(value);
235         }
236     const_iterator lower_bound(const value_type& value) const
237         {
238             return m_Container.lower_bound(value);
239         }
240     const_iterator upper_bound(const value_type& value) const
241         {
242             return m_Container.upper_bound(value);
243         }
244 
245     iterator begin(void)
246         {
247             return m_Container.begin();
248         }
249     iterator end(void)
250         {
251             return m_Container.end();
252         }
253     iterator find(const value_type& value)
254         {
255             return m_Container.find(value);
256         }
257     iterator lower_bound(const value_type& value)
258         {
259             return m_Container.lower_bound(value);
260         }
261     iterator upper_bound(const value_type& value)
262         {
263             return m_Container.upper_bound(value);
264         }
265 
266     pair<iterator, bool> insert(const value_type& value)
267         {
268             pair<iterator, bool> ins = m_Container.insert(value);
269             if ( ins.second ) {
270                 if ( ins.first == begin() )
271                     this->insertToStart(*ins.first);
272                 else {
273                     iterator prev = ins.first;
274                     this->insertAfter(*--prev, *ins.first);
275                 }
276             }
277             return ins;
278         }
279 
280     void erase(iterator iter)
281         {
282             if ( iter == begin() )
283                 this->removeFromStart(*iter);
284             else {
285                 iterator prev = iter;
286                 this->removeAfter(*--prev, *iter);
287             }
288             m_Container.erase(iter);
289         }
290 
291 private:
292     TContainer m_Container;
293 };
294 #endif
295 
296 template<typename Key>
297 class CLinkedMultisetBase
298 {
299 public:
300     typedef Key key_type;
301     typedef SLinkedSetValue<key_type> value_type;
302 
CLinkedMultisetBase(void)303     CLinkedMultisetBase(void)
304         : m_Start(0)
305         {
306         }
307 
empty(void) const308     bool empty(void) const
309         {
310             return m_Start == 0;
311         }
GetStart(void)312     value_type* GetStart(void)
313         {
314             return m_Start;
315         }
GetStart(void) const316     const value_type* GetStart(void) const
317         {
318             return m_Start;
319         }
320 
321 protected:
clear(void)322     void clear(void)
323         {
324             m_Start = 0;
325         }
326 
insertAfter(value_type & prevValue,value_type & newValue)327     void insertAfter(value_type& prevValue, value_type& newValue)
328         {
329             _ASSERT(!newValue.m_Next);
330             newValue.m_Next = prevValue.m_Next;
331             prevValue.m_Next = &newValue;
332         }
insertToStart(value_type & newValue)333     void insertToStart(value_type& newValue)
334         {
335             _ASSERT(!newValue.m_Next);
336             newValue.m_Next = m_Start;
337             m_Start = &newValue;
338         }
339 
removeAfter(value_type & prevValue,value_type & value)340     void removeAfter(value_type& prevValue, value_type& value)
341         {
342             _ASSERT(prevValue.m_Next == &value);
343             prevValue.m_Next = value.m_Next;
344             value.m_Next = 0;
345         }
removeFromStart(value_type & value)346     void removeFromStart(value_type& value)
347         {
348             _ASSERT(m_Start == &value);
349             m_Start = value.m_Next;
350             value.m_Next = 0;
351         }
352 
353 private:
354     value_type* m_Start;
355 };
356 
357 template<typename Mapped>
358 class CLinkedMultiset : public CLinkedMultisetBase<typename Mapped::key_type>
359 {
360     typedef CLinkedMultisetBase<typename Mapped::key_type> TParent;
361 public:
362     typedef multiset<Mapped> TContainer;
363     typedef typename TContainer::size_type size_type;
364     typedef typename TContainer::value_type value_type;
365     typedef typename TContainer::iterator iterator;
366     typedef typename TContainer::const_iterator const_iterator;
367 
size(void) const368     size_type size(void) const
369         {
370             return m_Container.size();
371         }
372 
clear(void)373     void clear(void)
374         {
375             m_Container.clear();
376             TParent::clear();
377         }
378 
begin(void) const379     const_iterator begin(void) const
380         {
381             return m_Container.begin();
382         }
end(void) const383     const_iterator end(void) const
384         {
385             return m_Container.end();
386         }
find(const value_type & value) const387     const_iterator find(const value_type& value) const
388         {
389             return m_Container.find(value);
390         }
lower_bound(const value_type & value) const391     const_iterator lower_bound(const value_type& value) const
392         {
393             return m_Container.lower_bound(value);
394         }
upper_bound(const value_type & value) const395     const_iterator upper_bound(const value_type& value) const
396         {
397             return m_Container.upper_bound(value);
398         }
399 
begin(void)400     iterator begin(void)
401         {
402             return m_Container.begin();
403         }
end(void)404     iterator end(void)
405         {
406             return m_Container.end();
407         }
find(const value_type & value)408     iterator find(const value_type& value)
409         {
410             return m_Container.find(value);
411         }
lower_bound(const value_type & value)412     iterator lower_bound(const value_type& value)
413         {
414             return m_Container.lower_bound(value);
415         }
upper_bound(const value_type & value)416     iterator upper_bound(const value_type& value)
417         {
418             return m_Container.upper_bound(value);
419         }
420 
insert(const value_type & value)421     iterator insert(const value_type& value)
422         {
423             iterator iter = m_Container.insert(value);
424             if ( iter == begin() )
425                 this->insertToStart(get(iter));
426             else {
427                 iterator prev = iter;
428                 this->insertAfter(get(--prev), get(iter));
429             }
430             return iter;
431         }
432 
erase(iterator iter)433     void erase(iterator iter)
434         {
435             if ( iter == begin() )
436                 this->removeFromStart(get(iter));
437             else {
438                 iterator prev = iter;
439                 this->removeAfter(get(--prev), get(iter));
440             }
441             m_Container.erase(iter);
442         }
443 
get(iterator iter)444     static value_type& get(iterator iter)
445         {
446             return const_cast<value_type&>(*iter);
447         }
448 
449 #if defined(_RWSTD_VER) && !defined(_RWSTD_STRICT_ANSI)
allocation_size(size_type buffer_size)450     size_type allocation_size(size_type buffer_size)
451         {
452             return m_Container.allocation_size(buffer_size);
453         }
454 #endif
455 
456 private:
457     TContainer m_Container;
458 };
459 
460 
461 /* @} */
462 
463 
464 //#include <util/linkedset.inl>
465 
466 END_NCBI_SCOPE
467 
468 #endif  /* LINKEDSET__HPP */
469