[Lazarus] Use of Move()?

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

[Lazarus] Use of Move()?

Bo Berglund
I think I have made an error.....
I have created a generalized buffer handler for my project and here I
have this function to read data from the buffer.

function TSSCommBuf.Read(Dest: Pointer; Count: Cardinal): Cardinal;
var
  num: Cardinal;
begin
  num := FWriteIndex - FReadIndex;  //Remaining data bytes in buffer
  if num >= Count then
    num := Count;
  if num > 0 then
  begin
    Move(FBuf[FReadIndex], Dest, num);
    FReadIndex := FReadIndex + num;
  end;
  Result := num;
end;

FWriteIndex is the next location in the byte array to write to and
FReadIndex is the next location to read from.
FBuf is a dynamic array of byte declared as:
type
  TByteArr = array of byte;
FBuf: TByteArr;

What happens here is that when I call the function to retrieve a byte
as follows it returns incorrect data.

function TSSCommBuf.Read(var Data: byte): boolean;
begin
  Result := Read(@Data, SizeOf(Data)) = SizeOf(Data);
end;

What I suspect is that I am not using the correct syntax for the Move
call.
I think I have read that there are subtle differences in FPC versus
Delphi concerning such things as addresses.....


Bo Berglund


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Use of Move()?

Burkhard Carstens
Am Dienstag, 1. Februar 2011 21:03 schrieb Bo Berglund:

> I think I have made an error.....
> I have created a generalized buffer handler for my project and here I
> have this function to read data from the buffer.
>
> function TSSCommBuf.Read(Dest: Pointer; Count: Cardinal): Cardinal;
> var
>   num: Cardinal;
> begin
>   num := FWriteIndex - FReadIndex;  //Remaining data bytes in buffer
>   if num >= Count then
>     num := Count;
>   if num > 0 then
>   begin
>     Move(FBuf[FReadIndex], Dest, num);

didn't read further, but: try Dest^ ..
(quick guess)

regards
 Burkhard


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Use of Move()?

Bo Berglund
On Tue, 1 Feb 2011 21:18:57 +0100, Burkhard Carstens <[hidden email]>
wrote:

>Am Dienstag, 1. Februar 2011 21:03 schrieb Bo Berglund:
>> I think I have made an error.....
>> I have created a generalized buffer handler for my project and here I
>> have this function to read data from the buffer.
>>
>> function TSSCommBuf.Read(Dest: Pointer; Count: Cardinal): Cardinal;
>> var
>>   num: Cardinal;
>> begin
>>   num := FWriteIndex - FReadIndex;  //Remaining data bytes in buffer
>>   if num >= Count then
>>     num := Count;
>>   if num > 0 then
>>   begin
>>     Move(FBuf[FReadIndex], Dest, num);
>
>didn't read further, but: try Dest^ ..
>(quick guess)
>

Did not work, but I am using Move() in a way that has worked for me
using Delphi for many years, so it may have to do with Delphi vs fpc
differences....

What I usually do is the following:

Move(Source, Dest, Count);
where normally Source is an array, for example a string and Dest is
for example a multi-byte variable:

