I have an app which normally needs to read several arrays of
different UDTs from disk files. Since many of these UDTs
contain dynamic strings, I can't simply read the entire array
directly, but must read the array into a buffer and then "parse"
it into the individual elements.
To further complicate the matter, I am not yet a PB purist - the
target arrays are VB6 arrays - and worse still, the UDTs are
ported from a 16bit app and VB6 DWORD aligns the data in a UDT.
The parsing step I perform is very fast, but I'm always
interested in performance tuning so I'm wondering about
coding a generic UDT parsing routine in PB.
I wrote such a routine in assembly for parsing VB3's UDT arrays,
but I couldn't figure out if there was a pointer in the array
descriptor that pointed at a "structure map" of the UDT - i.e.,
given an array of type MyType, is there something in the array
descriptor that points to a data structure that defines the
structure of MyType. Since I couldn't find such a pointer, I
had to pass a "structure map" to the routine whenever I wanted
to use it. So, the parsing routine was generic, but I had no
way of generating the structure map on the fly - it had to be
hard-coded and if I wanted to change my UDT, I'd have to find
every line of code where I called the parsing routine and
modify the hard-coded structure map string.
Confused?
Given the following:
Type MyType
A As String
B As Integer
C As Long
D As String
End Type
Global MyArray() As MyType
I would hard code the following structure map string:
chr$(3) & chr$(1) & chr$(6) & chr$(1)
This structure map means:
1. chr$(3) --> there are three blocks in this UDT
1. chr$(1) --> this block is a dynamic string
2. chr$(6) --> the next six characters can be loaded directly
3. chr$(1) --> this block is a dynamic string
In pseudocode, the parsing routine is:
Sub ReadUDTArray(ByVal lpArray&, lElementCount&, lBlockSize&,
lpStrucMap&, hFile&)
' hey this is pseudocode, assume all DIMs are here
hBuffer = GlobalAlloc(GMEM_FIXED,lBlockSize)
lpBuffer = GlobalLock(hBuffer)
Fill buffer from hFile
hMemCpy byteStrucLen, lpStrucMap, 1
lBuffOffset = 0
lOffset = 0
For X = 1 to lElementCount
For Y = 1 to byteStrucLen
Select case @(lpStrucMap + Y)
case 1 ' this is a dynamic string
hMemCpy iSLen, lpBuffer + lBuffOffset, 2
lBuffOffset = lBuffOffset + 2
hString = AllocateString(iSLen)
lpString = DerefString(hString)
hMemCpy lpString, lpBuffer + lBuffOffset, iSLen
lBuffOffset = lBuffOffset + iSLen
hMemCpy lpArray + lOffset, hString, 2
lpArray = lpArray + 2
case else ' non-dynamic string (I didn't use variants)
hMemCpy lpArray + lOffset, hString, @(lpStrucMap + Y)
lpArray = lpArray + @(lpStrucMap + Y)
End Select
Next
Next
unlock buffer and free it
end sub
This routine worked beautifully under VB3, but I would like to do
two things:
1. convert it to work under Win32/VB6
2. figure out how or if I can generate the structure map within
the parsing routine itself
Any thoughts?
chris judge,
formfill, inc.
different UDTs from disk files. Since many of these UDTs
contain dynamic strings, I can't simply read the entire array
directly, but must read the array into a buffer and then "parse"
it into the individual elements.
To further complicate the matter, I am not yet a PB purist - the
target arrays are VB6 arrays - and worse still, the UDTs are
ported from a 16bit app and VB6 DWORD aligns the data in a UDT.
The parsing step I perform is very fast, but I'm always
interested in performance tuning so I'm wondering about
coding a generic UDT parsing routine in PB.
I wrote such a routine in assembly for parsing VB3's UDT arrays,
but I couldn't figure out if there was a pointer in the array
descriptor that pointed at a "structure map" of the UDT - i.e.,
given an array of type MyType, is there something in the array
descriptor that points to a data structure that defines the
structure of MyType. Since I couldn't find such a pointer, I
had to pass a "structure map" to the routine whenever I wanted
to use it. So, the parsing routine was generic, but I had no
way of generating the structure map on the fly - it had to be
hard-coded and if I wanted to change my UDT, I'd have to find
every line of code where I called the parsing routine and
modify the hard-coded structure map string.
Confused?
Given the following:
Type MyType
A As String
B As Integer
C As Long
D As String
End Type
Global MyArray() As MyType
I would hard code the following structure map string:
chr$(3) & chr$(1) & chr$(6) & chr$(1)
This structure map means:
1. chr$(3) --> there are three blocks in this UDT
1. chr$(1) --> this block is a dynamic string
2. chr$(6) --> the next six characters can be loaded directly
3. chr$(1) --> this block is a dynamic string
In pseudocode, the parsing routine is:
Sub ReadUDTArray(ByVal lpArray&, lElementCount&, lBlockSize&,
lpStrucMap&, hFile&)
' hey this is pseudocode, assume all DIMs are here
hBuffer = GlobalAlloc(GMEM_FIXED,lBlockSize)
lpBuffer = GlobalLock(hBuffer)
Fill buffer from hFile
hMemCpy byteStrucLen, lpStrucMap, 1
lBuffOffset = 0
lOffset = 0
For X = 1 to lElementCount
For Y = 1 to byteStrucLen
Select case @(lpStrucMap + Y)
case 1 ' this is a dynamic string
hMemCpy iSLen, lpBuffer + lBuffOffset, 2
lBuffOffset = lBuffOffset + 2
hString = AllocateString(iSLen)
lpString = DerefString(hString)
hMemCpy lpString, lpBuffer + lBuffOffset, iSLen
lBuffOffset = lBuffOffset + iSLen
hMemCpy lpArray + lOffset, hString, 2
lpArray = lpArray + 2
case else ' non-dynamic string (I didn't use variants)
hMemCpy lpArray + lOffset, hString, @(lpStrucMap + Y)
lpArray = lpArray + @(lpStrucMap + Y)
End Select
Next
Next
unlock buffer and free it
end sub
This routine worked beautifully under VB3, but I would like to do
two things:
1. convert it to work under Win32/VB6
2. figure out how or if I can generate the structure map within
the parsing routine itself
Any thoughts?
chris judge,
formfill, inc.
Comment