4 * This module contains a simple dynamic array implementation for use in the
5 * Naive Garbage Collector. Standard D dynamic arrays can't be used because
6 * they rely on the GC itself.
9 * Copyright: Public Domain
10 * License: Public Domain
11 * Authors: Leandro Lucarella <llucax@gmail.com>
17 private import tango.stdc.stdlib: realloc;
18 private import tango.stdc.string: memmove;
20 // External runtime functions
21 private extern (C) void onOutOfMemoryError();
29 * This is a simple dynamic array implementation. D dynamic arrays can't be
30 * used because they rely on the GC, and we are implementing the GC.
37 /// Memory block to hold the array.
40 /// Total array capacity, in number of elements.
43 /// Current array size, in number of elements.
48 assert ((this.data && this.capacity)
49 || ((this.data is null) && (this.capacity == 0)));
50 assert (this.capacity >= this.size);
57 * Append a copy of the element x at the end of the array.
59 * This can trigger an allocation if the array is not big enough.
63 if (this.size == this.capacity)
65 this.data[this.size] = x;
70 * Remove the first element for which predicate(element) is true.
72 void remove_if(bool delegate(ref T) predicate)
74 for (size_t i = 0; i < this.size; i++) {
75 if (predicate(this.data[i])) {
77 // move the rest of the items one place to the front
78 memmove(this.data + i, this.data + i + 1,
79 (this.size - i) * T.sizeof);
86 * Remove the first occurrence of the element x from the array.
90 this.remove_if((ref T e) { return e == x; });
94 * Change the current capacity of the array to new_capacity.
96 * This can enlarge or shrink the array, depending on the current capacity.
97 * If new_capacity is 0, the array is enlarged to hold double the current
98 * size. If new_capacity is less than the current size, the current size is
99 * truncated, and the (size - new_capacity) elements at the end are lost.
101 void expand(in size_t new_capacity=0)
103 // adjust new_capacity if necessary
104 if (new_capacity == 0)
105 new_capacity = this.size * 2;
106 if (new_capacity == 0)
108 // reallocate the memory with the new_capacity
109 T* new_data = cast(T*) realloc(this.data, new_capacity * T.sizeof);
110 if (new_data is null)
111 onOutOfMemoryError();
112 this.data = new_data;
113 this.capacity = new_capacity;
114 // truncate the size if necessary
115 if (this.size > this.capacity)
116 this.size = this.capacity;
120 * Remove all the elements of the array and set the capacity to 0.
124 this.data = cast(T*) realloc(this.data, 0);
125 assert (this.data is null);
131 * Iterate over the array elements.
133 int opApply(int delegate(ref T) dg)
136 for (size_t i = 0; i < this.size; i++) {
137 result = dg(this.data[i]);
153 DynArray!(int) array;
154 assert (array.size == 0);
155 assert (array.capacity == 0);
156 assert (array.data is null);
158 assert (false, "there should be no elements in the array");
160 assert (array.size == 1);
161 assert (array.capacity >= 1);
162 assert (array.data !is null);
166 assert (array.size == 2);
167 assert (array.capacity >= 2);
168 assert (array.data !is null);
171 assert (x == 5 + i++);
174 assert (array.size == 1);
175 assert (array.capacity >= 1);
176 assert (array.data !is null);
180 assert (array.size == 1);
181 assert (array.capacity >= 100);
182 assert (array.data !is null);
186 assert (array.size == 0);
187 assert (array.capacity == 0);
188 assert (array.data is null);
190 assert (false, "there should be no elements in the array");
193 } // debug (UnitTest)
195 // vim: set et sw=4 sts=4 :