Showing posts from 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 site newsCodeSnip program and Code Snippets Database newsDelphiDabbler Code Library NewsDelphi Tips NewsThis blogTwitterMy 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.

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.

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:typeTArrayEx=class(TObject)public...classfunctionConcat<T>(constArrays:arrayofTArray<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:varA,A1,A2,A3:TArray<Integer>;beginA1:=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: classfunctionTArrayEx.Concat<T>(constArrays:arrayofTArray<T>):TArray<T>;varA:TArray<T>;ResLen:In…

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.Source code highlighting by DelphiDabbler PasHi.

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:usesTypes;varA:TIntegerDynArray;beginA:=TIntegerDynArray.Create(1,2,3,4);...end; This also works when you define your own array types, for example:varTMyByteArray=arrayofByte;beginA:=TMyByteArray.Create(1,2,3,4);...end; And it also works for the TArray<T> generic array type:varIntArray:TArray<Integer>;StrArray:TArray<string>;beginIntArray:=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 …

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:typeTArrayEx=class(TArray)public...classprocedureDeleteInPlace<T>(varA:TArray<T>;constIndex:Integer);end;...classprocedureTAr…

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:varA:arrayofInteger;beginA:=(1,2,3,4);// !! WRONGend; 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:functionCloneArray(constA:arrayofInteger):TIntegerDynArray;overload;varIdx:Integer;beginSetLength(Result,Length(A));forIdx:=Low(A)toHigh(A)doResult[Idx-Low(A)]:=A[Idx];end;functionCloneArray(constA:arrayofstring):TStringDynArray;overload;varIdx:Integer;beginSetLength(Result,Length(A));forIdx:=Low(A)toHigh(A)doResult[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 w…

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:functionIndexOf(constItem:string;constA:arrayofstring):Integer;overload;functionIndexOf(constItem:Integer;constA:arrayofInteger):Integer;overload; Oh, I thought, generics are a way round this, so I replaced the overloaded functions with something likefunctionIndexOf<T>(constItem:T;constA:arrayofT):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.typeTSomeClass=class(TObject)publicclassfunctionIndexOf<T>(constItem:T;constA:arrayofT):Integer;end; This works fine.I've not provided implementation details of any of this code since the details are not import…

Being dim #1: Array and set enumerators

One of my favourite additions to Delphi over the past years has been the construct and the associated enumerators. I just love the way we can dovarCh:Char;S:string;beginS:='Some text';forChinSdo// Do something with Chend; 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:constcMyArray:array[1..4]ofByte=(51,60,80,81);cMySet:setofByte=[50,51,80,81,40,30,32];varI:Integer;B:Byte;beginforB:=Low(Byte)toHigh(Byte)doifBincMySetthen// Do stuff with BforI:=Low(cMyArray)toHigh(cMyArray)do// Do stuff my cMyArray[I]end; When all along I could have been doing:constcMyArray:array[1..4]ofByte=(51,60,80,81);cMySet:setofByte=[50,51,80,81,40,30,32];varItem:Byte;beginforItemincMySetdo// Do stuff with ItemforItemincMyArraydo// Do stuff with Itemend; Duh…

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…

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.usesClasses,IdCoderMIME...functionBase64Decode(constEncodedText:string):TBytes;varDecodedStm:TBytesStream;Decoder:TIdDecoderMIME;beginDecoder:=TIdDecoderMIME.Create(nil);tryDecodedStm:=TBytesStream.Create;tryDecoder.DecodeBegin(DecodedStm);Decoder.Decode(EncodedText);Decoder.DecodeEnd;Result:=DecodedStm.Bytes;finallyDecodedStm.Free;end;finallyDecoder.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.Source code highlighting by DelphiDabbler PasHi.

Delphi Tips Editor Virus???

There have been a few reports of a possible virus in the third party Delphi Tips Editor published on 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 you're using the program please make sure you download the latest version here.


For a long time now I've been looking for a nice singleton implementation that meets my needs. I want a singleton that:Can't be created more than once.Can't be freed until the program terminates.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 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 …