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 }