Qt documentation explain how entities are represented in binary format.
Let me collect the related links.
I’ll post here when ready.
Nothing difficult to implement in Xojo.
Hello Ed,
the informations stated in the comment section (the green colored part) of the source at https://sourceforge.net/p/wsjt/wsjtx/ci/master/tree/NetworkMessage.hpp are the only one required.
In Qt all types starts with the “q” letter so: qint32 is an int32 in Xojo and so on.
A QByteArray is very similar to a MemoryBlock.
No classes are serialized in a network message so things are simpler.
The important parts are:
all numeric values are represented in big endian format not little endian as used natively by x86/x64 Intel processors
all strings are in utf8 format without an end of string marker but prepended with an int32 value containing the string length
special string length values are 0 for an empty string and &hffffffff for a null string
all values are in binary format so an int32 is represented as 4 bytes (remember in big endian format)
The MemoryBlock LittleEndian=false property can be used to set/get numeric values in big endian.
Values can be set/get into/from frames contained in a MemoryBlock using offsets: this can be tedious.
A QDataStream is a class used to manipulate files/QByteArray contents in a simpler way instead of referring to the contained data using offsets.
Something very similar can be implemented in Xojo subclassing a MemoryBlock and adding methods to insert/pull data from the MemoryBlock contents and mantaining, as a private property, an offset index that increment accordingly to what is inserted/extracted from the MemoryBlock.
This is the fastest/shortest reply I can give you here just to start.
Reports here if you need more help.
Regards.
With your generous help I am making sense of all of this. Thank You!
I should probably be embarrassed to ask this, but here goes:
What is the most straightforward method for converting an array of bytes into a decimal value?
For instance, I have the following array of bytes representing the Dial Frequency as a quint64: 00 00 00 00 00 36 85 08
This becomes &h0000000000368508 which converts to 3573000 decimal.
I thought using
function decodeFreq (QBlock As MemoryBlock, firstByte As Integer) As String
Dim m As New MemoryBlock(8)
Dim i As Integer
Dim aVal As Int64
for i = 0 to 7
m.byte( i ) = QBlock.byte( firstByte + i )
Next
aVal = m.Int64Value( 0 )
Return str( aVal )
might give the value but instead I got 613956297833840640!
Make sure your memoryblock has the right endianness
'For instance, I have the following array of bytes representing the Dial Frequency as a quint64: 00 00 00 00 00 36 85 08
'This becomes &h0000000000368508 which converts to 3573000 decimal.
dim mb as new memoryblock(8)
mb.UInt8Value(0) = &h00
mb.UInt8Value(1) = &h00
mb.UInt8Value(2) = &h00
mb.UInt8Value(3) = &h00
mb.UInt8Value(4) = &h00
mb.UInt8Value(5) = &h36
mb.UInt8Value(6) = &h85
mb.UInt8Value(7) = &h08
mb.LittleEndian = true
dim leI64 as Uint64 = mb.UInt64Value(0)
mb.LittleEndian = false
dim beI64 as Uint64 = mb.UInt64Value(0)
break
Seems like a hard way to do it, but this works for me.
============
function decodeQ64 (QBlock As MemoryBlock, firstByte As Integer) As String
Const blockSize = 8
Const stringSize = 16
Dim m As New MemoryBlock(blockSize)
Dim i, hVal As Integer
Dim aVal As Int64
Dim pFactor( stringSize ) As Int64
Dim byteValue As integer
Dim s, h1 As String
for i = stringSize DownTo 1
pFactor( i ) = Pow( stringSize, stringSize - i )
Next
for i = 0 to blockSize - 1
m.Byte(i) = QBlock.Byte( firstByte + i )
Next
for i = 0 to blockSize - 1
byteValue = m.Byte( i )
h1 = hex( byteValue )
if len( h1 ) = 1 Then h1 = “0” + h1
s = s + h1
Next
for i = 1 to stringSize
hVal = asc( mid( s, i, 1 ) )
Select case hVal
Case 48 to 57
hVal = hVal - 48
Case 65 to 70
hVal = ( hVal - 65) + 10
End
[quote=429661:@Ed Stokes]Seems like a hard way to do it, but this works for me.
[/quote]
The first bunch of lines is just me setting up the memory block with the data you suggested to show how using LITTLEENDIAN and Uint64Value would do this for you
Literally you need 2 lines
littlendian = false
read the Uint64 from whatever offset
mb.LittleEndian = false
dim beI64 as Uint64 = mb.UInt64Value(0)
Is the code getting a string that is the hex representation ? ie “00” , “00” or BYTES with those values ?
I’m setting littlendian here in UDPSocket.DataAvailable
Dim d As DataGram
Dim mb1, mb As MemoryBlock
d = UDPSocket1.Read
mb = d.Data
if mb <> NIL Then
mb1 = mb
mb1.LittleEndian = False
end
HexDump( mb1 )
Then in HexDump I call my function
if wsjtxData.Size = 0 Then Return
.
{Other code to dump the hex of the dataGram)
.
if wsjtxData.Byte( 11 ) = 1 Then
s = decodeQ64( wsjtxData, 22 )
outPut.AppendText s + chr( 13 )
end
ah you want to see the bytes from the block in hex … I though you just wanted the decimal value from the memry block based on your first post and what I replied with
and that returns the decimal converted value with just the lines I posted
if you wanted to add that as a string you could just use STR or FORMAT on the value the two lines I posted return
yeah if the MB already has the bytes and you just want the decimal value then
dim beI64 as Uint64 = mb.UInt64Value(offset) /// start at whatever byte offset in the memory block you need <<<
will give you an unsigned int 64 (8 bytes) with one line of code
instead of
if wsjtxData.Byte( 11 ) = 1 Then
s = decodeQ64( wsjtxData, 22 )
outPut.AppendText s + chr( 13 )
end if
and all the code in decodeQ64 you can do
if wsjtxData.Byte( 11 ) = 1 Then
dim beI64 as Uint64 = mb.UInt64Value(offset)
outPut.AppendText s + str(beI64) + chr(13) // you might use end of line here
end