Generate CUIDs in Delphi

Resources  |  Generate CUIDs in Delphi

Generating a CUID (Collision-resistant Unique Identifier) in Delphi involves using various functions to achieve timestamp generation, counter management, machine fingerprinting, and randomness. Delphi provides robust libraries for handling these operations, though some custom implementation is necessary.

Steps to Generate a CUID in Delphi

  1. Timestamp: Use the current timestamp.
  2. Counter: Implement a counter mechanism.
  3. Fingerprint: Generate a machine-specific fingerprint.
  4. Randomness: Add random characters.
  5. Base36 Encoding: Encode components in Base36.

Example Code

Here's an example implementation of a CUID generator in Delphi:

unit CUIDGenerator;

interface

uses
  System.SysUtils, System.DateUtils, System.Hash, System.Math, IdGlobal, IdStack, IdStackWindows;

function GenerateCUID: string;

implementation

const
  Base36Chars: array[0..35] of Char = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');

var
  LastTimeStamp: Int64 = 0;
  Counter: Integer = 0;

function EncodeBase36(Value: Int64): string;
begin
  Result := '';
  while Value > 0 do
  begin
    Result := Base36Chars[Value mod 36] + Result;
    Value := Value div 36;
  end;
  Result := Result.PadLeft(8, '0');
end;

function GetMachineFingerprint: string;
var
  Hash: THashMD5;
begin
  Hash := THashMD5.Create;
  try
    Result := Hash.GetHashString(GStack.LocalAddress);
    Result := Copy(Result, 1, 4);
  finally
    Hash.Free;
  end;
end;

function GetRandomString(Length: Integer): string;
var
  I: Integer;
begin
  Result := '';
  for I := 1 to Length do
    Result := Result + Base36Chars[Random(36)];
end;

function GenerateCUID: string;
var
  Timestamp: Int64;
  CounterValue: Integer;
  TimestampPart, CounterPart, FingerprintPart, RandomPart: string;
begin
  Timestamp := DateTimeToUnix(Now) * 1000;

  // Simple counter mechanism
  if Timestamp = LastTimeStamp then
  begin
    Inc(Counter);
  end
  else
  begin
    LastTimeStamp := Timestamp;
    Counter := 0;
  end;

  CounterValue := Counter;

  // Encode components in Base36
  TimestampPart := EncodeBase36(Timestamp);
  CounterPart := EncodeBase36(CounterValue);
  FingerprintPart := GetMachineFingerprint;
  RandomPart := GetRandomString(4);

  // Combine components to form the CUID
  Result := 'c' + TimestampPart + CounterPart + FingerprintPart + RandomPart;
end;

end.

Explanation

  1. Base36 Encoding:

    • The EncodeBase36 function converts a number to a Base36 encoded string, padded to ensure a consistent length.
  2. Timestamp:

    • Timestamp := DateTimeToUnix(Now) * 1000 gets the current timestamp in milliseconds.
  3. Counter:

    • The counter is incremented if the timestamp is the same as the last one, ensuring uniqueness for multiple CUIDs generated in quick succession.
  4. Machine Fingerprint:

    • GetMachineFingerprint generates a fingerprint using the machine's local IP address hashed with MD5, taking the first 4 characters.
  5. Random String:

    • GetRandomString generates a random string of specified length using Base36 characters.
  6. Combine Components:

    • The GenerateCUID function combines the timestamp, counter, fingerprint, and random parts to form the final CUID.

Summary

This Delphi implementation of CUID generation uses available libraries and functions to handle timestamps, hashing, and randomness. The approach ensures that the generated CUIDs are unique, readable, and collision-resistant, making them suitable for various applications.