Welcome to the new DelphiDabbler Code Library Documentation.

This is a new site that's currently running on alpha code. There are going to be bugs. If you discover any, please report them on the site's issues page (GitHub account required). Thanks.

Warning: Many URLs are going to change. Refer to the README file to discover which library project's documentation has been completed.

Calculate methods

Project: MD5 Message Digest Unit

Unit: PJMD5

Class: TPJMD5

Applies to: ~>1.0

class function Calculate(const X: TBytes; const StartIdx, Count: Cardinal):
  TPJMD5Digest; overload;
class function Calculate(const X: TBytes; const Count: Cardinal):
  TPJMD5Digest; overload;
class function Calculate(const X: TBytes): TPJMD5Digest; overload;
class function Calculate(const Buf; const Count: Cardinal): TPJMD5Digest;
  overload;
class function Calculate(const S: RawByteString): TPJMD5Digest; overload;
class function Calculate(const S: ShortString): TPJMD5Digest; overload;
class function Calculate(const S: WideString): TPJMD5Digest; overload;
class function Calculate(const S: UnicodeString;
  const Encoding: TEncoding): TPJMD5Digest; overload;
class function Calculate(const S: UnicodeString): TPJMD5Digest; overload;
class function Calculate(const Stream: TStream;
  const Count: Int64): TPJMD5Digest; overload;
class function Calculate(const Stream: TStream): TPJMD5Digest; overload;

Description

There a several different overloaded versions of the Calculate method, all of which are class methods that return a TPJMD5Digest record containing the digest of some specified data.

The methods provide a useful shortcut when all you need to do is create an MD5 hash of a single data item such as a stream, a string or a byte array. You can do this with just one call to Calculate - there is no need to create a TPJMD5 instance.

The disadvantages are:

Similar groups of methods are described below:

Byte array versions

class function Calculate(const X: TBytes; const StartIdx, Count: Cardinal):
  TPJMD5Digest; overload;
class function Calculate(const X: TBytes; const Count: Cardinal):
  TPJMD5Digest; overload;
class function Calculate(const X: TBytes): TPJMD5Digest; overload;

These methods generate a MD5 digest from a TBytes array.

  1. The first version processes Count bytes starting from index StartIdx in byte array X. If there are less than Count bytes in the array counting from StartIdx then an EPJMD5 exception is raised. If StartIdx is beyond the end of the array or if Count is zero no data is processed.
  2. The second version processes Count bytes from the beginning of byte array X. X must have at least Count elements otherwise an EPJMD5 exception is raised. If Count is zero then no data is processed.
  3. The last version processes the whole of byte array X. If the array is empty then no data is processed.

Examples

Create an MD5 digest of an eight element array of bytes:

var
  Digest: TPJMD5Digest;
  A: TBytes;
begin
  A := TBytes.Create(1,2,3,4,5,6,7,8);
  Digest := TPJMD5.Calculate(A);  // MD5 of 1,2,3,4,5,6,7,8
  ...
end;

Create an MD5 digest of the middle four bytes of an eight element array of bytes:

var
  Digest: TPJMD5Digest;
  A: TBytes;
begin
  A := TBytes.Create(1,2,3,4,5,6,7,8);
  Digest := TPJMD5.Calculate(A, 2, 4);  // MD5 of 3,4,5,6
  ...
end;

Untyped buffer version

class function Calculate(const Buf; const Count: Cardinal): TPJMD5Digest;
  overload;

Calculates a digest from Count bytes read from untyped buffer Buf. Buf must contain at least Count bytes.

Untyped example

Assume you have an array of long word values for which you want the MD5 hash. Here’s a function that gets it for you:

function MD5OfLongWordArray(const A: array of LongWord): TPJMD5Digest;
begin
  Result := TPJMD5.Calculate(A[0], SizeOf(LongWord) * Length(A));
end;

ANSI string version

class function Calculate(const S: RawByteString): TPJMD5Digest; overload;

Calculates a digest from the ordinal values of the characters of an ANSI string S. S can have any code page.

ANSI string example

Create an MD5 digest of an AnsiString containing the text Hello World:

var
  Digest: TPJMD5Digest;
  S: AnsiString;
begin
  S := 'Hello World';
  Digest := TPJMD5.Calculate(S);
  ...
end;

ShortString version

class function Calculate(const S: ShortString): TPJMD5Digest; overload;

Calculates a digest from the ordinal values of the characters of a short string S.

WideString version

class function Calculate(const S: WideString): TPJMD5Digest; overload;

Calculates a digest from the ordinal values of the WideChar characters of the WideString parameter, S.

Unicode string versions

class function Calculate(const S: UnicodeString;
  const Encoding: TEncoding): TPJMD5Digest; overload;
class function Calculate(const S: UnicodeString): TPJMD5Digest; overload;

Each of these methods creates a digest of a Unicode string S. Before processing the string it is converted to a sequence of bytes. The first version uses the encoding passed in the Encoding parameter to perform the conversion while the second version uses the TEncoding.Default encoding.

TStream versions

class function Calculate(const Stream: TStream;
  const Count: Int64): TPJMD5Digest; overload;
class function Calculate(const Stream: TStream): TPJMD5Digest; overload;

This pair of methods calculate a digest from the bytes read from stream Stream. Bytes are always read from the current position in Stream. Both methods modify the stream’s Position property.

The first version reads Count bytes from the stream. If Count is greater than number of bytes available then an EPJMD5 exception is raised. The second version reads to the end of the stream, processing Stream.Size - Stream.Position bytes.

The stream is read in chunks. The size of a chunk is given by the TPJMD5.DefReadBufferSize constant. This buffer size cannot be changed. If you need to change the buffer size you must create a TPJMD5 instance, set the buffer size using the ReadBufferSize property, then use the appropriate Process method.

TStream example

Create an MD5 digest of a TStream referenced by Stm. We write the ASCII characters Hello World to the stream and then get the MD5 of various parts of the stream.

var
  Digest1, Digest2, Digest3: TPJMD5Digest;
  Stm: TStringStream;
begin
  Stm := TStringStream.Create('Hello World', TEncoding.ASCII);
  try
    // get digest of ASCII chars 'Hello World'
    Stm.Position := 0;
    Digest1 := TPJMD5.Calculate(Stm);
    ...
    // get digest of ASCII chars 'llo'
    Stm.Position := 2;
    Digest2 := TPJMD5.Calculate(Stm, Int64(3));
    ...
    // get digest of ASCII chars 'World'
    Stm.Position := 6;
    Digest3 := TPJMD5.Calculate(Stm);
    ...
  finally
    Stm.Free;
  end;
end;