-
Notifications
You must be signed in to change notification settings - Fork 11
/
ARRAYDESC.ahk
145 lines (118 loc) · 4.5 KB
/
ARRAYDESC.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
/*
class: ARRAYDESC
a structure class that specifies the dimensions of an array and the type of its elements.
Authors:
- maul.esel (https://github.com/maul-esel)
License:
- *LGPL* (http://www.gnu.org/licenses/lpgl-2.1.txt)
Documentation:
- *class documentation* (http://maul-esel.github.com/COM-Classes/master/ARRAYDESC)
- *msdn* (http://msdn.microsoft.com/en-us/library/windows/desktop/ms221226)
Requirements:
AutoHotkey - AHK v2 alpha
Base classes - _CCF_Error_Handler_, StructBase
Structure classes - SAFEARRAYBOUND, TYPEDESC
*/
class ARRAYDESC extends StructBase
{
/*
Field: tdescElem
a TYPEDESC describing the element type. You may set this either to a class instance or a raw memory pointer.
Remarks:
When retrieved from an instance created with <FromStructPtr()> this is always a class instance.
*/
tdescElem := 0
/*
Field: cDims
The dimension count.
Remarks:
If you set <rgbounds> to an AHK-array, you may also leave this field unchanged. In this case, the value is assumed to be the member count of the array.
*/
cDims := -1
/*
Field: rgbounds
A variable-length array containing one SAFEARRAYBOUND element for each dimension.
Remarks:
You may set this field to
- ... an AHK-array containing SAFEARRAYBOUND class instances
- ... an AHK-array containing raw pointers to SAFEARRAYBOUND strcutures (may also be mixed with above)
- ... a raw memory pointer to the array
*/
rgbounds := 0
/*
Method: ToStructPtr
converts the instance to a script-usable struct and returns its memory adress.
Parameters:
[opt] PTR ptr - the fixed memory address to copy the struct to.
Returns:
PTR ptr - a pointer to the struct in memory
*/
ToStructPtr(ptr := 0)
{
static sab_size := SAFEARRAYBOUND.GetRequiredSize(), td_size := TYPEDESC.GetRequiredSize()
local count
if (!ptr)
{
ptr := this.Allocate(this.GetRequiredSize())
}
if (IsObject(this.rgbounds))
{
Loop count := this.cDims == -1 ? this.rgbounds.maxIndex() : this.cDims
IsObject(this.rgbounds[A_Index])
? this.rgbounds[A_Index].ToStructPtr(ptr + td_size + 2 + (A_Index - 1) * sab_size)
: CCFramework.CopyMemory(this.rgbounds[A_Index], ptr + td_size + 2 + (A_Index - 1) * sab_size, sab_size)
}
else
count := this.cDims, CCFramework.CopyMemory(ptr + td_size + 2, count * sab_size)
IsObject(this.tdescElem) ? this.tdescElem.ToStructPtr(ptr) : CCFramework.CopyMemory(this.tdescElem, ptr, td_size)
NumPut(count, 1*ptr, td_size, "UShort")
return ptr
}
/*
Method: FromStructPtr
(static) method that converts a script-usable struct into a new instance of the class
Parameters:
PTR ptr - a pointer to a ARRAYDESC struct in memory
[opt] BOOL own - false if the instance must no release the pointer (defaults to true)
Returns:
ARRAYDESC instance - the new ARRAYDESC instance
*/
FromStructPtr(ptr, own := true)
{
static td_size := TYPEDESC.GetRequiredSize(), sab_size := SAFEARRAYBOUND.GetRequiredSize()
local instance := new ARRAYDESC()
instance.SetOriginalPointer(ptr, own)
instance.tdescElem := TYPEDESC.FromStructPtr(ptr, false)
instance.cDims := NumGet(1*ptr, td_size, "UShort")
instance.rgbounds := []
Loop instance.cDims
instance.rgbounds.Insert(SAFEARRAYBOUND.FromStructPtr(ptr + td_size + 2 + (A_Index - 1) * sab_size, false))
return instance
}
/*
Method: GetRequiredSize
calculates the size a memory instance of this class requires.
Parameters:
[opt] OBJECT data - an optional data object that may cotain data for the calculation.
Returns:
UINT bytes - the number of bytes required
Remarks:
- This may be called as if it was a static method.
- The data object may contain a field called "cDims" to set the number of dimensions in the array.
If this is not present and the method is not called on an instance (in which case it would use the instance data), it is assumed to be 1.
*/
GetRequiredSize(data := "")
{
static td_size := TYPEDESC.GetRequiredSize(), sab_size := SAFEARRAYBOUND.GetRequiredSize()
local count := IsObject(data) && data.HasKey("cDims")
? data.cDims ; if cDims was passed: use this value
: (this != ARRAYDESC) ; if not called as static method but on instance:
? (this.cDims == -1) ; if user did not change original value:
? IsObject(this.rgbounds) ; if we have an AHK-array of dimension bounds:
? this.rgbounds.maxIndex() ; use its length
: 1 ; if it is not an AHK-array but a pointer, use 1
: this.cDims ; if cDims was changed by the user, use it
: 1 ; if called as static method, use 1
return td_size + 2 + count * sab_size
}
}