1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2015 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // Distributed under the Boost Software License, Version 1.0.
7 // http://www.boost.org/LICENSE_1_0.txt
8 
9 module ddmd.root.array;
10 
11 import core.stdc..string;
12 
13 import ddmd.root.rmem;
14 
15 extern (C++) struct Array(T)
16 {
17 public:
18     size_t dim;
19     T* data;
20 
21 private:
22     size_t allocdim;
23     enum SMALLARRAYCAP = 1;
24     T[SMALLARRAYCAP] smallarray; // inline storage for small arrays
25 
26 public:
27     ~this()
28     {
29         if (data != &smallarray[0])
30             mem.xfree(data);
31     }
32 
33     const(char)* toChars()
34     {
35         static if (is(typeof(T.init.toChars())))
36         {
37             const(char)** buf = cast(const(char)**)mem.xmalloc(dim * (char*).sizeof);
38             size_t len = 2;
39             for (size_t u = 0; u < dim; u++)
40             {
41                 buf[u] = data[u].toChars();
42                 len += strlen(buf[u]) + 1;
43             }
44             char* str = cast(char*)mem.xmalloc(len);
45 
46             str[0] = '[';
47             char* p = str + 1;
48             for (size_t u = 0; u < dim; u++)
49             {
50                 if (u)
51                     *p++ = ',';
52                 len = strlen(buf[u]);
53                 memcpy(p, buf[u], len);
54                 p += len;
55             }
56             *p++ = ']';
57             *p = 0;
58             mem.xfree(buf);
59             return str;
60         }
61         else
62         {
63             assert(0);
64         }
65     }
66 
67     void push(T ptr)
68     {
69         reserve(1);
70         data[dim++] = ptr;
71     }
72 
73     void append(typeof(this)* a)
74     {
75         insert(dim, a);
76     }
77 
78     void reserve(size_t nentries)
79     {
80         //printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", (int)dim, (int)allocdim, (int)nentries);
81         if (allocdim - dim < nentries)
82         {
83             if (allocdim == 0)
84             {
85                 // Not properly initialized, someone memset it to zero
86                 if (nentries <= SMALLARRAYCAP)
87                 {
88                     allocdim = SMALLARRAYCAP;
89                     data = SMALLARRAYCAP ? smallarray.ptr : null;
90                 }
91                 else
92                 {
93                     allocdim = nentries;
94                     data = cast(T*)mem.xmalloc(allocdim * (*data).sizeof);
95                 }
96             }
97             else if (allocdim == SMALLARRAYCAP)
98             {
99                 allocdim = dim + nentries;
100                 data = cast(T*)mem.xmalloc(allocdim * (*data).sizeof);
101                 memcpy(data, smallarray.ptr, dim * (*data).sizeof);
102             }
103             else
104             {
105                 allocdim = dim + nentries;
106                 data = cast(T*)mem.xrealloc(data, allocdim * (*data).sizeof);
107             }
108         }
109     }
110 
111     void remove(size_t i)
112     {
113         if (dim - i - 1)
114             memmove(data + i, data + i + 1, (dim - i - 1) * (data[0]).sizeof);
115         dim--;
116     }
117 
118     void insert(size_t index, typeof(this)* a)
119     {
120         if (a)
121         {
122             size_t d = a.dim;
123             reserve(d);
124             if (dim != index)
125                 memmove(data + index + d, data + index, (dim - index) * (*data).sizeof);
126             memcpy(data + index, a.data, d * (*data).sizeof);
127             dim += d;
128         }
129     }
130 
131     void insert(size_t index, T ptr)
132     {
133         reserve(1);
134         memmove(data + index + 1, data + index, (dim - index) * (*data).sizeof);
135         data[index] = ptr;
136         dim++;
137     }
138 
139     void setDim(size_t newdim)
140     {
141         if (dim < newdim)
142         {
143             reserve(newdim - dim);
144         }
145         dim = newdim;
146     }
147 
148     ref inout(T) opIndex(size_t i) inout
149     {
150         return data[i];
151     }
152 
153     inout(T)* tdata() inout
154     {
155         return data;
156     }
157 
158     Array!T* copy() const
159     {
160         auto a = new Array!T();
161         a.setDim(dim);
162         memcpy(a.data, data, dim * (void*).sizeof);
163         return a;
164     }
165 
166     void shift(T ptr)
167     {
168         reserve(1);
169         memmove(data + 1, data, dim * (*data).sizeof);
170         data[0] = ptr;
171         dim++;
172     }
173 
174     void zero()
175     {
176         data[0 .. dim] = T.init;
177     }
178 
179     T pop()
180     {
181         return data[--dim];
182     }
183 
184     int apply(int function(T, void*) fp, void* param)
185     {
186         static if (is(typeof(T.init.apply(fp, null))))
187         {
188             for (size_t i = 0; i < dim; i++)
189             {
190                 T e = data[i];
191                 if (e)
192                 {
193                     if (e.apply(fp, param))
194                         return 1;
195                 }
196             }
197             return 0;
198         }
199         else
200             assert(0);
201     }
202 
203     extern (D) inout(T)[] opSlice() inout
204     {
205         return data[0 .. dim];
206     }
207 
208     extern (D) inout(T)[] opSlice(size_t a, size_t b) inout
209     {
210         assert(a <= b && b <= dim);
211         return data[a .. b];
212     }
213 }
214 
215 struct BitArray
216 {
217     size_t length() const
218     {
219         return len;
220     }
221 
222     void length(size_t nlen)
223     {
224         immutable obytes = (len + 7) / 8;
225         immutable nbytes = (nlen + 7) / 8;
226         ptr = cast(size_t*)mem.xrealloc(ptr, nbytes);
227         if (nbytes > obytes)
228             (cast(ubyte*)ptr)[obytes .. nbytes] = 0;
229         len = nlen;
230     }
231 
232     bool opIndex(size_t idx) const
233     {
234         import core.bitop : bt;
235 
236         assert(idx < length);
237         return !!bt(ptr, idx);
238     }
239 
240     void opIndexAssign(bool val, size_t idx)
241     {
242         import core.bitop : btc, bts;
243 
244         assert(idx < length);
245         if (val)
246             bts(ptr, idx);
247         else
248             btc(ptr, idx);
249     }
250 
251     @disable this(this);
252 
253     ~this()
254     {
255         mem.xfree(ptr);
256     }
257 
258 private:
259     size_t len;
260     size_t *ptr;
261 }