Operátory u záznamů a TBytes

vložil Radek Červinka 4. dubna 2013 01:39

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.

Tagy: ,

Novinky v Delphi | Praxe

Komentáře

4.4.2013 7:13:15 #

pepak

Nešlo by nadefinovat svůj vlastní overloadnutý Length?

Každopádně by šlo nadefinovat metodu Length a místo Length(s8) psát s8.Length.

pepak

4.4.2013 9:50:25 #

radekc

Prima:

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

Upraven článek, díky.

radekc

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

love Delphi

O Delphi.cz

Delphi je moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX, Linux a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců