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