|
code
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Comparing UDTsI've written a function to compare two Variant variables some time ago. It could do variant arrays and all the simple data types (I don't know what's actually contained within the variant, it depends on what it's used for). Now I'd like to add a comparison between two variables of user-defined types (each stored in a variant). I don't know anything about their structure, excpect what I can get from the variant variable (that is: the size in bytes) I've found out that the variant hold a pointer to the UDT, and I can dump the memory content of the UDT into a byte (or long) array - info about the internal data structure can be found here: http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c7495/ Now, as soon as the UDT contains strings or variants, I'll once again have pointers within the data I wish to compare - and I don't know where they are, so I cannot compare strings stored within the UDT. Does anyone have an idea how I could compare two UDTs stored in a variant each? What I don't need are references to objects, but I do need the ability to compare strings stored in the UDTs. Here's the code I'm using so far: Private Declare Sub CopyMemoryRead Lib "kernel32" Alias _ "RtlMoveMemory" (Destination As Any, ByVal Source As Long, _ ByVal Length As Long) Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" ( _ Destination As Any, _ ByVal Length As Long) Public Function PackedVariantEqual(vntCmp1 As Variant, _ vntCmp2 As Variant) As Boolean ' Returns True if both variants contain exactly the same data Dim i As Long Dim ptr As Long Dim buf1() As Long Dim buf2() As Long PackedVariantEqual = False If (VarType(vntCmp1) <> VarType(vntCmp2)) Then Exit Function End If If (IsObject(vntCmp1) Or IsObject(vntCmp2)) Then ' Todo: Compare contents of objects Call Err.Raise(9753, "modClientMisc::PackedVariantEqual", "Internal error: Object comparison not possible!") End If If (Not (IsArray(vntCmp1))) Or (Not (IsArray(vntCmp2))) Then ' Simple types If (LenB(vntCmp1) <> LenB(vntCmp2)) Then Exit Function End If If (LenB(vntCmp1) > 0) Then ' Compare content ReDim buf1(1 To 4) ReDim buf2(1 To 4) If (VarType(vntCmp1) = vbString) Then ' vntCmp2 must have the same type anyway If (StrComp(vntCmp1, vntCmp2) <> 0) Then Exit Function End If Else Call CopyMemoryRead(buf1(1), VarPtr(vntCmp1), 16) Call CopyMemoryRead(buf2(1), VarPtr(vntCmp2), 16) If (VarType(vntCmp1) = vbUserDefinedType) Then ptr = buf1(3) ReDim buf1(1 To (LenB(vntCmp1) / 4) + 1) Call ZeroMemory(buf1(1), (UBound(buf1) - LBound(buf1) + 1) * 4) Call CopyMemoryRead(buf1(1), ptr, LenB(vntCmp1)) ptr = buf2(3) ReDim buf2(1 To (LenB(vntCmp2) / 4) + 1) Call ZeroMemory(buf2(1), (UBound(buf2) - LBound(buf2) + 1) * 4) Call CopyMemoryRead(buf2(1), ptr, LenB(vntCmp2)) ' Problem: If the UDT contains strings or variants, I'll only compare the pointers, ' not the data! End If For i = LBound(buf1) To UBound(buf1) If (buf1(i) <> buf2(i)) Then Exit Function End If Next i End If End If Else ' Arrays If ((LBound(vntCmp1) <> LBound(vntCmp2)) Or _ (UBound(vntCmp1) <> UBound(vntCmp2))) Then Exit Function End If For i = LBound(vntCmp1) To UBound(vntCmp2) ' Recursive call for each element of the array If (Not (PackedVariantEqual(vntCmp1(i), vntCmp2(i)))) Then Exit Function End If Next i End If PackedVariantEqual = True End Function Thanks for any ideas! Robert "Robert" <no***@nowhere.com> wrote in message Now that would be a good trick, because if you really /do/ meannews:O6DtzSW1FHA.1252@TK2MSFTNGP09.phx.gbl... > Now I'd like to add a comparison between two variables of > user-defined types (each stored in a variant). User Defined Type, as in ... Private Type SimplePoint X as Long Y as Long End Type .... you /cannot/ assign these to a Variant, since it fails with the error "Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late bound functions." or something like it. > I don't know anything about their structure, And that's the fundamental problem with UDT's; they're not"self-describing" (as opposed to Classes, which are), which is probably why Variants don't want to play with them. If you want to create, use and compare Classes, that's a whole new ball game, but I don't think you stand an awful lot of chance getting this to work with Types. Regards, Phill W. Since the UDT IS defined in a public class (public not creatable), I can
assign them to a Variant just fine. Well, the function itself doesn't know anything about the UDT, but the caller does. I would be happy if I could find a way the caller could tell the function how to handle the UDTs contained within the variant. Handing over a pointer to a compare function would be cool, but calling a function pointer is quite complicated (or does someone know a simple way to do this?). Any other simple way I could hand over a description of the UDT would be a fine solution, too. Robert Show quoteHide quote "Phill. W" <P.A.Ward@o-p-e-n-.-a-c-.-u-k> wrote in message news:dj80q8$59p$1@yarrow.open.ac.uk... > "Robert" <no***@nowhere.com> wrote in message > news:O6DtzSW1FHA.1252@TK2MSFTNGP09.phx.gbl... > > > Now I'd like to add a comparison between two variables of > > user-defined types (each stored in a variant). > > Now that would be a good trick, because if you really /do/ mean > User Defined Type, as in ... > > Private Type SimplePoint > X as Long > Y as Long > End Type > > ... you /cannot/ assign these to a Variant, since it fails with the error > > "Only user-defined types defined in public object modules can be > coerced to or from a variant or passed to late bound functions." > > or something like it. > > > I don't know anything about their structure, > > And that's the fundamental problem with UDT's; they're not > "self-describing" (as opposed to Classes, which are), which is > probably why Variants don't want to play with them. > > If you want to create, use and compare Classes, that's a whole > new ball game, but I don't think you stand an awful lot of > chance getting this to work with Types. > > Regards, > Phill W. > > Robert wrote:
> Now, as soon as the UDT contains strings or variants, I'll once again Take a look over here, for what looks to be a pretty cool method:> have pointers within the data I wish to compare - and I don't know > where they are, so I cannot compare strings stored within the UDT. ---- Original Message ---- From: "Schmidt" <s**@online.de> Newsgroups: microsoft.public.vb.comSent: Wednesday, October 19, 2005 6:15 PM Subject: Re: Convert user-defined data type to byte array? I haven't tried it yet, but I definitely intend to give it a workout myself! That's an interesting approach. However, I've found a simpler solution that
works for me: I create a class with the compare function, and whenever I stumble across a UDT, I raise an event asking my parent to compare it for me. Works just fine in my case. Thanks all Robert Show quoteHide quote "Karl E. Peterson" <k***@mvps.org> wrote in message news:emBoI%23Z1FHA.2788@TK2MSFTNGP10.phx.gbl... > Robert wrote: > > Now, as soon as the UDT contains strings or variants, I'll once again > > have pointers within the data I wish to compare - and I don't know > > where they are, so I cannot compare strings stored within the UDT. > > Take a look over here, for what looks to be a pretty cool method: > > ---- Original Message ---- > From: "Schmidt" <s**@online.de> > Newsgroups: microsoft.public.vb.com > Sent: Wednesday, October 19, 2005 6:15 PM > Subject: Re: Convert user-defined data type to byte array? > > I haven't tried it yet, but I definitely intend to give it a workout myself! > -- > Working Without a .NET? > http://classicvb.org/petition > >
CommandButton!
Using shell command to map drive can't get redirect result to file Modal form stops code in another form INSERT INTO how to split numeric part from letters in string Shrink Wrap SCC API implementation Object variable or With block variable not set Rotating a graphic text files & strings |
|||||||||||||||||||||||