MKoD - D Programming Language

D-Sourcery XArrayT Template for overlapping slices in D Arrays - code-name XArrayT.d

Very Kool! 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>
Mars: fourth Rock from the Sun.