Memory Block Q. with Bytes

I am trying to wrap my head around when to use Memory Blocks. For example I am using a method I wrote to convert Decimal to Hex to Ascii codes to put on the wire in a frame over TCP. Could I use Memory block to do this conversion quicker/easier than my code below? I have read through the LR and I am not 100% clear when/why to use it. I see alot of you using it so it must be good to use :slight_smile:

Thanks again!!

My Packet Design allows for user readability using Decimals.

Private Function ConvertDec2Hex2Asc(InputString as integer) As String
  Dim ConvertToHex as String = Hex(InputString)
  Dim Result, ToProcess as String
  Dim CountLength as Integer = Len(ConvertToHex)
  
  for i as integer = 2 to CountLength step 2
    ToProcess = Left(ConvertToHex,i)
    ToProcess = "&h" + ToProcess
    Result = Result + ChrB(CDbl(ToProcess))
  next i  
  Return Result

End Function

Mike, I’m not at expert at this but below is a method I use to send HEX characters over serial:

Method: Hex2String
Parameters: HexValue As UInt32, Bytes As UInt8
Return Type: String

[code] 'converts a 32-bit (4-byte) hex value into a string (MSB first)

Dim s As String
Dim msb As UInt8
Dim mb As New MemoryBlock(4)
mb.LittleEndian = False

If (Bytes > 0) And (Bytes < 5) Then
msb = 4-Bytes
Else
msb = 0
End If

mb.UInt32Value(0) = HexValue
s = mb.StringValue(msb,Bytes)
Return s[/code]

No offense, but that is some very convoluted code. It also contains some potentially serious errors. In essence, all you are doing is pulling one byte at a time out of the integer and converting it to a character. The result will be a “binary string”. The memoryblock equivalent would be

Private Function ConvertDec2Hex2Asc(InputString as integer) as string
  dim mb as new MemoryBlock(4)
  dim Result as String = chrb(0)

  mb.IntegerValue(0) = InputString
  for i as integer = 0 to 3
     if mb.byte(i)<> 0 then
        Result = mb.StringValue(i, 4-i)
        exit
    end if
  next
  return Result
end function

This code is more complicated than it needs to be, but it should match your existing functionality where you strip off any leading zero bytes via the Hex() function. However, you get a variable length string as a result, which I’m sure will cause complexity in your transmission protocol. Are you sending the length of the string as well? How are you decoding it on the other end? I would think it would be easier to transmit a fixed length 4-byte value. The code would then be

Private Function ConvertDec2Hex2Asc(InputString as Integer) as String
  dim mb as new MemoryBlock(4)
  dim Result as String

  mb.IntegerValue(0) = InputString
  Result = mb.StringValue(0,4)
  return Result
end function

Or, better, use a Structure for the entire transmission frame.

My comments were directed at Mike’s code, not L Rodriquez.

Thanks Tim! Yes it is convoluted as it represents my thought process which isn’t smooth on this yet :slight_smile: I am also still new to programming in general :slight_smile: Thank you for your help!

Thanks also L Rodriguez!

Thanks again Tim! When Kem asked me about this last week I really didn’t know what he was saying 100% and then I went on PTO :slight_smile:

Xojo Structure Link

Im checking this out now and thanks again!

Tim this is my protocol design which yes I have designed fixed width headers so thank you for helping me on this.

My Protocol overall header design

Header Option Details.

Since your header frame is fixed length and all of it is numeric, I wouldn’t do any kind of individual string conversions. Just stuff it into a Structure and pull the entire string out in one go. Note, however, that you may need to align your integers on an even byte boundary, so your SOF might need to be 2 bytes instead of one to make it all work smoothly.

dim s as myStructure
dim head as string

s.Preamble = 4607
s.SOF = 255
s.Version = 1
s.NodeID = 5000
head = s.StringValue(false)

I just looked over to my printed version and yes I had aligned SOF to “2” already :slight_smile: :slight_smile: thanks again Tim!! I just debugged your code while seeing how MB worked. Pretty awesome and man so much easier than what I was trying to do!!

