Archive for June, 2009

Translating flags in API calls, part 1

OK, so we have all seen the way that flags are passed to API calls. Take the ShowWindow function. In Delphi it is declared as this:

function ShowWindow(hWnd: HWND; nCmdShow: Integer): BOOL; stdcall;

Now, there is nothing wrong with the declaration – it will work, is well documented and is of course not seen by most Delphi developers, since the calls are all wrapped up in the Delphi VCL.

Thing is, that the nCmdShow parameter is declared as in integer (even in the Windows API docs) but functionally, it acts as an enumerated type. That is to say, it has a defined set of values, and only those values are permissible. What’s more, those values are sequential from 0 to 10.

Sounds familiar? Sound a little like an enumerated type, now doesn’t it? You can look up the imports used in Delphi in Windows.pas, but here is an alternative version:

function ShowWindow(hWnd: HWND; nCmdShow: TShowWindowValues): BOOL; stdcall;

and TShowWindowValues declared as:

type
  {$Z4}
  TShowWindowValues = (SW_HIDE = 0,
    SW_SHOWNORMAL = 1, SW_NORMAL = SW_SHOWNORMAL,
    SW_SHOWMINIMIZED = 2, SW_SHOWMAXIMIZED = 3,
    SW_MAXIMIZE = 3, SW_SHOWNOACTIVATE = 4,
    SW_SHOW = 5, SW_MINIMIZE = 6,
    SW_SHOWMINNOACTIVE = 7, SW_SHOWNA = 8,
    SW_RESTORE = 9, SW_SHOWDEFAULT = 10,
    SW_MAX = SW_SHOWDEFAULT);
  {$Z1}

OK, so a few things to note:

  1. The {$Z4} directive is necessary because the API type for the parameter is a four-byte integer and Delphi’s enumerated types are one byte in size by default.
  2. I specified the numeric values even though they are not specifically needed in this case (everything is sequential). This of course won’t work at all in Delphi 3 and earlier.
  3. Two of the values are assigned a value held by one of their siblings. So even when two values are equivalent, you can still use an enum.
  4. Given that the function is now type safe, it is even possible to change the names of the identifiers – fix the case and remove the underscores – if you feel like it, without confusing anyone.

How about flags that are combined?

These work differently and the values are not sequential. The idea being that the values can be mixed using the or operator. Consider the DrawEdge function:

function DrawEdge(hdc: HDC; var qrc: TRect; edge: UINT; grfFlags: UINT): BOOL; stdcall;

The edge parameter takes a combination of four values. These values are declared as:

BDR_RAISEDOUTER = 1;
BDR_SUNKENOUTER = 2;
BDR_RAISEDINNER = 4;
BDR_SUNKENINNER = 8;

Powers of two are used, so that when these values are added together (or combined with or) you would retain all the values. Because these are never meant to be used on their own, but rather in combinations, I like using sets:

TBorder = (BDR_RAISEDOUTER, BDR_SUNKENOUTER, BDR_RAISEDINNER, BDR_SUNKENINNER);
TBorders = set of TBorder;

At first glance, this may seem like a disaster. The values of the three enum values are 0, 1, 2 and 3 respectively, which is not as they are declared in Windows.pas.

But the way that set types work is identical to the way flags do. While the value of BDR_RAISEDINNER may be 2, the value of [BDR_RAISEDINNER] is in fact 4. Two to the power of two is four, remember?

Some readers may know already that the declarations above don’t work. The concept is fine, but the type sizes are all wrong. TBorders is one byte in size, not four. And {$Z4} does nothing to change it.

You see, set values are stored as bit flags, but the size is determined by the range of the ordinal type. I have four values in TBorder, so TBorders only uses the four least significant bits of a byte. So how do we get TBorders to be four bytes in size? Easy, we add a value that should be stored in bit 31:

TBorder = (BDR_RAISEDOUTER, BDR_SUNKENOUTER, BDR_RAISEDINNER, BDR_SUNKENINNER, BDR_Range = 31);
TBorders = set of TBorder;

The extra BDR_Range value stretches TBorders to four bytes and we have a type safe version of DrawEdge.

There is more to come, but I think that will wait for the next post.

