I'm trying to port opensource C++ code into my own Pascal application.

Specifically, I'm using libredwg source to read an AutoCAD drawing file so that I can extract text attributes and populate a database using Lazarus.

char* 
copy_bytes_16(char *dst, char *src)
{
  *(uint64_t*)dst = *(uint64_t*)(src + 8);
  *(uint64_t*)(dst + 8) = *(uint64_t*)src;  
  return dst + 16;
}

If I write the following Pascal code, is it equivalent? Obviously I would call the Procedure with copy_bytes(dst,src,posd,poss,16):

procedure copy_bytes(var dest: array of byte; src: array of byte; dp: integer; sp: integer; n: integer);
var
  i, j: integer;
begin
  i:=n+sp-1;
  while i<n do
  begin
    dest[dp]:=src[i];
    Inc(dp);
    Dec(i);
  end;
end;

The source also uses other functions to do a similar job, for example:

char* 
copy_bytes_3(char *dst, char *src)
{
  dst[0] = src[2];
  dst[1] = src[1];
  dst[2] = src[0];
  return dst + 3;
}

Which I'm hoping to call using copy_bytes(dst,src,posd,poss,3):

I'd obviously increment pos_d and pos_s by the relevant amount. Is this feasible?

Hi Triumphost,

Thanks for your reply.

I'm specifically looking at the order of the bytes.

The Libredwg source appears to reverse the order of the bytes.

~ Dave

Well I haven't done Pascal in ages but the "EXACT" Translation of the C++ code would be:

type PInt64 = ^Int64;

Function CopyBytes_16(var Dest: Pointer; Src: Pointer): Pointer;
begin
  PInt64(Dest)^ := PInt64(Src + 8)^;
  PInt64(Dest + 8)^ := PInt64(Src)^;
  Result := Dest + 16;
end;


//Which I used like:

var
  Dest, Src: Array Of Char;
begin

  //Src := 'This Is Cool';
  Src := [#84, #104, #105, #115, #32, #73, #115, #32, #67, #111, #111, #108];

  SetLength(Dest, 4);

  CopyBytes_16(Pointer(Dest), Pointer(Src));

  writeln(Dest);  //Prints 'Cool';
end.

Not sure if that's what you mean but yeah.

It works and does the exact same thing that your C++ Code does. You can test it by doing:

#include <iostream>

char* copy_bytes_16(char *dst, char *src)
{
  *(uint64_t*)dst = *(uint64_t*)(src + 8);
  *(uint64_t*)(dst + 8) = *(uint64_t*)src;
  return dst + 16;
}

int main()
{
    char Src[] = {'T','h','i','s',' ','I','s',' ','C','o','o','l'};
    char Dest[4] = {0};
    copy_bytes_16(Dest, Src);
    std::cout<<Dest;
}

Edited 4 Years Ago by triumphost

Thanks.

Basically if I have a src:=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,20]

and the first 100 bytes of dest are already populated, then if I want to copy the 16 bytes from src[6], then I would call:

copy_bytes(dest,src,100,6,16);

So this would populate the dest array (from byte 100) thusly:

[.,.,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6]

In other words [6..21] would be added to the end of the dest array, but in reverse.

I'm asking if the following code:

  *(uint64_t*)dst = *(uint64_t*)(src + 8);
  *(uint64_t*)(dst + 8) = *(uint64_t*)src; 

would achieve this? I know my Pascal code would do it, but I'm not sure if it would replicate the C++ code above. Would it?

I tried your code. Your code doesn't copy anything :S Didn't work for me. This did though:

type PByte  = ^Byte;
type PInt64 = ^Int64;

Procedure CopyBytes(var Dest: Pointer; Src: Pointer; DestOffset, SourceOffset, Size: Integer; CopyInReverse: Boolean);
var
  I, J: Integer;
begin
  If (Size < 1) Then
    Exit;

  For I := 0 To Size - 1 Do
    If CopyInReverse Then
      PByte(Dest + DestOffset + I)^ := PByte(Src + SourceOffset + (Size - I - 1))^
    Else
      PByte(Dest + DestOffset + I)^ := PByte(Src + SourceOffset + I)^;
end;

I tested it like:

var
  Dest, Src: Array Of Byte;
begin
  SetLength(Dest, 100);
  Src := [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,20];

  copybytes(Pointer(dest), Pointer(src), 10, 6, 16, True);
  Writeln(Dest);
end. 

Now you should note that if the Destination array isn't large enough to copy at that offset, it will indeed throw an access violation or have undefined behaviour.

Example:

Dest is 100 in length. If you tried to copy 6 bytes starting from 100, it will crash. Why? Because Dest should be 106 if you want to do such a thing.

Okay.

So if I read your code correctly, this:

  *(uint64_t*)dst = *(uint64_t*)(src + 8);
  *(uint64_t*)(dst + 8) = *(uint64_t*)src;

does not reverse the bytes and I will need to make a special case to do so.

Many thanks, that was what I was actually asking. :*)

This question has already been answered. Start a new discussion instead.