New Lexer:
; Binary AHK Array RC2
; (w) by DerRaphael
;
; Released under the Terms of European Public License (EUPL 1.0)
;    see http://ec.europa.eu/idabc/en/document/7330
;    for translations in your language.

A_Put(ByRef Array, ByRef Data, Index=-1, dSize=-1){
    If !(A_Array(Array)) ; No Array ? Do an ArrayInit to get a proper Structure
        A_Init(Array)

    if ((Index=-1) || (A_Count(Array)+1=Index)) {
        Gosub, GetArrayStats
    
         nSize := aSize+dSize+8                         ; calculate new size
        VarSetCapacity(tmpArray, nSize, 32)            ; create tmpArray for our new data
        A_ArrayMM(&tmpArray, &Array, aSize)            ; Copy entire array to TMP
    
        NumPut(nSize,       tmpArray, 12)              ; Update size of array in total
        NumPut(tSize+8,     tmpArray, 16)              ; Update tableLenght
        NumPut(oSize+dSize, tmpArray, 20)              ; Update length of new ArrayStructure
        NumPut(ElmCount+1,  tmpArray, 24)              ; Update elementcount
    
        A_ArrayMM( &tmpArray + tSize + 8               ; Shift ArrayData for 8 bytes
                    , &Array + tSize, oSize )
        A_ArrayMM(&tmpArray+aSize+8,&Data,dSize)       ; copy data to tmpArray
    
        Offset := 28                                   ; move offsets for array contents
        Loop, % ElmCount+1
             NumPut( NumGet(tmpArray
                    ,(Offset+(A_index-1)*8))+8         ; get last known value and 
                    ,tmpArray,(Offset+(A_index-1)*8))  ; increment it by 8

        NumPut(aSize+8, tmpArray, tSize)               ; Set offsetpointer to new data
        NumPut(dSize, tmpArray, tSize+4)               ; Set size of new element

        VarSetCapacity(Array,nSize,32)                 ; Resize the array
        A_ArrayMM(&Array, &tmpArray, nSize)            ; copy tmpArray back to array

        Return ElmCount+1
    } else if ((A_Count(Array)>=Index) && (Index!=0)) {
        Gosub, GetArrayStats
        
         ElmPtr  := NumGet(Array,28+(Index-1)*8)
        ElmSize := NumGet(Array,32+(Index-1)*8)
        
        if ((dSize>ElmSize) || (dSize<ElmSize)) {      ; Fix table offsets to new size
    
            OffSet  := 28+Index*8                      ; GetStarting offset in table
            ptrDiff := dSize-ElmSize                   ; Get difference

            nSize := aSize+ptrDiff                     ; calculate new size
            VarSetCapacity(tmpArray, nSize, 32)        ; create tmpArray for our new data
            A_ArrayMM(&tmpArray, &Array                ; Copy entire array to TMP
                , ((aSize>nSize) ? nSize : aSize))     ; with a correct calculated length
            NumPut(nSize, tmpArray, 12)                ; Update size of array in total
            NumPut(oSize+ptrDiff, tmpArray, 20)        ; Update length of new ArrayStructure
            NumPut(dSize, tmpArray, Offset-4)          ; Set size of new element

            Loop,% ElmCount-Index                      ; loop remaining elements
                 NumPut( NumGet(tmpArray
                    ,(Offset+(A_index-1)*8))+ptrDiff   ; get last known value and 
                    ,tmpArray,(Offset+(A_index-1)*8))  ; add the difference

            Offset := NumGet(tmpArray,Offset-8)
            A_ArrayMM(&tmpArray+Offset, &Data, dSize)  ; Copy new data into tmpArray
            A_ArrayMM(&tmpArray+Offset+dSize           ; remaining ArrayData to new offset
                    , &Array+Offset+ElmSize, aSize-(OffSet+ElmSize))

            VarSetCapacity(Array,nSize,32)             ; Resize the array
            A_ArrayMM(&Array, &tmpArray, nSize)        ; copy tmpArray back to array

        } else if (dSize=ElmSize) {                    ; No need to fix tableoffsets
            A_ArrayMM(&Array+ElmPtr,&Data,dSize)       ; speeeed!
        } else {                                       ; THIS SHOULD NEVER HAPPEN
            ErrorLevel := "Internal Binary Array Structure Error / Invalid Binary Array Object"
            return -1
        }
        Return ElmCount
    } else {
        ErrorLevel := "Binary Array Index Mismatch"
        Return -1
    }

    GetArrayStats:
        ElmCount := A_Count(Array)       ; update ElementCount
        aSize    := A_Size(Array)        ; current ByteSize of entire Array
        oSize    := A_Length(Array)      ; current ByteSize of contained data in Array
        tSize    := NumGet(Array,16)     ; table size
        If (dSize<=-1)                   ; No size given - assume it's a string and fix it!
            RegExReplace(Data,".","",dSize)
    return
}

