Public Function Join12(SourceArray As Variant, _
Optional Delimiter As Variant = " ") As String
'made by Egbert Nierop at egbert_nierop.nospam@hotmail.com at april 2001, 20020528
' remove the spam prevention by robots to email
' win95 does not have NTDLL.DLL I think :< but if you have win95,
' install a decent windows please :)
' or just leave the idemode = True intact
' warning! Testing with this precompiled switch to False will
' crash the VB IDE
' in compiled mode however, vb compiles the __cdecl correct by
' ADD ESP, -12 whichs means decrement stack pointer by 12 (each pointer is 4 bytes)
#Const idemode = True
Dim lUbound As Long
Dim lDelimLen As Long
' important. The compiled location from these two variables just differ 4 bytes
' because they are anyway on the stack
' this way I have no TYPE/ struct overhead
' so do not place any variables between them!
Dim lElemLen As Long
Dim lMaxLen As Long
Dim lOldLen As Long
Dim lLbound As Long
Dim sTemp() As String
Dim lTemp As Long
Dim iVType As Integer
Dim psaData As Long
Dim sDelimiter As String
Dim bFill As Boolean
Const VT_BYREF = &H4000
Dim psa As Long
Dim sPtr As Long
#If idemode = True Then
kernel.MoveMemory iVType, SourceArray, 2
kernel.MoveMemory SourceArray, vbLong, 2
psa = SourceArray
kernel.MoveMemory SourceArray, iVType, 2
#Else
ntdll.MoveMemory iVType, SourceArray, 2
ntdll.MoveMemory SourceArray, vbLong, 2
psa = SourceArray
ntdll.MoveMemory SourceArray, iVType, 2
#End If
If iVType And (vbArray Or vbString) = 0 Then Exit Function
' reindex if the variant parameter was sent by reference
' one of the optimizations for oleaut :)
If iVType And VT_BYREF Then
#If idemode = True Then
kernel.MoveMemory psa, ByVal psa, 4
#Else
ntdll.MoveMemory psa, ByVal psa, 4
#End If
End If
'dont process non-initialised SafeArrays
If psa = 0 Then Err.Raise 9
#If idemode = True Then
kernel.MoveMemory ByVal ArrayPtr.VarPtrStringArray(sTemp()), psa, 4
#Else
ntdll.MoveMemory ByVal ArrayPtr.VarPtrStringArray(sTemp()), psa, 4
#End If
' If UBound(sTemp(), 1) <> 1 Then Err.Raise 9
sDelimiter = Delimiter
lLbound = OleAut.SafeArrayGetLBound(psa, 1)
lUbound = OleAut.SafeArrayGetUBound(psa, 1)
lDelimLen = OleAut.SysStringByteLen(sDelimiter)
Dim x As Long
For x = lLbound To lUbound
lMaxLen = lMaxLen + OleAut.SysStringByteLen(sTemp(x)) + lDelimLen
Next
lMaxLen = lMaxLen - lDelimLen
If lUbound - lLbound = 0 Then
Err.Raise 9
End If
sPtr = OleAut.SysAllocStringByteLenPtr(ByVal 0&, lMaxLen)
For lLbound = lLbound To lUbound
lElemLen = OleAut.SysStringByteLen(sTemp(lLbound))
#If idemode = True Then
kernel.MoveMemoryFromStr ByVal sPtr + lOldLen, sTemp(lLbound), lElemLen
lOldLen = lOldLen + lElemLen
If lDelimLen Then
kernel.MoveMemoryFromStr ByVal sPtr + lOldLen, sDelimiter, lDelimLen
lOldLen = lOldLen + lDelimLen
End If
#Else 'compilemode
ntdll.MoveMemoryFromStr ByVal sPtr + lOldLen, sTemp(lLbound), lElemLen
lOldLen = lOldLen + lElemLen
If lDelimLen Then
ntdll.MoveMemoryFromStr ByVal sPtr + lOldLen, sDelimiter, lDelimLen
lOldLen = lOldLen + lDelimLen
End If
#End If
Next
kernel.ZeroMemory ByVal ArrayPtr.VarPtrStringArray(sTemp()), 4
#If idemode = True Then
kernel.MoveMemory Join12, sPtr, Len(sPtr)
#Else
ntdll.MoveMemory Join12, sPtr, Len(sPtr)
#End If
End Function
|