summaryrefslogtreecommitdiff
path: root/src/list.h
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2007-05-11 07:51:40 +0000
committerMike Buland <eichlan@xagasoft.com>2007-05-11 07:51:40 +0000
commit033c41ed57348abb3a418166b1fb39bfad3312de (patch)
tree72edbb0b7ff35ef35e4d533bca384b4f7c986942 /src/list.h
parentad92dc50b7cdf7cfe086f21d19442d03a90fd05d (diff)
downloadlibbu++-033c41ed57348abb3a418166b1fb39bfad3312de.tar.gz
libbu++-033c41ed57348abb3a418166b1fb39bfad3312de.tar.bz2
libbu++-033c41ed57348abb3a418166b1fb39bfad3312de.tar.xz
libbu++-033c41ed57348abb3a418166b1fb39bfad3312de.zip
Added a list template class, seems to work pretty well for now, I may have
forgotten proper cleanup in the deconstructor, but besides that you can do almost everything you need. I'll make a slist/stack next, probably with the same basic code, just a different structure (not doubley-linked). The xml system from old-libbu++ is almost completely converted, I was going to re-write it, but this seemed easier at first, it may not have been, we'll see. It almost parses everything again, and almost outputs again, and it does use streams now. The FString is partway to doing minimum chunk allocations, so that adding single-characters will be really fast up to the minimum chunk size. I also figured out how to add this optimization without any extra variables taking up space, and it's optional in the template, which is cool. You can specify the size of the blocks (default 256 bytes), if it's 0 then they'll be like the old FString, 1 chunk per operation. The next FString update should be allowing efficient removal from the begining of the string by faking it, and simply moving a secondary base pointer ahead, and then optimizing appends after that fact to simply move the existing data around if you shouldn't have to re-allocate (alla FlexBuf). The final fun addition that I'm planning is a simple switch in the template (boolean) that will switch an FString into a thread-safe mode without changing the interface or anything that you can do with them at all. It may increasing memory usage, but they should still be better than std::strings, and totally thread-safe. The best part of that is that if it's done with a boolean template parameter and if statements that only test that parameter controlling flow, the code that you don't want (threadsafe/non-threadsafe) won't be included at all post-optimization.
Diffstat (limited to 'src/list.h')
-rw-r--r--src/list.h176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/list.h b/src/list.h
new file mode 100644
index 0000000..ec63496
--- /dev/null
+++ b/src/list.h
@@ -0,0 +1,176 @@
1#ifndef LIST_H
2#define LIST_H
3
4#include <memory>
5#include "bu/exceptionbase.h"
6
7namespace Bu
8{
9 template<typename value>
10 struct ListLink
11 {
12 value *pValue;
13 ListLink *pNext;
14 ListLink *pPrev;
15 };
16 template<typename value, typename valuealloc=std::allocator<value>, typename linkalloc=std::allocator<struct ListLink<value> > >
17 class List
18 {
19 private:
20 typedef struct ListLink<value> Link;
21 typedef class List<value, valuealloc, linkalloc> MyType;
22
23 public:
24 List() :
25 pFirst( NULL ),
26 pLast( NULL )
27 {
28 }
29
30 void append( value v )
31 {
32 Link *pNew = la.allocate( sizeof( Link ) );
33 pNew->pValue = va.allocate( sizeof( value ) );
34 va.construct( pNew->pValue, v );
35 if( pFirst == NULL )
36 {
37 // Empty list
38 pFirst = pLast = pNew;
39 pNew->pNext = pNew->pPrev = NULL;
40 }
41 else
42 {
43 pNew->pNext = NULL;
44 pNew->pPrev = pLast;
45 pLast->pNext = pNew;
46 pLast = pNew;
47 }
48 }
49
50 void prepend( value v )
51 {
52 Link *pNew = la.allocate( sizeof( Link ) );
53 pNew->pValue = va.allocate( sizeof( value ) );
54 va.construct( pNew->pValue, v );
55 if( pFirst == NULL )
56 {
57 // Empty list
58 pFirst = pLast = pNew;
59 pNew->pNext = pNew->pPrev = NULL;
60 }
61 else
62 {
63 pNew->pNext = pFirst;
64 pNew->pPrev = NULL;
65 pFirst->pPrev = pNew;
66 pFirst = pNew;
67 }
68 }
69
70 typedef struct iterator
71 {
72 friend class List<value, valuealloc, linkalloc>;
73 private:
74 Link *pLink;
75 iterator() :
76 pLink( NULL )
77 {
78 }
79
80 iterator( Link *pLink ) :
81 pLink( pLink )
82 {
83 }
84
85 public:
86 bool operator==( const iterator &oth )
87 {
88 return ( pLink == oth.pLink );
89 }
90
91 bool operator==( const Link *pOth )
92 {
93 return ( pLink == pOth );
94 }
95
96 bool operator!=( const iterator &oth )
97 {
98 return ( pLink != oth.pLink );
99 }
100
101 bool operator!=( const Link *pOth )
102 {
103 return ( pLink != pOth );
104 }
105
106 value &operator*()
107 {
108 return *(pLink->pValue);
109 }
110
111 value *operator->()
112 {
113 return pLink->pValue();
114 }
115
116 iterator operator++()
117 {
118 if( pLink != NULL )
119 pLink = pLink->pNext;
120 return *this;
121 }
122
123 iterator operator--()
124 {
125 if( pLink != NULL )
126 pLink = pLink->pPrev;
127 return *this;
128 }
129
130 iterator operator++( int )
131 {
132 if( pLink != NULL )
133 pLink = pLink->pNext;
134 return *this;
135 }
136
137 iterator operator--( int )
138 {
139 if( pLink != NULL )
140 pLink = pLink->pPrev;
141 return *this;
142 }
143
144 iterator operator=( const iterator &oth )
145 {
146 pLink = oth.pLink;
147 }
148 };
149
150 iterator begin()
151 {
152 return iterator( pFirst );
153 }
154
155 const Link *end()
156 {
157 return NULL;
158 }
159
160 int getSize()
161 {
162 int j = 0;
163 for( Link *pCur = pFirst; pCur; pCur = pCur->pNext )
164 j++;
165 return j;
166 }
167
168 private:
169 Link *pFirst;
170 Link *pLast;
171 linkalloc la;
172 valuealloc va;
173 };
174}
175
176#endif