Class

MemoryBlock


Description

A MemoryBlock object allocates a sequence of bytes in memory and manipulates those bytes directly. A MemoryBlock can be passed in place of a Ptr when used in a Declare call.

Properties

Name

Type

Read-Only

Shared

LittleEndian

Boolean

Size

Integer

Methods

Name

Parameters

Returns

Shared

BooleanValue

Offset As Integer

Boolean

Byte

Offset As Integer

Integer

ColorValue

Offset As Integer, Bits As Integer

Color

Constructor

bytes As UInteger

data As String

CopyBytes

source As MemoryBlock, offset As Integer, length As Integer, Optional targetOffset As Integer = 0

CString

Offset As Integer

String

CurrencyValue

Offset As Integer

Currency

DoubleValue

Offset As Integer

Double

Int16Value

Offset As Integer

Int16

Int32Value

Offset As Integer

Int32

Int64Value

Offset As Integer

Int64

Int8Value

Offset As Integer

Int8

LeftB

Bytes As Integer

MemoryBlock

Long

Offset As Integer

Integer

MidB

Offset As Integer, [Length As Integer]

MemoryBlock

Operator_Add

value As MemoryBlock

MemoryBlock

Operator_Compare

Integer

Operator_Convert

Ptr

String

PString

Offset As Integer

String

Ptr

Offset As Integer

Ptr

RightB

Bytes As Integer

MemoryBlock

Short

Offset As Integer

Integer

SingleValue

Offset As Integer

Double

StringValue

Offset As Integer, Length As Integer, Optional Encoding As TextEncoding = Nil

String

UInt16Value

Offset As Integer

UInt16

UInt32Value

Offset As Integer

UInt32

UInt64Value

Offset As Integer

UInt64

UInt8Value

Offset As Integer

UInt8

UShort

Offset As Integer

Integer

WString

Offset As Integer

String

Constants

The following class constant is returned by Size when the size of the MemoryBlock cannot be determined.

Class Constant

Description

SizeUnknown

The size of the MemoryBlock cannot be determined.

Property descriptions


MemoryBlock.LittleEndian

LittleEndian As Boolean

Sets the endianness of a MemoryBlock. The default is the endianness of the platform on which the code is being compiled.

All current CPU targets (x86-32, x86-64, ARM-32, ARM-64) default to LittleEndian = True.

Var mb1 As New MemoryBlock(2) ' currently Little Endian = True on all platforms
mb1.Int8Value(0) = 1
mb1.Int8Value(1) = 2

Var firstUInt16 As Int16
firstUInt16 = mb1.UInt16Value(0)
' firstUInt16 = (256 * 2) + (1 * 1) = 513

mb1.LittleEndian = False
Var secondUInt16 As Int16
secondUInt16 = mb1.UInt16Value(0)
' secondUInt16 = (256 * 1) + (1 * 2) = 258

MemoryBlock.Size

Size As Integer

The size of the MemoryBlock in bytes.

If you assign a value to this property, the MemoryBlock is resized, retaining as much of the existing data as possible.

MemoryBlock has a class constant, SizeUnknown (Integer), whose value is -1. Size returns SizeUnknown when the MemoryBlock is of unknown size. You can get this condition with Declare statements. Also, Ptr returns a MemoryBlock with an unspecified, so it sets Size to -1; however, the MemoryBlock can still be used to access the data that is stored in the MemoryBlock.

Method descriptions


MemoryBlock.BooleanValue

BooleanValue(Offset As Integer) As Boolean

Gets and sets boolean (True/False) values.

0 is False while any non-zero value is True. Offset is in bytes from the beginning of the MemoryBlock.

This example sets a byte in the MemoryBlock and then reads it.

Var mm As New MemoryBlock(4)
mm.BooleanValue(0) = True

If mm.BooleanValue(0) Then
  MessageBox("True")
End If

MemoryBlock.Byte

Byte(Offset As Integer) As Integer

Gets or sets the passed byte value. Returns an integer. Offset is in bytes from the beginning of the MemoryBlock.

The following code stores character byte values in a MemoryBlock and displays it as a String:

Var m As New MemoryBlock(12)
m.Byte(0) = 72
m.Byte(1) = 101
m.Byte(2) = 108
m.Byte(3) = 108
m.Byte(4) = 111
m.Byte(5) = 32
m.Byte(6) = 87
m.Byte(7) = 111
m.Byte(8) = 114
m.Byte(9) = 108
m.Byte(10) = 100
m.Byte(11) = 33