Do you normally send the padded zeros if you have any or do you clip them prior to transmission to keep it clean?

Thanks!

I would send them. It’s easier to decode a fixed length string.

Tim I have both ways working and I was wondering how you have handled variable length payloads using either MB or Structures or both?

Thanks!

Ok so tell me if I am off path.

If I take my variable string, measure it, and convert that to bytes I can add this number as a header field right before the payload to tell the other side how much payload to expect.

Ok I think I have it. Here is my new Frame Header Format to represent my changes:

Any thoughts or suggestions are always welcome :slight_smile: Thank you again!!!

Private Function BuildFrame() As String
  Dim Header As EVIP_Structure
  Dim FrameHeader As String
  
Dim PayloadTest As String = "{""menu"":{""id"": ""file"",""value"":""File"",""popup"":{""menuitem"":[{""value"": ""New"", ""onclick"": ""CreateNewDoc()""},{""value"":""Open""onclick"":""OpenDoc()""},{""value"":""Close"",""onclick"":""CloseDoc()""}]}}}"
  Dim PayLoadLen As Integer = PayloadTest.Len
  
// Build the Frame Header via Structure
  Header.Preamble = 4607
  Header.SOF = 255
  Header.ProtVer = 1
  Header.NodeID = 5555
  Header.OptionType  = 5001
  Header.OptionData = 187
  Header.PayloadSize = PayloadTest.Len
  FrameHeader = Header.StringValue(TargetLittleEndian)
  
  // Build Payload via Memory Block with Size defined by Length of Payload String
  Dim PayloadMB As New MemoryBlock(PayLoadLen)
  Dim FrameToSend As String
  PayloadMB.LittleEndian = False
  PayloadMB.StringValue(0,PayLoadLen) = PayloadTest
  
  FrameToSend = FrameHeader + PayloadMB.StringValue(0,PayLoadLen)
  
  
  Return FrameToSend
End Function

FYI, MemoryBlocks self-convert to and from strings, so you can just say:

FrameToSend = FrameHeader + PayloadMB

Also, to create a MemoryBlock from a string, you can do this:

dim s as string = "some string"
dim mb as MemoryBlock = s

The mb.Size will equal s.LenB.

OH, and that underscores a bug in your code: You are using Len instead of LenB. If all of your characters are in the low-ascii range, it doesn’t matter, but you should use LenB just to be safe.

In fact, I’d restructure it to use a MemoryBlock for everything:

…
dim PayloadMB as MemoryBlock = PayloadTest
// Build the Frame Header via Structure
  Header.Preamble = 4607
  Header.SOF = 255
  Header.ProtVer = 1
  Header.NodeID = 5555
  Header.OptionType  = 5001
  Header.OptionData = 187
  Header.PayloadSize = PayloadMB.Size
  FrameHeader = Header.StringValue(TargetLittleEndian)
  
  Dim FrameToSend As String
  PayloadMB.LittleEndian = False // Don't think this matters since you are just storing a string
  
  FrameToSend = FrameHeader + PayloadMB

Kem thanks and I appreciate it! I have learned a ton from you and Tim on this forum … Thank you!!

Ironically, Tim learned everything he knows from me. And not just about Xojo either.

This is more remarkable when you consider that we “met” only about two years ago…

@Kem Tekinay - Lolz. I’m sure this is mostly true.

@Mike Cotrone - You don’t need the memoryblock. Xojo Strings are sufficient for your purposes.

FrameToSend = FrameHeader + PayloadTest

And be sure to use LenB

Header.PayloadSize = PayloadTest.LenB

I did swap in LenB and will move to the regular string. Thanks again.

On second thought, the memoryblock does serve a purpose if you’re using it to control the Endianness of the string. If that’s your goal, then I defer to Kem.

I don’t think endiness matters with a string. UTF8 string are always read from left to right as bits anyway.