Delphi: Required package “rtl” not found

A while back I got this interesting error when Installing a package into a newly installed copy of Delphi 2010 saying “required package rtl not found”. I recall having had this problem before once when I had Delphi 2009 and 2010 installed at the same time, it just so happens that now I had 2010 and XE installed. Here’s an easy solution to the problem:

Add “$(BDS)\lib” and “$(BDSCOMMONDIR)\dcp” to your library path. This solution will probably only work for later versions of Delphi, though for all versions it should simply be a matter of adding your lib path and dcp output path to the library path.

In my case the cause of this problem is fairly simple. Whenever you install Delphi, the installer will set up all paths like the library path in the windows registry. However, if a path is already present, it will use that, since the user might just be reinstalling the IDE and wouldn’t want to loose their settings. Some component installers allow you to install the components for IDE’s that aren’t actually installed on your computer yet, they will append their library paths to the non-existing path for the IDE which means they will simply create it. This results in a library path that does not contain any of the paths to the standard VCL library and components included with Delphi.

A less delicate solution to this problem would be to just erase all registry content for the version of Delphi you’re trying to install and then install it. This will ensure you have all paths set up correctly, because the previous solution will only ensure VCL works correctly, not the components that come with the IDE like the Indy library. The registry values for the IDEs are located in HKEY_CURRENT_USER\Software\Borland for old releases, HKEY_CURRENT_USER\Software\CodeGear for all releases up to Delphi 2010 and HKEY_CURRENT_USER\Software\Embarcadero for XE and newer.

Read More

Delphi: FileSystem Searching

The windows api comes with several functions to search through files in a computer’s filesystem such as FindFirstFile, FindNextFile, … The RTL library in Delphi encapsulates these functions in 3 easy to use functions. These are FindFirst, FindNext and FindClose. Unlike what you may be used to from the win32 api, these functions return 0 not if something went wrong, but if they were successful. You have to pass the function a mask for the files, this consists out of a filemask to search in the current directory or a filemask including a folderpath. An example would be “c:\*”, this would return all files or folders in c:\ depending on what flags you pass to the FindFirst function. Note that the functions are not recursive, so they will only return the content of a folder and not it’s subfolders. The second parameter of the FindFirst function specifies flags that tell the functions what it is searching for. A few flags are faNormal, faHidden, faSysFile, faDirectory, … These can also be combined to select several types of files/directories. The following example shows you how to loop through all files and directories in the c:\ folder:

program FindTest;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  sRec: TSearchRec;
begin
  if FindFirst('c:*', faNormal or faDirectory, sRec) = 0 then
  begin
    repeat
      WriteLn(sRec.Name + ' - ' + IntToStr(sRec.Size));
    until FindNext(sRec) <> 0;
    FindClose(sRec);
  end;
  ReadLn; // Prevent window from closing
end.

If you would for example change your mask to “c:\*.txt”, it would only return the txt files.

Some of you will also want to be able to recurse this, this can easily be achieved by setting it up in a recursive algoritm:

program FindTest;

{$APPTYPE CONSOLE}

uses
  SysUtils;

procedure RecurseFileSystem(const Folder, Mask: string);
var
  sRec: TSearchRec;
  t: string;
begin
  t := IncludeTrailingPathDelimiter(Folder);
  if FindFirst(t + Mask, faNormal or faDirectory, sRec) = 0 then
  begin
    repeat
      if ((sRec.Attr and faDirectory) <> 0) and (sRec.Name <> '.') and
        (sRec.Name <> '..') then
        RecurseFileSystem(t + sRec.Name, Mask)
      else
        WriteLn(t + sRec.Name + ' - ' + IntToStr(sRec.Size));
    until FindNext(sRec) <> 0;
    FindClose(sRec);
  end;
end;

begin
  RecurseFileSystem('c:', '*');
  ReadLn; // Prevent window from closing
end.

This example will loop through the entire filesystem on the c drive and show you all of the regular files including their path and size.

Read More

Delphi: Collections

