XArrayT Template for overlapping array slices example:
/+
' Source : XArrayT.d - D array extenders
' : Template functions to handle array overlapping slices
' Author : Andrew Fedoniouk
' Created : 28.Apr.05 with D v0.122
' Modified : 31.Jul.05 by David L. Davis
' : Changed one '===' (which is now deprecated) with an 'is', plus
' : added the missing *memmove() C function, then created a unittest
' : for all the functions, and complied / tested under D v0.128.
' :
' : 21.Nov.05 by Chris
' : added the indexr() function that's analogous to the indexOf()
' : in Java, which finds the first index of range of elements in an
' : array, otherwise it returns -1 if not found. (Thanks Chris!)
' :
' : Unittests added for the new indexr() function, and put in the
' : missing assert() tests. Re-Compiled and Tested with dmd v0.139.
' :
' : 28.May.06 Recompiled and Tested with dmd v0.159.
' : 19.Jul.06 Recompiled and Tested with dmd v0.163, and fixed two
' : shadowing declaration errors in the unittest.
' :
' Reference : http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=22651
' ----------------------------------------------------------------------------------
' To complie for a unittest:
' dmd xarrayt.d -debug=xarrayt -unittest
'
' To compile a D program that uses xarrayt.d:
' dmd MySource.d xarrayt.d
+/
module xarrayt;
debug( xarrayt ) private import std.stdio;
// Need to import the C memmove() function
extern (C) void *memmove(void*, void*, uint);
//|
//| std D array extenders, these should be intrinsic ops for arrays in ideal D
//|
template xarrayT(T)
{
// append array by one element
void push(inout T[] elements, T v)
{
int l = elements.length;
elements.length = l + 1;
elements[l] = v;
}
// del last element and return it
T pop(inout T[] elements)
{
int l = elements.length - 1;
assert(l >= 0);
T t = elements[l];
elements.length = l;
return t;
}
// insert element into array
void ins(inout T[] elements, uint at, T v)
{
uint l = elements.length;
if (at >= l)
{
elements ~= v;
return;
}
// for some reasons this does not compile:
// elements = elements[0..at] ~ v ~ elements[at..elements.length];
// so we use C way:
elements.length = l + 1;
memmove(&elements[at + 1], &elements[at], (l - at) * T.sizeof);
elements[at] = v;
}
// insert array into array
void insr(inout T[] elements, uint at, T[] va )
{
uint l = elements.length;
if (at >= l)
{
elements ~= va;
return;
}
elements.length = l + va.length;
memmove(&elements[at + va.length], &elements[at], (l - at) * T.sizeof);
elements[at..at + va.length] = va;
}
// del element and return it
T cut(inout T[] elements, uint at)
{
uint l = elements.length - 1;
if (at >= l)
return pop(elements);
T t = elements[at];
memmove(&elements[at], &elements[at + 1], (l - at) * T.sizeof);
elements.length = l;
return t;
}
// del range and return its content
T[] cutr(inout T[] elements, uint at, uint end)
{
assert(at <= end);
if (at == end)
return null;
T[] t = elements[at..end].dup;
uint l = elements.length - (end - at);
//if (at < l) { elements.length = at; return t; }
if (l - at <= 0)
{
elements.length = at;
return t;
}
memmove(&elements[at], &elements[end], (l - at) * T.sizeof);
elements.length = l;
return t;
}
// just del range
void del(inout T[] elements, int at, int end)
{
assert(at <= end);
if (at == end)
return;
uint l = elements.length - (end - at);
if (at >= l)
{
elements.length = at;
return;
}
memmove(&elements[at], &elements[end], (l - at) * T.sizeof);
elements.length = l;
}
// find index of the element in array, -1 if not found
int index(in T[] elements, T t)
{
int i = elements.length - 1;
for (; i >= 0; --i)
if ( elements[i] is t )
break;
return i;
}
// find first index of range of elements in array, -1 if not found
int indexr(in T[] elements, in T[] t)
{
if (t.length == 0)
return -1;
int i = elements.length - 1;
for(; i >= 0; --i)
{
if (elements[i] is t[0])
{
bool m = true;
for (int j = 1; j < t.length; ++j)
{
if (elements[i + j] != t[j])
{
m = false;
break;
}
}
if (m)
break;
}
}
return i;
}
}
alias xarrayT!(byte).push push;
alias xarrayT!(ubyte).push push;
alias xarrayT!(short).push push;
alias xarrayT!(ushort).push push;
alias xarrayT!(int).push push;
alias xarrayT!(uint).push push;
alias xarrayT!(long).push push;
alias xarrayT!(ulong).push push;
alias xarrayT!(float).push push;
alias xarrayT!(double).push push;
alias xarrayT!(real).push push;
alias xarrayT!(ifloat).push push;
alias xarrayT!(idouble).push push;
alias xarrayT!(ireal).push push;
alias xarrayT!(cfloat).push push;
alias xarrayT!(cdouble).push push;
alias xarrayT!(creal).push push;
alias xarrayT!(char).push push;
alias xarrayT!(wchar).push push;
alias xarrayT!(dchar).push push;
alias xarrayT!(byte).pop pop;
alias xarrayT!(ubyte).pop pop;
alias xarrayT!(short).pop pop;
alias xarrayT!(ushort).pop pop;
alias xarrayT!(int).pop pop;
alias xarrayT!(uint).pop pop;
alias xarrayT!(long).pop pop;
alias xarrayT!(ulong).pop pop;
alias xarrayT!(float).pop pop;
alias xarrayT!(double).pop pop;
alias xarrayT!(real).pop pop;
alias xarrayT!(ifloat).pop pop;
alias xarrayT!(idouble).pop pop;
alias xarrayT!(ireal).pop pop;
alias xarrayT!(cfloat).pop pop;
alias xarrayT!(cdouble).pop pop;
alias xarrayT!(creal).pop pop;
alias xarrayT!(char).pop pop;
alias xarrayT!(wchar).pop pop;
alias xarrayT!(dchar).pop pop;
alias xarrayT!(byte).ins ins;
alias xarrayT!(ubyte).ins ins;
alias xarrayT!(short).ins ins;
alias xarrayT!(ushort).ins ins;
alias xarrayT!(int).ins ins;
alias xarrayT!(uint).ins ins;
alias xarrayT!(long).ins ins;
alias xarrayT!(ulong).ins ins;
alias xarrayT!(float).ins ins;
alias xarrayT!(double).ins ins;
alias xarrayT!(real).ins ins;
alias xarrayT!(ifloat).ins ins;
alias xarrayT!(idouble).ins ins;
alias xarrayT!(ireal).ins ins;
alias xarrayT!(cfloat).ins ins;
alias xarrayT!(cdouble).ins ins;
alias xarrayT!(creal).ins ins;
alias xarrayT!(char).ins ins;
alias xarrayT!(wchar).ins ins;
alias xarrayT!(dchar).ins ins;
alias xarrayT!(byte).insr insr;
alias xarrayT!(ubyte).insr insr;
alias xarrayT!(short).insr insr;
alias xarrayT!(ushort).insr insr;
alias xarrayT!(int).insr insr;
alias xarrayT!(uint).insr insr;
alias xarrayT!(long).insr insr;
alias xarrayT!(ulong).insr insr;
alias xarrayT!(float).insr insr;
alias xarrayT!(double).insr insr;
alias xarrayT!(real).insr insr;
alias xarrayT!(ifloat).insr insr;
alias xarrayT!(idouble).insr insr;
alias xarrayT!(ireal).insr insr;
alias xarrayT!(cfloat).insr insr;
alias xarrayT!(cdouble).insr insr;
alias xarrayT!(creal).insr insr;
alias xarrayT!(char).insr insr;
alias xarrayT!(wchar).insr insr;
alias xarrayT!(dchar).insr insr;
alias xarrayT!(byte).cut cut;
alias xarrayT!(ubyte).cut cut;
alias xarrayT!(short).cut cut;
alias xarrayT!(ushort).cut cut;
alias xarrayT!(int).cut cut;
alias xarrayT!(uint).cut cut;
alias xarrayT!(long).cut cut;
alias xarrayT!(ulong).cut cut;
alias xarrayT!(float).cut cut;
alias xarrayT!(double).cut cut;
alias xarrayT!(real).cut cut;
alias xarrayT!(ifloat).cut cut;
alias xarrayT!(idouble).cut cut;
alias xarrayT!(ireal).cut cut;
alias xarrayT!(cfloat).cut cut;
alias xarrayT!(cdouble).cut cut;
alias xarrayT!(creal).cut cut;
alias xarrayT!(char).cut cut;
alias xarrayT!(wchar).cut cut;
alias xarrayT!(dchar).cut cut;
alias xarrayT!(byte).cutr cutr;
alias xarrayT!(ubyte).cutr cutr;
alias xarrayT!(short).cutr cutr;
alias xarrayT!(ushort).cutr cutr;
alias xarrayT!(int).cutr cutr;
alias xarrayT!(uint).cutr cutr;
alias xarrayT!(long).cutr cutr;
alias xarrayT!(ulong).cutr cutr;
alias xarrayT!(float).cutr cutr;
alias xarrayT!(double).cutr cutr;
alias xarrayT!(real).cutr cutr;
alias xarrayT!(ifloat).cutr cutr;
alias xarrayT!(idouble).cutr cutr;
alias xarrayT!(ireal).cutr cutr;
alias xarrayT!(cfloat).cutr cutr;
alias xarrayT!(cdouble).cutr cutr;
alias xarrayT!(creal).cutr cutr;
alias xarrayT!(char).cutr cutr;
alias xarrayT!(wchar).cutr cutr;
alias xarrayT!(dchar).cutr cutr;
alias xarrayT!(byte).del del;
alias xarrayT!(ubyte).del del;
alias xarrayT!(short).del del;
alias xarrayT!(ushort).del del;
alias xarrayT!(int).del del;
alias xarrayT!(uint).del del;
alias xarrayT!(long).del del;
alias xarrayT!(ulong).del del;
alias xarrayT!(float).del del;
alias xarrayT!(double).del del;
alias xarrayT!(real).del del;
alias xarrayT!(ifloat).del del;
alias xarrayT!(idouble).del del;
alias xarrayT!(ireal).del del;
alias xarrayT!(cfloat).del del;
alias xarrayT!(cdouble).del del;
alias xarrayT!(creal).del del;
alias xarrayT!(char).del del;
alias xarrayT!(wchar).del del;
alias xarrayT!(dchar).del del;
alias xarrayT!(byte).index index;
alias xarrayT!(ubyte).index index;
alias xarrayT!(short).index index;
alias xarrayT!(ushort).index index;
alias xarrayT!(int).index index;
alias xarrayT!(uint).index index;
alias xarrayT!(long).index index;
alias xarrayT!(ulong).index index;
alias xarrayT!(float).index index;
alias xarrayT!(double).index index;
alias xarrayT!(real).index index;
alias xarrayT!(ifloat).index index;
alias xarrayT!(idouble).index index;
alias xarrayT!(ireal).index index;
alias xarrayT!(cfloat).index index;
alias xarrayT!(cdouble).index index;
alias xarrayT!(creal).index index;
alias xarrayT!(char).index index;
alias xarrayT!(wchar).index index;
alias xarrayT!(dchar).index index;
alias xarrayT!(byte).indexr indexr;
alias xarrayT!(ubyte).indexr indexr;
alias xarrayT!(short).indexr indexr;
alias xarrayT!(ushort).indexr indexr;
alias xarrayT!(int).indexr indexr;
alias xarrayT!(uint).indexr indexr;
alias xarrayT!(long).indexr indexr;
alias xarrayT!(ulong).indexr indexr;
alias xarrayT!(float).indexr indexr;
alias xarrayT!(double).indexr indexr;
alias xarrayT!(real).indexr indexr;
alias xarrayT!(ifloat).indexr indexr;
alias xarrayT!(idouble).indexr indexr;
alias xarrayT!(ireal).indexr indexr;
alias xarrayT!(cfloat).indexr indexr;
alias xarrayT!(cdouble).indexr indexr;
alias xarrayT!(creal).indexr indexr;
alias xarrayT!(char).indexr indexr;
alias xarrayT!(wchar).indexr indexr;
alias xarrayT!(dchar).indexr indexr;
debug( xarrayt )
{
void displayLongArray(in long[] la)
{
if (la.length > 1)
for ( int i = 0; i < la.length - 1; i++ )
writef("%d,", la[i]);
writefln("%d", la[la.length - 1]);
}
unittest
{
writefln( "xarryt.unittest started." );
char[] s;
char[] st = "To Kill a Mocking Bird!";
char[] sub;
static long[] lsa = [ 10L, 20L, 21L, 25L, 30L, 40L, 45L, 50L ];
static long[] lsx = [ 30L, 40L, 50L ];
long[] la = lsa;
long[] la2;
int i;
// ============
// String test
// ============
writefln("String (char[]) Array Test.");
// Appends one char at a time
for ( i = 0; i < st.length; i++ )
s.push(st[i]);
writefln("push() s=\"%s\"", s);
assert(s == "To Kill a Mocking Bird!");
// Removes the last character
for ( i = 0; i < st.length; i++ )
s.pop();
writefln("pop() s=\"%s\" (Looped thru to remove all the characters)", s);
assert(s == "");
// Inserts one character into a string
s = st;
s.ins(3, 'S');
writefln("ins() s=\"%s\"", s);
assert(s == "To SKill a Mocking Bird!");
// Delete a character from [start] to [end] within a string
s.del(3, 4);
writefln("del() s=\"%s\"", s);
assert(s == "To Kill a Mocking Bird!");
// Replace a substring within the string
s.del(3, 7);
s.insr(3, "Raise");
writefln("del() and insr() s=\"%s\"", s);
assert(s == "To Raise a Mocking Bird!");
// Replace a substring within the string
s = st;
s.del(5, 7);
s.insr(5, "ss");
writefln("del() and insr() s=\"%s\"", s);
assert(s == "To Kiss a Mocking Bird!");
// Cut a substring out of the string and append to it
sub = s.cutr(10, 23);
s ~= "puppy Dog!";
writefln("cutr() and '~=' s=\"%s\" sub=\"%s\"", s, sub);
assert(s == "To Kiss a puppy Dog!");
assert(sub == "Mocking Bird!");
// Get the position of a value
i = s.index('K');
writefln("index() 'K' found at position %d", i );
assert(i == 3);
// Remove a value and insert another value.
s.cut(19);
s.ins(19, '.');
writefln("cut() '!' and ins() '.' s=\"%s\"", s);
assert(s == "To Kiss a puppy Dog.");
// Cut a range of characters.
s.cutr(2, 5);
writefln("cutr() ' Ki' s=\"%s\"", s);
assert(s == "Toss a puppy Dog.");
// Get the position of a string (a range of sequential characters)
i = s.indexr("puppy Dog");
writefln("indexr() \"puppy Dog\" found at position %d", i );
assert(i == 7);
i = s.indexr("muddy Hog");
writefln("indexr() \"muddy Hog\" found at position %d", i );
assert(i == -1);
// ===============
// Numerical test
// ===============
//la = [ 10, 20, 21, 25, 30, 40, 45, 50 ];
writefln();
writefln("Numerical (long[]) Array Test.");
writef("la[]=");
displayLongArray(la);
// Add 60 and 70 to the long array
la.push(60);
la.push(70);
writef("push() la[]=");
displayLongArray(la);
assert(la[0] == 10);
assert(la[1] == 20);
assert(la[2] == 21);
assert(la[3] == 25);
assert(la[4] == 30);
assert(la[5] == 40);
assert(la[6] == 45);
assert(la[7] == 50);
assert(la[8] == 60);
assert(la[9] == 70);
// Removes the last value from the array
la.pop();
writef("pop() la[]=");
displayLongArray(la);
assert(la[0] == 10);
assert(la[1] == 20);
assert(la[2] == 21);
assert(la[3] == 25);
assert(la[4] == 30);
assert(la[5] == 40);
assert(la[6] == 45);
assert(la[7] == 50);
assert(la[8] == 60);
// Inserts a new value into the array
la.ins(1, 15);
writef("ins() la[]=");
displayLongArray(la);
assert(la[0] == 10);
assert(la[1] == 15);
assert(la[2] == 20);
assert(la[3] == 21);
assert(la[4] == 25);
assert(la[5] == 30);
assert(la[6] == 40);
assert(la[7] == 45);
assert(la[8] == 50);
assert(la[9] == 60);
// Removes a value from the array
la.del(3,4);
writef("del() la[]=");
displayLongArray(la);
assert(la[0] == 10);
assert(la[1] == 15);
assert(la[2] == 20);
assert(la[3] == 25);
assert(la[4] == 30);
assert(la[5] == 40);
assert(la[6] == 45);
assert(la[7] == 50);
assert(la[8] == 60);
// Cut a range of values to another array
la2 = la.cutr(1, 4);
writef("cutr() la[]=");
displayLongArray(la);
assert(la[0] == 10);
assert(la[1] == 30);
assert(la[2] == 40);
assert(la[3] == 45);
assert(la[4] == 50);
assert(la[5] == 60);
writef("la's cut to la2[]=");
displayLongArray(la2);
assert(la2[0] == 15);
assert(la2[1] == 20);
assert(la2[2] == 25);
// Find and cut value from the original array
i = la.index(45);
writefln("index() value 45 found at position %d", i);
assert(i == 3);
la2.length = 1;
la2[0] = la.cut(i);
writef("cut() la[]=");
displayLongArray(la);
assert(la[0] == 10);
assert(la[1] == 30);
assert(la[2] == 40);
assert(la[3] == 50);
assert(la[4] == 60);
writef("la's cut to la2[]=");
displayLongArray(la2);
assert(la2[0] == 45);
// Get the position of a range of sequential numbers
// lsx = [ 30L, 40L, 50L ]
i = la.indexr(lsx);
writefln("indexr() range [ 30L, 40L, 50L ] found at position %d", i);
writef("Items in the array: ");
displayLongArray(la);
assert(i == 1);
}
}
debug( xarrayt )
{
int main()
{
std.stdio.writefln( "xarrayt.unittest finished!" );
return 0;
}
}
C:\dmd>dmd xarrayt.d -debug=xarrayt -unittest
C:\dmd\bin\..\..\dm\bin\link.exe xarrayt,,,user32+kernel32/noi;
C:\dmd>xarrayt
xarryt.unittest started.
String (char[]) Array Test.
push() s="To Kill a Mocking Bird!"
pop() s="" (Looped thru to remove all the characters)
ins() s="To SKill a Mocking Bird!"
del() s="To Kill a Mocking Bird!"
del() and insr() s="To Raise a Mocking Bird!"
del() and insr() s="To Kiss a Mocking Bird!"
cutr() and '~=' s="To Kiss a puppy Dog!" sub="Mocking Bird!"
index() 'K' found at position 3
cut() '!' and ins() '.' s="To Kiss a puppy Dog."
cutr() ' Ki' s="Toss a puppy Dog."
indexr() "puppy Dog" found at position 7
indexr() "muddy Hog" found at position -1
Numerical (long[]) Array Test.
la[]=10,20,21,25,30,40,45,50
push() la[]=10,20,21,25,30,40,45,50,60,70
pop() la[]=10,20,21,25,30,40,45,50,60
ins() la[]=10,15,20,21,25,30,40,45,50,60
del() la[]=10,15,20,25,30,40,45,50,60
cutr() la[]=10,30,40,45,50,60
la's cut to la2[]=15,20,25
index() value 45 found at position 3
cut() la[]=10,30,40,50,60
la's cut to la2[]=45
indexr() range [ 30L, 40L, 50L ] found at position 1
Items in the array: 10,30,40,50,60
xarrayt.unittest finished!
C:\dmd>