PageRenderTime 65ms CodeModel.GetById 16ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  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}