Like Java and other languages, Delphi supports collections. This support was however only added after Delphi 7. You can find all of the included generic collection classes in the unit Generics.Collections. In this post I’ll show you 2 collectiontypes from the unit which are commonly used. You can use these in your applications to easily manage various types of data.

The TList class is an item collection which uses integer indices as keys for your collectionitems. The TList class allows you to perform any variety of actions on your collections such as inserting, deleting, moving and finding items. The TList class like all collection classes in the unit is a generic class, this means it’s not specific to a certain type, you have to bind it to a certain type while defining the instance of the collection. Any type can be used with these collections including basetypes. Here’s an example that stores and outputs integer values:

program CollectionsTest;

{$APPTYPE CONSOLE}

uses
  SysUtils, Generics.Collections;

var
  Items: TList<Integer>;
  i, l: Integer;
begin
  Items := TList<Integer>.Create;
  Items.Add(5);
  Items.Add(9);
  Items.Add(1);
  Items.Add(52);
  Items.Add(24);
  l := Items.Count;
  for i := 0 to l - 1 do
    WriteLn(Items[i]);
  Items.Free;
  ReadLn; // Prevent window from closing.
end.

The next collection type I would like to discuss is the dictionary. The dictionary collection is the same as a hashmap in Java. It uses hashes and lineair probing to find items, You can use many different types as a key to bind to your data, the most commonly used type for keys are strings. Here’s an example:

program CollectionsTest;

{$APPTYPE CONSOLE}

uses
  SysUtils, Generics.Collections;

var
  Items: TDictionary<string, string>;
  Enum: TDictionary<string, string>.TPairEnumerator;
begin
  Items := TDictionary<string, string>.Create;
  Items.Add('first', 'item1');
  Items.Add('second', 'item2');
  Items.Add('third', 'item3');
  Enum := Items.GetEnumerator;
  while Enum.MoveNext do
    WriteLn('Key: ' + Enum.Current.Key + ' - Value: ' + Enum.Current.Value);
  Items.Free;
  ReadLn; // Prevent window from closing.
end.

As you can see in this last example, collections also allow you to use various enumerators to access their data in a convenient way. Also take note that the TDictionary type does not keep the stored data in the order it was entered.

Read More

Delphi: FastShareMem

FastShareMem is a very lightweight memory manager for Delphi that was designed to replace the default memory manager that required the inclusion of a dll with applications. However, due to the addition of unicode support to Delphi 2009/2010, the include is no longer compatible with dlls compiled with older versions of Delphi using it. So I’ve written a copy that that will work in Delphi 2009/2010 and still is compatible with the older versions. Due take in mind this version of the include isn’t written for older versions of Delphi. For an older version use the original you can find here: http://www.codexterity.com/fastsharemem.htm

unit FastShareMem;

// By Frederic Hannes (http://ibeblog.com)
// Based on FastShareMem by Emil M. Santos (http://www.codexterity.com)

interface

var
  GetAllocMemCount: function: Integer;
  GetAllocMemSize: function: Integer;

implementation

uses Windows;

const
  ClassName = '_com.codexterity.fastsharemem.dataclass';

type
  TFastShareMem = record
    MemoryManager: TMemoryManagerEx;
    _GetAllocMemSize: function: Integer;
    _GetAllocMemCount: function: Integer;
  end;

function _GetAllocMemCount: Integer;
var
  State: TMemoryManagerState;
  i: Integer;
begin
  GetMemoryManagerState(State);
  Result := 0;
  for i := 0 to High(State.SmallBlockTypeStates) do
    Inc(Result, State.SmallBlockTypeStates[i].AllocatedBlockCount);
  Inc(Result, State.AllocatedMediumBlockCount + State.AllocatedLargeBlockCount);
end;

function _GetAllocMemSize: Integer;
var
  State: TMemoryManagerState;
  i: Integer;
begin
  GetMemoryManagerState(State);
  Result := 0;
  for i := 0 to High(State.SmallBlockTypeStates) do
    Inc(Result, State.SmallBlockTypeStates[i].AllocatedBlockCount *
      State.SmallBlockTypeStates[i].UseableBlockSize);
  Inc(Result, State.TotalAllocatedMediumBlockSize +
    State.TotalAllocatedLargeBlockSize);
end;

var
  wc: TWndClassA;
  IsHost: Boolean;
  ShareMem: TFastShareMem;

initialization
  if not GetClassInfoA(HInstance, ClassName, wc) then
  begin
    GetMemoryManager(ShareMem.MemoryManager);
    ShareMem._GetAllocMemCount := @_GetAllocMemCount;
    ShareMem._GetAllocMemSize := @_GetAllocMemSize;
    GetAllocMemCount := @_GetAllocMemCount;
    GetAllocMemSize := @_GetAllocMemSize;

    FillChar(wc, SizeOf(wc), 0);
    wc.lpszClassName := ClassName;
    wc.style := CS_GLOBALCLASS;
    wc.hInstance := HInstance;
    wc.lpfnWndProc := @ShareMem;

    if RegisterClassA(wc) = 0 then
    begin
      MessageBox(0, 'Shared Memory Allocator setup failed: Cannot register class.',
        'FastShareMem', 0);
      Halt;
    end;

    IsHost := True;
  end else begin
    SetMemoryManager(TFastShareMem(wc.lpfnWndProc^).MemoryManager);
    GetAllocMemCount := TFastShareMem(wc.lpfnWndProc^)._GetAllocMemCount;
    GetAllocMemSize := TFastShareMem(wc.lpfnWndProc^)._GetAllocMemSize;
    IsHost := False;
  end;
finalization
  if IsHost then
    UnregisterClassA(ClassName, HInstance);
end.

Read More

JNI For Delphi Preview

I’m currently developing a new modernized JNI wrapper for Delphi 2010 and up.  The old wrappers found here and here do work, but my wrapper requires less work to set up and uses a lot of new Delphi language features to ensure it works smoothly. The wrapper has been rewritten from scratch to include all features of JNI in JDK 1.6. Note that this wrapper is NOT backwards compatible with the old JNI wrappers, but switching to this one shouldn’t be too hard. At the moment the wrapper itself is far from complete, but it’s a preview including a small sample application. Afterwards I might also be wrapping JVMTI and create a bigger more user-friendly framework to encapsulate JNI. You can download the preview here: http://ibeblog.com/files/JNIForDelphi%200.1.rar

Read More

Delphi: Converting color values to HTML colors

Delphi uses a decimal representation for colors, the way these are built up is simply like integer values which means that in the memory the colors are stored not as RGB, but BGR. If we want to convert these color values to HTML hex colors, we need to take these into account as those are represented as RGB. Here are some methods to perform the conversion:

function ColorToHtml(const Color: Integer): AnsiString;
const
  Hex = '0123456789ABCDEF';
var
  b, s: Byte;
begin
  Result := '#';
  s := 0;
  repeat
    b := (Color shr s) and $FF;
    Result := Result + Hex[b div 16 + 1] + Hex[b mod 16 + 1];
    Inc(s, 8);
  until s = 24;
end;

function HtmlToColor(const Html: AnsiString): Integer;
const
  Hex = '0123456789ABCDEF';
var
  p, s: Byte;
begin
  Result := 0;
  s := 0;
  p := 1;
  if Html[1] = '#' then
    Inc(p);
  repeat
    Result := Result or (((Pos(Html[p], Hex) - 1) * 16 +
      Pos(Html[p + 1], Hex) - 1) shl s);
    Inc(p, 2);
    Inc(s, 8);
  until s = 24;
end;

Read More

Delphi <=> Java: Datatypes

So you know Delphi or Java and want to learn the other language? A very important thing to know is what datatypes you are using, as these differ in each language.

