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     char* toChars()
34     {
35         static if (is(typeof(T.init.toChars())))
36         {
37             char** buf = cast(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 T opIndex(size_t i)
149     {
150         return data[i];
151     }
152 
153     T* tdata()
154     {
155         return data;
156     }
157 
158     typeof(this)* copy()
159     {
160         auto a = new typeof(this)();
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         memset(data, 0, dim * (data[0]).sizeof);
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 }