16 December 2010

RIP DelphiDabbler Mailing Lists

If you have been a subscriber to my mailing lists you may have noticed that there have been no mailings since about June 2010. That's because I've decided to stop producing newsletters.

The reason? I'm afraid I just don't have the time. There are more efficient and much more timely ways of getting site news out there via news feeds and through my Twitter account.

Here are the RSS feed links:

My twitter account is @delphidabbler. And don't worry, I don't (t)witter on about my personal life - you won't get to know about my dogs' birthdays (both 13 in January actually - damn!) or what brand of perfume my wife likes - it's just limited to site and blog news!

Finally my website's news section pulls most of this stuff together.

06 December 2010

CodeSnip v4

I've started development of version 4 of CodeSnip, the Delphi source code snippets editor and viewer.

I am inviting suggestions for new features. If you have any ideas please use the project's Feature Tracker on SourceForge. If you prefer to discuss your ideas then please leave a comment to this posting.

There's a new branch of CodeSnip's Subversion repository that contains the v4 development code.

I've only just started work on this and I don't expect to release the first beta for a number of months yet. In the meantime I will be maintaining the v3 code base and may even add some simple enhancements. But don't expect any major changes to v3.

05 November 2010

Concatenating Dynamic Arrays

Another day another unit test and another extension to my little TArrayEx class. This time I found myself having to concatenate some dynamic arrays. After solving the problem for the particular array type I decided to produce a generic solution. Here's the method I came up with:

type
  TArrayEx = class(TObject)
  public
    ...
    class function Concat<T>(const Arrays: array of TArray<T>): TArray<T>;
    ...
  end;