A_Get(ByRef Array, Index) {
    If !(A_Array(Array)) {
        ErrorLevel := "No valid binary Array"
        return -1
    } else if ((Index>A_Count(Array)) || (Index<=0)) {
        ErrorLevel := "Binary Array Index mismatch - no such Index"
        return -1
    } else {
        Offset  := 28+(Index-1)*8                      ; Get starting offset in table
        ElmPtr  := NumGet(Array,Offset)
        ElmSize := NumGet(Array,Offset+4)

        VarSetCapacity(ArrayElement,ElmSize,32)        ; Initialise the returnbuffer
        A_ArrayMM(&ArrayElement,&Array+ElmPtr,ElmSize) ; Copy the binary data
        
        ErrorLevel := ElmSize
        Return ArrayElement
    }
}

; Returns a joined string of given Array and glue parameter
; Length is returned as ErrorLevel
A_Implode(ByRef Array, glue=" ") {
    If !(A_Array(Array)) {
        ErrorLevel := "No valid binary Array"
        return -1
    } else {
        lGlue      := glue
        glueLength := StrLen(lGlue)
        aSize      := A_Length(Array)                  ; current DataSize of array
        elmCount   := A_Count(Array)                   ; get ElementCount of Array
        ErrorLevel := (elmCount-1)*glueLength + aSize  ; count new Size of returnString
        Offset     := 0                                ; set Offset for A_ArrayMM Loop

        VarSetCapacity(String,ErrorLevel,32)           ; Allocate space for new return

        Loop,% elmCount
         {
            elmLength  := NumGet(Array,32+(A_Index-1)*8)  ; current element's length
            elmPos     := NumGet(Array,28+(A_Index-1)*8)  ; current element's position in Array
            A_ArrayMM(&String+Offset, &Array+elmPos, elmLength)  ; Move it to ReturnData
            Offset     += elmLength                       ; calculate Offset
            if (A_Index!=elmCount)
                A_ArrayMM(&String+Offset, &lGlue, glueLength) ; Move Glue to ReturnData
            Offset     += glueLength                      ; calculate Offset again
        }
        return String
    }
}

; Returns an array of strings, each of which is a substring of string formed 
; by splitting it on boundaries formed by the string delimiter. 
; unlike Stringsplit, multiple chars are allowed in dString
A_Explode(ByRef Array, dString, sString, Limit=0, trimChars="", trimCharsIsRegEx=False, dStringIsRegEx=False) {
    if !(A_Array(Array))
        A_Init(Array)

    oIF := A_FormatInteger            ; Store current Integerformat
    SetFormat,Integer,H

     If !(trimCharsIsRegEx) {          ; Build RegExNeedle for trimming if non given
        Loop,Parse,TrimChars          ; parse each char and build hexescaped needle
             escTrimChars .=  "|^\" SubStr(asc(A_LoopField),2) "|\" SubStr(asc(A_LoopField),2) "$"
        trimChars := "(" SubStr(escTrimChars,2) ")"
    }

    gLen := StrLen(dString)           ; get length of delimiterString
    sLen := StrLen(sString)           ; get length of string
                                      ; since this is not a byref parameter,
                                      ; binary values need to be assigned direct in call such as 
                                      ; A_Explode(Array,"\x0",FileGetContent("myfile.dat"),"",0,1)

    If !(dStringIsRegEx) {            ; Build RegExNeedle for matching if non given
        Loop,Parse,dString            ; parse each char and build hexescaped needle
             escdString .=  "|\" SubStr(asc(A_LoopField),2)
        dString := "(" SubStr(escdString,2) ")"
    }
    SetFormat,Integer,% oIF

     Loop,
        if (nPos := RegExMatch(sString,dString)) {
            sLen -= nPos                                         ; calculate new length
            data := RegExReplace(sString,"(.{" sLen+gLen "}$)")  ; generate data to store in Array
            _tmp := RegExReplace(data,".","",dLen)               ; fix length for data
            sString := RegExReplace(sString,"(^.{" nPos "})")    ; generate new sourceString
            _tmp := RegExReplace(sString,".","",sLen)            ; fix length for binary Arrays
            A_Put(Array,Data,-1,dLen)                            ; store to Array
        } else {
            A_Put(Array,sString,-1,sLen)
            Break
         }
    return A_Count(Array)
}