As you may know, Java does not have any unsigned datatypes, Delphi however has both signed and unsigned datatypes. Because of this the unsigned types are not listed in the table below, but in order for the integer types these are Byte/UInt8, Word/UInt16, Cardinal/LongWord/UInt32, UInt64. Delphi also has ansi strings/chars, these can be stores in string and Char but those can also hold unicode versions, the actual ansi types are AnsiString and AnsiChar. And of course Delphi also comes with a Pointer type as well as it has the ability to create types that hold pointers to specific types.

JavaDelphiTypeData
byteShortInt, Int88-bit signed integer-128 to 127
shortSmallInt, Int1616-bit signed integer-32768 to 32767
intInteger, LongInt, Int3232-bit signed integer-2147483648 to 2147483647
longInt6464-bit signed integer-9223372036854775808 to 9223372036854775807
floatSingle32-bit floating point value
doubleDouble64-bit floating point value
booleanBooleanboolean valuetrue or false
charChar (stores both ansi and unicode chars), WideChar, UnicodeChar16-bit unicode charactera single unicode character
Stringstring (stores both ansi and unicode strings), Widestring, UnicodeStringunicode stringa string consisting out of unicode characters
ObjectTObjectan objectobject pointer

Read More

Delphi: Basic Brainfuck Interpreter

This is a really basic commandline brainfuck interpreter, it’s not written for speed or performance, it just shows you how a brainfuck interpreter should work. Of course you can speed it up by converting the code to a form of bytecode, working with pointers or even convert it to machine code.

program Brainfuck;

{$APPTYPE CONSOLE}

uses
  Classes;

const
  ARRAY_SIZE = 30000;

type
  TBFEngine = class
  private
    FScript: TStrings;
    FCompiled: AnsiString;
    FArr: array of Byte;
    FIndex: Integer;
    procedure Compile;
    procedure ClearArray;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Run;
    property Script: TStrings read FScript;
  end;

{ TBFEngine }

procedure TBFEngine.ClearArray;
var
  i, l: Integer;
begin
  l := Length(FArr);
  for i := 0 to l - 1 do
    FArr[i] := 0;
end;

procedure TBFEngine.Compile;
var
  i, l: Integer;
begin
  l := Length(FScript.Text);
  FCompiled := '';
  for i := 1 to l do
    if FScript.Text[i] in ['>', '<', '+', '-', '.', ',', '[', ']'] then
      FCompiled := FCompiled + FScript.Text[i];
end;

constructor TBFEngine.Create;
begin
  FScript := TStringList.Create;
  SetLength(FArr, ARRAY_SIZE);
end;

destructor TBFEngine.Destroy;
begin
  FScript.Free;
end;

procedure TBFEngine.Run;
var
  c: AnsiChar;
  i, j, l, t: Integer;
begin
  Compile;
  ClearArray;
  t := 0;
  FIndex := 0;
  l := Length(FCompiled);
  i := 1;
  while i <= l do
  begin
    case FCompiled[i] of
      '>':
        if FIndex <> (ARRAY_SIZE - 1) then
          Inc(FIndex);
      '<':
        if FIndex <> 0 then
          Dec(FIndex);
      '+': Inc(FArr[FIndex]);
      '-': Dec(FArr[FIndex]);
      '.': Write(Chr(FArr[FIndex]));
      ',': Read(FArr[FIndex]);
      '[':
        if not Boolean(FArr[FIndex]) then
          for j := i + 1 to l do
          begin
            c := FCompiled[j];
            if c = '[' then
              Inc(t)
            else if c = ']' then
              if t <> 0 then
                Dec(t)
              else begin
                i := j;
                Break;
              end;
          end;
      ']':
        if Boolean(FArr[FIndex]) then
          for j := i - 1 downto 1 do
          begin
            c := FCompiled[j];
            if c = ']' then
              Inc(t)
            else if c = '[' then
              if t <> 0 then
                Dec(t)
              else begin
                i := j;
                Break;
              end;
          end;
    end;
    Inc(i);
  end;
end;

var
  Engine: TBFEngine;
begin
  if ParamCount = 1 then
  begin
    Engine := TBFEngine.Create;
    Engine.Script.LoadFromFile(ParamStr(1));
    Engine.Run;
    Engine.Free;
  end;
