Einzelnen Beitrag anzeigen

Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#32

AW: TGUID - einzigartige ID auf andere Computer Systeme ?

  Alt 30. Okt 2023, 14:58
Vielen Dank für die Infos und Hilfen!


Ich habe mir mal angehen, wie TSystemTime realisiert ist.
Nur mal eine kurze Übersicht, falls es jemanden direkt interessiert:
Delphi-Quellcode:
  PSystemTime = ^TSystemTime;
  _SYSTEMTIME = record
    wYear: Word;
    wMonth: Word;
    wDayOfWeek: Word;
    wDay: Word;
    wHour: Word;
    wMinute: Word;
    wSecond: Word;
    wMilliseconds: Word;
  end;
  {$EXTERNALSYM _SYSTEMTIME}
  TSystemTime = _SYSTEMTIME;
  SYSTEMTIME = _SYSTEMTIME;
  {$EXTERNALSYM SYSTEMTIME}
Das braucht natürlich einiges an Speicherplatz. Ich habe mich jetzt für GetTickCount entschieden, das die Systemlaufzeit als Cardinalwert zurück liefert.

Als Korrektur will ich die neue Unit nochmal hier einbinden. Vielleich hilf es ja mal jemandem.

Delphi-Quellcode:
unit myGuid;

interface

  uses

    System.Classes;

  type

    PmyGUID = ^TmyGUID;

    TmyGUID = record //: 12 Byte / 96 Bit
      C : Cardinal; //: 4 Byte / 32 Bit
      TS1: Cardinal; //: 4 Byte / 32 Bit
      TS2: Cardinal; //: 4 Byte / 32 Bit
      class function Create(const aGuid: PmyGUID): TmyGUID; overload; static;
      class function Create(const aGuid: String): TmyGUID; overload; static;
      class function Create(const aGuid: TmyGUID): TmyGUID; overload; static;
      class function CreateEmpty: TmyGUID; static;
      class function CreateNew: TmyGUID; static;
      class function StringIsValidGuid(const aGuid: String): Boolean; static;
      class operator Equal(const Left, Right: TmyGUID): Boolean;
      class operator NotEqual(const Left, Right: TmyGUID): Boolean; inline;
      function GetHashCode: Integer;
      function IsEmpty: Boolean;
      function ToString: String;
      procedure DoEmpty;
      procedure DoNew;
      procedure FromString(const aGuid: String);
      procedure ReadFromStream(const aStream: TMemoryStream);
      procedure WriteToStream(const aStream: TMemoryStream);
    end;