; Deletes ItemIndex of given Array
A_Del(ByRef Array, Item=-1){
    If !(A_Array(Array)) {
        ErrorLevel := "No valid binary Array"
        return -1
    } else if ((Item+0<=0) || (Item>A_Count(Array))) {
        ErrorLevel := "No valid Index"
        return -1
    } else {
        aSize      := A_Size(Array)                    ; current DataSize of Array
        VarSetCapacity(tmpArray, aSize, 32)
        A_ArrayMM(&tmpArray, &Array, aSize)            ; copy Array

        VarSetCapacity(Array,0)                        ; delete Old Array
        Loop,% A_Count(tmpArray)
         {
            elmData   := A_Get(tmpArray,A_Index)
            if (A_Index!=Item)
                A_Put(Array,elmData,-1,ErrorLevel)
        }

        data  := A_Get(tmpArray,Item)                  ; Get return data
        size  := ErrorLevel                            ; store size for reuse
        VarSetCapacity(out,0)                          ; prepare element
        VarSetCapacity(out,size,32)
        A_ArrayMM(&out, &data, size)                   ; copy data to return var
        ErrorLevel := size                             ; update ErrorLevel
        Return out
    }
}

; Returns the element off the end of array and removes it
; Length is returned as ErrorLevel
A_Pop(ByRef Array){
    If !(A_Array(Array)) {
        ErrorLevel := "No valid binary Array"
        return -1
    } else {
        Item := A_Count(Array)
        data  := A_Del(Array,Item)                     ; Get return data
        size  := ErrorLevel                            ; store size for reuse
        VarSetCapacity(out,0)                          ; prepare element
        VarSetCapacity(out,size,32)
        A_ArrayMM(&out, &data, size)                   ; copy data to return var
        ErrorLevel := size                             ; update ErrorLevel
        Return out
    }
}

; Shift an element off the beginning of array and returns it
; Length is returned as ErrorLevel
A_Shift(ByRef Array){
    If !(A_Array(Array)) {
        ErrorLevel := "No valid binary Array"
        return -1
    } else {
        Item := 1
        data  := A_Del(Array,Item)                     ; Get return data
        size  := ErrorLevel                            ; store size for reuse
        VarSetCapacity(out,0)                          ; prepare element
        VarSetCapacity(out,size,32)
        A_ArrayMM(&out, &data, size)                   ; copy data to return var
        ErrorLevel := size                             ; update ErrorLevel
        Return out
    }
}

; Swaps element IdxA with element IdxB in given Array
A_Swap(ByRef Array, IdxA, IdxB) {
    If !(A_Array(Array)) {
        ErrorLevel := "No valid binary Array"
        return -1
    } else {
        elmA  := A_Get(Array,IdxA), sizeA := ErrorLevel
        elmB  := A_Get(Array,IdxB), sizeB := ErrorLevel
        A_Put(Array,elmB,idxA,sizeB)
        A_Put(Array,elmA,idxB,sizeA)
        return true
    }
}

; sArray's given intersection Elements are appended to Array, which
; will be created at runtime if neccessary
A_Slice(ByRef Array, ByRef sArray, Start, End) {
    If !(A_Array(sArray)) {
        ErrorLevel := "No valid source Array"
        return -1
    } else if ((cnt := A_Count(sArray)) 
                    && (Start>0) && (cnt<Start)
                    && (End>0) && (cnt<End)) {
        ErrorLevel := "Wrong Start or End of sArray"
        return -1
    } else {
        If !(A_Array(Array))
            A_Init(Array)
        startIndex := (Start > End)? End : Start
        endIndex   := (start==startIndex) ? End : Start
        Loop, % endIndex - StartIndex + 1 {
             elm  := A_Get(sArray, StartIndex-1+A_Index), size := ErrorLevel
            cnt := A_Put(Array, elm, -1, size)
        }
        ErrorLevel := cnt
    }
}

; Appends entire sArray to Array
A_Merge(Byref Array, ByRef sArray) {
    If (!(A_Array(sArray)) || (A_Count(sArray)<1)) {
        ErrorLevel := "No valid source Array"
        return -1
    } else {
        If !(A_Array(Array))
            A_Init(Array)
        A_Slice(Array,sArray,1,A_Count(sArray))
    }
}

; Returns TRUE if Array, FALSE otherwise - Thx, Lexikos
A_Array(byRef Array) {
    Return Array="Array()" && VarSetCapacity(Array)>=28 && NumGet(Array,8)=0x1001
}

; Returns current element count of given array or -1 if no valid binary array
A_Count(byRef Array) {
    If !(A_Array(Array)) {
        ErrorLevel := "No valid binary Array"
        return -1
    } else {
        ErrorLevel := 0
        Return NumGet(Array,24,"uInt")
    }
}

