Archive

Archive for June, 2009

DeHL 0.6 available

June 21st, 2009 alex 1 comment

DeHL

Yes I know I have skipped 0.5. The reality is that 0.5 was due a long time ago, but I did not have enough free time on my hands to complete the unit testing for all new features added. I always try to add as many unit tests as possible to test all possible scenarios.

This release features a general reorganization of some key concepts, new type extension mechanics, boxing, a lot more collections, better support for associative collections through specific Enex extensions … and many more. I am not going to lay out all the changes here since there are quite a few of them. You can view the change log here.

One important note, check out the DeHL.Base.pas unit. There are a number of TOGGLE_XXXXX constants. Toggle them to true or false (if you are using Weaver FT builds) to enable or disable specific functionality. In Tiburon (Delphi 2009) all the features are disabled by default (to be on the safe side).

Get the latest build here. If you stumble upon some bugs please report them here.

Have Fun!

Categories: Programming

Update for FSEnum

June 15th, 2009 alex 5 comments

Since some people asked me to improve FSEnum unit (see this post). I decided to give it another go and add some features and improve the others.

So what’s new?

  • Optional Boolean parameter for all methods that tells the enumerator whether to return the relative paths (like it did before) or absolute ones.
  • There are two levels of “mask matching” (if the enumeration is recursive). The first level allows everything to pass since you need to recurse into all directories. The real mask matching is done at the second level using the TMask (unit Masks).
  • Two new methods (overloaded): FileSystemEntries which returns an enumerable over TFileSystemEntry structure.
  • A new TFileSystemEntry structure that contains more information about a file/directory.

The next example shows the use of TDirectory.FileSystemEntries method:

var
  Entry: TFileSystemEntry;

begin
  { Show all read-only executable files on drive I: bigger than 1MB }
  for Entry in TDirectory.FileSystemEntries('i:', '*.exe', true) do
    if (Entry.Size > 1000000) and Entry.IsReadOnly then WriteLn(Entry.FullName);

  ReadLn;
end.

The unit is the same (has been updated!)  and can be found here: File system enumeration (1054)

Categories: Programming

Extending TObject with data at runtime

June 13th, 2009 alex 8 comments

In a recent comment on this blog Patrick van Logchem suggested a way of extending an existing object instance with custom data at run-time (originally the idea of Thorsten Engler). The main idea is to be able to “assign” to an arbitrary object (whose sources you cannot change) some other object at run-time. This may prove to be useful in different scenarios when you need some additional data to be carried by an object.

The suggested idea was to use the monitor field which all TObject instances have. If you are not familiar with monitors in Delphi, let me explain: All TObject instances carry a new “hidden” field which is a pointer to a TMonitor (see System unit) structure. This referenced TMonitor structure is actually a kind of synchronization object that lets you solve some common threading tasks easier. You can read more about this in other posts, since this post is about using that field to store data.

The restrictions:

  • The solution must not be too simplistic. Simply rewriting the pointer in TObject instances is not allowed.
  • Normal monitor routines must function as they did before. This means that we must store a real monitor there alongside with the data.
  • No custom functions to simulate monitor support, and no class helpers. See previous item.
  • The attached data must be disposed when the object is disposed so to avoid memory and resource leaks.

The features:

  • Possibility to extend an object with another object: ExtendObject(Object, Extension);
  • Possibility to query an object for an extension: GetObjectExtension(Object): Extension;
  • Possibility to remove an extension from an object: RemoveObjectExtension(Object): Extension;
  • Object is any type of object in Delphi! No restrictions, no common ancestor; just plain TObject!
  • Extension is also simply a TObject value. It’s user-defined in it’s implementation and purpose.

The first implementation I came up with is non-intrusive. I wanted to avoid patching the System exposed functions at run-time. The following list enumerates the design and restrictions of the first implementation:

  • The unit must me USED directly after the inclusion of SysUtils in the main source file. This is an inconvenience of course, but it is a required one. Note that the unit must be included AFTER and not BEFORE SysUtils.
  • The unit overrides the values in the System.MonitorSupport variable and inserts it’s own custom routines used to obtain and release synchronization objects.
  • The unit uses the old System.MonitorSupport routines to do the real job. These routines are normally provided by the SysUtils unit — thus the dependency on SysUtils.
  • For each synchronization object requested, my custom routines return a fake handle which is actually a pointer to a structure containing a real handle and a TObject value.
  • This method does not use the monitor field per se; rather, it uses a field in the monitor itself.
  • Class helpers are used in implementation section to obtain access to internal method in the TMonitor structure.
  • While this method is non-intrusive at assembly level, it is surely more complex and uses more CPU cycles.

The second implementation is intrusive! It patches some functions in System unit so that my handler are executed in certain scenarios. The following list enumerates what’s going on in this one:

  • The unit should be USED after or before SysUtils. This restriction comes from the fact that monitors initialized before this unit is included have a different format. So there may be (or maybe not) problems.
  • Two functions are patched in System unit: TMonitor.Destroy(TObject) and TMonitor.Create(). First one is executed when a monitor is destroyed – normally at object death; and the second one is called when a monitor value is needed for the first time.
  • The two injected functions do basically the same thing as the System versions, with a slight turn – a TMonitor + Pointer value is created/destroyed. This bonus Pointer value hold the extension object.
  • Class helpers are used internally to gain access to some monitor support routines.
  • This method does not incur any overhead on normal monitor operations, so it is the preferred one.

And now to some code:

uses
  SysUtils,
  ObjectExtensions_Intrusive;

