/src/rt/arrayassign.d
D | 188 lines | 128 code | 21 blank | 39 comment | 11 complexity | 2daa19c2fa6a3ebfc4cdd8f9b6989ff0 MD5 | raw file
1/** 2 * Implementation of array assignment support routines. 3 * 4 * Copyright: Copyright Digital Mars 2000 - 2010. 5 * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. 6 * Authors: Walter Bright 7 */ 8 9/* Copyright Digital Mars 2000 - 2010. 10 * Distributed under the Boost Software License, Version 1.0. 11 * (See accompanying file LICENSE or copy at 12 * http://www.boost.org/LICENSE_1_0.txt) 13 */ 14module rt.arrayassign; 15 16private 17{ 18 import rt.util.string; 19 import core.stdc.string; 20 import core.stdc.stdlib; 21 debug(PRINTF) import core.stdc.stdio; 22} 23 24/** 25 * Does array assignment (not construction) from another 26 * array of the same element type. 27 * ti is the element type. 28 * Handles overlapping copies. 29 */ 30extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to) 31{ 32 debug(PRINTF) printf("_d_arrayassign(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize); 33 34 if (to.length != from.length) 35 { 36 char[10] tmp1 = void; 37 char[10] tmp2 = void; 38 string msg = "lengths don't match for array copy, "c; 39 msg ~= tmp1.uintToString(to.length) ~ " = " ~ tmp2.uintToString(from.length); 40 throw new Error(msg); 41 } 42 43 auto element_size = ti.tsize; 44 45 /* Need a temporary buffer tmp[] big enough to hold one element 46 */ 47 void[16] buf = void; 48 void[] tmp; 49 if (element_size > buf.sizeof) 50 tmp = alloca(element_size)[0 .. element_size]; 51 else 52 tmp = buf[]; 53 54 55 if (to.ptr <= from.ptr) 56 { 57 foreach (i; 0 .. to.length) 58 { 59 void* pto = to.ptr + i * element_size; 60 void* pfrom = from.ptr + i * element_size; 61 memcpy(tmp.ptr, pto, element_size); 62 memcpy(pto, pfrom, element_size); 63 ti.postblit(pto); 64 ti.destroy(tmp.ptr); 65 } 66 } 67 else 68 { 69 for (auto i = to.length; i--; ) 70 { 71 void* pto = to.ptr + i * element_size; 72 void* pfrom = from.ptr + i * element_size; 73 memcpy(tmp.ptr, pto, element_size); 74 memcpy(pto, pfrom, element_size); 75 ti.postblit(pto); 76 ti.destroy(tmp.ptr); 77 } 78 } 79 return to; 80} 81 82/** 83 * Does array initialization (not assignment) from another 84 * array of the same element type. 85 * ti is the element type. 86 */ 87extern (C) void[] _d_arrayctor(TypeInfo ti, void[] from, void[] to) 88{ 89 debug(PRINTF) printf("_d_arrayctor(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize); 90 91 if (to.length != from.length) 92 { 93 char[10] tmp = void; 94 string msg = "lengths don't match for array initialization,"c; 95 msg ~= tmp.uintToString(to.length) ~ " = " ~ tmp.uintToString(from.length); 96 throw new Error(msg); 97 } 98 99 auto element_size = ti.tsize; 100 101 size_t i; 102 try 103 { 104 for (i = 0; i < to.length; i++) 105 { 106 // Copy construction is defined as bit copy followed by postblit. 107 memcpy(to.ptr + i * element_size, from.ptr + i * element_size, element_size); 108 ti.postblit(to.ptr + i * element_size); 109 } 110 } 111 catch (Throwable o) 112 { 113 /* Destroy, in reverse order, what we've constructed so far 114 */ 115 while (i--) 116 { 117 ti.destroy(to.ptr + i * element_size); 118 } 119 120 throw o; 121 } 122 return to; 123} 124 125 126/** 127 * Do assignment to an array. 128 * p[0 .. count] = value; 129 */ 130extern (C) void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti) 131{ 132 void* pstart = p; 133 134 auto element_size = ti.tsize; 135 136 //Need a temporary buffer tmp[] big enough to hold one element 137 void[16] buf = void; 138 void[] tmp; 139 if (element_size > buf.sizeof) 140 { 141 tmp = alloca(element_size)[0 .. element_size]; 142 } 143 else 144 tmp = buf[]; 145 146 foreach (i; 0 .. count) 147 { 148 memcpy(tmp.ptr, p, element_size); 149 memcpy(p, value, element_size); 150 ti.postblit(p); 151 ti.destroy(tmp.ptr); 152 p += element_size; 153 } 154 return pstart; 155} 156 157/** 158 * Do construction of an array. 159 * ti[count] p = value; 160 */ 161extern (C) void* _d_arraysetctor(void* p, void* value, int count, TypeInfo ti) 162{ 163 void* pstart = p; 164 auto element_size = ti.tsize; 165 166 try 167 { 168 foreach (i; 0 .. count) 169 { 170 // Copy construction is defined as bit copy followed by postblit. 171 memcpy(p, value, element_size); 172 ti.postblit(p); 173 p += element_size; 174 } 175 } 176 catch (Throwable o) 177 { 178 // Destroy, in reverse order, what we've constructed so far 179 while (p > pstart) 180 { 181 p -= element_size; 182 ti.destroy(p); 183 } 184 185 throw o; 186 } 187 return pstart; 188}