end.

Hello world in brainfuck:
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.——.——–.>+.>.

Read More

Delphi: Binary Data Storage

When developing software you’ll often have to store data for some purpose, whether this being int he form of files that your program outputs, settings or other things. One of the things you’ll certainly almost always have to store are boolean values, True or False. This can be done in various ways, the worst way to tackle the problem would be to create a delimited string with the boolean values as strings ‘True’ and ‘False’, which would result in a string like ‘True|True|False|True|False|False|False|True’. The reason this is the worst way to handle the problem is simply because it takes up so much space. A boolean is a single bit value, meaning it contains a value that can be stored in 1 bit. By storing it in the previous manner you will be using 4 bytes or 32 bits for “True’ and 5 bytes or 40 bits for False and an additional 1 byte or 8 bits for each delimiter.

Another way to store the booleans is simple by converting them to byte values. Bytes are the smallest primitive datatypes in the Delphi programming language, they are 1 byte or 8-bit unsigned values. So by converting the booleans to this datatype, you can store a boolean as a single byte. This can be done by casting it to Byte and preferably convert it to a Char and back to Byte so you get the characters 0 and 1 as result Byte(Chr(Byte(MyBoolean))). Because the length of True and False is now the same, you can append this into a single string without delimiters, so your result will be something like ‘11010001’.

If you’ve counted the number of booleans in my previous examples you probably see where this is going. The previous method is ok to use but if you really want to conserve file size you should take it even a step further. The previous method uses a byte value to store a boolean, a byte contains 8 bits and as I mentioned before a boolean can be stored in a single bit as it can only be 2 values. so in theory this would let us store 8 booleans in a single byte. to do this we will have to write a bit more complex code. We will use bitshiting to shift up to 8 boolean values into a single byte and then reverse the process.

Selecting the most right bit in a value can be done by applying the bitwise and operator to the value along with the value 1. When you do this to a bit you can cast it directly to Boolean. If you want the next bit, you use a right bitshift of a single position to shift the value and then you can select that first bit again, only this time it will be the bit that used to be next in line. The same is true the other way around, to shift bits into a single value, you just convert a boolean to an integer and apply it to the value with a bitwise or, then you shift the value 1 position to the left with a left bitshift and you can repeat the process.

Here’s an example:

program BoolsTest;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TBooleanArray = array of Boolean;

function BoolToChar(const Bools: TBooleanArray): Char;
var
  Buffer: Byte;
  i, l: Integer;
begin
  Buffer := 0;
  i := 0;
  l := Length(Bools);
  while (i < l) and (i <> 8) do
  begin
    Buffer := (Buffer shl 1) or Integer(Bools[i]);
    Inc(i);
  end;
  Result := Chr(Buffer);
end;

procedure CharToBool(const c: Char; out Bools: TBooleanArray;
  const Len: Integer = 8);
var
  Buffer: Byte;
  i: Integer;
begin
  Buffer := Ord(c);
  SetLength(Bools, Len);
  for i := Len - 1 downto 0 do
  begin
    Bools[i] := Boolean(Buffer and 1);
    Buffer := Buffer shr 1;
  end;
end;

var
  Booleans: TBooleanArray;
  c: Char;
begin
  // Initialize boolean array
  SetLength(Booleans, 8);
  Booleans[0] := True;
  Booleans[1] := False;
  Booleans[2] := True;
  Booleans[3] := False;
  Booleans[4] := False;
  Booleans[5] := True;
  Booleans[6] := True;
  Booleans[7] := False;
  // Convert booleans to char
  c := BoolToChar(Booleans);
  WriteLn(c);
  // Set the boolean array to False
  FillChar(Booleans, 8, 0);
  // Convert char back to boolean array
  CharToBool(c, Booleans);
  // Convert back to char to show the output is the same
  c := BoolToChar(Booleans);
  WriteLn(c);
  ReadLn; // Prevent window from closing
end.

Read More