1 module lifetime.array_; 2 3 import lifetime.common; 4 5 version(LWDR_DynamicArray): 6 7 extern(C) void[] _d_newarrayU(const TypeInfo ti, size_t length) nothrow 8 { 9 auto tinext = unqualify(ti.next); 10 auto size = tinext.tsize; 11 12 void* ptr = lwdrInternal_alloc(size * length); 13 zeroMem(ptr, size * length); 14 return ptr[0 .. size * length]; 15 } 16 17 extern(C) void[] _d_newarrayT(const TypeInfo ti, size_t length) nothrow 18 { 19 return _d_newarrayU(ti, length); 20 } 21 22 /** 23 * For when the array has a non-zero initializer. 24 */ 25 extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length) nothrow 26 { 27 import core.internal.traits : AliasSeq; 28 29 void[] result = _d_newarrayU(ti, length); 30 auto tinext = unqualify(ti.next); 31 auto size = tinext.tsize; 32 33 auto init = tinext.initializer(); 34 35 switch (init.length) 36 { 37 foreach (T; AliasSeq!(ubyte, ushort, uint, ulong)) 38 { 39 case T.sizeof: 40 (cast(T*)result.ptr)[0 .. size * length / T.sizeof] = *cast(T*)init.ptr; 41 return result; 42 } 43 44 default: 45 { 46 import core.stdc.string; 47 immutable sz = init.length; 48 for (size_t u = 0; u < size * length; u += sz) 49 memcpy(result.ptr + u, init.ptr, sz); 50 return result; 51 } 52 } 53 } 54 55 void finalize_array(void* p, size_t size, const TypeInfo_Struct si) 56 { 57 // Due to the fact that the delete operator calls destructors 58 // for arrays from the last element to the first, we maintain 59 // compatibility here by doing the same. 60 auto tsize = si.tsize; 61 for (auto curP = p + size - tsize; curP >= p; curP -= tsize) 62 { 63 // call destructor 64 si.dtor(curP); 65 } 66 } 67 68 extern(C) void _d_delarray_t(void[]* p, const TypeInfo_Struct ti) 69 { 70 if(!p) return; 71 72 if(ti) // ti non-null only if ti is a struct with dtor 73 { 74 finalize_array(p.ptr, p.length * ti.tsize, ti); 75 } 76 77 lwdrInternal_free((*p).ptr); 78 *p = null; 79 } 80 81 extern(C) void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen, size_t elemsz) 82 { 83 auto d = cast(ubyte*) dst; 84 auto s = cast(ubyte*) src; 85 auto len = dstlen * elemsz; 86 87 while(len) 88 { 89 *d = *s; 90 d++; 91 s++; 92 len--; 93 } 94 } 95 96 extern(C) byte[] _d_arrayappendcTX(const TypeInfo ti, return scope ref byte[] px, size_t n) 97 { 98 auto tinext = unqualify(ti.next); 99 auto elemSize = tinext.tsize; 100 101 auto length = px.length; 102 auto size = length * elemSize; 103 auto newLength = length + n; 104 auto newSize = newLength * elemSize; 105 106 auto newArray = _d_newarrayU(ti, newLength); 107 108 import core.stdc.string; 109 110 memcpy(newArray.ptr, cast(void*)px.ptr, size); 111 (cast(void **)(&px))[1] = newArray.ptr; 112 *cast(size_t *)&px = cast(size_t)newLength; 113 114 return px; 115 } 116 117 extern(C) byte[] _d_arraycatT(const TypeInfo ti, byte[] x, byte[] y) 118 { 119 auto tiNext = unqualify(ti.next); 120 auto sizeElem = tiNext.tsize; 121 122 size_t xlen = x.length * sizeElem; 123 size_t ylen = y.length * sizeElem; 124 size_t len = xlen + ylen; 125 126 byte[] newArr = cast(byte[])lwdrInternal_alloc(len)[0..len]; 127 128 import core.stdc.string; 129 130 memcpy(newArr.ptr, x.ptr, xlen); 131 memcpy(newArr.ptr + xlen, y.ptr, ylen); 132 133 return newArr[0..x.length + y.length]; 134 } 135 136 template _d_arraysetlengthTImpl(Tarr : T[], T) 137 { 138 /** 139 * Resize dynamic array 140 * Params: 141 * arr = the array that will be resized, taken as a reference 142 * newlength = new length of array 143 * Returns: 144 * The new length of the array 145 * Bugs: 146 * The safety level of this function is faked. It shows itself as `@trusted pure nothrow` to not break existing code. 147 */ 148 size_t _d_arraysetlengthT(return scope ref Tarr arr, size_t newlength) @trusted nothrow 149 { 150 pragma(inline, false); 151 version (D_TypeInfo) 152 { 153 auto ti = typeid(Tarr); 154 155 static if (__traits(isZeroInit, T)) 156 ._d_arraysetlengthT(ti, newlength, cast(void[]*)&arr); 157 else 158 ._d_arraysetlengthiT(ti, newlength, cast(void[]*)&arr); 159 160 return arr.length; 161 } 162 else 163 assert(0, errorMessage); 164 } 165 } 166 167 private size_t getCopyLength(size_t newlength, size_t originalLength) nothrow @nogc 168 { 169 if(newlength > originalLength) 170 return originalLength; 171 else return newlength; // newlength less than originalLength 172 } 173 174 extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p) nothrow 175 { 176 auto tiNext = unqualify(ti.next); 177 auto sizeElem = tiNext.tsize; 178 auto newArr = _d_newarrayU(ti, newlength); 179 180 import core.stdc.string; 181 182 auto numElemToCopy = getCopyLength(newlength, p.length); 183 memcpy(newArr.ptr, p.ptr, numElemToCopy * sizeElem); 184 185 *p = newArr[0 .. newlength]; 186 return *p; 187 } 188 189 extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p) nothrow 190 { 191 import core.stdc.string; 192 static void doInitialize(void *start, void *end, const void[] initializer) 193 { 194 if (initializer.length == 1) 195 { 196 memset(start, *(cast(ubyte*)initializer.ptr), end - start); 197 } 198 else 199 { 200 auto q = initializer.ptr; 201 immutable initsize = initializer.length; 202 for (; start < end; start += initsize) 203 { 204 memcpy(start, q, initsize); 205 } 206 } 207 } 208 209 auto tiNext = unqualify(ti.next); 210 auto sizeElem = tiNext.tsize; 211 auto newArr = _d_newarrayU(ti, newlength); 212 213 import core.stdc.string; 214 215 size_t numElemToCopy = getCopyLength(newlength, p.length); 216 memcpy(newArr.ptr, p.ptr, numElemToCopy * sizeElem); 217 218 if(newlength >= p.length) { 219 doInitialize(newArr.ptr + p.length * sizeElem, 220 newArr.ptr + newlength * sizeElem, 221 tiNext.initializer); 222 } 223 224 *p = newArr[0 .. newlength]; 225 return *p; 226 }