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 }