Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi XE3 -> Integer to array of Bytes

I have a data structure:

data = array of integer;

I have filled it from an

source = array of byte;

with

data[x] := Source[offset] or (Source[offset + 1] shl 8) or
    (Source[offset + 2] shl 16) or (Source[offset + 3] shl 24);

after processing these blocks i have to bring them back to "bytes"...

any idea?

like image 351
Michael Grenzer Avatar asked Nov 29 '12 20:11

Michael Grenzer


3 Answers

You can do this in a one-liner using Move.

Move(source[0], dest[0], Length(source)*SizeOf(source[0]));

If you need to perform a network/host byte order transformation, then you can run across the integer array after the Move.

In the opposite direction you do it all in reverse.

If you haven't got byte order issues then you might not actually need to convert to a byte array at all. It's possible that you can use the integer array as is. Remember that, without byte order issues, the memory layout of the byte and integer arrays are the same (which is why you are able to blit with Move).

like image 195
David Heffernan Avatar answered Nov 13 '22 05:11

David Heffernan


You mean like this?

var
  i: integer;
  b1, b2, b3, b4: byte;
begin
  b1 := byte(i);
  b2 := byte(i shr 8);
  b3 := byte(i shr 16);
  b4 := byte(i shr 24);

Try, for instance,

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
  b1, b2, b3, b4: byte;
begin
  i := $AABBCCDD;
  b1 := byte(i);
  b2 := byte(i shr 8);
  b3 := byte(i shr 16);
  b4 := byte(i shr 24);
  ShowMessage(IntToHex(b1, 2));
  ShowMessage(IntToHex(b2, 2));
  ShowMessage(IntToHex(b3, 2));
  ShowMessage(IntToHex(b4, 2));
end;
like image 7
Andreas Rejbrand Avatar answered Nov 13 '22 05:11

Andreas Rejbrand


Hmmm... I see an answer using Move and one using shifts, but what about a simple cast?:

var
  I: Integer;
  B: array[0..3] of Byte;
begin
  // from bytes to integer:
  I := PInteger(@B)^;
  // from integer to bytes:
  PInteger(@B)^ := I;

Or with your arrays:

data[i] := PInteger(@source[offset])^;

and vice versa:

// get low byte
source[offset] := PByte(@data[i])^; // or := PByte(@data[i])[0];
// get second byte
secondByte := PByte(@data[i])[1]; // or := (PByte(@data[i]) + 1)^;

or

PInteger(@source[offset])^ := data[i];

As you see, you can get a long way by casting to pointers. This does not actually take the pointer, the compiler is clever enough to access the items directly.

like image 7
Rudy Velthuis Avatar answered Nov 13 '22 06:11

Rudy Velthuis