Delphi.cz

Český portál Delphi

Operátory u záznamů a TBytes

Myslím, že celkem nedoceněnou vlastností je přetěžovaní operátorů u datové struktury record. Z cvičných důvodů ukáži jak např. emulovat 8bit string za pomocí TBytes.

Operátory a jejich syntaxe je popsaná v helpu, např. Operator Overloading.

Pro začátek si ujasněme co je TBytes.

TBytes = TArray<Byte>

TBytes je preferovaný způsob pro práci s daty v paměti (dříve se pro to hodně používal např. PChar, Pointer atd). Všimněte si, že i např. TBookmark je nyní deklarován jako TBytes. Cílem je nejen větší typová bezpečnost.

unit uString8;

interface
uses
  System.SysUtils;

type
  TString8 = record
  private
    FValue: TBytes;
    procedure SetValue(const Value: TBytes);
  public
    property Value: TBytes read FValue write SetValue;
    class operator Add (a, b: TString8): TString8;
    class operator Implicit (n: TString8): TBytes;
    class operator Implicit (s: UnicodeString): TString8;
    class operator Implicit (n: TString8): UnicodeString;
  end;

  function Length(s8:TString8):Integer; overload;


implementation

{ TString }
function Length(s8:TString8):Integer;
begin
  Result := System.Length(s8.Value);
end;

class operator TString8.Add(a, b: TString8): TString8;
begin
  SetLength(Result.FValue, Length(a) + Length(b));
  move(a.Value[0], Result.Value[0], Length(a));
  move(b.Value[0], Result.Value[Length(a)], Length(b));
end;

class operator TString8.Implicit(n: TString8): TBytes;
begin
  SetLength(Result, Length(n));
  move(n.Value[0], Result[0], Length(n));
end;

class operator TString8.Implicit(s: UnicodeString): TString8;
begin
  Result.FValue := BytesOf(s);
end;

class operator TString8.Implicit(n: TString8): UnicodeString;
begin
  Result := StringOf(n);
end;

procedure TString8.SetValue(const Value: TBytes);
begin
  FValue := Value;
end;

end.

Deklarován je nyní typ TString8, který je interně postaven na TBytes a definuje některé operace jako přetypování z a na některé typy a navíc je implementována operace sčítání (jako u normálních řetezců).

Díky tomu lze napsat např.

var
  s8:TString8;
  s: string;

  function readTest:TString8;
  begin
    Result := 'Hello';
  end;

begin
  s8 := 'Radek';

  writeln(Length(s8));
  s8 := s8 + ' delphi.cz';
  s := s8;
  writeln(s);

  s := readTest;
  writeln(s);

BytesOf a StringOf jsou funkce z RTL, které provádí konverzi mezi unicodestring a TBytes.

Není to dokonalé. Bohužel jsem nenašel způsob jak napsat přímo writeln(Length(s8)). Nějaký nápad?

Update: Pepák navrh overload Length a to je způsob.

Datum: 2013-04-04 00:39:00 Tagy: kompilátor, RTL

Novinky v Delphi Praxe