-
Notifications
You must be signed in to change notification settings - Fork 71
/
A.ahk
450 lines (394 loc) · 16.9 KB
/
A.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
; 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
*/