 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
olegbl
Joined: 13 Dec 2006 Posts: 48
|
Posted: Fri Nov 07, 2008 7:57 pm Post subject: [Concept Showcase] [Library] AHK Linked Lists |
|
|
So, I've been toying around with the idea of converting AHKA to a linked list. I doubt I'll actually do that, but I did create a working Linked List. (I'd like to say right here that AHK REAAAALLLLLYYYYY needs referenced variables AKA proper dereferencing).
The functionality is very basic so far.
Available Linked List Functions:
new
copy
add - full forwards/backwards index support (SA style, not AHKA style)
get - full forwards/backwards index support (SA style, not AHKA style)
print - displays something like "Austria@12345678 -> Brazil@12346789 -> 0"
The linked list involves two libraries:
The linked list node (LLN)
The linked list (LL)
Put both of them into your /Lib/ folder, and then you can use it...
(Well, you should know that if you're looking at a concept showcase)
LLN
| Code: | ; class LLN // Linked List Node
; {
; UInt size; // Size of data
; UInt next; // Pointer to next node
; Char [] data; // Array of characters (up to 64 KB worth of characters)
; }
LLN_Allocate()
{
global
LLN_ += 1
LLN_%LLN_% := 0
VarSetCapacity(LLN_%LLN_%, 64 * 1024 + 8, 0) ; Change the 64 here to the number of KB you want each list node to be capable of storing
return &LLN_%LLN_%
}
LLN_New(data, next=0)
{
global LLN_
node := LLN_Allocate()
size := StrLen(data)
NumPut(size, node + 0, 0, "UInt")
NumPut(next, node + 0, 4, "UInt")
Loop, %size%
NumPut(Asc(SubStr(data, A_Index, 1)), node + 0, 7 + A_Index, "UChar")
;next := LLN_GetNext(node)
;MsgBox, Created [%node%] -> [%next%]
return node
}
LLN_SetContent(node, data)
{
size := StrLen(data)
NumPut(size, node + 0, 0, "UInt")
Loop, %size%
NumPut(Asc(SubStr(data, A_Index, 1)), node + 0, 7 + A_Index, "UChar")
}
LLN_SetNext(node, next)
{
NumPut(next, node + 0, 4, "UInt")
}
LLN_GetContent(node)
{
size := NumGet(node + 0, 0, "UInt")
data := ""
Loop, %size%
data .= Chr(NumGet(node + 0, 7 + A_Index, "UChar"))
return data
}
LLN_GetNext(node)
{
return NumGet(node + 0, 4, "UInt")
}
LLN_GetSize(node)
{
return NumGet(node + 0, 0, "UInt")
}
LLN_Print(node)
{
if (node != 0)
return LLN_GetContent(node) . "@" . node . " -> " . LLN_Print(LLN_GetNext(node))
else
return node
} |
LL
| Code: | ; class LL // Linked List
; {
; UInt head; // Pointer to top node
; UInt size; // Number of nodes in the array
; }
LL_Allocate()
{
global
LL_ += 1
LL_%LL_% := 0
VarSetCapacity(LL_%LL_%, 8, 0)
return &LL_%LL_%
}
LL_New()
{
global LL_
arr := LL_Allocate()
NumPut(0, arr + 0, 0, "UInt")
NumPut(0, arr + 0, 4, "UInt")
return arr
}
LL_Copy(arr1)
{
arr2 := LL_Allocate()
size := LL_GetSize(arr1)
NumPut(0, arr2 + 0, 0, "UInt")
NumPut(size, arr2 + 0, 4, "UInt")
Loop, %size%
{
LL_Add(arr2, LL_Get(arr1, A_Index))
}
return arr2
}
LL_GetHead(arr)
{
return NumGet(arr + 0, 0, "UInt")
}
LL_SetHead(arr, head)
{
NumPut(head, arr + 0, 0, "UInt")
}
LL_GetSize(arr)
{
return NumGet(arr + 0, 4, "UInt")
}
LL_SetSize(arr, size)
{
NumPut(size, arr + 0, 4, "UInt")
}
LL_Print(arr)
{
return LLN_Print(LL_GetHead(arr))
}
LL_Add(arr, data, index=-1)
{
ptr := LL_GetHead(arr)
prv := 0
size := LL_GetSize(arr)
Loop
{
if (ptr == 0 || index == A_Index || size + 1 + index + 1 == A_Index)
break
prv := ptr
ptr := LLN_GetNext(ptr)
}
if (prv == 0)
LL_SetHead(arr, LLN_New(data, ptr))
else
LLN_SetNext(prv, LLN_New(data, ptr))
LL_SetSize(arr, LL_GetSize(arr) + 1)
}
LL_Get(arr, index=-1)
{
ptr := LL_GetHead(arr)
prv := 0
size := LL_GetSize(arr)
Loop
{
if (ptr == 0 || index == A_Index || size + index + 1 == A_Index)
break
prv := ptr
ptr := LLN_GetNext(ptr)
}
if (ptr == 0)
return "IndexOutOfBounds"
return LLN_GetContent(ptr)
} |
Tester
| Code: | #SingleInstance force
NodeTest:
node1 := LLN_New("Austria")
node3 := LLN_New("Canada")
node2 := LLN_New("Britain", node3)
LLN_SetNext(node1, node2)
MsgBox,,Node Test, % LLN_Print(node1)
LLN_SetNext(node1, node3)
MsgBox,,Node Test, % LLN_Print(node1)
LLN_SetContent(node1, "Australlia")
MsgBox,,Node Test, % LLN_Print(node1)
LLN_SetContent(node2, "Bulgaria")
LLN_SetContent(node3, "Columbia")
LLN_SetNext(node1, node2)
MsgBox,,Node Test, % LLN_Print(node1)
ArrTest:
arr1 := LL_New()
MsgBox, % LL_Print(arr1)
LL_Add(arr1, "Apple")
MsgBox, % LL_Print(arr1)
LL_Add(arr1, "Banana")
MsgBox, % LL_Print(arr1)
LL_Add(arr1, "Cantelupe")
LL_Add(arr1, "Date")
MsgBox, % LL_Print(arr1)
arr1_4 := LL_Get(arr1)
arr1_1 := LL_Get(arr1, 1)
arr1_2 := LL_Get(arr1, 2)
arr1_3 := LL_Get(arr1, -2)
arr1p := LL_Print(arr1)
MsgBox, %arr1_1% -> %arr1_2% -> %arr1_3% -> %arr1_4%`r`n%arr1p%
LL_Add(arr1, "2", 2)
LL_Add(arr1, "-2", -2)
MsgBox, % LL_Print(arr1)
arr2 := LL_Copy(arr1)
LL_Add(arr2, "Final")
MsgBox, % LL_Print(arr1)
MsgBox, % LL_Print(arr2) |
|
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 7293 Location: Australia
|
Posted: Mon Nov 10, 2008 9:11 am Post subject: |
|
|
It may be more efficient and "clean" to allocate memory via DllCall rather than using a global array. For instance,
| Code: | LLN_Allocate() {
return DllCall("GlobalAlloc","uint",0x40,"uint", 64 * 1024 + 8)
}
LLN_Deallocate(pnode) {
DllCall("GlobalFree","uint",pnode)
} | Also, to copy data, rather than
| Code: | Loop, %size%
NumPut(Asc(SubStr(data, A_Index, 1)), node + 0, 7 + A_Index, "UChar") | it would be more efficient to use | Code: | | DllCall("RtlMoveMemory", "uint", node + 8, "str", data, "uint", size) | This can be used regardless of whether you use GlobalAlloc.
| Quote: | | (I'd like to say right here that AHK REAAAALLLLLYYYYY needs referenced variables AKA proper dereferencing). | Some interesting things can be done with LowLevel.
| Code: | ; Initialize __alias and other __functions.
LowLevel_init()
; Store a reference to myvar%n% in ...
NumPut(__getVar(myvar%n%), ...)
; Retrieve a variable reference from ... and assign it the alias myvarref.
__alias(myvarref, NumGet(...))
; Assign a value to myvar%n%.
myvarref := "a value"
|
|
|
| Back to top |
|
 |
olegbl
Joined: 13 Dec 2006 Posts: 48
|
Posted: Mon Nov 10, 2008 9:35 am Post subject: |
|
|
Hmm, this is very interesting.
I haven't familiarized myself with DLLCall yet, so that is definetly a better way. LowLevel is quite an amazing library.. Didn't think such great progress had been made on AHK.
Wow. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|