Var hello As String = m.StringValue(0, m.Size) ' Hello World!

MemoryBlock.ColorValue

ColorValue(Offset As Integer, Bits As Integer) As Color

Gets or sets a Color in one of three formats, selected by Bits.

Bits can take on the following values:

Value

Description

32

32-bit color (high byte unused)

24

24-bit color

16

16-bit color (5 bits per color, high bit unused)

Returns a Color. Offset is in bytes from the beginning of the MemoryBlock.

This example stores a color in a MemoryBlock and then accesses it.

Var c As Color
Var m As New MemoryBlock(4)
m.ColorValue(0, 32) = &c43A245

c = m.ColorValue(0, 32)

MemoryBlock.Constructor

Constructor(bytes as UInteger)

Note

Constructors are special methods called when you create an object with the New keyword and pass in the parameters above.

Creates a new MemoryBlock with the size specified in bytes.

For 32-bit apps, you can request a maximum of about 2 to 3 GB depending on the OS. Generally Windows is closer to 2GB and macOS/Linux are closer to 3GB. There is no practical limit for 64-bit apps.

The following example reads a real number into a memory block and then displays it:

Var m As New MemoryBlock(4)
Var d As Single
m.SingleValue(0) = 123.456
d = m.SingleValue(0)
MessageBox(d.ToString)

The following example stores a string in a MemoryBlock and displays it:

Var m As New MemoryBlock(13)
m.Byte(0) = 12
m.Byte(1) = 72
m.Byte(2) = 101
m.Byte(3) = 108
m.Byte(4) = 108
m.Byte(5) = 111
m.Byte(6) = 32
m.Byte(7) = 87
m.Byte(8) = 111
m.Byte(9) = 114
m.Byte(10) = 108
m.Byte(11) = 100
m.Byte(12) = 33
MessageBox(m.PString(0))

MemoryBlock.Constructor

Constructor(data as String)

Creates a MemoryBlock from the data passed.

Important

This signature is supported for Android only.


MemoryBlock.CopyBytes

CopyBytes(source As MemoryBlock, offset As Integer, length As Integer, Optional targetOffset As Integer = 0)

Copies length bytes from the source MemoryBlock starting at offset to targetOffset.


MemoryBlock.CString

CString(Offset As Integer) As String

Returns a String. Offset is in bytes from the beginning of the MemoryBlock.

A CString is a sequence of non-zero bytes followed by a terminating Chr(0) that marks the end of the CString. MemoryBlock.CString returns a String consisting of the non-zero bytes beginning at Offset and ending before the terminating 0 byte.

When setting MemoryBlock.CString, one extra byte of space is needed for the CString terminator. Thus, for example, when setting the CString property of a MemoryBlock to a 15-byte string, 16 bytes of the MemoryBlock are actually set.

Var m As New MemoryBlock(16)
m.CString(0) = "Ecce quam bonum"

This example shows how to add the terminating null if the string doesn't already have it. It uses the string that was constructed in the Byte example.

Var m As New MemoryBlock(14)
m.Byte(0) = 12 ' length byte for a PString
m.Byte(1) = 72
m.Byte(2) = 101
m.Byte(3) = 108
m.Byte(4) = 108
m.Byte(5) = 111
m.Byte(6) = 32
m.Byte(7) = 87
m.Byte(8) = 111
m.Byte(9) = 114
m.Byte(10) = 108
m.Byte(11) = 100
m.Byte(12) = 33
MessageBox(m.PString(0))

' To read the string using CString, set the terminating byte before the call.
m.Byte(13) = 0
MessageBox(m.CString(1)) ' Skip first value which is the length for the String

MemoryBlock.CurrencyValue

CurrencyValue(Offset As Integer) As Currency

Gets or sets a Currency value. Offset is in bytes from the beginning of the MemoryBlock.

This example sets a Currency value and then accesses it.

Var c As Currency
Var m As New MemoryBlock(8)
m.CurrencyValue(0) = 34.54
c = m.CurrencyValue(0)

MemoryBlock.DoubleValue

DoubleValue(Offset As Integer) As Double

Gets or sets a Double value. Offset is in bytes from the beginning of the MemoryBlock.

This example sets a double value and then accesses it.

Var d As Double
Var m As New MemoryBlock(8)
m.DoubleValue(0) = 3.14159265358979323846264338327950

d = m.DoubleValue(0)

MemoryBlock.Int16Value

Int16Value(Offset As Integer) As Int16

