Mercurial > projects > hoofbaby
comparison src/impl/hoofbaby/util/array.d @ 0:3425707ddbf6
Initial import (hopefully this mercurial stuff works...)
author | fraserofthenight |
---|---|
date | Mon, 06 Jul 2009 08:06:28 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3425707ddbf6 |
---|---|
1 /** | |
2 * Hoofbaby -- http://www.dsource.org/projects/hoofbaby | |
3 * Copyright (C) 2009 Robert Fraser | |
4 * | |
5 * This program is free software; you can redistribute it andor | |
6 * modify it under the terms of the GNU General Public License | |
7 * as published by the Free Software Foundation; either version 2 | |
8 * of the License, or (at your option) any later version. | |
9 * | |
10 * This program is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 * GNU General Public License for more details. | |
14 */ | |
15 | |
16 module hoofbaby.util.array; | |
17 | |
18 import tango.core.BitManip : bsr; | |
19 import tango.core.Traits : isReferenceType; | |
20 import tango.core.Memory : GC; | |
21 import tango.stdc.string : memcpy, memset; | |
22 | |
23 | |
24 public struct Array(T, size_t START_SIZE = 16, bool doScan = isReferenceType!(T), | |
25 alias Realloc = GC.realloc, alias Free = GC.free) | |
26 { | |
27 T* arr = null; | |
28 size_t len = 0; | |
29 size_t cap = 0; | |
30 | |
31 public void opCatAssign(T v) | |
32 { | |
33 len++; | |
34 if(len >= cap) | |
35 grow(cap ? cap * 2 : START_SIZE); | |
36 arr[len - 1] = v; | |
37 } | |
38 | |
39 public void opCatAssign(T[] v) | |
40 { | |
41 int newlen = len + v.length; | |
42 if(newlen > cap) | |
43 { | |
44 if(newlen < START_SIZE) | |
45 grow(START_SIZE); | |
46 else | |
47 grow(2 << bsr(newlen + 1)); // Next power of 2 | |
48 } | |
49 memcpy(arr + len, v.ptr, (newlen - len) * T.sizeof); | |
50 len = newlen; | |
51 } | |
52 | |
53 public void opCatAssign(Array!(T) v) | |
54 { | |
55 opCatAssign(v.toArray()); | |
56 } | |
57 | |
58 public T[] toArray() | |
59 { | |
60 return arr[0 .. len]; | |
61 } | |
62 | |
63 public size_t length() | |
64 { | |
65 return len; | |
66 } | |
67 | |
68 public T opIndex(size_t n) | |
69 { | |
70 assert(n < len); | |
71 return arr[n]; | |
72 } | |
73 | |
74 public void opIndexAssign(T v, size_t n) | |
75 { | |
76 assert(n < len); | |
77 arr[n] = v; | |
78 } | |
79 | |
80 public T[] opSlice() | |
81 { | |
82 return toArray(); | |
83 } | |
84 | |
85 public T[] opSlice(size_t low, size_t high) | |
86 { | |
87 assert(low <= high); | |
88 assert(high < len); | |
89 return arr[low .. high]; | |
90 } | |
91 | |
92 public void opSliceAssign(T v) | |
93 { | |
94 arr[0 .. len] = v; | |
95 } | |
96 | |
97 public void opSliceAssign(T v, size_t low, size_t high) | |
98 { | |
99 assert(low <= high); | |
100 assert(high < len); | |
101 arr[low .. high] = v; | |
102 } | |
103 | |
104 public void opSliceAssign(T[] v, size_t low, size_t high) | |
105 { | |
106 assert(low <= high); | |
107 assert(high < len); | |
108 assert(v.length == high - low); | |
109 memcpy(arr + low, v.ptr, v.length * T.sizeof); | |
110 } | |
111 | |
112 public void opSliceAssign(Array!(T) v, size_t low, size_t high) | |
113 { | |
114 opSliceAssign(v.toArray(), low, high); | |
115 } | |
116 | |
117 public bool isEmpty() | |
118 { | |
119 return len == 0; | |
120 } | |
121 | |
122 public void clear() | |
123 { | |
124 len = 0; | |
125 } | |
126 | |
127 public void free() | |
128 { | |
129 if(arr) | |
130 { | |
131 Free(arr); | |
132 arr = null; | |
133 } | |
134 len = 0; | |
135 } | |
136 | |
137 public void zero() | |
138 { | |
139 if(arr) | |
140 { | |
141 memset(arr, 0, cap * T.sizeof); | |
142 Free(arr); | |
143 arr = null; | |
144 } | |
145 len = 0; | |
146 } | |
147 | |
148 public void addNull() | |
149 { | |
150 len++; | |
151 if(len >= cap) | |
152 grow(cap ? cap * 2 : START_SIZE); | |
153 } | |
154 | |
155 public bool contains(T elem) | |
156 { | |
157 for(int i = 0; i < len; i++) | |
158 if(arr[i] == elem) | |
159 return true; | |
160 return false; | |
161 } | |
162 | |
163 static if(doScan) | |
164 private static const BlkAttr = 0; | |
165 else | |
166 private static const BlkAttr = GC.BlkAttr.NO_SCAN; | |
167 | |
168 private void grow(size_t sz) | |
169 { | |
170 arr = cast(T*) Realloc(arr, sz * T.sizeof, BlkAttr); | |
171 static if(doScan) | |
172 { | |
173 memset(arr + cap, 0, (sz - cap) * T.sizeof); | |
174 } | |
175 cap = sz; | |
176 } | |
177 } | |
178 | |
179 public struct Stack(T, size_t START_SIZE = 16, bool doScan = true, bool zeroOnPop = false, | |
180 alias ArrayType = Array, ArrayArgs...) | |
181 { | |
182 private ArrayType!(T, START_SIZE, doScan, ArrayArgs) arr; | |
183 | |
184 public void pushNull() | |
185 { | |
186 arr.addNull(); | |
187 } | |
188 | |
189 public void push(T v) | |
190 { | |
191 arr ~= v; | |
192 } | |
193 | |
194 public T pop() | |
195 { | |
196 assert(arr.len > 0); | |
197 T ret = arr.arr[arr.len - 1]; | |
198 static if(zeroOnPop) | |
199 arr.arr[arr.len - 1] = T.init; | |
200 arr.len--; | |
201 return ret; | |
202 } | |
203 | |
204 public T peek() | |
205 { | |
206 assert(arr.len > 0); | |
207 return arr.arr[arr.len - 1]; | |
208 } | |
209 | |
210 public bool isEmpty() | |
211 { | |
212 return arr.isEmpty(); | |
213 } | |
214 | |
215 public void clear() | |
216 { | |
217 static if(zeroOnPop) | |
218 arr.zero(); | |
219 else | |
220 arr.clear(); | |
221 } | |
222 | |
223 public bool contains(T elem) | |
224 { | |
225 return arr.contains(elem); | |
226 } | |
227 | |
228 public T[] toArray() | |
229 { | |
230 return arr.toArray(); | |
231 } | |
232 } |