xref: /netbsd-src/external/gpl3/gcc.old/dist/libphobos/libdruntime/rt/adi.d (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /**
2  * Implementation of dynamic array property support routines.
3  *
4  * Copyright: Copyright Digital Mars 2000 - 2015.
5  * License: Distributed under the
6  *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7  *    (See accompanying file LICENSE)
8  * Authors:   Walter Bright
9  * Source: $(DRUNTIMESRC src/rt/_adi.d)
10  */
11 
12 module rt.adi;
13 
14 //debug=adi;            // uncomment to turn on debugging printf's
15 
16 private
17 {
18     debug(adi) import core.stdc.stdio;
19     import core.stdc.string;
20     import core.stdc.stdlib;
21     import core.memory;
22     import rt.util.utf;
23 
24     extern (C) void[] _adSort(void[] a, TypeInfo ti);
25 }
26 
27 private dchar[] mallocUTF32(C)(in C[] s)
28 {
29     size_t j = 0;
30     auto p = cast(dchar*)malloc(dchar.sizeof * s.length);
31     auto r = p[0..s.length]; // r[] will never be longer than s[]
32     foreach (dchar c; s)
33         r[j++] = c;
34     return r[0 .. j];
35 }
36 
37 /**********************************************
38  * Sort array of chars.
39  */
40 
41 extern (C) char[] _adSortChar(char[] a)
42 {
43     if (a.length > 1)
44     {
45         auto da = mallocUTF32(a);
46         _adSort(*cast(void[]*)&da, typeid(da[0]));
47         size_t i = 0;
48         foreach (dchar d; da)
49         {   char[4] buf;
50             auto t = toUTF8(buf, d);
51             a[i .. i + t.length] = t[];
52             i += t.length;
53         }
54         free(da.ptr);
55     }
56     return a;
57 }
58 
59 /**********************************************
60  * Sort array of wchars.
61  */
62 
63 extern (C) wchar[] _adSortWchar(wchar[] a)
64 {
65     if (a.length > 1)
66     {
67         auto da = mallocUTF32(a);
68         _adSort(*cast(void[]*)&da, typeid(da[0]));
69         size_t i = 0;
70         foreach (dchar d; da)
71         {   wchar[2] buf;
72             auto t = toUTF16(buf, d);
73             a[i .. i + t.length] = t[];
74             i += t.length;
75         }
76         free(da.ptr);
77     }
78     return a;
79 }
80 
81 /***************************************
82  * Support for array equality test.
83  * Returns:
84  *      1       equal
85  *      0       not equal
86  */
87 
88 extern (C) int _adEq(void[] a1, void[] a2, TypeInfo ti)
89 {
90     debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
91     if (a1.length != a2.length)
92         return 0; // not equal
93     auto sz = ti.tsize;
94     auto p1 = a1.ptr;
95     auto p2 = a2.ptr;
96 
97     if (sz == 1)
98         // We should really have a ti.isPOD() check for this
99         return (memcmp(p1, p2, a1.length) == 0);
100 
101     for (size_t i = 0; i < a1.length; i++)
102     {
103         if (!ti.equals(p1 + i * sz, p2 + i * sz))
104             return 0; // not equal
105     }
106     return 1; // equal
107 }
108 
109 extern (C) int _adEq2(void[] a1, void[] a2, TypeInfo ti)
110 {
111     debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
112     if (a1.length != a2.length)
113         return 0;               // not equal
114     if (!ti.equals(&a1, &a2))
115         return 0;
116     return 1;
117 }
118 unittest
119 {
120     debug(adi) printf("array.Eq unittest\n");
121 
122     auto a = "hello"c;
123 
124     assert(a != "hel");
125     assert(a != "helloo");
126     assert(a != "betty");
127     assert(a == "hello");
128     assert(a != "hxxxx");
129 
130     float[] fa = [float.nan];
131     assert(fa != fa);
132 }
133 
134 /***************************************
135  * Support for array compare test.
136  */
137 
138 extern (C) int _adCmp(void[] a1, void[] a2, TypeInfo ti)
139 {
140     debug(adi) printf("adCmp()\n");
141     auto len = a1.length;
142     if (a2.length < len)
143         len = a2.length;
144     auto sz = ti.tsize;
145     void *p1 = a1.ptr;
146     void *p2 = a2.ptr;
147 
148     if (sz == 1)
149     {   // We should really have a ti.isPOD() check for this
150         auto c = memcmp(p1, p2, len);
151         if (c)
152             return c;
153     }
154     else
155     {
156         for (size_t i = 0; i < len; i++)
157         {
158             auto c = ti.compare(p1 + i * sz, p2 + i * sz);
159             if (c)
160                 return c;
161         }
162     }
163     if (a1.length == a2.length)
164         return 0;
165     return (a1.length > a2.length) ? 1 : -1;
166 }
167 
168 extern (C) int _adCmp2(void[] a1, void[] a2, TypeInfo ti)
169 {
170     debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
171     return ti.compare(&a1, &a2);
172 }
173 unittest
174 {
175     debug(adi) printf("array.Cmp unittest\n");
176 
177     auto a = "hello"c;
178 
179     assert(a >  "hel");
180     assert(a >= "hel");
181     assert(a <  "helloo");
182     assert(a <= "helloo");
183     assert(a >  "betty");
184     assert(a >= "betty");
185     assert(a == "hello");
186     assert(a <= "hello");
187     assert(a >= "hello");
188     assert(a <  "я");
189 }
190 
191 /***************************************
192  * Support for array compare test.
193  */
194 
195 extern (C) int _adCmpChar(void[] a1, void[] a2)
196 {
197   version (D_InlineAsm_X86)
198   {
199     asm
200     {   naked                   ;
201 
202         push    EDI             ;
203         push    ESI             ;
204 
205         mov    ESI,a1+4[4+ESP]  ;
206         mov    EDI,a2+4[4+ESP]  ;
207 
208         mov    ECX,a1[4+ESP]    ;
209         mov    EDX,a2[4+ESP]    ;
210 
211         cmp     ECX,EDX         ;
212         jb      GotLength       ;
213 
214         mov     ECX,EDX         ;
215 
216 GotLength:
217         cmp    ECX,4            ;
218         jb    DoBytes           ;
219 
220         // Do alignment if neither is dword aligned
221         test    ESI,3           ;
222         jz    Aligned           ;
223 
224         test    EDI,3           ;
225         jz    Aligned           ;
226 DoAlign:
227         mov    AL,[ESI]         ; //align ESI to dword bounds
228         mov    DL,[EDI]         ;
229 
230         cmp    AL,DL            ;
231         jnz    Unequal          ;
232 
233         inc    ESI              ;
234         inc    EDI              ;
235 
236         test    ESI,3           ;
237 
238         lea    ECX,[ECX-1]      ;
239         jnz    DoAlign          ;
240 Aligned:
241         mov    EAX,ECX          ;
242 
243         // do multiple of 4 bytes at a time
244 
245         shr    ECX,2            ;
246         jz    TryOdd            ;
247 
248         repe                    ;
249         cmpsd                   ;
250 
251         jnz    UnequalQuad      ;
252 
253 TryOdd:
254         mov    ECX,EAX          ;
255 DoBytes:
256         // if still equal and not end of string, do up to 3 bytes slightly
257         // slower.
258 
259         and    ECX,3            ;
260         jz    Equal             ;
261 
262         repe                    ;
263         cmpsb                   ;
264 
265         jnz    Unequal          ;
266 Equal:
267         mov    EAX,a1[4+ESP]    ;
268         mov    EDX,a2[4+ESP]    ;
269 
270         sub    EAX,EDX          ;
271         pop    ESI              ;
272 
273         pop    EDI              ;
274         ret                     ;
275 
276 UnequalQuad:
277         mov    EDX,[EDI-4]      ;
278         mov    EAX,[ESI-4]      ;
279 
280         cmp    AL,DL            ;
281         jnz    Unequal          ;
282 
283         cmp    AH,DH            ;
284         jnz    Unequal          ;
285 
286         shr    EAX,16           ;
287 
288         shr    EDX,16           ;
289 
290         cmp    AL,DL            ;
291         jnz    Unequal          ;
292 
293         cmp    AH,DH            ;
294 Unequal:
295         sbb    EAX,EAX          ;
296         pop    ESI              ;
297 
298         or     EAX,1            ;
299         pop    EDI              ;
300 
301         ret                     ;
302     }
303   }
304   else
305   {
306     debug(adi) printf("adCmpChar()\n");
307     auto len = a1.length;
308     if (a2.length < len)
309         len = a2.length;
310     auto c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
311     if (!c)
312         c = cast(int)a1.length - cast(int)a2.length;
313     return c;
314   }
315 }
316 
317 unittest
318 {
319     debug(adi) printf("array.CmpChar unittest\n");
320 
321     auto a = "hello"c;
322 
323     assert(a >  "hel");
324     assert(a >= "hel");
325     assert(a <  "helloo");
326     assert(a <= "helloo");
327     assert(a >  "betty");
328     assert(a >= "betty");
329     assert(a == "hello");
330     assert(a <= "hello");
331     assert(a >= "hello");
332 }
333