Change the endianness of a Xojo.Core.MemoryBlock

What is the fastest way to switch the endianness of a Xojo.Core.MemoryBlock – not the property LittleEndian, but how the data is laid out in memory ?

What does it hold?


No, seriously: UInt32 and Ptr.

Found this on stackoverflow (translated from C):

[code]Dim mb As New Xojo.Core.MutableMemoryBlock(4)
mb.LittleEndian = False
mb.UInt32Value(0) = 1234

Dim mb2 As New Xojo.Core.MutableMemoryBlock(4)
mb2.LittleEndian = True
mb2.Left(4) = mb

Dim ui As UInt32 = mb2.UInt32Value(0) // ui is 3523477504 instead of 1234

Dim ui1 As UInt32 = Bitwise.ShiftLeft(ui, 24)
Dim ui2 As UInt32 = Bitwise.BitAnd(Bitwise.ShiftLeft(ui, 8), &h00ff0000)
Dim ui3 As UInt32 = Bitwise.BitAnd(Bitwise.ShiftRight(ui, 8), &h0000ff00)
Dim ui4 As UInt32 = Bitwise.ShiftRight(ui, 24)

ui = Bitwise.BitOr(ui1, ui2, ui3, ui4) // ui is now 1234[/code]

I think all you can do is create a second MemoryBlock with the “right” endiness, then copy the data over manually.

Can you not use a Structure instead?

I haven’t found a way to assign the result of aStructure.StringValue(littleEndian As Boolean) to a Xojo.Core.MutableMemoryBlock. I tried it via CStringValue, but had unstable results.

Yes. Or the above bit fiddling I found.

The interesting thing is, that assigning scalar values does take LittleEndian into account, but assigning blocks of memory not:

[code]Dim mb As New Xojo.Core.MutableMemoryBlock(4)
mb.LittleEndian = False
mb.UInt32Value(0) = 1234 // 1234 will be stored by what mb.LittleEndian is set to

Dim mb As New Xojo.Core.MutableMemoryBlock(4)
mb.LittleEndian = False
mb.Left(4) = anotherMB // 1234 will be stored by what anotherMB.LittleEndian is set to[/code]
It would be nice to have Left (and Mid and Right):

Sub Left(bytes As UInteger, Assigns value As MemoryBlock)

overloaded with:

Sub Left(bytes As UInteger, littleEndian As Boolean, Assigns value As MemoryBlock)

I found a way.

  dim omb as MemoryBlock = SomeStruct.StringValue( false )
  dim p as Ptr = omb
  dim mb as new Xojo.Core.MutableMemoryBlock( p, SomeStruct.Size )

There should be a “This partially answers my question” button… That is a great help for now.

I think it would be great if at some point in the future there could be a “new framework-only” solution.

You can get at the structure’s bytes via the ByteValue member of the structure. This returns an array of UInt8, which you can pass to the MemoryBlock constructor.

That’s the first I’m hearing about ByteValue. Is it new? Or new-ish?

Oh, I didn’t know there was a Structure data type in the new framework.

Yeah. Added in 2014r3 specifically to supersede StringValue.

Autocomplete does not show ByteValue. A Using clause will not help as Structure is not part of a namespace, but part of the language.

I guess autocomplete didn’t get updated (which you should file a bug about). Have you tried something like this:

Dim bytes() As UInt8 = SomeStruct.ByteValue( False ) Dim mb as New Xojo.Core.MutableMemoryBlock( bytes )

Off the top of my head (meaning, I’m too lazy to test right now), I’d think my proposal is faster but requires the classic framework. The ByteValue method is cleaner.

I don’t think it’d be much faster, if any.