Move(SrcArr[Index], DestVar, SizeOf(DestVar);

Delphi manages to deduce what to use correctly so that the source is
the address of the array element Index and destination is the address
of the variable.

But when using FPC this may not really happen and this is what I am
trying to find out how to solve.
Here is the function that actually stuffs data into the buffer array:

function TSSCommBuf.Write(Source: Pointer; Count: Cardinal): boolean;
begin
  Result := false;
  if (FBufSize - FWriteIndex) < Count then
    ExpandBuffer(FWriteIndex - FBufSize + Count);
  Move(Source, FBuf[FWriteIndex], Count);
  FWriteIndex := FWriteIndex + Count;
  Result := true;
end;

Do I need to put @ or ^ characters in any part of this to make the
Move function work correctly?


Bo Berglund


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Use of Move()?

Marc Weustink
On 1-2-2011 23:11, Bo Berglund wrote:

> On Tue, 1 Feb 2011 21:18:57 +0100, Burkhard Carstens<[hidden email]>
> wrote:
>
>> Am Dienstag, 1. Februar 2011 21:03 schrieb Bo Berglund:
>>> I think I have made an error.....
>>> I have created a generalized buffer handler for my project and here I
>>> have this function to read data from the buffer.
>>>
>>> function TSSCommBuf.Read(Dest: Pointer; Count: Cardinal): Cardinal;
>>> var
>>>    num: Cardinal;
>>> begin
>>>    num := FWriteIndex - FReadIndex;  //Remaining data bytes in buffer
>>>    if num>= Count then
>>>      num := Count;
>>>    if num>  0 then
>>>    begin
>>>      Move(FBuf[FReadIndex], Dest, num);
>>
>> didn't read further, but: try Dest^ ..
>> (quick guess)
>>
>
> Did not work, but I am using Move() in a way that has worked for me
> using Delphi for many years, so it may have to do with Delphi vs fpc
> differences....

Also in Delphi you must use Dest^, otherwise you are overwriting your
pointer. (unless they have some overloaded Move)

> What I usually do is the following:
>
> Move(Source, Dest, Count);
> where normally Source is an array, for example a string and Dest is
> for example a multi-byte variable:
>
> Move(SrcArr[Index], DestVar, SizeOf(DestVar);

Just tested:

program MoveTest;
{$mode objfpc}{$H+}
uses
   SysUtils;
var
   S: String;
   I: Integer;
   P: Pointer;
begin
   S := 'Bla';
   S := S + S;
   P := @I;
   Move(S[1], P^, SizeOf(I));

   WriteLn(Format('%x %x %x %x %8.8x', [Ord(S[1]), Ord(S[2]), Ord(S[3]),
Ord(S[4]), i]));
end.

$ ./movetest
42 6C 61 42 42616C42


Marc

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Use of Move()?

Bo Berglund
On Tue, 01 Feb 2011 23:33:58 +0100, Marc Weustink
<[hidden email]> wrote:

>
>Just tested:
>
>program MoveTest;
>{$mode objfpc}{$H+}
>uses
>   SysUtils;
>var
>   S: String;
>   I: Integer;
>   P: Pointer;
>begin
>   S := 'Bla';
>   S := S + S;
>   P := @I;
>   Move(S[1], P^, SizeOf(I));
>
>   WriteLn(Format('%x %x %x %x %8.8x', [Ord(S[1]), Ord(S[2]), Ord(S[3]),
>Ord(S[4]), i]));
>end.
>
>$ ./movetest
>42 6C 61 42 42616C42
>

My code is a bit more complex because I want to be able to read and
write different types of variables to the buffer handler.
As an example I have the case of a string variable. To write it into
the buffer I use this overloaded write:

function TSSCommBuf.Write(const Source: string): boolean;
begin
  Result := Write(@Source[1], Length(Source));
end;

and for a Cardinal argument I use this:

function TSSCommBuf.Write(const Source: Cardinal): boolean;
begin
  Result := Write(@Source, SizeOf(Source));
end;

both of which then calls the main Write:

function TSSCommBuf.Write(Source: Pointer; Count: Cardinal): boolean;
var
  b: byte; //For debugging, will be removed later
  Dst: Pointer; //Suggestion from Marc Weustink
begin
  Result := false;
  //Check buffer size and grow if needed
  if (FBufSize - FWriteIndex) < Count then
    ExpandBuffer(FWriteIndex - FBufSize + Count);
  Dst := @FBuf[FWriteIndex];
  Move(Source, Dst^, Count); // Source and Dst are pointers
  b := FBuf[FWriteIndex]; //To check what actually was written
  FWriteIndex := FWriteIndex + Count;
  Result := true;
end;

When I call the Write method with a string argument I get first to the
small overloaded function, which unifies the arguments and calls the
main Write.

But when I test this with the string containing the single char #6
then the value that actually gets written is #64....

So somehow I am missing something important here...


Bo Berglund


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Use of Move()?

Marc Weustink
On 1-2-2011 23:51, Bo Berglund wrote:

> On Tue, 01 Feb 2011 23:33:58 +0100, Marc Weustink
> <[hidden email]>  wrote:
>
>>
>> Just tested:
>>
>> program MoveTest;
>> {$mode objfpc}{$H+}
>> uses
>>    SysUtils;
>> var
>>    S: String;
>>    I: Integer;
>>    P: Pointer;
>> begin
>>    S := 'Bla';
>>    S := S + S;
>>    P := @I;
>>    Move(S[1], P^, SizeOf(I));
>>
>>    WriteLn(Format('%x %x %x %x %8.8x', [Ord(S[1]), Ord(S[2]), Ord(S[3]),
>> Ord(S[4]), i]));
>> end.
>>
>> $ ./movetest
>> 42 6C 61 42 42616C42
>>
>
> My code is a bit more complex because I want to be able to read and
> write different types of variables to the buffer handler.
> As an example I have the case of a string variable. To write it into
> the buffer I use this overloaded write:
>
> function TSSCommBuf.Write(const Source: string): boolean;
> begin
>    Result := Write(@Source[1], Length(Source));
> end;
>
> and for a Cardinal argument I use this:
>
> function TSSCommBuf.Write(const Source: Cardinal): boolean;
> begin
>    Result := Write(@Source, SizeOf(Source));
> end;
>
> both of which then calls the main Write:
>
> function TSSCommBuf.Write(Source: Pointer; Count: Cardinal): boolean;
> var
>    b: byte; //For debugging, will be removed later
>    Dst: Pointer; //Suggestion from Marc Weustink
> begin
>    Result := false;
>    //Check buffer size and grow if needed
>    if (FBufSize - FWriteIndex)<  Count then
>      ExpandBuffer(FWriteIndex - FBufSize + Count);
>    Dst := @FBuf[FWriteIndex];
>    Move(Source, Dst^, Count); // Source and Dst are pointers
>    b := FBuf[FWriteIndex]; //To check what actually was written
>    FWriteIndex := FWriteIndex + Count;
>    Result := true;
> end;
>
> When I call the Write method with a string argument I get first to the
> small overloaded function, which unifies the arguments and calls the
> main Write.
>
> But when I test this with the string containing the single char #6
> then the value that actually gets written is #64....
>
> So somehow I am missing something important here...

Move expects 2 untyped parameters, so dereference your pointers

   Move(Source^, Dst^, Count); // Source and Dst are pointers

Marc

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Use of Move()?

Bo Berglund
On Wed, 02 Feb 2011 00:00:35 +0100, Marc Weustink
<[hidden email]> wrote:

>> So somehow I am missing something important here...
>
>Move expects 2 untyped parameters, so dereference your pointers
>
>   Move(Source^, Dst^, Count); // Source and Dst are pointers
>
Thanks!
Finally my buffer handler works as expected for the initial one-char
test. :-)


Bo Berglund


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus