Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

root/trunk/tango/util/container/more/Vector.d

Revision 5664, 10.4 kB (checked in by mwarning, 10 months ago)

fixes #2064 :: Memory corruption; thanks denis-shel

  • Property svn:eol-style set to native
Line 
1 /*******************************************************************************
2
3         copyright:      Copyright (c) 2008 Kris Bell. All rights reserved
4
5         license:        BSD style: $(LICENSE)
6         
7         version:        Initial release: April 2008     
8         
9         author:         Kris
10
11         Since:          0.99.7
12
13 *******************************************************************************/
14
15 module tango.util.container.more.Vector;
16
17 private import tango.core.Exception : ArrayBoundsException;
18 private import tango.stdc.string : memmove;
19
20 /******************************************************************************
21
22         A vector of the given value-type V, with maximum depth Size. Note
23         that this does no memory allocation of its own when Size != 0, and
24         does heap allocation when Size == 0. Thus you can have a fixed-size
25         low-overhead instance, or a heap oriented instance.
26
27 ******************************************************************************/
28
29 struct Vector (V, int Size = 0)
30 {
31         alias add       push;
32         alias slice     opSlice;
33         alias push      opCatAssign;
34
35         static if (Size == 0)
36                   {
37                   private uint depth;
38                   private V[]  vector;
39                   }
40                else
41                   {
42                   private uint     depth;
43                   private V[Size]  vector;
44                   }
45
46         /***********************************************************************
47
48                 Clear the vector
49
50         ***********************************************************************/
51
52         Vector* clear ()
53         {
54                 depth = 0;
55                 return this;
56         }
57
58         /***********************************************************************
59                 
60                 Return depth of the vector
61
62         ***********************************************************************/
63
64         uint size ()
65         {
66                 return depth;
67         }
68
69         /***********************************************************************
70                 
71                 Return remaining unused slots
72
73         ***********************************************************************/
74
75         uint unused ()
76         {
77                 return vector.length - depth;
78         }
79
80         /***********************************************************************
81                 
82                 Returns a (shallow) clone of this vector
83
84         ***********************************************************************/
85
86         Vector clone ()
87         {       
88                 Vector v;
89                 static if (Size == 0)
90                            v.vector.length = vector.length;
91                
92                 v.vector[0..depth] = vector[0..depth];
93                 v.depth = depth;
94                 return v;
95         }
96
97         /**********************************************************************
98
99                 Add a value to the vector.
100
101                 Throws an exception when the vector is full
102
103         **********************************************************************/
104
105         V* add (V value)
106         {
107                 static if (Size == 0)
108                           {
109                           if (depth >= vector.length)
110                               vector.length = vector.length + 64;
111                           vector[depth++] = value;
112                           }
113                        else
114                           {                         
115                           if (depth < vector.length)
116                               vector[depth++] = value;
117                           else
118                              error (__LINE__);
119                           }
120                 return &vector[depth-1];
121         }
122
123         /**********************************************************************
124
125                 Add a value to the vector.
126
127                 Throws an exception when the vector is full
128
129         **********************************************************************/
130
131         V* add ()
132         {
133                 static if (Size == 0)
134                           {
135                           if (depth >= vector.length)
136                               vector.length = vector.length + 64;
137                           }
138                        else
139                           if (depth >= vector.length)
140                               error (__LINE__);
141
142                 auto p = &vector[depth++];
143                 *p = V.init;
144                 return p;
145         }
146
147         /**********************************************************************
148
149                 Add a series of values to the vector.
150
151                 Throws an exception when the vector is full
152
153         **********************************************************************/
154
155         Vector* append (V[] value...)
156         {
157                 foreach (v; value)
158                          add (v);
159                 return this;
160         }
161
162         /**********************************************************************
163
164                 Remove and return the most recent addition to the vector.
165
166                 Throws an exception when the vector is empty
167
168         **********************************************************************/
169
170         V remove ()
171         {
172                 if (depth)
173                     return vector[--depth];
174
175                 return error (__LINE__);
176         }
177
178         /**********************************************************************
179
180                 Index vector entries, where a zero index represents the
181                 oldest vector entry.
182
183                 Throws an exception when the given index is out of range
184
185         **********************************************************************/
186
187         V remove (uint i)
188         {
189                 if (i < depth)
190                    {
191                    if (i is depth-1)
192                        return remove;
193                    --depth;
194                    auto v = vector [i];
195                    memmove (vector.ptr+i, vector.ptr+i+1, V.sizeof * (depth-i));
196                    return v;
197                    }
198
199                 return error (__LINE__);
200         }
201
202         /**********************************************************************
203
204                 Index vector entries, as though it were an array
205
206                 Throws an exception when the given index is out of range
207
208         **********************************************************************/
209
210         V opIndex (uint i)
211         {
212                 if (i < depth)
213                     return vector [i];
214
215                 return error (__LINE__);
216         }
217
218         /**********************************************************************
219
220                 Assign vector entries as though it were an array.
221
222                 Throws an exception when the given index is out of range
223
224         **********************************************************************/
225
226         V opIndexAssign (V value, uint i)
227         {
228                 if (i < depth)
229                    {
230                    vector[i] = value;
231                    return value;
232                    }
233
234                 return error (__LINE__);
235         }
236
237         /**********************************************************************
238
239                 Return the vector as an array of values, where the first
240                 array entry represents the oldest value.
241                 
242                 Doing a foreach() on the returned array will traverse in
243                 the opposite direction of foreach() upon a vector
244                 
245         **********************************************************************/
246
247         V[] slice ()
248         {
249                 return vector [0 .. depth];
250         }
251
252         /**********************************************************************
253
254                 Throw an exception
255
256         **********************************************************************/
257
258         private V error (size_t line)
259         {
260                 throw new ArrayBoundsException (__FILE__, line);
261         }
262
263         /***********************************************************************
264
265                 Iterate from the most recent to the oldest vector entries
266
267         ***********************************************************************/
268
269         int opApply (int delegate(ref V value) dg)
270         {
271                         int result;
272
273                         for (int i=depth; i-- && result is 0;)
274                              result = dg (vector [i]);
275                         return result;
276         }
277
278         /***********************************************************************
279
280                 Iterate from the most recent to the oldest vector entries
281
282         ***********************************************************************/
283
284         int opApply (int delegate(ref V value, ref bool kill) dg)
285         {
286                         int result;
287
288                         for (int i=depth; i-- && result is 0;)
289                             {
290                             auto kill = false;
291                             result = dg (vector[i], kill);
292                             if (kill)
293                                 remove (i);
294                             }
295                         return result;
296         }
297 }
298
299
300 /*******************************************************************************
301
302 *******************************************************************************/
303
304 debug (Vector)
305 {
306         import tango.io.Stdout;
307
308         void main()
309         {
310                 Vector!(int, 0) v;
311                 v.add (1);
312                
313                 Vector!(int, 10) s;
314
315                 Stdout.formatln ("add four");
316                 s.add (1);
317                 s.add (2);
318                 s.add (3);
319                 s.add (4);
320                 foreach (v; s)
321                          Stdout.formatln ("{}", v);
322
323                 s = s.clone;
324                 Stdout.formatln ("pop one: {}", s.remove);
325                 foreach (v; s)
326                          Stdout.formatln ("{}", v);
327
328                 Stdout.formatln ("remove[1]: {}", s.remove(1));
329                 foreach (v; s)
330                          Stdout.formatln ("{}", v);
331
332                 Stdout.formatln ("remove two");
333                 s.remove;
334                 s.remove;
335                 foreach (v; s)
336                          Stdout.formatln ("> {}", v);
337
338                 s.add (1);
339                 s.add (2);
340                 s.add (3);
341                 s.add (4);
342                 foreach (v, ref k; s)
343                          k = true;
344                 Stdout.formatln ("size {}", s.size);
345         }
346 }
347        
Note: See TracBrowser for help on using the browser.