type
  TStrExtenstion = class
  end;

  TIntExtension = class
  end;

procedure DoStuff(const A: TObject);
var
  Extension: TObject;
begin
  if A = nil then
    Exit;

  Extension := GetObjectExtension(A);

  if Extension = nil then
    Exit;

  WriteLn(Extension.ClassName);
end;

var
  a, b, c: TObject;
begin
  a := TObject.Create;
  b := TObject.Create;
  c := TObject.Create;

  ExtendObject(a, TStrExtenstion.Create);
  ExtendObject(b, TIntExtension.Create);

  DoStuff(a);
  DoStuff(b);
  DoStuff(c);

  ReadLn;
end.

It’s not hard to imagine that this method can be used is different circumstances – the ideas are all yours!

MEGA WARNING: The attached code is barely tested, possibly unstable and even worse – maybe destructive. This is just a fun and proof of concept code and not something that can be used in applications.

The code can be found in this archive: Object Extensions (629)

Mentioned the authors of the idea.

Categories: Programming

Enumerating over a directory structure

June 12th, 2009 alex 13 comments

Me again, and again with enumeration techniques. In this post I will try to coven a very common problem all programmers have to face one time or another: enumerating all files recursively in a directory.

Yesterday I had to do it again, and again following the standard FindFirst … FindNext and FindClose pattern. So I decided to make my life easier and use enumerators for that. Behold the results:

var
  S: String;
begin
  for S in TDirectory.Entries('I:', true) do
    WriteLn(S);
end;

That’s all you have to do to traverse the directory structure for the I:\ drive — simple and clean.

So how does this work and what are the advantages:

  • The method Entries is a static method of TDirectory structure. There are two more methods: Files, which returns only files and Directories which returns only directories.
  • The exposes static methods return an IEnumerable<String> interface which exposes the GetEnumerator() method. This is an important aspect of the implementation since exposing an interface helps you pass the lifetime management of the enumerable object to the compiler.
  • The for .. in loop then extracts a IEnumerator<String> interface and starts iterating over the directory tree.
  • The TDirectory.TEnumerator object does not use recursion internally to traverse the tree. It stores the TSearchRec at each level in a TStack<> instance (well it’s kinda like recursion).
  • You can “break” off the loop at any moment. Simple and easy.
  • It executes more instruction per iteration but I think it’s a manageable trade-off for its ease of use.

Again, th unit can be found here:  File system enumeration (1054).

Have fun!

Categories: Programming

Arbitrary precision integers

June 10th, 2009 alex 7 comments

I have decided to extract the BigInteger and BigCardinal data types from DeHL and make a bundle with them separately. Someone may be interested in these types and not so much in DeHL. The attached unit should compile on D2007 and D2006 (not sure for earlier versions).

What can you learn:

  • Shows you how to develop “value types” with predictable states in Delphi using records, operator overloading and “managed types” (in this case a dynamic array).
  • How to develop a proxy class that plugs your type into the Variant manager.
  • Demonstrates how to use operator overloading (and I have overloaded a lot of operators there).
  • The reliance of the predictable state of the managed types to check whether a value is initialized or not.
  • Shows how the use an in-place BCD-izer algorithm that helps converting a big number into a string. It took me a quite some time and tweaking to come up with it so it may be interesting to someone.

Where can you use it:

  • Everywhere, except FOR loops of course.
  • The types are transparent and should be used the exact way as normal integer do.
  • Use it in applications that require very big integer values.
  • … you’ll come up with something else.

A small example of course:

var
  a, b: BigInteger;
begin
  a := StrToBigInteger('8942374632463284632623837643468589' +
        '26367423509458904389575645349857');
  b := a * a;
  WriteLn(IntToStr(b));
end.

… or as variants …

var
  a, b: Variant;
begin
  a := StrToBigInteger('8942374632463284632623837643468589' +
        '26367423509458904389575645349857');
  b := a * a;
  WriteLn(b);
end.

Final note: the code is tested since it’s a part of DeHL (in which I try to test everything I can) so it’s safe to use. BUT if you find any bugs, please drop me a line.

Finally! The code! You can find it here: Arbitrary precision Integers (574)

Categories: Programming

Playing with Windows 7

June 10th, 2009 alex 20 comments

I was playing around with some (default Windows) programs these days and noticed that taskbar items for those programs show some cool effects whenever there is some progress going on So I decided to write a little unit to take advantage of these effects in one of my Delphi applications.

To take advantage of the new Windows 7 TaskBar API take a look at the ITaskBarList3 interface (an probably 4 for that matter). I have translated the interface to Delphi and added some initialization code and came up with a little unit that exposes a class helper for TCustomForm.

The final user-friendly code looks like this:

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetProgressState(tbpsError);
  SetProgressValue(50, 100);
end;

The SetProgressState and SetProgressValue methods are inserted by the class helper. The example makes the taskbar icon for the window look like a 50% complete red progress bar (indicating an error):

error_task_bar

or something like this for a “indefinite” state (of course the animation is missing so you can’t see the effects):

ind_task_item

If you want to play with the unit, take a look here: Windows 7 TaskBar helper for Delphi (1016)

Categories: Programming

DeHL documentation

June 9th, 2009 alex No comments

Since I had a few requests, I have started putting together some documentation on DeHL. It’s pretty basic and only includes some conceptual stuff, not API documentation. You can find it here.

Version 0.5 is shaping up quite well with tons of changes, and new stuff coming in — but that’s a another story.

Not much in this post,  Cheers!

Categories: Programming