Gets or sets an Int16 value. Offset is in bytes from the beginning of the MemoryBlock.

This example sets an Int16 value and then accesses it.

Var i As Int16
Var m As New MemoryBlock(2)
m.Int16value(0) = 34

i = m.Int16Value(0)

MemoryBlock.Int32Value

Int32Value(Offset As Integer) As Int32

Gets or sets an Int32 value. Offset is in bytes from the beginning of the MemoryBlock.

This example sets a 32-bit integer and then accesses it.

Var i As Int32
Var m As New MemoryBlock(4)
m.Int32value(0) = 256495

i = m.Int32Value(0)

MemoryBlock.Int64Value

Int64Value(Offset As Integer) As Int64

Gets or sets an Int64 value. Offset is in bytes from the beginning of the MemoryBlock.

This example sets a 64-bit integer and then accesses it.

Var i As Int64
Var m As New MemoryBlock(8)
m.Int64value(0) = 256495900

i = m.Int64Value(0)

MemoryBlock.Int8Value

Int8Value(Offset As Integer) As Int8

Gets or sets an Int8 value. Offset is in bytes from the beginning of the MemoryBlock.


MemoryBlock.LeftB

LeftB(Bytes As Integer) As MemoryBlock

Returns a new MemoryBlock of the specified size using the same endianness as the source MemoryBlock.

This example uses LeftB to set the value of a new MemoryBlock.

Var m As New MemoryBlock(8)
m.Int64value(0) = 256495900

Var n As New MemoryBlock(8)
n = m.LeftB(8)

MemoryBlock.Long

Long(Offset As Integer) As Integer

Returns an Integer, four bytes in length. Offset is in bytes from the beginning of the MemoryBlock.

Equivalent to Int32Value, which you should use instead.


MemoryBlock.MidB

MidB(Offset As Integer, [Length As Integer]) As MemoryBlock

Returns a new MemoryBlock of the specified size using the same endianness as the source MemoryBlock. Offset is in bytes from the beginning of the MemoryBlock.

This example extracts two bytes from a MemoryBlock.

Var m As New MemoryBlock(12)
.
.
Var n As New MemoryBlock(4)
n = m.MidB(1, 2)

MemoryBlock.Operator_Add

Operator_Add(value As MemoryBlock) As MemoryBlock

Overloads the + operator for the MemoryBlock class, providing a way to add the passed MemoryBlock to the Self instance. Returns the result as a MemoryBlock.


MemoryBlock.Operator_Compare

Operator_Compare As Integer

Defines the following comparison operators for the MemoryBlock class: =, <, >, <=, >=, <>. It compares the passed MemoryBlock to the Self instance.

Operator_Compare returns an integer whose meaning is as follows: <0 means that Self is less than the passed parameter, 0 means that Self is equal to the passed parameter, and >0 means that Self is greater than the passed parameter.


MemoryBlock.Operator_Convert

Operator_Convert As Ptr

Converts a MemoryBlock to a Ptr.

Operator_Convert As String

Converts a MemoryBlock to a String.


MemoryBlock.PString

PString(Offset As Integer) As String

Returns a String, up to 255 characters. The first byte is the length of the string. Offset is in bytes from the beginning of the MemoryBlock.

The following example stores a string in a MemoryBlock and displays it:

Var m As New MemoryBlock(13)
m.Byte(0) = 12
m.Byte(1) = 72
m.Byte(2) = 101
m.Byte(3) = 108
m.Byte(4) = 108
m.Byte(5) = 111
m.Byte(6) = 32
m.Byte(7) = 87
m.Byte(8) = 111
m.Byte(9) = 114
m.Byte(10) = 108
m.Byte(11) = 100
m.Byte(12) = 33
MessageBox(m.PString(0))

MemoryBlock.Ptr

Ptr(Offset As Integer) As Ptr

Gets or sets a MemoryBlock at the specified offset. Offset is in bytes from the beginning of the MemoryBlock.

If the MemoryBlock's size is not known, then the MemoryBlock this returns will also have an unknown (-1) size, although it can still be used to access its data.

MemoryBlocks automatically convert to Ptr.

This code converts a MemoryBlock to a Ptr:

Var p As Ptr = mb

This code retrieves another MemoryBlock (within the original MemoryBlock) at the specified offset and converts it to a Ptr:

Var p As Ptr = mb.Ptr(n)

This example stores a Ptr to a MemoryBlock property. If the MemoryBlock property goes out of scope, the Ptr will be invalid when retrieved.

