Mercurial > hg > CbC > CbC_gcc
diff libphobos/libdruntime/rt/adi.d @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libphobos/libdruntime/rt/adi.d Thu Feb 13 11:34:05 2020 +0900 @@ -0,0 +1,332 @@ +/** + * Implementation of dynamic array property support routines. + * + * Copyright: Copyright Digital Mars 2000 - 2015. + * License: Distributed under the + * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). + * (See accompanying file LICENSE) + * Authors: Walter Bright + * Source: $(DRUNTIMESRC src/rt/_adi.d) + */ + +module rt.adi; + +//debug=adi; // uncomment to turn on debugging printf's + +private +{ + debug(adi) import core.stdc.stdio; + import core.stdc.string; + import core.stdc.stdlib; + import core.memory; + import rt.util.utf; + + extern (C) void[] _adSort(void[] a, TypeInfo ti); +} + +private dchar[] mallocUTF32(C)(in C[] s) +{ + size_t j = 0; + auto p = cast(dchar*)malloc(dchar.sizeof * s.length); + auto r = p[0..s.length]; // r[] will never be longer than s[] + foreach (dchar c; s) + r[j++] = c; + return r[0 .. j]; +} + +/********************************************** + * Sort array of chars. + */ + +extern (C) char[] _adSortChar(char[] a) +{ + if (a.length > 1) + { + auto da = mallocUTF32(a); + _adSort(*cast(void[]*)&da, typeid(da[0])); + size_t i = 0; + foreach (dchar d; da) + { char[4] buf; + auto t = toUTF8(buf, d); + a[i .. i + t.length] = t[]; + i += t.length; + } + free(da.ptr); + } + return a; +} + +/********************************************** + * Sort array of wchars. + */ + +extern (C) wchar[] _adSortWchar(wchar[] a) +{ + if (a.length > 1) + { + auto da = mallocUTF32(a); + _adSort(*cast(void[]*)&da, typeid(da[0])); + size_t i = 0; + foreach (dchar d; da) + { wchar[2] buf; + auto t = toUTF16(buf, d); + a[i .. i + t.length] = t[]; + i += t.length; + } + free(da.ptr); + } + return a; +} + +/*************************************** + * Support for array equality test. + * Returns: + * 1 equal + * 0 not equal + */ + +extern (C) int _adEq(void[] a1, void[] a2, TypeInfo ti) +{ + debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); + if (a1.length != a2.length) + return 0; // not equal + auto sz = ti.tsize; + auto p1 = a1.ptr; + auto p2 = a2.ptr; + + if (sz == 1) + // We should really have a ti.isPOD() check for this + return (memcmp(p1, p2, a1.length) == 0); + + for (size_t i = 0; i < a1.length; i++) + { + if (!ti.equals(p1 + i * sz, p2 + i * sz)) + return 0; // not equal + } + return 1; // equal +} + +extern (C) int _adEq2(void[] a1, void[] a2, TypeInfo ti) +{ + debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); + if (a1.length != a2.length) + return 0; // not equal + if (!ti.equals(&a1, &a2)) + return 0; + return 1; +} +unittest +{ + debug(adi) printf("array.Eq unittest\n"); + + auto a = "hello"c; + + assert(a != "hel"); + assert(a != "helloo"); + assert(a != "betty"); + assert(a == "hello"); + assert(a != "hxxxx"); + + float[] fa = [float.nan]; + assert(fa != fa); +} + +/*************************************** + * Support for array compare test. + */ + +extern (C) int _adCmp(void[] a1, void[] a2, TypeInfo ti) +{ + debug(adi) printf("adCmp()\n"); + auto len = a1.length; + if (a2.length < len) + len = a2.length; + auto sz = ti.tsize; + void *p1 = a1.ptr; + void *p2 = a2.ptr; + + if (sz == 1) + { // We should really have a ti.isPOD() check for this + auto c = memcmp(p1, p2, len); + if (c) + return c; + } + else + { + for (size_t i = 0; i < len; i++) + { + auto c = ti.compare(p1 + i * sz, p2 + i * sz); + if (c) + return c; + } + } + if (a1.length == a2.length) + return 0; + return (a1.length > a2.length) ? 1 : -1; +} + +extern (C) int _adCmp2(void[] a1, void[] a2, TypeInfo ti) +{ + debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); + return ti.compare(&a1, &a2); +} +unittest +{ + debug(adi) printf("array.Cmp unittest\n"); + + auto a = "hello"c; + + assert(a > "hel"); + assert(a >= "hel"); + assert(a < "helloo"); + assert(a <= "helloo"); + assert(a > "betty"); + assert(a >= "betty"); + assert(a == "hello"); + assert(a <= "hello"); + assert(a >= "hello"); + assert(a < "я"); +} + +/*************************************** + * Support for array compare test. + */ + +extern (C) int _adCmpChar(void[] a1, void[] a2) +{ + version (D_InlineAsm_X86) + { + asm + { naked ; + + push EDI ; + push ESI ; + + mov ESI,a1+4[4+ESP] ; + mov EDI,a2+4[4+ESP] ; + + mov ECX,a1[4+ESP] ; + mov EDX,a2[4+ESP] ; + + cmp ECX,EDX ; + jb GotLength ; + + mov ECX,EDX ; + +GotLength: + cmp ECX,4 ; + jb DoBytes ; + + // Do alignment if neither is dword aligned + test ESI,3 ; + jz Aligned ; + + test EDI,3 ; + jz Aligned ; +DoAlign: + mov AL,[ESI] ; //align ESI to dword bounds + mov DL,[EDI] ; + + cmp AL,DL ; + jnz Unequal ; + + inc ESI ; + inc EDI ; + + test ESI,3 ; + + lea ECX,[ECX-1] ; + jnz DoAlign ; +Aligned: + mov EAX,ECX ; + + // do multiple of 4 bytes at a time + + shr ECX,2 ; + jz TryOdd ; + + repe ; + cmpsd ; + + jnz UnequalQuad ; + +TryOdd: + mov ECX,EAX ; +DoBytes: + // if still equal and not end of string, do up to 3 bytes slightly + // slower. + + and ECX,3 ; + jz Equal ; + + repe ; + cmpsb ; + + jnz Unequal ; +Equal: + mov EAX,a1[4+ESP] ; + mov EDX,a2[4+ESP] ; + + sub EAX,EDX ; + pop ESI ; + + pop EDI ; + ret ; + +UnequalQuad: + mov EDX,[EDI-4] ; + mov EAX,[ESI-4] ; + + cmp AL,DL ; + jnz Unequal ; + + cmp AH,DH ; + jnz Unequal ; + + shr EAX,16 ; + + shr EDX,16 ; + + cmp AL,DL ; + jnz Unequal ; + + cmp AH,DH ; +Unequal: + sbb EAX,EAX ; + pop ESI ; + + or EAX,1 ; + pop EDI ; + + ret ; + } + } + else + { + debug(adi) printf("adCmpChar()\n"); + auto len = a1.length; + if (a2.length < len) + len = a2.length; + auto c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len); + if (!c) + c = cast(int)a1.length - cast(int)a2.length; + return c; + } +} + +unittest +{ + debug(adi) printf("array.CmpChar unittest\n"); + + auto a = "hello"c; + + assert(a > "hel"); + assert(a >= "hel"); + assert(a < "helloo"); + assert(a <= "helloo"); + assert(a > "betty"); + assert(a >= "betty"); + assert(a == "hello"); + assert(a <= "hello"); + assert(a >= "hello"); +}