First, there is something that I want to clear up. Suppose you read this and you like the concept, now what? ShowWindow and DrawEdge both have their definitions in Windows.pas and I am in no way suggesting that these must be changed or that we should all import them separately.

The one (secondary) point here is that the declarations in Windows.pas are almost certainly generated by some tool. If Nick and the boys were to become real inspired they could change the tool to generate type safe overloads. There are probably some good reasons why this was not done from the start (you couldn’t assign numeric values to enum elements before Delphi 4 is one that comes to mind), but it is still a good idea.

More generally though, there are many APIs that Delphi doesn’t have imports for. Lots of programmers import these and some even share large repositories of them. When you find the need to do an API import, there is nothing stopping you from making it type safe.

In part 2, I’ll discuss what to do when your API call has a conditional set of values for a parameter – check out DrawFrameControl if you want a preview.

Update: Part 2 has now been published.

Comments (1)

12 Delphi code templates to save keystrokes

Sometimes, typing is just no fun. As a programmer there are certain things that you need to type over and over (and over and over) again, with only the smallest of differences.

For example, how often have you declared a property that looks like this:

property SomeProp: Integer read GetSomeProp write SetSomeProp;

Next, you press Ctrl+C to auto-complete the declaration and then only do you get to writing the beef of what you’re trying to accomplish. OK, so it isn’t painful, but it is monotonous.

Suppose you could have the declaration above created by only supplying the property name and type? Like this:

Code template for properties

That’s the cool thing about code templates, which had its debut in Delphi 2006 Delphi 2005 (I think). Delphi ships with a number of ready-made templates, most of which are very nicely done. We can add a few more to make for less repetitive property declarations. But that’s not the best bit.

Delphi 2009 has support for generics, which allow (among many other things) the quick creation of type-safe enumerators, lists and hash tables. If you don’t have Delphi 2009 yet, that’s no reason to write these from scratch every time and it certainly is no reason to just throw your valuable data into lists designed for pointers.

Enter my code templates for type-safe object lists, enumerators and TBucketLists. Suppose I need an enumerator for TClientAccountList which contains TClientAccount objects, I only need to place my cursor among the private field declarations of TClientAccountList and type:

enumarray

Then press Tab. There are three placeholders, namely enumerator class name (TAccountEnumerator), list item class name (TClientAccount) and item list class name (TClientAccountList):

    type
      TAccountEnumerator = record
      private
        FIndex: Integer;
        FOwner: TClientAccount;
      public
        function GetCurrent: TClientAccountList; inline;
        function MoveNext: Boolean; inline;
        property Current: TClientAccountList read GetCurrent;

        constructor Create(AOwner: TClientAccount);
      end;

You also get a public GetEnumerator method and the implementations of these declarations, which you unfortunately will need to move to the implementation section of the unit yourself – I couldn’t find a way of doing this from within the template.

If you think the enumerator above looks a little strange, check out Hallvard Vassbotn’s excellent write-up on enumerators.

The code template for object lists obviously includes enumerators and work in a similar way.

So before I give you the downloads, a couple of instructions.

For Delphi 2007 and 2009, the XML files should be stored to My Documents\RAD Studio\code_templates and for Delphi 2006 you place it in \Program Files\Borland\BDS\4.0\Objrepos\code_templates\delphi.

Some of my templates expand automatically. If you find that annoying, (or would like another one to do that) change the following line near the top:

<template name=”namehere” invoke=”auto”>

to

<template name=”namehere” invoke=”manual”>

or vice versa.

Also, because there are many different permutations of property declarations, I used a naming convention (imagine!):

prop[i][f/c][f/c/nothing]

So they all start with prop, if your property is an array property, you add an i (for index) and then either f (for field) or c (for code) for each of the read and write specifiers.

If that only server to confuse you, some examples may help:

  1. propf is a read-only property that reads a private field.
  2. propicc is an array property with a get-function and a set-procedure.
  3. propfc is a property that reads from a field but writes to a procedure.
  4. and so on.

Enough talking. Here is a zip file with all twelve code templates. Feel free to use them any which way you please.

Comments (5)

What’s wrong with floating-point?

Every so often, floating-point data types come under renewed criticism. There are plenty of good reasons to whisper behind their backs, but are they really all bad?