MBProperty = New MemoryBlock(8)
MBProperty.StringValue(0, 8) = "a string"

Var mb As New MemoryBlock(8)
Var p As Ptr = MBProperty
mb.Ptr(0) = p

Because of implicit conversion between a Ptr and MemoryBlock, this can be shortened.

Var mb As New MemoryBlock(4)
mb.Ptr(0) = MBProperty

This code will retrieve the MemoryBlock later.

Var mb1 As MemoryBlock = mb.Ptr(0) ' Size will be unknown (-1)
Var s As String = mb1.StringValue(0, 8)

This code will store a Ptr to two methods.

Var mb As New MemoryBlock(8)
mb.Ptr(0) = AddressOf someMethod
mb.Ptr(4) = AddressOf someOtherMethod

MemoryBlock.RightB

RightB(Bytes As Integer) As MemoryBlock

Returns a new MemoryBlock of the specified size using the same endianness as the source MemoryBlock.

This example uses RightB to set the value of a new MemoryBlock.

Var m As New MemoryBlock(8)
m.Int64value(0) = 256495900

Var n As New MemoryBlock(8)
n = m.RightB(8)

MemoryBlock.Short

Short(Offset As Integer) As Integer

Returns a signed 16-bit Integer. Offset is in bytes from the beginning of the MemoryBlock.

This is equivalent to Int16Value which you should use instead.


MemoryBlock.SingleValue

SingleValue(Offset As Integer) As Double

Returns a 4-byte representation of a single-precision floating number as a Double. Offset is in bytes from the beginning of the MemoryBlock.

The following example sets a value in a MemoryBlock using Single and then gets it.

Var d As Double
Var m As New MemoryBlock(8)
m.SingleValue(0) = 256

d = m.SingleValue(0)

MemoryBlock.StringValue

StringValue(Offset As Integer, Length As Integer, Optional Encoding As TextEncoding = Nil) As String

Gets and sets a String of arbitrary size; it may contain nulls, and is not prefixed with a length byte. When setting, if Length is greater than the length of the string, it is padded with zeros. Offset is in bytes from the beginning of the MemoryBlock.

This example sets a string and then reads it back.

Var s As String
Var m As New MemoryBlock(8)
m.StringValue(0, 2) = "Ha"
s = m.StringValue(0, 2)

MemoryBlock.UInt16Value

UInt16Value(Offset As Integer) As UInt16

Gets or sets a UInt16 value. Offset is in bytes from the beginning of the MemoryBlock.

This example sets a UInt16 in a MemoryBlock and accesses it.

Var i As UInt16
Var m As New MemoryBlock(8)
m.UInt16Value(0) = 15

i = m.UInt16Value(0)

MemoryBlock.UInt32Value

UInt32Value(Offset As Integer) As UInt32

Gets or sets a UInt32 value. Offset is in bytes from the beginning of the MemoryBlock.

This example sets a UInt32 value in a MemoryBlock and then accesses it.

Var i As UInt32
Var m As New MemoryBlock(4)
m.UInt32Value(0) = 48000

i = m.UInt32Value(0)

MemoryBlock.UInt64Value

UInt64Value(Offset As Integer) As UInt64

Gets or sets a UInt64 value. Offset is in bytes from the beginning of the MemoryBlock.

This example sets a UInt64 in a MemoryBlock and then accesses it.

Var i As UInt64
Var m As New MemoryBlock(8)
m.UInt64Value(0) = 48000

i = m.UInt64Value(0)

MemoryBlock.UInt8Value

UInt8Value(Offset As Integer) As UInt8

Gets or sets a UInt8 value. Offset is in bytes from the beginning of the MemoryBlock.

This example sets a UInt8 to a MemoryBlock and then accesses it.

Var i As UInt8
Var m As New MemoryBlock(1)
m.UInt8Value(0) = 6

i = m.UInt8Value(0)

MemoryBlock.UShort

UShort(Offset As Integer) As Integer

Returns an unsigned 16 bit Integer. Offset is in bytes from the beginning of the MemoryBlock.

Equivalent to UInt16Value which you should use instead.


MemoryBlock.WString

WString(Offset As Integer) As String

Allows you to get and set null-terminated WStrings (UTF-16 strings) in a MemoryBlock. Offset is in bytes from the beginning of the MemoryBlock. The String returned by MemoryBlock.WString has encoding UTF-16.

Notes

MemoryBlocks can be used whenever you need a container for any arbitrary binary data.

