Re: working with byte arrays
From: Peter (-)
Date: 11/13/04
- Previous message: Eric: "MAPI Problem"
- In reply to: Mark Alexander Bertenshaw: "Re: working with byte arrays"
- Next in thread: Rick Rothstein: "Re: working with byte arrays"
- Messages sorted by: [ date ] [ thread ]
Date: Sat, 13 Nov 2004 10:25:53 +0100
Hi Mark
Thanks again for your answer.
concerning bytearray comparisson:
I thought about a fast API function written in asm or c.
I haven't tried out your code yet but I think I would prefer Rick's solution
where he just uses InstrB(1,a,b) but I haven't made any performance tests
yes. Anyway, thanks again for this idea.
concerning redimension of bytearrays:
I found out the following:
Dim a() as byte
Dim b() as byte
Load something into but leave a() untouched
now:
- a=b works and afterwards ubound(a) is equal to ubound(b)
- a(0)=65 does not work(error subscript out of range) I need to redim a
first that it works:
Conclusion: operations like a=b,a=strconv(sText,vbfromunicode) or RightBA =
MidBA(abytValue, lLen - lByteCount + 1) seem to automatically redim the
array before the values are assigned.
operations like a(x)=y,Get #1,,a(File I/O),CopyMemory require a redim first
Before I allways thought that ALL bytearray operations require a redim,
that's why I made subs instead of functions.
Now I will change my subs to functions(like yours) which returns the result
byte array.
I think that
Redim a(100)
a=LeftAB(b,10) will redim b automatically to 10 does not create any problems
for my application because after executing LeftAB I would expect to have
only 10 elements in array a.
concerning b=RightAB(b,10):
Thanks for this input. I thought that the return value is byref. If it is
byval then b=RightAB(b,10) where bytearray b is parameter and receptor of
result should work(I haven't tested it yet).
Regards
Peter
"Mark Alexander Bertenshaw" <mark.bertenshaw@virgin.net> schrieb im
Newsbeitrag news:Owp0w6MyEHA.3784@tk2msftngp13.phx.gbl...
>
> "Peter" <-> wrote in message
> news:%23WgkY2LyEHA.2752@TK2MSFTNGP11.phx.gbl...
>> Hi Mark
>> Thank you very much for your answer.
>> I came to the same conclusion inbetween and have already created similar
>> functions(subs) that use CopyMemory API like yours.
>> This is the confirmation for me that this is a good solution, thanks for
>> your help.
>
> My pleasure!
>
>> In addition I found out that InstrB defenitely works with byte arrays
>> therefore no new function is required for that.
>> dim a() as byte
>> dim b() as byte
>> load some values into a and b
>> x=InstrB(1,a,b,vbBinary) works!!! Only thing to know is that x does not
>> return the index of the array where the first byte match, instead it
> returns
>> index+1
>
> I imagine that all your byte arrays start at zero, and InStrB follows the
> way that InStr works - with 1 as the first position.
>
>> I have also made a function
>> IsEqualByte(a() as byte,b() as byte) as boolean
>> because you can not do something like
>> if a=b then...
>> My IsEqualByte just compares each byte of both arrays, to my surprise a
> byte
>> array comparisson with 1MB of size was very fast
>> for i=0 toUBound(a) 'as I use the bytearrays as a replacement for strings
>> all arrays start at index 0
>> if a(i)<>b(i) then...
>> next i
>> If you know a better way to compare two byte arrays then please let me
> know.
>
> On a 32-bit processor machine, the most efficient way to compare two
> numbers
> is by comparing two 32-bit numbers. So I suppose that if you wanted to
> have
> the most efficient algorithm, then you would try to compare 4 bytes at a
> time from each array. As it happens, there is a nice technique that I saw
> in the Curland book with allows you to point an array variable at an
> arbitary piece of memory. If you creates a Long array variable and
> iterated
> through (LenBA(abytData()) \ 4) elements of each array, comparing each
> position, then you could do this.
>
> modSafeArray.bas (from Advanced Visual Basic 6) :
> ------------------------------------------------------
>
> '***************************************************************
> ' (c) Copyright 2000 Matthew J. Curland
> '
> ' This file is from the CD-ROM accompanying the book:
> ' Advanced Visual Basic 6: Power Techniques for Everyday Programs
> ' Author: Matthew Curland
> ' Published by: Addison-Wesley, July 2000
> ' ISBN: 0-201-70712-8
> ' http://www.PowerVB.com
> '
> ' You are entitled to license free distribution of any application
> ' that uses this file if you own a copy of the book, or if you
> ' have obtained the file from a source approved by the author. You
> ' may redistribute this file only with express written permission
> ' of the author.
> '
> ' This file depends on:
> ' References:
> ' VBoostTypes6.olb (VBoost Object Types (6.0))
> ' Files:
> ' None
> ' Minimal VBoost conditionals:
> ' None
> ' Conditional Compilation Values:
> ' None
> '
> ' This file is discussed in Chapter 2.
> '***************************************************************
> Option Explicit
>
> Public Sub ShareMemoryViaArray(ByVal ArrayPtr As Long, SA1D As
> SafeArray1D,
> Optional ByVal MemPtr As Long, Optional ByVal ElemByteLen As Long)
> With SA1D
> 'cbElements is optional because this is a 1 element array,
> 'so cbElements is not needed to walk the array. If Erase
> 'is called on an array with .cbElements = 0, VB will still
> 'free all pointer types, but non-pointer types will not get
> 'zeroed out. Note that the compiler calculates the length
> 'of a structure at compile time, so LenB(MyStruct(0)) is
> 'valid regardless of whether or not MyStruct is actually allocated.
> .cbElements = ElemByteLen
> .cDims = 1
> 'This means that if the
> 'array goes out of scope, then the pointed
> 'to memory will be cleaned, but no attempt
> 'will be made to free the array pointer
> 'or descriptor.
> .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE
> .pvData = MemPtr
> .cElements = 1
> End With
> CopyMemory ByVal ArrayPtr, VarPtr(SA1D), 4
> End Sub
>
> Public Sub UnshareMemory(ByVal ArrayPtr As Long)
> ZeroMemory ByVal ArrayPtr, 4
> End Sub
>
> ------------------------------------------------------
>
> Another module:
> ------------------------------------------------------
>
> Option Explicit
>
> Public Declare Sub CopyMemory Lib "Kernel32.dll" Alias "RtlMoveMemory" ( _
> ByRef pDest As Any, ByRef pSrc As Any, ByVal lBytes As Long _
> )
>
> Public Declare Sub ZeroMemory Lib "Kernel32.dll" ( _
> ByRef pDest As Any, ByVal lBytes As Long _
> )
>
> Public Const FADF_AUTO = &H1
> Public Const FADF_STATIC = &H2
> Public Const FADF_EMBEDDED = &H4
> Public Const FADF_FIXEDSIZE = &H10
>
> Public Type SafeArray1D
> cDims As Integer
> fFeatures As Integer
> cbElements As Long
> cLocks As Long
> pvData As Long
> cElements As Long
> lLBound As Long
> End Type
>
> Private Declare Function VarPtrArray Lib "MSVBVM60.DLL" Alias "VarPtr"
> (ByRef a() As Any) As Long
>
> Public Function ByteArraysEqual(ByRef abyt1() As Byte, ByRef abyt2() As
> Byte) As Boolean
> Dim udtSafeArray1 As SafeArray1D
> Dim udtSafeArray2 As SafeArray1D
> Dim lMax As Long
> Dim al1() As Long
> Dim al2() As Long
> Dim lIndex As Long
>
> ' If the bounds don't match, then raise an error.
> If LBound(abyt1) <> LBound(abyt2) Or UBound(abyt1) <> UBound(abyt2)
> Then
> Err.Raise 5, , "Invalid"
> End If
>
> ' Find the greatest number of 32 bit integers we can compare.
> lMax = UBound(abyt1) \ 4
>
> ' Point al1() at abyt1()
> ShareMemoryViaArray VarPtrArray(al1), udtSafeArray1,
> VarPtr(abyt1(LBound(abyt1))), 4
> udtSafeArray1.lLBound = 1
> udtSafeArray1.cElements = lMax
>
> ' Point al2() at abyt2()
> ShareMemoryViaArray VarPtrArray(al2), udtSafeArray2,
> VarPtr(abyt2(LBound(abyt2))), 4
> udtSafeArray2.lLBound = 1
> udtSafeArray2.cElements = lMax
>
> ' Iterate through both long arrays, comparing each element.
> For lIndex = 1 To lMax
> If al1(lIndex) <> al2(lIndex) Then
> Exit Function
> End If
> Next lIndex
>
> ' Iterate through any remaining bytes in the byte arrays.
> For lIndex = (UBound(abyt1) - (UBound(abyt1) Mod 4)) To UBound(abyt1)
> If abyt1(lIndex) <> abyt2(lIndex) Then
> Exit Function
> End If
> Next lIndex
>
> ByteArraysEqual = True
>
> End Function
>
> ------------------------------------------------------
>
>
>> I addition, all my functions(I made subs instead of functions) do not
> return
>> a byte array like yours, instead the subs return a separate parameter
>> bArrayResult() which holds the result. I thought I do this because I am
> not
>> sure how vb behaves because of the different dimensions like:
>> Dim b() as byte
>> Redim b(100)
>> b=RightBA(a,10)
>> Doesn't that redim b to 10 ???
>
> It completely replaces the b() variable with the return value from
> RightBA(). Try stepping through the final assignment line of one of my
> functions, watching both the return value (i.e. the function variable) and
> the internal array variable. It's pretty interesting.
>
>> Each sub in my collection creates a copy of the parameters inside the sub
>> otherwise it would not be possible to do something like
>> b=RightBA(b,10) because all parameters are byref.
>
> Return values are always ByVal.
>
>> In addition the function String$() can be rebuild using FillMemory API, I
>> have also ceated a sub AddByte() to add/concatenate two byte arrays.
>> And I made a function LoadText() to load standard text into a byte array.
>> This is neccessary because
>> b="ABC" would load 65,0,66,0,67,0 into b on systems with unicode
>>
>> Again, that you very much for your answer
>> Regards
>> Peter
>
>
> --
> Mark Bertenshaw
> LEAX Controls Ltd
> UK
>
>
- Previous message: Eric: "MAPI Problem"
- In reply to: Mark Alexander Bertenshaw: "Re: working with byte arrays"
- Next in thread: Rick Rothstein: "Re: working with byte arrays"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|