Question

i am using the move command its working for one byte to string conversion for record values,but when i add more values it displays garbage value. here is the code

interface

type
  tcommand = (
    cmd_login,
    cmd_logout,
    cmd_userinfo,
    cmd_removeuser,
    cmd_response
  );

  tprotocol = record
    username: string;
    receipent_username: string;
    arr: tbytes;
    case command_id: tcommand of
      cmd_userinfo:
        (username2: shortstring; ip: shortstring; port: word); // new info
      cmd_response:
        (status: boolean);
      cmd_removeuser:
        (username_remove: shortstring);
  end;

  pprotocol = ^tprotocol;

procedure encode_packet(obj: pprotocol);
procedure decode_packet(arr1: tbytes);

implementation

procedure encode_packet(obj: pprotocol);
begin
  setlength(obj.arr, length(obj.username) * 2);
  move(obj.username[1], obj.arr[0], length(obj.username) * 2);

  setlength(obj.arr, length(obj.receipent_username) * 2);
  // SetLength(Destination, SourceSize);
  move(obj.receipent_username[1], obj.arr[1],
    length(obj.receipent_username) * 2);
  // problem starts from here
end;

procedure decode_packet(arr1: tbytes);
begin
  setlength(username, length(arr1));
  move(arr1[0], username[1], length(arr1));

  setlength(s, length(arr1));
  move(arr1[1], s[1], length(arr1));
end;

Usage:

showmessage(username);
// displays correct value if recepient_username is not encoded
showmessage(s);

procedure TForm1.encodeClick(Sender: TObject); // button click
var
  obj2: pprotocol;
begin
  new(obj);
  new(obj2);
  memo1.Lines.Add('encode click');
  obj.username           := 'ahmd';
  obj.receipent_username := 'ali';

  encode_packet(obj);
  decode_packet(obj.arr);

end;

i think i have to make some indexing from where to start and stop decoding the byte array but i dont know how ? can anyone explain me how a string is stored in a byte array (when i debug i saw there are numbers and some nil values how could one get the string from indexing if they are so mixed up with nil values?)

Was it helpful?

Solution

You copy with move command length*2 bytes on one side, but length only bytes on other side. If you use unicode strings, then you need to use length*2 bytes on the both sides.

Another problem here is that you copy two strings in one array, one by one. If you want to save both strings in one array, then you have to allocate enough of space inside array, also put information about length of strings and write content of both strings. Example how to put 2 strings into 1 array of bytes:

procedure test;
var
  len: integer;
  buf: array of byte;
  a,b: string;
begin
  a := 'try';
  b := 'that';

  // save
  setlength(buf, SizeOf(Char)*(Length(a)+Length(b))+8);
  len := length(a);
  move(len, buf[0], 4);
  len := length(b);
  move(len, buf[4], 4);
  move(a[1], buf[8], length(a)*SizeOf(char));
  move(b[1], buf[8+length(a)*SizeOf(char)], length(a)*SizeOf(char));

  // restore
  a := '';
  b := '';
  move(buf[0], len, 4);
  setlength(a, len);
  move(buf[4], len, 4);
  setlength(b, len);
  move(buf[8], a[1], length(a)*SizeOf(char));
  move(buf[8+length(a)*SizeOf(char)], b[1], length(a)*SizeOf(char));
end;

But i recommend you do not play with pointers and use any kind of serialization instead, for example memory streams.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top