Re: working with byte arrays

Tech-Archive recommends: Fix windows errors by optimizing your registry

From: Peter (-)
Date: 11/13/04

  • Next message: Peter: "Re: working with byte arrays"
    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
    >
    >


  • Next message: Peter: "Re: working with byte arrays"

    Relevant Pages

    • Re: Updated datestamp doesnt work
      ... Public Sub StoreMyOldVals ... ' store values of current row in array ... Dim dbs As DAO.Database, rst As DAO.Recordset ... Dim var As Variant ...
      (microsoft.public.access.gettingstarted)
    • Re: Multiple OUs?
      ... something is up with adding multiple values to the array... ... ' If the AD enumeration runs into an OU object, call the Sub again to ... strLine = Trim ... strNewContents = strNewContents & strLine & vbCrLf ...
      (microsoft.public.scripting.vbscript)
    • Re: Packages and returning errors
      ... > array intact. ... sub is_a_instance_method { ... my $class = shift; ... You need to fix the scope of $error by moving its declaration outside ...
      (comp.lang.perl.misc)
    • Re: Updated datestamp doesnt work
      ... Public Sub StoreMyOldVals ... ' store values of current row in array ... Dim dbs As DAO.Database, rst As DAO.Recordset ... Dim var As Variant ...
      (microsoft.public.access.gettingstarted)
    • Re: Updated datestamp doesnt work
      ... Public Sub StoreMyOldVals ... ' store values of current row in array ... Dim dbs As DAO.Database, rst As DAO.Recordset ... Dim var As Variant ...
      (microsoft.public.access.gettingstarted)