/src/rt/arrayassign.d

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