The method takes an array of the arrays you want to concatenate (don't forget the [] notation) and returns the concatenated array. Here's an example where the resultant array A contains the integers 1 to 10 in order:

var
  A, A1, A2, A3: TArray<Integer>;
begin
  A1 := TArray<Integer>.Create(1, 2, 3);
  A2 := TArray<Integer>.Create(4, 5, 6);
  A3 := TArray<Integer>.Create(7, 8, 9, 10);
  A := TArrayEx.Concat<Integer>([A1, A2, A3]);
  ...
end;
Here is the implementation:
class function TArrayEx.Concat<T>(const Arrays: array of TArray<T>): TArray<T>;
var
  A: TArray<T>;
  ResLen: Integer;
  ResIdx, Idx: Integer;
begin
  ResLen := 0;
  for A in Arrays do
    Inc(ResLen, Length(A));
  SetLength(Result, ResLen);
  ResIdx := 0;
  for A in Arrays do
  begin
    for Idx := Low(A) to High(A) do
    begin
      Result[ResIdx] := A[Idx];
      Inc(ResIdx);
    end;
  end;
end;

My other blogs about TArrayEx and working with dynamic arrays are:

11 September 2010

DelphiDabbler Code Library help

Some users of the components and units from the DelphiDabbler Code Library have contacted me to ask if the library's help is available in HTML help format because WinHelp format I used for the library won't work by default on Windows Vista and later.

The answer is no - and I don't have time to do the conversions.

However, all is not lost because there is now a Wiki for each of the Code Library projects hosted on Google Code. In future the Wikis will be updated in preference to the old WinHelp help files.

View the list of available Wikis.

Initialising dynamic arrays - take 2

In my earlier post on this subject I presented some methods to use to initialise and clone dynamic arrays. Some comments to that post suggested a simpler approach using compiler features I didn't know existed. In this post I've simply collected the information from those comments together in one place.

To initialise an array from literal values you can use the special array constructor provided by the compiler:

uses
  Types;

var
  A: TIntegerDynArray;
begin
  A := TIntegerDynArray.Create(1,2,3,4);
  ...
end;

This also works when you define your own array types, for example:

var
  TMyByteArray = array of Byte;
begin
  A := TMyByteArray.Create(1,2,3,4);
  ...
end;

And it also works for the TArray<T> generic array type:

var
  IntArray: TArray<Integer>;
  StrArray: TArray<string>;
begin
  IntArray := TArray<Integer>.Create(1, 2, 3);
  StrArray := TArray<string>.Create('bonnie', 'clyde');
  ...
end; 

The above constructors will only initialise an array from constant values. To make a copy of an existing dynamic array we can use a single parameter version of the Copy procedure as follows:

uses
  Types;

var
  A1, A2: TIntegerDynArray;
begin
  A1 := TIntegerDynArray.Create(1,2,3,4);
  A2 := Copy(A1);
  ...
end;

So we don't really need the TArrayEx.CloneArray<T> method I presented in the earlier post because Delphi already has the functionality built in. Duh!

Thanks a lot to Chris who commented on the original post to point these matters out.

24 June 2010

Deleting elements from a dynamic array

In my blog "Initialising Dynamic Arrays" I mentioned I have been writing some unit tests that needed numerous repetative array initialisation operations. Well, one of the other common operations I found myself writing was the deletion of items from dynamic arrays. So I decided to find a generic way of doing this.

Assuming we know the index of the item to be deleted we need the equivalent of Delphi's built-in Delete procedure for strings. If you read the previous post you won't be surprised to learn that I decided to further extend the Generics.Collections.TArray class by adding to the TArrayEx class I introduced there.

My first attempt emulates Delphi's Delete procedure by deleting the array element in-place: i.e. it updates the array passed as a parameter. Unsurprisingly the method is called DeleteInPlace. Here's how it goes:

type
  TArrayEx = class(TArray)
  public
    ...
    class procedure DeleteInPlace<T>(var A: TArray<T>; const Index: Integer);
  end;

...

class procedure TArrayEx.DeleteInPlace<T>(var A: TArray<T>;
  const Index: Integer);
var
  IdxA: Integer;
begin
  Assert((Index >= Low(A)) and (Index <= High(A)));
  for IdxA := Index to Pred(High(A)) do
    A[IdxA] := A[Succ(IdxA)];
  SetLength(A, Length(A) - 1);
end;

This uses a common algorithm. It just copies all array elements above the index of the deleted item down one place then shrinks the array by one element.

Next I decided it would also be useful to be able to construct a new array that contained a copy of a given array with the specified element removed. Continuing my startlingly inspired naming plan I called this method Delete. Here it is:

type
  TArrayEx = class(TArray)
  public
    ...
    class function Delete<T>(const A: array of T; const Index: Integer):
      TArray<T>;
  end;

...

class function TArrayEx.Delete<T>(const A: array of T; const Index: Integer):
  TArray<T>;
var
  IdxSrc, IdxRes: Integer;
begin
  Assert((Index >= Low(A)) and (Index <= High(A)));
  SetLength(Result, Length(A) - 1);
  IdxRes := Low(Result);
  for IdxSrc := Low(A) to High(A) do
  begin
    if IdxSrc <> Index then
    begin
      Result[IdxRes] := A[IdxSrc];
      Inc(IdxRes);
    end;
  end;
end;

This is pretty self-explanatory. It simply creates a new array of the required size and copies all the array elements to it, except for the one that is to be deleted.

I could have implemented Delete in terms of DeleteIinPlace like this, using CloneArray from the previous post:

class function TArrayEx.Delete<T>(const A: array of T; const Index: Integer):
  TArray<T>;
var
  IdxSrc, IdxRes: Integer;
begin
  Assert((Index >= Low(A)) and (Index <= High(A)));
  Result := CloneArray<T>(A);
  DeleteInPlace<T>(Result, Index);
end;

But I decided against this to avoid looping through the array 1.5 times on average instead of once. (CloneArray loops through the array once and DeleteInPlace loops through half the array on average.)

OK, I'll come clean. I actually wrote Delete first and then DeleteInPlace after I found the compiler wouldn't accept it as an overload of Delete, but the story goes better the way I told it!
Does anyone know why the compiler won't accept that methods with different return types (or no return types) have different signatures anyway? Leave a comment if you know please.

23 June 2010

Initialising dynamic arrays

When writing some unit tests a while ago I found myself needing to initialise some dynamic arrays with test data. It would be nice if we could do something like this:

var
  A: array of Integer;
begin
  A := (1,2,3,4);  // !! WRONG
end;

but we can't. So I decided to write some functions to initialise dynamic arrays to the contents of another array, be it a constant, a literal or another dynamic array.

The result was a set of overloaded routines, one for each data type I needed to handle, for example for Integer and string arrays I had:

function CloneArray(const A: array of Integer): TIntegerDynArray; overload;
var
  Idx: Integer;
begin
  SetLength(Result, Length(A));
  for Idx := Low(A) to High(A) do
    Result[Idx - Low(A)] := A[Idx];
end;

function CloneArray(const A: array of string): TStringDynArray; overload;
var
  Idx: Integer;
begin
  SetLength(Result, Length(A));
  for Idx := Low(A) to High(A) do
    Result[Idx - Low(A)] := A[Idx];
end;

Noticing how similar these functions were - only the first line differs - I decided to try a generic approach. Since I didn't want to parameterise both the type of the array (e.g. the TIntegerDynArray return value) and the array element (e.g. Integer) I first decided to change the return values of the functions to use the TArray<T> type defined in the System unit. So the function prototypes got changed to

function CloneArray(const A: array of Integer): TArray<Integer>; overload;

and

function CloneArray(const A: array of string): TArray<string>; overload;

The implementation of the routines did not need changing. It seemed clear how to parameterise the routines: just replace the Integer or string types with T, like this:

function CloneArray<T>(const A: array of T): TArray<T>;

Wrong! At this point I learned that you can't parameterise global routines, as my blog entry "Being dim #2: No generic global procedures" explains. I needed to make the CloneArray routine a class method of some suitable class. Rather than create a new class I cast around and decided to extend the TArray class defined in the Generics.Collections unit.

type
  TArrayEx = class(TArray)
  public
    class function CloneArray<T>(const A: array of T): TArray<T>;
  end;

...

class function TArrayEx.CloneArray<T>(const A: array of T): TArray<T>;
var
  Idx: Integer;
begin
  SetLength(Result, Length(A));
  for Idx := Low(A) to High(A) do
    Result[Idx - Low(A)] := A[Idx];
end;

Don't confuse Generics.Collections.TArray with System.TArray<T> - the first is a class, the second a generic dynamic array type.

CloneArray assumes that straighforward assignment of array elements is what we want. For example if the array elements are objects, just the object pointer is copied. If you need the object's fields to be physically copied this simplistic approach won't work.

I'll close this post with an example of use. Here's a code fragment that initialises string and integer arrays:

var
  IA: TArray<Integer>;
  SA: TArray<string>;
begin
  IA := TArrayEx.CloneArray<Integer>([1,2,3,5,7,11]);
  SA := TArrayEx.CloneArray<string>(['bonnie', 'clyde']);
end;

22 June 2010

Being dim #2: No generic global procedures

The other day I was writing some unit tests and needed some helper functions to look up some array elements of in arrays of different base types. I had several overloaded functions to do the job, like this:

function IndexOf(const Item: string; const A: array of string): Integer; overload;
function IndexOf(const Item: Integer; const A: array of Integer): Integer; overload;

Oh, I thought, generics are a way round this, so I replaced the overloaded functions with something like

function IndexOf<T>(const Item: T; const A: array of T): Integer;

only to be get compiler error 2530: Type parameters not allowed on global procedure or function. Now, I didn't know that and I'm sharing it in case some of you didn't either.

And the solution? I sorted it by using a static class to hold the code, i.e.

type
  TSomeClass = class(TObject)
  public
    class function IndexOf<T>(const Item: T; const A: array of T): Integer;
  end;

This works fine.

I've not provided implementation details of any of this code since the details are not important in this context.

Being dim #1: Array and set enumerators

One of my favourite additions to Delphi over the past years has been the for..in construct and the associated enumerators. I just love the way we can do

var
  Ch: Char;
  S: string;
begin
  S := 'Some text';
  for Ch in S do
    // Do something with Ch
end;

So how come I missed that enumerators work on sets and arrays? I'm mentioning this here just in case it's slipped past anyone else, and in case you can tell me about any other enumerators I might have missed!

Since forever I've being having to do stuff like this for arrays and sets:

const
  cMyArray: array[1..4] of Byte = (51, 60, 80, 81);
  cMySet: set of Byte = [50, 51, 80, 81, 40, 30, 32];
var
  I: Integer;
  B: Byte;
begin
  for B := Low(Byte) to High(Byte) do
    if B in cMySet then
      // Do stuff with B
  for I := Low(cMyArray) to High(cMyArray) do
    // Do stuff my cMyArray[I]
end;

When all along I could have been doing:

const
  cMyArray: array[1..4] of Byte = (51, 60, 80, 81);
  cMySet: set of Byte = [50, 51, 80, 81, 40, 30, 32];
var
  Item: Byte;
begin
  for Item in cMySet do
    // Do stuff with Item
  for Item in cMyArray do
    // Do stuff with Item
end;

Duh! A refactoring I will go!

27 May 2010

Top Secret Code Snippets Test Code

For about three months now I've had some code that tests and exercises some of the snippets in the Code Snippets Database. But, if you don't get the Code Snippets newsletter, you won't know about it because I forgot to tell anyone else!

Anyhow, the code is stored in my Delphi Doodlings Subversion repository on Assembla in the CodeSnippets sub-directory of the trunk.

There are currently three test projects:

  • TestDriveCat.dpr in the Src/Cat-Drive sub-directory.
    This is a demo program that exercises all the routines in the Code Snippets database's Drive Management category. This project was updated today to bring up to date with a new addition to the category.
  • TestHexCat.dpr in the Src/Cat-Hex sub-directory
    This is a set of DUnit tests for all the routines in the Hex Utilities category.
  • TestWinSysCat.dpr in the Src/Cat-WynSys sub-directory.
    This new demo program was added today and exercises all the routines in the Windows System category.

I'm only updating this project as I need the tests or as code comes my way. So if you've written any tests for the any of the code from the database, please let me have it.

Decoding Base 64 encoded data

A while ago someone asked me how to go about decoding Base 64 encoded code in a single routine.

Here's what I came up with. It uses the Indy internet component suite to do the grunt work and simply wraps the various Indy calls into a function.

uses
  Classes, IdCoderMIME

...

function Base64Decode(const EncodedText: string): TBytes;
var
  DecodedStm: TBytesStream; 
  Decoder: TIdDecoderMIME;  
begin
  Decoder := TIdDecoderMIME.Create(nil);
  try
    DecodedStm := TBytesStream.Create;
    try
      Decoder.DecodeBegin(DecodedStm);
      Decoder.Decode(EncodedText);
      Decoder.DecodeEnd;
      Result := DecodedStm.Bytes;
    finally
      DecodedStm.Free;
    end;
  finally
    Decoder.Free;
  end;
end;

This function decodes the encoded text passed in EncodedText, which must contain only valid Base 64 encoding characters, and returns the resulting raw data as an array of bytes.

We use Indy's TIdDecoderMIME component to decode the text into a TByteStream and read of the result from the stream's Bytes property.

09 May 2010

Delphi Tips Editor Virus???

There have been a few reports of a possible virus in the third party Delphi Tips Editor published on DelphiDabbler.com.

Just to let everyone know that this is likely (but not guaranteed) to have been a false positive due to the exe compressor used by the author.

However, to be on the safe side the offending code has been replaced by a recompiled version that passes all the tests at http://www.virustotal.com/.

If you're using the program please make sure you download the latest version here.

05 April 2010

Singletons

For a long time now I've been looking for a nice singleton implementation that meets my needs. I want a singleton that:

  1. Can't be created more than once.
  2. Can't be freed until the program terminates.
  3. Can be used as a common base class for all the program's singletons.

There are plenty of implementations around that meet requirements 1 and 2, but most of those can't be overridden (usually because they retain a reference to the singleton object in a private global variable or a class var field).

Then I found some code by Yoav Abrahami in his article on Delphi3000.com that can be used as a base class.

The code was written for a old version of Delphi and used a TStringList to record instances of each singleton class created and only permits one instance of each class. I've adapted Yoav's code to use features of Delphi 2010 to avoid the need for TStringList and use of private global variables. I've also taken advantage of Delphi 2010's new class constructor and destructor to avoid having initialization and finalization code.

Here's the TSingleton class declaration:

type
  TSingleton = class(TObject)
  strict private
    // Frees object instance.
    procedure Dispose;
  strict protected
    // Initialises object. Descendants should override instead of
    // constructor. Does nothing in this base class.
    procedure Initialize; virtual;
    // Tidies up object. Descendants should override this method
    // instead of destructor. Does nothing in this base class.
    procedure Finalize; virtual;
  public
    // Destructor tears down object only if singleton manager permits.
    destructor Destroy; override;
    // Constructor creates new instance only if one does not already exist.
    class function NewInstance: TObject; override;
    // Frees instance data only if singleton manager permits.
    procedure FreeInstance; override;
  end;

And the implementation:

destructor TSingleton.Destroy;
begin
  // Do not override to tidy up unless you first check
  // TSingletonManager.Destroying and only tidy up if it returns true.
  // Override Finalize instead.
  if TSingletonManager.Destroying then
  begin
    Finalize;
    inherited;
  end;
end;

procedure TSingleton.Dispose;
begin
  inherited FreeInstance;
end;

procedure TSingleton.Finalize;
begin
  // Override this to tidy up the object instead of overriding the destructor
end;

procedure TSingleton.FreeInstance;
begin
  // Check if object can be destroyed
  if TSingletonManager.Destroying then
    inherited;
end;

procedure TSingleton.Initialize;
begin
  // Override to initialise code that would normally be placed in constructor
end;

class function TSingleton.NewInstance: TObject;
var
  S: TSingleton;  // reference to a new singleton
begin
  if not TSingletonManager.SingletonExists(Self.ClassName) then
  begin
    S := TSingleton(inherited NewInstance);
    try
      S.Initialize;
      TSingletonManager.RegisterSingleton(S);
    except
      S.Dispose;
      raise;
    end;
  end;
  Result := TSingletonManager.Lookup(Self.ClassName);
end;

The code might be familiar if you've used similar singletons before. If not, here's a brief overview.

TSingleton's constructor calls the virtual NewInstance to allocate space for the object. Here NewInstance has been overridden to only allocate space for the singleton if it doesn't already exist.

We check TSingletonManager, explained below, to find out if an instance already exists. If not, a new instance is created (using inherited NewInstance), is recorded by the singleton manager and then finally returned in the last line via the Lookup method. Should an exception occur NewInstance frees the object instance via the Dispose method. If the singleton already exists its object reference is looked up and returned without a new instance being created.

The up shot of all this is that only one instance for each singleton type is ever created.

Calling a TSingleton descendant's Destroy method only has any effect if the singleton manager has flagged that the singleton can be destroyed (see below). FreeInstance (which is call from destructors) is responsible for freeing an object's instance data. Here FreeInstance is overridden to only free the instance if the singleton manager permits.

Finally there are the virtual, do nothing, Initialize and Finalize methods. These are designed to be overridden by descendant classes to perform object setup and tear down. This is to avoid having to override the constructor or destructor with all the complications that may bring.

As you can see TSingleton depends on the TSingletonManager to keep track of singleton instances and to tell them when they can be destroyed. Here is the declaration of TSingletonManager:

type
  TSingletonManager = class(TObject)
  strict private
    // Indicates if manager is destroying singletons
    class var fDestroying: Boolean;
    // Map of class names to singleton instances
    class var fMap: TDictionary<string,TSingleton>;
  protected
    // Frees all registered singletons.
    class procedure FreeAll;
    // Creates empty singleton class map if it doesn't exist
    class procedure CreateMap;
  public
    // Class constructor. Sets up required class vars.
    class constructor Create;
    // Class destructor. Frees all singletons.
    class destructor Destroy;
    // Register new singleton. Do nothing if already registered.
    class procedure RegisterSingleton(const S: TSingleton);
    // Checks if a singlton of given class name already registered.
    class function SingletonExists(const ClsName: string): Boolean;
    // Look up singelton class name in map. EListError if not found.
    class function Lookup(const ClsName: string): TSingleton;
    // Indicates if the this class is destroying singletons. Singleton
    // instances use this property to allow themselves to be destroyed
    class property Destroying: Boolean read fDestroying write fDestroying;
  end;

There are two class variables:

  1. fDestroying is the value of the Destroying property which is set true only when the program is closing down. We have seen that TSingleton tests this property to see if an instance can be destroyed.
  2. fMap is a dictionary that maps singleton class names to their instances.

New to Delphi 2010, the class constructor and destructor are automatically called when the program initializes and closes down. They avoid having to use initialization and finalization sections and have some linking advantages:

class constructor TSingletonManager.Create;
begin
  CreateMap;
end;

class destructor TSingletonManager.Destroy;
begin
  FreeAll;
end;

The class constructor and destructor simply call the CreateMap and FreeAll class methods that are listed below. This was done purely to aid testing and the code of these methods could be included directly in the class constructor and destructor.

class procedure TSingletonManager.CreateMap;
begin
  if not Assigned(fMap) then
    fMap := TDictionary<string,TSingleton>.Create;
end;

class procedure TSingletonManager.FreeAll;
var
  SPair: TPair<string, TSingleton>; // classname, singleton instance pair
begin
  // indicate to singletons they can destroy
  Destroying := True;
  // free the singletons in the map, then the map itself
  for SPair in fMap do
    SPair.Value.Free;
  FreeAndNil(fMap);
  Destroying := False;
  // we set fMap = nil and Destroying = False to make it safe to
  // re-create map when testing. Don't bother with this if not testing
end;

CreateMap simply creates the dictionary object and stores it in the fMap class var.

FreeAll first sets the Destroying property true then frees all the recorded singleton instances and finally frees the dictionary. Remember that TSingleton checks Destroying and only frees itself when the property is true.

The rest of TSingletonManager is concerned with maintaining the list of singleton instances. The methods are quite simple:

class function TSingletonManager.Lookup(const ClsName: string): TSingleton;
begin
  Result := fMap[ClsName];
end;

class procedure TSingletonManager.RegisterSingleton(const S: TSingleton);
begin
  if not SingletonExists(S.ClassName) then
    fMap.Add(S.ClassName, S);
end;

class function TSingletonManager.SingletonExists(
  const ClsName: string): Boolean;
begin
  Result := fMap.ContainsKey(ClsName);
end;

Lookup simply looks up a class name in the dictionary and returns the singleton instance for that class. It raises an EListError exception if there is no matching instance.

RegisterSingleton is the method that registers a singleton with the manager. It maps the singleton's class name to the instance. If the singleton is already registered it does nothing.

SingletonExists simply returns True if a singleton with a given class name exists.

So, that's it. It's the singleton implementation that suits my needs best. There's a sample project in my Delphi Doodlings repo that contains TSingleton and TSingletonManager along with some unit tests.