The basic problem is that floating-point types represent any value as an approximation. It works really well too. In fact, for most whole numbers that you’re likely to encounter the approximation is exact, so 1 is always 1 and 10124 is always 10124.

It gets messy in two scenarios. First, when the value is greater than the precision for your floating point type you start losing least significant digits. The precision for Double is about sixteen digits, so this is the kind of problems you run into:

MyVal := 12345678901234567; // Seventeen digits
if MyVal = 12345678901234567 then
  ShowMessage('This doesn'' show')
else
  ShowMessage('But this does');

Note that Double can represent far larger numbers than this, but only at this 53 bit precision. Integer on the other hand has a fixed upper value (MaxInt) after which it wraps around and your huge number is suddenly very small. Try it:

MyVal := MaxInt + 1;
if MyVal = -MaxInt-1 then
 ShowMessage('Where''d my big number go?');

The second problem – and the one I believe is more common – arises when working with fractions. The problem here is that not all fractions can be represented in a finite number of digits. Working with decimal (base 10) numbers, you can immediately point to 1÷3. This hands you a value that repeats forever and will never be completely accurate, no matter how many threes you add to the end of it. The same happens in binary systems and on numbers you don’t expect – for example, the decimal value 0.1 repeats forever when you convert it to binary. And that means that the approximation is off and all calculations using that value are inaccurate.

It works often enough that many programmers get away with code that compares floating point values using the equality operators (=, <, >). In fact, when you round it for display or storage the value is normally spot-on what you expect it to be. Things go well until you compare two values that should be the same but were calculated in different ways. To remedy this, one should always compare values within ranges, like so:

if abs(x - y) < 0.0001 then
  DoSomething();

The above is a little unintuitive, and Delphi now sports a couple of functions to make it all look pretty:

function CompareValue(const A: Double; const B: Double; Epsilon: Double = 0): TValueRelationship; overload;
function IsZero(const A: Double; Epsilon: Double = 0): Boolean; overload;
function SameValue(const A: Double; const B: Double; Epsilon: Double = 0): Boolean; overload;

Each of these have a few overloads to safely work with Single and Extended values as well. Think of these as you would of utility functions that compare the contents of objects – a necessary way of dealing with these data types. Direct use of the equality operators should be banned for safety’s sake.

So, how about the alternatives? The advice most often given is to store real values as integers, fractions or BCD values.

Integers can be used to implement a fixed-point number, but pose a problem in their limited scale and ease of use. If you’re going to work with fewer that ten digits in total, an Integer could work just fine. As long as you remember to consistently multiply, divide and round as needed. See the problem? For most values that this works for, plain old Double will probably give you results that are at least as good with far less greying of the hair. You could of course wrap this in a record with some overloaded operators, but I have personally not had the need.

Currency is a special Integer case, which is implemented as a 64 bit signed Integer with four places after the decimal point.

A lot of the inaccuracy with floating-point arithmetic arise when dividing two integer values. Popular solution to this? Just keep the original integer values in a record structure. You know what this means don’t you? Even more maintenance work than the fixed-point integer solution listed above. You need to make sure when adding and subtracting these numbers that you work with a common denominator and probably write some code to simplify your fractions. To make matters worse this can only store rational numbers, so PI will be a very poor approximation. Again, this has never seemed like a solution worth implementing to me.

Finally, there is BCD. Every four binary fits store a single decimal digit, so four bits can store up to decimal  nine, eight up to ninety-nine and so on. BCD can store huge numbers. No, even bigger than that. In the Delphi implementation, a total of sixty-four digits. That’s a lot. The tradeoff is memory footprint and also some performance penalty because every BCD value takes a whopping 34 bytes of memory, which could be a lot if you’re passing them on the stack as parameters to functions. Moreover, BCD isn’t a pleasure to work with natively – you need special functions to add them, multiply them, even assign them. It gets a little easier (and still less efficient) if you declare and manipulate them as Variants. Check out the FmtBcd unit for info on working in high precision.

Personally, I use Double as my workhorse type for real numbers with Extended as my backup. They’re more than accurate enough for nearly all scenarios, give adequate performance and use clean, simple syntax. Life is Zen as long as you use SameValue, CompareValue and IsZero religiously. I reserve BCD for cases where exceptional many-decimal accuracy is a must and use Integer for integers only.

What heuristics do you apply?

Leave a Comment