implementation

  uses

    System.SysUtils, System.Hash, Winapi.Windows;

  const

    MaxCardinal = 4294967295;

  var

    customTS1: Cardinal = 0;
    customTS2: Cardinal = 0;
    customC : Cardinal = 0;

  {: **************************************** TmyGUID *************************************** :}

  {: ---------------------------------------- default --------------------------------------- :}

  //: 2023-10-30
  class function TmyGUID.Create(const aGuid: String): TmyGUID;
  begin
    if (aGuid <> '') then
      begin
        Result := TmyGUID.CreateEmpty;
        Result.FromString(aGuid)
      end
    else
      begin
        Result := TmyGUID.CreateNew;
      end;
  end;

  //: 2023-10-30
  class function TmyGUID.Create(const aGuid: TmyGUID): TmyGUID;
  begin
    Result := aGuid;
  end;

  //: 2023-10-30
  class function TmyGUID.Create(const aGuid: PmyGUID): TmyGUID;
  begin
    Result := aGuid^;
  end;

  //: 2023-10-30
  class function TmyGUID.CreateEmpty: TmyGUID;
  begin
    Result.TS1 := 0;
    Result.TS2 := 0;
    Result.C := 0;
  end;

  //: 2023-10-30
  class function TmyGUID.CreateNew: TmyGUID;
  begin
    customTS2 := GetTickCount;
    Result.TS1 := customTS1;
    Result.TS2 := customTS2;
    Result.C := customC;
    if (customC = MaxCardinal) then
      customC := 0
    else
      Inc(customC);
  end;

  //: 2023-10-30
  class function TmyGUID.StringIsValidGuid(const aGuid: String): Boolean;
  var
    I: Integer;
    C: Char;
  begin
    //: #FFFFFFFF-FFFFFFFF-FFFFFFFF
    //: 123456789012345678901234567 - > Length = 27
    if (Length(aGuid) = 27) then
      begin
        Result := True;
        for I := 1 to Length(aGuid) do
          begin
            C := aGuid[I];
            case I of
              1:
                if C <> '#then
                  begin
                    Result := False;
                    Break;
                  end;
              10, 19:
                if C <> '-then
                  begin
                    Result := False;
                    Break;
                  end;
            else
              if not CharInSet(C, ['0'..'9', 'A'..'F']) then
                begin
                  Result := False;
                  Break;
                end;
            end;
          end;
      end
    else
      Result := False;
  end;

  //: 2023-10-30
  class operator TmyGUID.Equal(const Left, Right: TmyGUID): Boolean;
  begin
    Result := ((Left.TS1 = Right.TS1) and (Left.TS2 = Right.TS2) and (Left.C = Right.C));
  end;

  //: 2023-10-30
  class operator TmyGUID.NotEqual(const Left, Right: TmyGUID): Boolean;
  begin
    Result := ((Left.TS1 <> Right.TS1) or (Left.TS2 <> Right.TS2) or (Left.C <> Right.C));
  end;

  //: 2023-10-30
  function TmyGuid.GetHashCode: Integer;
  begin
    Result := 17;
    Result := Result * 397 + Integer(C);
    Result := Result * 397 + THashBobJenkins.GetHashValue(TS1, sizeOf(Cardinal), 5);
    Result := Result * 397 + THashBobJenkins.GetHashValue(TS2, sizeOf(Cardinal), 7);
  end;

  //: 2023-10-30
  function TmyGUID.IsEmpty: Boolean;
  begin
    Result := ((TS1 = 0) and (Ts2 = 0) and (C = 0));
  end;

  function TmyGUID.ToString: String;
  begin
    //: #FFFFFFFF-FFFFFFFF-FFFFFFFF
    //: 123456789012345678901234567 - > Length = 27
    Result := '#' + TS1.ToHexString + '-' + TS2.ToHexString + '-' + C.ToHexString;
  end;

  //: 2023-10-30
  procedure TmyGUID.DoEmpty;
  begin
    TS1 := 0;
    TS2 := 0;
    C := 0;
  end;

  //: 2023-10-30
  procedure TmyGUID.DoNew;
  var
    lGuid: TmyGUID;
  begin
    lGuid := CreateNew;
    TS1 := lGuid.TS1;
    TS2 := lGuid.TS2;
    C := lGuid.C;
  end;

  //: 2023-10-30
  procedure TmyGUID.FromString(const aGuid: String);
  begin
    //: #FFFFFFFF-FFFFFFFF-FFFFFFFF
    //: 123456789012345678901234567 - > Length = 27
    if (StringIsValidGuid(aGuid)) then
      begin
        TS1 := StrToInt('$' + Copy(aGuid, 2, 8));
        TS2 := StrToInt('$' + Copy(aGuid, 11, 8));
        C := StrToInt('$' + Copy(aGuid, 20, 8));
      end
    else
      begin
        TS1 := 0;
        Ts2 := 0;
        C := 0;
      end;
  end;

  //: 2023-10-30
  procedure TmyGUID.ReadFromStream(const aStream: TMemoryStream);
  begin
    aStream.ReadData(C);
    aStream.ReadData(TS1);
    aStream.ReadData(Ts2);
  end;

  //: 2023-10-30
  procedure TmyGUID.WriteToStream(const aStream: TMemoryStream);
  begin
    aStream.WriteData(C);
    aStream.WriteData(TS1);
    aStream.WriteData(Ts2);
  end;

initialization

  //: 2023-10-30
  customTS1 := GetTickCount;
  customTS2 := GetTickCount;
  customC := 0;

end.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat