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?

Recommended Answers

All 7 Replies

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;
}

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. :*)

Correct. It didn't reverse it at all; It copied from an offset to an offset. That's it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.