; for internal use only - initialises bytestructure of array
A_Init(byRef Array) {
    ; ATM 28 Bytes is minimum for AHK binary array structure
    ArraySize := 28 
    VarSetCapacity(Array,ArraySize,32)

    Array = Array()

    NumPut(0x1001,    Array, 8)   ; Array version
    NumPut(ArraySize, Array, 12)  ; ArraySize in bytes
    NumPut(0x1c,      Array, 16)  ; TableLength in bytes
    NumPut(0x0,       Array, 20)  ; ArrayLength in bytes
    NumPut(0x0,       Array, 24)  ; Element count
    Return True
}

; for internal use only - returns ArrayStructuresize
A_Size(ByRef Array){
    If !(A_Array(Array)) {
        ErrorLevel := "No valid binary Array"
        return -1
    } else {
        ErrorLevel := 0
        Return NumGet(Array,12,"uInt")
    }
}

; for internal use only - returns DataLength of Array
A_Length(ByRef Array){
    If !(A_Array(Array)) {
        ErrorLevel := "No valid binary Array"
        return -1
    } else {
        ErrorLevel := 0
        Return NumGet(Array,20,"uInt")
    }
}

A_Dump(ByRef Array) {
    If !(A_Array(Array)) {
        ErrorLevel := "No valid binary Array"
        return -1
    } else {
        out := "Array(" A_Count(Array) ")`n{`n" A_Implode(Array,"`n`t=>`t") "`n}`n"
        Loop,parse,out,`n
             if ((A_Index>=3) && (A_Count(Array)+2>=A_Index))
                out .= "   [" A_Index-2 "]" ((A_index-2=1) ? "`t=>`t" : "") A_LoopField "`n"
            else 
                out := ((A_Index=1) ? A_LoopField : out A_LoopField) "`n"
         Return out
    }
}

; for internal use only - SyntaxSugar for RtlMoveMemory
A_ArrayMM(Target, Source, Length) {
    DllCall("RtlMoveMemory","uInt",Target,"uInt",Source,"uInt",Length)
}

; for debugging purposes only
A___ArrayBin(ByRef Array,offset,length){
    SetFormat,Integer,h
     n := 0
    Loop,% length
     {
        c := NumGet(Array,offset+A_Index-1,"uchar")
        o .= SubStr("0" SubStr(c,3),-1) " " ((n=16) ? "`t" chars "`n" : "" )
        chars := ((n=16) ? "" : chars (RegExMatch(chr(c),"[^\x0-\x1f\x7f-\xa0]") ? chr(c) : "."))
        n:= ((n=16) ? 0 : n+1)
    }
    SetFormat,Integer,D
     if (n) && (n!=16) {
        VarSetCapacity(spc,(16-n)*3,32)
        r := spc "`t" chars
    }
    return o r
}

; for debugging purposes only - to dump an array use A_Dump(Array)
A___ArrayInsideView(Array) {
    A_ArrayMM(&(as1:="-------"), &Array, 7)
    as2 := ((x:=NumGet(Array, 7,"uchar"))=0) ? "\0" : x
    av  := NumGet(Array, 8)   ; Array version
    as  := NumGet(Array, 12)  ; ArraySize in bytes    (Structure)

    tl  := NumGet(Array, 16)  ; TableLength in bytes
    al  := NumGet(Array, 20)  ; ArrayLength in bytes  (Data)
    ec  := NumGet(Array, 24)  ; Element count
    
    offset := 28
    Loop,% (tl-offset) // 8
     {
        elms .= "&" offset+((A_index-1)*8)   " ptr elm " a_index 
                    . "`t->`t" (o:=NumGet(Array,offset+((A_index-1)*8)))   "`n"
              . "&" offset+((A_index-1)*8)+4 " len elm " a_index 
                    . "`t->`t" (l:=NumGet(Array,offset+4+((A_index-1)*8))) "`n"
        data .= "&" o ": " A___ArrayBin(Array,o,l) "`n"
    }
    
    out=
        (LTrim 
            aSignature    &0    %as1%
            Terminator    &7    %as2%
            arrayVersion    &8    %av%
            tArraySize    &12    %as%
            tableLength    &16    %tl%
            arrayLength    &20    %al%
            elementCount    &24    %ec%
                        
            %elms%
            %data%
        )

    return out 
}

/*
a_array - by derRaphael - exmaple internal table layout

  &0    (str)     Array()
  &7    (uchar)    \0
  &8    (uint)    AHK Array Version Major/Minor ::atm dec 4097 or 0x1001::
 &12    (uint)    ArraySize in bytes
 &16    (uint)    TableLength ::subject to change:: will stay reserved
 &20    (uint)    ArrayLength
 &24    (uint)    ElementsCount
 &28    (uint)    Elm1Offset ::In this case &36::
 &32    (uint)    elm1Length
 &36     rawdata
*/