Mercurial > projects > ldc
diff lphobos/internal/adi.d @ 662:88e23f8c2354
Applied downs' latest Phobos patch
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Mon, 06 Oct 2008 21:40:33 +0200 |
parents | 373489eeaf90 |
children |
line wrap: on
line diff
--- a/lphobos/internal/adi.d Mon Oct 06 21:27:29 2008 +0200 +++ b/lphobos/internal/adi.d Mon Oct 06 21:40:33 2008 +0200 @@ -1,838 +1,838 @@ -//_ adi.d - -/** - * Part of the D programming language runtime library. - * Dynamic array property support routines - */ - -/* - * Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com - * Written by Walter Bright - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, in both source and binary form, subject to the following - * restrictions: - * - * o The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * o Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * o This notice may not be removed or altered from any source - * distribution. - */ - -//debug=adi; // uncomment to turn on debugging printf's - -//import std.stdio; -import std.c.stdio; -import std.c.stdlib; -import std.c.string; -//import std.string; -import std.outofmemory; -import std.utf; - -pragma(no_typeinfo) -struct Array -{ - size_t length; - void* ptr; -} - -/********************************************** - * Reverse array of chars. - * Handled separately because embedded multibyte encodings should not be - * reversed. - */ - -extern (C) char[] _adReverseChar(char[] a) -{ - if (a.length > 1) - { - char[6] tmp; - char[6] tmplo; - char* lo = a.ptr; - char* hi = &a[length - 1]; - - while (lo < hi) - { auto clo = *lo; - auto chi = *hi; - - //printf("lo = %d, hi = %d\n", lo, hi); - if (clo <= 0x7F && chi <= 0x7F) - { - //printf("\tascii\n"); - *lo = chi; - *hi = clo; - lo++; - hi--; - continue; - } - - uint stridelo = std.utf.UTF8stride[clo]; - - uint stridehi = 1; - while ((chi & 0xC0) == 0x80) - { - chi = *--hi; - stridehi++; - assert(hi >= lo); - } - if (lo == hi) - break; - - //printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi); - if (stridelo == stridehi) - { - - memcpy(tmp.ptr, lo, stridelo); - memcpy(lo, hi, stridelo); - memcpy(hi, tmp.ptr, stridelo); - lo += stridelo; - hi--; - continue; - } - - /* Shift the whole array. This is woefully inefficient - */ - memcpy(tmp.ptr, hi, stridehi); - memcpy(tmplo.ptr, lo, stridelo); - memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo); - memcpy(lo, tmp.ptr, stridehi); - memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo); - - lo += stridehi; - hi = hi - 1 + (stridehi - stridelo); - } - } - return a; -} - -unittest -{ - string a = "abcd"; - string r; - - r = a.dup.reverse; - //writefln(r); - assert(r == "dcba"); - - a = "a\u1235\u1234c"; - //writefln(a); - r = a.dup.reverse; - //writefln(r); - assert(r == "c\u1234\u1235a"); - - a = "ab\u1234c"; - //writefln(a); - r = a.dup.reverse; - //writefln(r); - assert(r == "c\u1234ba"); - - a = "\u3026\u2021\u3061\n"; - r = a.dup.reverse; - assert(r == "\n\u3061\u2021\u3026"); -} - - -/********************************************** - * Reverse array of wchars. - * Handled separately because embedded multiword encodings should not be - * reversed. - */ - -extern (C) wchar[] _adReverseWchar(wchar[] a) -{ - if (a.length > 1) - { - wchar[2] tmp; - wchar* lo = a.ptr; - wchar* hi = &a[length - 1]; - - while (lo < hi) - { auto clo = *lo; - auto chi = *hi; - - if ((clo < 0xD800 || clo > 0xDFFF) && - (chi < 0xD800 || chi > 0xDFFF)) - { - *lo = chi; - *hi = clo; - lo++; - hi--; - continue; - } - - int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF); - - int stridehi = 1; - if (chi >= 0xDC00 && chi <= 0xDFFF) - { - chi = *--hi; - stridehi++; - assert(hi >= lo); - } - if (lo == hi) - break; - - if (stridelo == stridehi) - { int stmp; - - assert(stridelo == 2); - assert(stmp.sizeof == 2 * (*lo).sizeof); - stmp = *cast(int*)lo; - *cast(int*)lo = *cast(int*)hi; - *cast(int*)hi = stmp; - lo += stridelo; - hi--; - continue; - } - - /* Shift the whole array. This is woefully inefficient - */ - memcpy(tmp.ptr, hi, stridehi * wchar.sizeof); - memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof); - memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof); - memcpy(lo, tmp.ptr, stridehi * wchar.sizeof); - - lo += stridehi; - hi = hi - 1 + (stridehi - stridelo); - } - } - return a; -} - -unittest -{ - wstring a = "abcd"; - wstring r; - - r = a.dup.reverse; - assert(r == "dcba"); - - a = "a\U00012356\U00012346c"; - r = a.dup.reverse; - assert(r == "c\U00012346\U00012356a"); - - a = "ab\U00012345c"; - r = a.dup.reverse; - assert(r == "c\U00012345ba"); -} - - -/********************************************** - * Support for array.reverse property. - */ - -extern (C) Array _adReverse(Array a, size_t szelem) -{ - if (a.length >= 2) - { - byte* tmp; - byte[16] buffer; - - void* lo = a.ptr; - void* hi = a.ptr + (a.length - 1) * szelem; - - tmp = buffer.ptr; - if (szelem > 16) - { - //version (Win32) - tmp = cast(byte*) alloca(szelem); - //else - //tmp = new byte[szelem]; - } - - for (; lo < hi; lo += szelem, hi -= szelem) - { - memcpy(tmp, lo, szelem); - memcpy(lo, hi, szelem); - memcpy(hi, tmp, szelem); - } - - version (Win32) - { - } - else - { - //if (szelem > 16) - // BUG: bad code is generate for delete pointer, tries - // to call delclass. - //delete tmp; - } - } - return a; -} - -unittest -{ - debug(adi) printf("array.reverse.unittest\n"); - - int[] a = new int[5]; - int[] b; - size_t i; - - for (i = 0; i < 5; i++) - a[i] = i; - b = a.reverse; - assert(b is a); - for (i = 0; i < 5; i++) - assert(a[i] == 4 - i); - - struct X20 - { // More than 16 bytes in size - int a; - int b, c, d, e; - } - - X20[] c = new X20[5]; - X20[] d; - - for (i = 0; i < 5; i++) - { c[i].a = i; - c[i].e = 10; - } - d = c.reverse; - assert(d is c); - for (i = 0; i < 5; i++) - { - assert(c[i].a == 4 - i); - assert(c[i].e == 10); - } -} - -/********************************************** - * Support for array.reverse property for bit[]. - */ - -version (none) -{ -extern (C) bit[] _adReverseBit(bit[] a) - out (result) - { - assert(result is a); - } - body - { - if (a.length >= 2) - { - bit t; - int lo, hi; - - lo = 0; - hi = a.length - 1; - for (; lo < hi; lo++, hi--) - { - t = a[lo]; - a[lo] = a[hi]; - a[hi] = t; - } - } - return a; - } - -unittest -{ - debug(adi) printf("array.reverse_Bit[].unittest\n"); - - bit[] b; - b = new bit[5]; - static bit[5] data = [1,0,1,1,0]; - int i; - - b[] = data[]; - b.reverse; - for (i = 0; i < 5; i++) - { - assert(b[i] == data[4 - i]); - } -} -} - -/********************************************** - * Sort array of chars. - */ - -extern (C) char[] _adSortChar(char[] a) -{ - if (a.length > 1) - { - dstring da = toUTF32(a); - da.sort; - size_t i = 0; - foreach (dchar d; da) - { char[4] buf; - string t = toUTF8(buf, d); - a[i .. i + t.length] = t[]; - i += t.length; - } - delete da; - } - return a; -} - -/********************************************** - * Sort array of wchars. - */ - -extern (C) wchar[] _adSortWchar(wchar[] a) -{ - if (a.length > 1) - { - dstring da = toUTF32(a); - da.sort; - size_t i = 0; - foreach (dchar d; da) - { wchar[2] buf; - wstring t = toUTF16(buf, d); - a[i .. i + t.length] = t[]; - i += t.length; - } - delete da; - } - return a; -} - -/********************************************** - * Support for array.sort property for bit[]. - */ - -version (none) -{ -extern (C) bit[] _adSortBit(bit[] a) - out (result) - { - assert(result is a); - } - body - { - if (a.length >= 2) - { - size_t lo, hi; - - lo = 0; - hi = a.length - 1; - while (1) - { - while (1) - { - if (lo >= hi) - goto Ldone; - if (a[lo] == true) - break; - lo++; - } - - while (1) - { - if (lo >= hi) - goto Ldone; - if (a[hi] == false) - break; - hi--; - } - - a[lo] = false; - a[hi] = true; - - lo++; - hi--; - } - Ldone: - ; - } - return a; - } - -unittest -{ - debug(adi) printf("array.sort_Bit[].unittest\n"); -} -} - -/*************************************** - * Support for array equality test. - */ - -extern (C) int _adEq(Array a1, Array a2, TypeInfo ti) -{ - // 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.next.tsize(); - auto p1 = a1.ptr; - auto p2 = a2.ptr; - -/+ - for (int i = 0; i < a1.length; i++) - { - printf("%4x %4x\n", (cast(short*)p1)[i], (cast(short*)p2)[i]); - } - printf("sz = %u\n", sz); -+/ - - 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.next.equals(p1 + i * sz, p2 + i * sz)) - return 0; // not equal - } - return 1; // equal -} - -unittest -{ - debug(adi) printf("array.Eq unittest\n"); - - string a = "hello"; - - assert(a != "hel"); - assert(a != "helloo"); - assert(a != "betty"); - assert(a == "hello"); - assert(a != "hxxxx"); -} - -/*************************************** - * Support for bit array equality test for bit arrays. - */ - -version (none) -{ -extern (C) int _adEqBit(Array a1, Array a2) -{ size_t i; - - if (a1.length != a2.length) - return 0; // not equal - auto p1 = cast(byte*)a1.ptr; - auto p2 = cast(byte*)a2.ptr; - auto n = a1.length / 8; - for (i = 0; i < n; i++) - { - if (p1[i] != p2[i]) - return 0; // not equal - } - - ubyte mask; - - n = a1.length & 7; - mask = cast(ubyte)((1 << n) - 1); - //printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]); - return (mask == 0) || (p1[i] & mask) == (p2[i] & mask); -} - -unittest -{ - debug(adi) printf("array.EqBit unittest\n"); - - static bit[] a = [1,0,1,0,1]; - static bit[] b = [1,0,1]; - static bit[] c = [1,0,1,0,1,0,1]; - static bit[] d = [1,0,1,1,1]; - static bit[] e = [1,0,1,0,1]; - - assert(a != b); - assert(a != c); - assert(a != d); - assert(a == e); -} -} - -/*************************************** - * Support for array compare test. - */ - -extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti) -{ - //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; -} - -unittest -{ - debug(adi) printf("array.Cmp unittest\n"); - - string a = "hello"; - - 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"); -} - -/*************************************** - * Support for char array compare test. - */ - -extern (C) int _adCmpChar(Array a1, Array 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 -{ - int len; - int c; - - //printf("adCmpChar()\n"); - len = a1.length; - if (a2.length < len) - len = a2.length; - 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"); - - string a = "hello"; - - 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"); -} - -/*************************************** - * Support for bit array compare test. - */ - -version (none) -{ -extern (C) int _adCmpBit(Array a1, Array a2) -{ - int len; - uint i; - - len = a1.length; - if (a2.length < len) - len = a2.length; - ubyte *p1 = cast(ubyte*)a1.ptr; - ubyte *p2 = cast(ubyte*)a2.ptr; - uint n = len / 8; - for (i = 0; i < n; i++) - { - if (p1[i] != p2[i]) - break; // not equal - } - for (uint j = i * 8; j < len; j++) - { ubyte mask = cast(ubyte)(1 << j); - int c; - - c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask); - if (c) - return c; - } - return cast(int)a1.length - cast(int)a2.length; -} - -unittest -{ - debug(adi) printf("array.CmpBit unittest\n"); - - static bit[] a = [1,0,1,0,1]; - static bit[] b = [1,0,1]; - static bit[] c = [1,0,1,0,1,0,1]; - static bit[] d = [1,0,1,1,1]; - static bit[] e = [1,0,1,0,1]; - - assert(a > b); - assert(a >= b); - assert(a < c); - assert(a <= c); - assert(a < d); - assert(a <= d); - assert(a == e); - assert(a <= e); - assert(a >= e); -} -} - -/********************************** - * Support for array.dup property. - */ - -extern(C) -void* _d_realloc(void*, size_t); - -extern(C) -Array _adDupT(TypeInfo ti, Array a) -{ - Array r; - if (a.length) - { - auto sizeelem = ti.next.tsize(); // array element size - auto size = a.length * sizeelem; - r.ptr = _d_realloc(null,size); - r.length = a.length; - memcpy(r.ptr, a.ptr, size); - } - return r; -} - -unittest -{ - int[] a; - int[] b; - int i; - - debug(adi) printf("array.dup.unittest\n"); - - a = new int[3]; - a[0] = 1; a[1] = 2; a[2] = 3; - b = a.dup; - assert(b.length == 3); - for (i = 0; i < 3; i++) - assert(b[i] == i + 1); -} +//_ adi.d + +/** + * Part of the D programming language runtime library. + * Dynamic array property support routines + */ + +/* + * Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, in both source and binary form, subject to the following + * restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + +//debug=adi; // uncomment to turn on debugging printf's + +//import std.stdio; +import std.c.stdio; +import std.c.stdlib; +import std.c.string; +//import std.string; +import std.outofmemory; +import std.utf; + +pragma(no_typeinfo) +struct Array +{ + size_t length; + void* ptr; +} + +/********************************************** + * Reverse array of chars. + * Handled separately because embedded multibyte encodings should not be + * reversed. + */ + +extern (C) char[] _adReverseChar(char[] a) +{ + if (a.length > 1) + { + char[6] tmp; + char[6] tmplo; + char* lo = a.ptr; + char* hi = &a[length - 1]; + + while (lo < hi) + { auto clo = *lo; + auto chi = *hi; + + //printf("lo = %d, hi = %d\n", lo, hi); + if (clo <= 0x7F && chi <= 0x7F) + { + //printf("\tascii\n"); + *lo = chi; + *hi = clo; + lo++; + hi--; + continue; + } + + uint stridelo = std.utf.UTF8stride[clo]; + + uint stridehi = 1; + while ((chi & 0xC0) == 0x80) + { + chi = *--hi; + stridehi++; + assert(hi >= lo); + } + if (lo == hi) + break; + + //printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi); + if (stridelo == stridehi) + { + + memcpy(tmp.ptr, lo, stridelo); + memcpy(lo, hi, stridelo); + memcpy(hi, tmp.ptr, stridelo); + lo += stridelo; + hi--; + continue; + } + + /* Shift the whole array. This is woefully inefficient + */ + memcpy(tmp.ptr, hi, stridehi); + memcpy(tmplo.ptr, lo, stridelo); + memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo); + memcpy(lo, tmp.ptr, stridehi); + memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo); + + lo += stridehi; + hi = hi - 1 + (stridehi - stridelo); + } + } + return a; +} + +unittest +{ + string a = "abcd"; + string r; + + r = a.dup.reverse; + //writefln(r); + assert(r == "dcba"); + + a = "a\u1235\u1234c"; + //writefln(a); + r = a.dup.reverse; + //writefln(r); + assert(r == "c\u1234\u1235a"); + + a = "ab\u1234c"; + //writefln(a); + r = a.dup.reverse; + //writefln(r); + assert(r == "c\u1234ba"); + + a = "\u3026\u2021\u3061\n"; + r = a.dup.reverse; + assert(r == "\n\u3061\u2021\u3026"); +} + + +/********************************************** + * Reverse array of wchars. + * Handled separately because embedded multiword encodings should not be + * reversed. + */ + +extern (C) wchar[] _adReverseWchar(wchar[] a) +{ + if (a.length > 1) + { + wchar[2] tmp; + wchar* lo = a.ptr; + wchar* hi = &a[length - 1]; + + while (lo < hi) + { auto clo = *lo; + auto chi = *hi; + + if ((clo < 0xD800 || clo > 0xDFFF) && + (chi < 0xD800 || chi > 0xDFFF)) + { + *lo = chi; + *hi = clo; + lo++; + hi--; + continue; + } + + int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF); + + int stridehi = 1; + if (chi >= 0xDC00 && chi <= 0xDFFF) + { + chi = *--hi; + stridehi++; + assert(hi >= lo); + } + if (lo == hi) + break; + + if (stridelo == stridehi) + { int stmp; + + assert(stridelo == 2); + assert(stmp.sizeof == 2 * (*lo).sizeof); + stmp = *cast(int*)lo; + *cast(int*)lo = *cast(int*)hi; + *cast(int*)hi = stmp; + lo += stridelo; + hi--; + continue; + } + + /* Shift the whole array. This is woefully inefficient + */ + memcpy(tmp.ptr, hi, stridehi * wchar.sizeof); + memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof); + memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof); + memcpy(lo, tmp.ptr, stridehi * wchar.sizeof); + + lo += stridehi; + hi = hi - 1 + (stridehi - stridelo); + } + } + return a; +} + +unittest +{ + wstring a = "abcd"; + wstring r; + + r = a.dup.reverse; + assert(r == "dcba"); + + a = "a\U00012356\U00012346c"; + r = a.dup.reverse; + assert(r == "c\U00012346\U00012356a"); + + a = "ab\U00012345c"; + r = a.dup.reverse; + assert(r == "c\U00012345ba"); +} + + +/********************************************** + * Support for array.reverse property. + */ + +extern (C) Array _adReverse(Array a, size_t szelem) +{ + if (a.length >= 2) + { + byte* tmp; + byte[16] buffer; + + void* lo = a.ptr; + void* hi = a.ptr + (a.length - 1) * szelem; + + tmp = buffer.ptr; + if (szelem > 16) + { + //version (Win32) + //tmp = cast(byte*) alloca(szelem); + //else + tmp = (new byte[szelem]).ptr; + } + + for (; lo < hi; lo += szelem, hi -= szelem) + { + memcpy(tmp, lo, szelem); + memcpy(lo, hi, szelem); + memcpy(hi, tmp, szelem); + } + + version (Win32) + { + } + else + { + //if (szelem > 16) + // BUG: bad code is generate for delete pointer, tries + // to call delclass. + //delete tmp; + } + } + return a; +} + +unittest +{ + debug(adi) printf("array.reverse.unittest\n"); + + int[] a = new int[5]; + int[] b; + size_t i; + + for (i = 0; i < 5; i++) + a[i] = i; + b = a.reverse; + assert(b is a); + for (i = 0; i < 5; i++) + assert(a[i] == 4 - i); + + struct X20 + { // More than 16 bytes in size + int a; + int b, c, d, e; + } + + X20[] c = new X20[5]; + X20[] d; + + for (i = 0; i < 5; i++) + { c[i].a = i; + c[i].e = 10; + } + d = c.reverse; + assert(d is c); + for (i = 0; i < 5; i++) + { + assert(c[i].a == 4 - i); + assert(c[i].e == 10); + } +} + +/********************************************** + * Support for array.reverse property for bit[]. + */ + +version (none) +{ +extern (C) bit[] _adReverseBit(bit[] a) + out (result) + { + assert(result is a); + } + body + { + if (a.length >= 2) + { + bit t; + int lo, hi; + + lo = 0; + hi = a.length - 1; + for (; lo < hi; lo++, hi--) + { + t = a[lo]; + a[lo] = a[hi]; + a[hi] = t; + } + } + return a; + } + +unittest +{ + debug(adi) printf("array.reverse_Bit[].unittest\n"); + + bit[] b; + b = new bit[5]; + static bit[5] data = [1,0,1,1,0]; + int i; + + b[] = data[]; + b.reverse; + for (i = 0; i < 5; i++) + { + assert(b[i] == data[4 - i]); + } +} +} + +/********************************************** + * Sort array of chars. + */ + +extern (C) char[] _adSortChar(char[] a) +{ + if (a.length > 1) + { + dstring da = toUTF32(a); + da.sort; + size_t i = 0; + foreach (dchar d; da) + { char[4] buf; + string t = toUTF8(buf, d); + a[i .. i + t.length] = t[]; + i += t.length; + } + delete da; + } + return a; +} + +/********************************************** + * Sort array of wchars. + */ + +extern (C) wchar[] _adSortWchar(wchar[] a) +{ + if (a.length > 1) + { + dstring da = toUTF32(a); + da.sort; + size_t i = 0; + foreach (dchar d; da) + { wchar[2] buf; + wstring t = toUTF16(buf, d); + a[i .. i + t.length] = t[]; + i += t.length; + } + delete da; + } + return a; +} + +/********************************************** + * Support for array.sort property for bit[]. + */ + +version (none) +{ +extern (C) bit[] _adSortBit(bit[] a) + out (result) + { + assert(result is a); + } + body + { + if (a.length >= 2) + { + size_t lo, hi; + + lo = 0; + hi = a.length - 1; + while (1) + { + while (1) + { + if (lo >= hi) + goto Ldone; + if (a[lo] == true) + break; + lo++; + } + + while (1) + { + if (lo >= hi) + goto Ldone; + if (a[hi] == false) + break; + hi--; + } + + a[lo] = false; + a[hi] = true; + + lo++; + hi--; + } + Ldone: + ; + } + return a; + } + +unittest +{ + debug(adi) printf("array.sort_Bit[].unittest\n"); +} +} + +/*************************************** + * Support for array equality test. + */ + +extern (C) int _adEq(Array a1, Array a2, TypeInfo ti) +{ + // 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.next.tsize(); + auto p1 = a1.ptr; + auto p2 = a2.ptr; + +/+ + for (int i = 0; i < a1.length; i++) + { + printf("%4x %4x\n", (cast(short*)p1)[i], (cast(short*)p2)[i]); + } + printf("sz = %u\n", sz); ++/ + + 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.next.equals(p1 + i * sz, p2 + i * sz)) + return 0; // not equal + } + return 1; // equal +} + +unittest +{ + debug(adi) printf("array.Eq unittest\n"); + + string a = "hello"; + + assert(a != "hel"); + assert(a != "helloo"); + assert(a != "betty"); + assert(a == "hello"); + assert(a != "hxxxx"); +} + +/*************************************** + * Support for bit array equality test for bit arrays. + */ + +version (none) +{ +extern (C) int _adEqBit(Array a1, Array a2) +{ size_t i; + + if (a1.length != a2.length) + return 0; // not equal + auto p1 = cast(byte*)a1.ptr; + auto p2 = cast(byte*)a2.ptr; + auto n = a1.length / 8; + for (i = 0; i < n; i++) + { + if (p1[i] != p2[i]) + return 0; // not equal + } + + ubyte mask; + + n = a1.length & 7; + mask = cast(ubyte)((1 << n) - 1); + //printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]); + return (mask == 0) || (p1[i] & mask) == (p2[i] & mask); +} + +unittest +{ + debug(adi) printf("array.EqBit unittest\n"); + + static bit[] a = [1,0,1,0,1]; + static bit[] b = [1,0,1]; + static bit[] c = [1,0,1,0,1,0,1]; + static bit[] d = [1,0,1,1,1]; + static bit[] e = [1,0,1,0,1]; + + assert(a != b); + assert(a != c); + assert(a != d); + assert(a == e); +} +} + +/*************************************** + * Support for array compare test. + */ + +extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti) +{ + //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; +} + +unittest +{ + debug(adi) printf("array.Cmp unittest\n"); + + string a = "hello"; + + 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"); +} + +/*************************************** + * Support for char array compare test. + */ + +extern (C) int _adCmpChar(Array a1, Array 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 +{ + int len; + int c; + + //printf("adCmpChar()\n"); + len = a1.length; + if (a2.length < len) + len = a2.length; + 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"); + + string a = "hello"; + + 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"); +} + +/*************************************** + * Support for bit array compare test. + */ + +version (none) +{ +extern (C) int _adCmpBit(Array a1, Array a2) +{ + int len; + uint i; + + len = a1.length; + if (a2.length < len) + len = a2.length; + ubyte *p1 = cast(ubyte*)a1.ptr; + ubyte *p2 = cast(ubyte*)a2.ptr; + uint n = len / 8; + for (i = 0; i < n; i++) + { + if (p1[i] != p2[i]) + break; // not equal + } + for (uint j = i * 8; j < len; j++) + { ubyte mask = cast(ubyte)(1 << j); + int c; + + c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask); + if (c) + return c; + } + return cast(int)a1.length - cast(int)a2.length; +} + +unittest +{ + debug(adi) printf("array.CmpBit unittest\n"); + + static bit[] a = [1,0,1,0,1]; + static bit[] b = [1,0,1]; + static bit[] c = [1,0,1,0,1,0,1]; + static bit[] d = [1,0,1,1,1]; + static bit[] e = [1,0,1,0,1]; + + assert(a > b); + assert(a >= b); + assert(a < c); + assert(a <= c); + assert(a < d); + assert(a <= d); + assert(a == e); + assert(a <= e); + assert(a >= e); +} +} + +/********************************** + * Support for array.dup property. + */ + +extern(C) +void* _d_realloc(void*, size_t); + +extern(C) +Array _adDupT(TypeInfo ti, Array a) +{ + Array r; + if (a.length) + { + auto sizeelem = ti.next.tsize(); // array element size + auto size = a.length * sizeelem; + r.ptr = _d_realloc(null,size); + r.length = a.length; + memcpy(r.ptr, a.ptr, size); + } + return r; +} + +unittest +{ + int[] a; + int[] b; + int i; + + debug(adi) printf("array.dup.unittest\n"); + + a = new int[3]; + a[0] = 1; a[1] = 2; a[2] = 3; + b = a.dup; + assert(b.length == 3); + for (i = 0; i < 3; i++) + assert(b[i] == i + 1); +}