MemoryBlocks are used when accessing entry points in shared libraries and when making OS calls using the Declare function.

MemoryBlocks supports creating a zero-length MemoryBlock.

For 32-bit apps, you can request a maximum of about 2 to 3 GB depending on the OS. Generally Windows is closer to 2GB and Mac/Linux are closer to 3GB. There is no practical limit for 64-bit apps.

The contents of a MemoryBlock can be viewed in the Debugger.

You can initialize a MemoryBlock from a string without using the constructor and declaring its size. For example, the following initializes a MemoryBlock from a String.

Var s As String = "abcde"
Var mb As MemoryBlock
mb = s
MessageBox(mb.Size.ToString) ' displays 5

You can convert this MemoryBlock back to a String with an assignment statement or a call that accepts a string. This statement converts the MemoryBlock back to a String.

Var a As String
a = mb

You can also pass this MemoryBlock to a function that expects a String. For example:

MessageBox(mb)  ' displays "abcde"

OutOfBoundsExceptions with StringValue

Accessing invalid StringValues can raise an OutOfBoundsException. Examples include:

Accessing a MemoryBlock StringValue with a size of 0:

Var mb As New MemoryBlock(0)
Var s As String = mb.StringValue(0, 0) ' OutOfBounds because size = 0

Accessing a MemoryBlockStringValue with a size less than 0:

Var mb As New MemoryBlock(0)
Var s As String = mb.StringValue(5, -1) ' OutOfBounds because size < 0

You will also get an OutOfBoundsException if the StringValue length is less than 0.

Sample code

The Faster String Appending with MemoryBlock project (included with Xojo in: Examples/Language/) uses MemoryBlocks to append two strings together as fast as possible. The main window has two TextFields, a Button, and a Label for displaying the result.

The user enters strings into the TextFields and clicks the Button. The Pressed event for the Button is the following:

Var m As MemBlockString

' create a New memBlockString
m = New MemBlockString

' add the strings into the memBlockString
m.AppendString(TextField1.Text)
m.AppendString(TextField2.Text)

' retreive the string
Label1.Text = m.GetString

The MemBlockString object is a custom class. It has the properties:

The constructor is:

' This is a class to use a memoryBlock as a temporary buffer
' while creating long strings by appending to already existing
' strings.  It can be a lot quicker than s = s + "more text" if
' you have very long strings

' This is both the size of the original memoryBlock
' but also how much it increases by each time if needed
BufferSize = 100000 ' bigger than really needed

mb = New MemoryBlock(BufferSize)
TotalLength = BufferSize

The appendString method is called in the DesktopButton's Pressed event:

Sub AppendString(s As String)
  #Pragma DisableBackgroundTasks

  Var l As Integer

  l = s.Length
  mb.StringValue(length, l) = s
  length = length + l

Exception
  ' If we write beyond the end of the memoryBlock we need to replace it with a newer ' bigger one
  TotalLength = TotalLength + bufferSize
  mb.Size = TotalLength
  mb.StringValue(length, l) = s
  length = length + l

Finally, the Pressed event handler calls getString to assign the appended string to the text property of the DesktopLabel.

Sub GetString() As String
  #Pragma DisableBackgroundTasks
  Return mb.StringValue(0, length)

The following example reads a real number into a memory block and then displays it:

Var m As New MemoryBlock(4)
Var d As Single
m.SingleValue(0) = 123.456
d = m.SingleValue(0)
MessageBox(d.ToString)

The following example stores a string in a MemoryBlock and displays it:

Var m As New MemoryBlock(13)
m.Byte(0) = 12
m.Byte(1) = 72
m.Byte(2) = 101
m.Byte(3) = 108
m.Byte(4) = 108
m.Byte(5) = 111
m.Byte(6) = 32
m.Byte(7) = 87
m.Byte(8) = 111
m.Byte(9) = 114
m.Byte(10) = 108
m.Byte(11) = 100
m.Byte(12) = 33
MessageBox(m.PString(0))

To read the string using CString, add the terminating byte before the call, i.e.,

m.Byte(13) = 0
MessageBox(m.CString(1))

This example backs a BinaryStream with a MemoryBlock that is declared 0-sized:

Var mb As New MemoryBlock(0)
Var bs As New BinaryStream(mb)
bs.WriteInt32(4)
bs.WriteDouble(3.14)
bs.Close
MessageBox(mb.Long(0).ToString)

Compatibility

All project types on all supported operating systems.

See also

Object parent class; BinaryStream class; Declare statement.