Attribute VB_Name = "mTestStrArrays"
Option Explicit

Private Declare Sub CopyMemByV Lib "kernel32" Alias "RtlMoveMemory" (ByVal lpDest As Long, ByVal lpSrc As Long, ByVal lByteLen As Long)
Private Declare Sub ZeroMemByV Lib "kernel32" Alias "RtlZeroMemory" (ByVal lpDest As Long, ByVal lLenB As Long)

Private sTestArray() As String
Private
lAbuf() As Long

' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'
' This is intended as a sort testing aid, and though it may be
' a handy technique to use elsewhere, care should be taken to
' ensure no memory violations occur.
'
' Distinctive usage:
'
' - This is intended to be used where the string items and
' the number of string items in the array are not changing.
'
' - This caches the string pointers only, not the strings,
' and is intended for use when re-ordering but not altering
' the string array, so care must be taken to reset the cached
' pointers whenever array items are added, removed, or modified.
'
' - When caching with CacheArrayPtrs the passed string array
' must contain at least one item or errors will occur.
'
' - When resetting with ResetArrayPtrs the passed string array
' size must match the cached size or errors will occur.
'
' - This uses RtlZeroMemory to nullify string pointers but only
' when calling ResetArrayPtrs with bNullify set to True; see
' SaveOriginal below. An un-confirmed mis-trust hangs over the
' use of RtlZeroMemory on some OS's?
'
' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Public Sub ResetArrayPtrs(sArr() As String, Optional ByVal bNullify As Boolean)

Dim lpStr As Long, lpBuf As Long
Dim
LBd As Long, UBd As Long

LBd = LBound(sArr)
UBd = UBound(sArr)

lpStr = VarPtr(sArr(LBd))
' Cache string array pointer

If bNullify Then
If
(UBd - LBd) Then
ZeroMemByV lpStr, ((UBd - LBd) + 1&) * 4&
End If
Else
lpBuf = VarPtr(lAbuf(LBd)) ' Cache buffer array pointer

If (UBd - LBd) Then
CopyMemByV lpStr, lpBuf, ((UBd - LBd) + 1&) * 4&
End If
End If
End Sub

Public Sub
CacheArrayPtrs(sArr() As String)

Dim lpStr As Long, lpBuf As Long
Dim
LBd As Long, UBd As Long

LBd = LBound(sArr)
UBd = UBound(sArr)

ReDim lAbuf(LBd To UBd) As Long

lpStr = VarPtr(sArr(LBd)) ' Cache string array pointer
lpBuf = VarPtr(lAbuf(LBd)) ' Cache buffer array pointer

If (UBd - LBd) Then
CopyMemByV lpBuf, lpStr, ((UBd - LBd) + 1&) * 4&
End If
End Sub

' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' Demo code only follows:

Sub LoadArray()

' Code to load test strings into array
'...

' Whenever the array is re-loaded cache the
' pointers in their original order
CacheArrayPtrs sTestArray

End Sub

Sub
SortTest()

' Reset the array items back to their original
' positions just before each new sorting test
ResetArrayPtrs sTestArray

' Do the sorting
strSort sTestArray

' I leave the array sorted to access the sorted data
' and don't reset until starting a new sort test

End Sub

Sub
CommitChanges()

' I cache the array pointers when one of the following occurs:

' Load the array with new items
' Add item(s) to the array
' Delete item(s) from the array
' Modify item(s) the strings themselves in any way
' Alter the array order and wish to test or save the resulting order

CacheArrayPtrs sA
End Sub

Sub
SaveOriginal()

' I use the temp array when I don't wish to alter
' the current sort state of the test array

Dim sTmp() As String

' This array must be erased or uninitialised
' (must contain only null string pointers)

ReDim sTmp(lb To ub) As String

' This makes an illegal copy
ResetArrayPtrs sTmp

' Code
'...

' Must nullify before going out of scope
ResetArrayPtrs sTmp, True
End Sub


 
目前有0条回应
Comment
Trackback
你目前的身份是游客,请输入昵称和电邮!