@@ -55,15 +55,16 @@ function scalarfunc(expr::Expr)
55
55
return scalarfunc (f)
56
56
end
57
57
58
- # convert a bytearray to an int arr[1] is 256^0, arr[2] is 256^1...
59
- # TODO : would making this a method of convert needlessly pollute the Base namespace?
60
- function bytestoint (arr:: Vector{UInt8} )
61
- l = length (arr)
58
+ # convert a byteptr to an int, ptr[start] -> 256^0, ptr[start+1] -> 256^1...
59
+ # TODO : this assumes little-endian
60
+ function bytestoint (ptr:: Ptr{UInt8} , start:: Int , len:: Int )
62
61
s = 0
63
- for (i, v) in enumerate (arr)
64
- s += v * 256 ^ (i - 1 )
62
+ for i in start: start+ len- 1
63
+ v = unsafe_load (ptr, i)
64
+ s += v * 256 ^ (i - start)
65
65
end
66
- s
66
+
67
+ return s
67
68
end
68
69
69
70
function stepfunc (init, func, fsym= symbol (string (func)* " _step" ))
@@ -74,31 +75,25 @@ function stepfunc(init, func, fsym=symbol(string(func)*"_step"))
74
75
intsize = sizeof (Int)
75
76
ptrsize = sizeof (Ptr)
76
77
acsize = intsize + ptrsize
77
- acarr = pointer_to_array (
78
- convert (Ptr{UInt8}, sqlite3_aggregate_context (context, acsize)),
79
- acsize,
80
- false ,
81
- )
82
- # acarr will be zeroed-out if this is the first iteration
78
+ acptr = convert (Ptr{UInt8}, sqlite3_aggregate_context (context, acsize))
79
+ # acptr will be zeroed-out if this is the first iteration
83
80
ret = ccall (
84
81
:memcmp , Cint, (Ptr{UInt8}, Ptr{UInt8}, Cuint),
85
- zeros (UInt8, acsize), acarr , acsize,
82
+ zeros (UInt8, acsize), acptr , acsize,
86
83
)
87
84
try
88
85
if ret == 0
89
86
acval = $ (init)
90
- # TODO : i'm sure there's a better way
87
+ # TODO : allocate 256 byte
91
88
valsize = sizeof (sqlserialize (acval))
92
89
valptr = convert (Ptr{UInt8}, c_malloc (valsize))
93
90
else
94
- # retrieve the size of the serialized value (first sizeof(Int) bytes)
95
- sizebuf = zeros (UInt8, intsize)
96
- unsafe_copy! (sizebuf, 1 , acarr, 1 , intsize)
97
- valsize = bytestoint (sizebuf)
98
- # retrieve the ptr to the serialized value (last sizeof(Ptr) bytes)
99
- ptrbuf = zeros (UInt8, ptrsize)
100
- unsafe_copy! (ptrbuf, 1 , acarr, intsize+ 1 , ptrsize)
101
- valptr = reinterpret (Ptr{UInt8}, bytestoint (ptrbuf))
91
+ # size of serialized value is first sizeof(Int) bytes
92
+ valsize = bytestoint (acptr, 1 , intsize)
93
+ # ptr to serialized value is last sizeof(Ptr) bytes
94
+ valptr = reinterpret (
95
+ Ptr{UInt8}, bytestoint (acptr, intsize+ 1 , ptrsize)
96
+ )
102
97
# deserialize the value pointed to by valptr
103
98
acvalbuf = zeros (UInt8, valsize)
104
99
unsafe_copy! (pointer (acvalbuf), valptr, valsize)
@@ -110,21 +105,24 @@ function stepfunc(init, func, fsym=symbol(string(func)*"_step"))
110
105
newsize > valsize && (valptr = convert (Ptr{UInt8}, c_realloc (valptr, newsize)))
111
106
# copy serialized return value
112
107
unsafe_copy! (valptr, pointer (funcret), newsize)
108
+ # following copies are easier with arrays
109
+ acptr = pointer_to_array (acptr, acsize, false )
113
110
# copy the size of the serialized value
114
111
unsafe_copy! (
115
- acarr , 1 ,
112
+ acptr , 1 ,
116
113
reinterpret (UInt8, [newsize]), 1 ,
117
114
intsize,
118
115
)
119
- # copy the value of the pointer to the serialized value
120
- # TODO : can we just use ptrbuf here?
116
+ # copy the address of the pointer to the serialized value
121
117
unsafe_copy! (
122
- acarr , intsize+ 1 ,
118
+ acptr , intsize+ 1 ,
123
119
reinterpret (UInt8, [valptr]), 1 ,
124
120
ptrsize,
125
121
)
126
122
catch
127
- # TODO : this won't catch all memory leaks so add an else clause
123
+ # TODO :
124
+ # this won't catch all memory leaks so add an else clause
125
+ # alternatively use c-style checking in this function
128
126
if isdefined (:valptr )
129
127
c_free (valptr)
130
128
end
@@ -140,28 +138,25 @@ function finalfunc(init, func, fsym=symbol(string(func)*"_final"))
140
138
nm = isdefined (Base,fsym) ? :(Base.$ fsym) : fsym
141
139
return quote
142
140
function $ (nm)(context:: Ptr{Void} , nargs:: Cint , values:: Ptr{Ptr{Void}} )
143
- acptr = sqlite3_aggregate_context (context, 0 )
141
+ acptr = convert (Ptr{UInt8}, sqlite3_aggregate_context (context, 0 ) )
144
142
# step function wasn't run
145
- if acptr === C_NULL
143
+ if acptr == C_NULL
146
144
sqlreturn (context, $ (init))
147
145
else
148
146
intsize = sizeof (Int)
149
147
ptrsize = sizeof (Ptr)
150
148
acsize = intsize + ptrsize
151
- acarr = pointer_to_array (convert (Ptr{UInt8}, acptr), acsize, false )
152
149
# load size
153
- sizebuf = zeros (UInt8, intsize)
154
- unsafe_copy! (sizebuf, 1 , acarr, 1 , intsize)
155
- valsize = bytestoint (sizebuf)
150
+ valsize = bytestoint (acptr, 1 , intsize)
156
151
# load ptr
157
- ptrbuf = zeros (UInt8, ptrsize)
158
- unsafe_copy! (ptrbuf, 1 , acarr , intsize+ 1 , ptrsize)
159
- valptr = reinterpret (Ptr{UInt8}, bytestoint (ptrbuf) )
152
+ valptr = reinterpret (
153
+ Ptr{UInt8}, bytestoint (acptr , intsize+ 1 , ptrsize)
154
+ )
160
155
# load value
161
156
acvalbuf = zeros (UInt8, valsize)
162
157
unsafe_copy! (pointer (acvalbuf), valptr, valsize)
163
-
164
158
acval = sqldeserialize (acvalbuf)
159
+
165
160
ret = $ (func)(acval)
166
161
c_free (valptr)
167
162
sqlreturn (context, ret)
0 commit comments