Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2017-07

Delete and Add for TBytes?

5 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bo Berglund

I would like to replace a buffer handling scheme in an old application (written in Delphi) where the buffer was originally of type string and later when unicode appeared changed to AnsiString.

But AnsiString also causes potential headaches so I would like to get rid of it altogether by using a TBytes container instead. The problem is that the code utilizes heavily a few string oriented functions like:

To remove Count processed bytes from the beginning:

Buffer: AnsiString;

Delete(Buffer, 1, Count)
or worse:
Buffer := Copy(Buffer, Count+1, Length(Buffer));

For adding new data (c: AnsiChar) to the end:

Buffer := Buffer + c;

I would like to instead use TBytes as container but then I would not like to rewrite all of the code so I would like to be able to do something like:

Buf: TBytes;
b: byte;
Delete(Buf, Index, Count);  //Removes Count bytes at Index
BufAdd(Buf, b); //Extends size of Buf and puts b last

Is it possible to overload Delete() so it can be called with TBytes as argument?
For adding data the + operator would have been fine but I have no idea how one could do that...

Bo Berglund Developer in Sweden
Michael Van Canneyt
to Bo Berglund
Bo Berglund wrote 34 lines
I would like to replace a buffer handling scheme in an old application (written in Delphi) where the buffer was originally of type string and later when unicode appeared changed to AnsiString. But AnsiString also causes potential headaches so I would like to get rid of it altogether by using a TBytes container instead. The problem is that the code utilizes heavily a few string oriented functions like: To remove Count processed bytes from the beginning: Buffer: AnsiString; Delete(Buffer, 1, Count) or worse: Buffer := Copy(Buffer, Count+1, Length(Buffer)); For adding new data (c: AnsiChar) to the end: Buffer := Buffer + c; I would like to instead use TBytes as container but then I would not like to rewrite all of the code so I would like to be able to do something like: Buf: TBytes; b: byte; Delete(Buf, Index, Count); //Removes Count bytes at Index BufAdd(Buf, b); //Extends size of Buf and puts b last Is it possible to overload Delete() so it can be called with TBytes as argument?

It is.

For adding data the + operator would have been fine but I have no idea how one could do that...

Just define an operator. Plenty of examples.

uses sysutils;
operator + (a : TBytes; B : Char) c : TBytes;
begin
   SetLength(C,Length(A)+1);
   Move(A[0],C[0],Length(A));
   C[Length(A)]:=Ord(B);
end;
Procedure Dump(a : TBytes);
Var
   B : byte;
begin
   For B in A do
     Write(char(B));
   Writeln;
end;
Var
   A : TBytes;
begin
   A:=A+'c';
   Dump(A);
end.

outputs 'c' for me.

Michael.

Bo Berglund
to Michael Van Canneyt
Michael Van Canneyt wrote 5 lines
> Is it possible to overload Delete() so it can be called with TBytes as > argument? It is.

OK, then I am doing it erroneously....
(Testing in Delphi XE5 at the moment, but trying to write it to be portable since the unit that needs this is used both in Delphi and FPC)

This is how I did it:

In a utility unit "CommonFuncs" normally put into the uses clause of most source files I added this:

interface
....
// Byte buffer handling 2017-07-12 BB
procedure Delete(var Buf: TBytes; Index, Count: integer); overload;
...
implementation
....
procedure Delete(var Buf: TBytes, Index, Count: integer); overload;
begin
  Move(Buf[Index+Count], Buf[Index], Length(Buf)-Index - Count);
  SetLength(Buf, Length(Buf) - Count);
end;

Then I did a syntax check and it errored out on a line way up in CommonFuncs (actually the first use of Delete in the implementation section):

[dcc32 Error] CommonFuncs.pas(357): E2250 There is no overloaded version of 'Delete' that can be called with these arguments

The line looks like this:
	Delete(sVal, i, 1);

where sVal is a string, i.e. it should not be affected by the new Delete since it is not a TBytes variable.

Apparently the System.Delete procedure is missing the "overload" attribute....

So, what steps do I take in order to "overload" Delete in such a way that strings will still use the System.Delete?

Bo Berglund Developer in Sweden
Sven Barth
to Bo Berglund: I would like to replace a buffer handling scheme in an old application (written in…
"Bo Berglund" wrote 7 lines
To remove Count processed bytes from the beginning: Buffer: AnsiString; Delete(Buffer, 1, Count) or worse: Buffer := Copy(Buffer, Count+1, Length(Buffer));

FPC trunk supports Delete() and Insert() on dynamic arrays (TBytes is merely a dynamic array) and Copy() is supported for longer already. You merely need to adjust the indices to 0-based instead of 1-based. Delete() and Insert() are also supported by Delphi XE8 and newer I think.

For adding new data (c: AnsiChar) to the end: Buffer := Buffer + c;

The + operator is not yet implemented by default on FPC (neither is Concat()), but you can easily declare that yourself.

Regards,
Sven

Michael Schnell
to Bo Berglund: I would like to replace a buffer handling scheme in an old application (written in…
Bo Berglund wrote
I would like to instead use TBytes as container

As a dynamic array (TBytes) does not support lazy copy, this might introduce some performance and other trouble.

AFAIK, FPC's ANSISTring should not introduce any (Unicode) translations as long as you use the same string (UTF-8) type everywhere.

But of course this is not compatible with Delphi XE, that uses UTF-16)

-Michael