Posts tagged OOP

TZDB 1.8.2014b

A new version of TZDB has been release (1.8.2014b). This version fixes a few issues around the Windows TZ aliases provided by CLDR project. Obviously the database has been updated to the most recent version (2014b).

 

The biggest news is the fact that we have moved to GitHub! The old Google Code url will still be around for a while, after which point it will be deleted.

 

Also, I would like to thank Pierre Yager for the fixes and the release itself as I do not have access to a Delphi license any longer.

 

TZDB is an open source project that provides Delphi (7+) and FreePascal (2.0+) users with a “built-in” timezone database. The same source of data is used in most Unixes, Java, MacOS and multiple other projects out there.

Delphi anonymous methods are …

… too fat.

Surely writing code like this gets frustrating very fast. I want my lambdas!!

  { Lovely, isn't it? }
  LGroupJoined := LOwners.Op.GroupJoin<TPet, TPerson, TOwnedPets>(LPets,
    function(Arg1: TPerson): TPerson begin Result := Arg1; end,
    function(Arg1: TPet): TPerson begin Result := Arg1.FOwner; end,
    function(Arg1: TPerson; Arg2: ISequence<TPet>): TOwnedPets
    begin
      Result.FOwnerName := Format('%s, %s', [Arg1.FLast, Arg1.FFirst]);
      Result.FPetNames := Arg2.Op.Select<String>(
        function(Arg1: TPet): String begin Result := Arg1.FName; end);
    end
  );

  for LOwnedPets in LGroupJoined do
  begin
    WriteLn('Person ', LOwnedPets.FOwnerName, ' owns: ');
    Write('    ');

    for LName in LOwnedPets.FPetNames do
      Write(LName, ', ');

    WriteLn;
  end;

In other news, there is a working version of Collections 2.0 in the SVN. Most of the changes were sitting on my hard drive for a year now. I just made sure that the last touches are applied and that this version compiles in Delphi XE2. I have also applied a few fixes that enabled the package to work in 64 bit environment.

 

Be advised: The unit tests are completely broken. I have no short term plans on making them work. The amount of time needed for that is staggering. I am currently focused on features so I won’t touch them in a while.

 

P.S. I have to say that I am very disappointed with the quality of the IDE when generics are involved. I had countless unpleasant problems in the past but was expecting things to get better in XE2. Not so. My IDE froze countless time when trying to edit some source files. Whenever I would type a “.” or a “(” it would be gone for good. This makes me wonder whether Collections will be usable at all to you guys. With such buggy support I can predict only crashes. And don’t get me started on the EXE size …

Get over the FreeAndNil thing already!

‘Nuff Said!

TZDB 1.7 with 27 June Database

After a few months of inactivity I give you the latest update to TZDB featuring the last published TZ database. This realease also fixes a bug in the importer that could not properly read only hour based offsets which resulted in wrong calculations for some timezones.

For people trying to user Etc\xxxxx time zones. Those time zones have their sign inverted as specified by POSIX. This means that Etc\GMT+2 is actually GMT-2. This is not a bug in TZDB, it’s just the way these pseudo-timezones are defined.

 

For those unaware: TZDB is an open source project that provides Delphi (7+) and FreePascal (2.0+) users with a “built-in” timezone database. The same source of data is used in most Unixes, Java, MacOS and multiple other projects out there.

Grab the latest version here, and view the latest changes here.

TZDB 1.7.110207 and Collections 1.1.1

TZDB 1.7.110207

No code changes, just an updated DB from “The tz Database“. There are a small number of changes there so upgrade only if you want to stay 100% up to date. I would just recommend you skip it. As usual, you can get the latest version here.

Collections 1.1.1

This is a bug fix release that addresses the following issues:

  1. No possibility to remove an value from a list or associative collection without invoking the “removal procedures”. This results in freed objects for object based collections. In pre-1.1 versions this wasn’t necessarily an issue. (Thanks Mason for the report, hope this unblocks your scripting project)
  2. Removal procedures were not invoked for bidirectional dictionaries.
  3. TObjectMultiMap<TKey, TValue> still used a “class” restriction on TValue type parameter.
  4. Fixed Delphi 2010 build. Note that by “fix” I mean — disabled Collections.Dynamic code and TBitSet class. Cannot make the compiler accept those (circular unit problems that were fixed in XE).

Get the bug fix release here.

Collections 1.1 is out

I’m proud to present version 1.1 of Collections package.



The major highlights of this release are:

  • TLinkedDictionary<TKey, TValue>, same as the standard dictionary but with predictable insertion order.
  • TLinkedStack<T>, same as standard set but with some predictability in element order.
  • TBitSet, a sorted set designed to store 16-bit numbers only.
  • TBidiDictionary<TKey, TValue>, a dictionary that enforces one key, one value on both ends.
  • TSortedBidiDictionary<TKey, TValue>, a sorted bidirectional dictionary.
  • TDoubleSortedDictionary<TKey, TValue>, a bidirectional dictionary sorted on both keys and values.
  • TSortedLinkedList<T>, a linked list with automated sorting.
  • RTTI based selectors. See overloads of Op.Select.
  • A rewrite of TLinkedList<T>, TLinkedQueue<T> and TLinkedStack<T>.
  • TArraySet<T> is not a sorted set and optimized a lot.
  • Multiple optimizations all over the place.
  • A new Op.GroupBy<T> operation.
  • Some internal cleanup.
  • Documentation fixes (Thanks Denisa once again).

On the project organization side, the project home page has got quite some love:

  • Three simplified diagrams of classes and interfaces in Collections.
  • A FAQ page that I hope will be useful to people. If you have a question not answered there please leave a comment and I will respond ASAP.
  • A page that states the differences between this project ans stock RTL collections.
  • A list with short descriptions for all Enex operations supported by collections.
  • A detailed “map” of all collections provided by the project with explanations of when to use, some implementation details and etc useful information that can help you better chose the collection you need.

On the documentation side of things, you will find two sample projects in the bundle. Only two at the moment, will add more when I have enough free time to.

Get the latest version or view the changelog!

Collections 1.0.1 soon

I will get an 1.0.1 update soon addressing XE compatibility issues some people are experiencing and some documentation fixes. Stay tuned.

DeHL 0.8.2 is out

DeHL

I’ve just released the version 0.8.2 of DeHL. The downloads can be found on this page and changelog on this page.
Again, this is a minor release with a few bugs fixed and a new feature: TString (as asked in this comment).
As you might have guessed already, TString is a wrapper record modeled on .NET’s System.String class. Unfortunately I was unable to use most of the RTL’s string functionality so the “wrapper” grew quite a bit from my original expectations.

But … enough talk, here are some usage scenarios that someone may find useful:

var
  LStr: TString;
begin
  { Overloaded operators and a special function "U" }
  LStr := U('Hello World for the ') + 10 + 'th time!';

  { Do some random operations }
  if (LStr.ToUpper().Contains('HELLO')) and
     (LStr.Contains('HeLLo', scLocaleIgnoreCase)) then
  WriteLn(LStr.ToString);

  { Now let's select all the distinct chars from the string }
  WriteLn(
    LStr.Concat(LStr.AsCollection.Distinct.Op.Cast<string>).ToString
  );
end.

TString overloads all sane operators: Equality, Inequality, Implicit conversions, Addition, Subtraction and offers functions to convert to and from UTF8 and UCS4 (via RTL of course). I also need to iron a few things about about Enex integration for the next minor release.

The other small improvement that I added relates to the collection package. All simple collections (not the Key/Value pair ones) implement a sort of “where T is the_class, select it as such” operation. Check out this example:

var
  LList: TList<TObject>;
  LBuilder: TStringBuilder;
  LObject: TObject;
begin
  LList := TList<TObject>.Create;

  { Populate the list with some random objects }
  LList.Add(TInterfacedObject.Create);
  LList.Add(TStringBuilder.Create);
  LList.Add(TStringBuilder.Create);
  LList.Add(TObject.Create);

  { Now select the objects we're interested in (string builders) }
  for LBuilder in LList.Op.Select<TStringBuilder> do
    WriteLn(LBuilder.ClassName); // Do stuff

  { Or select everything (not actually required - an example) }
  for LObject in LList.Op.Select<TObject> do
    WriteLn(LObject.ClassName); // Do stuff
end.

If it’s still not clear what this operations does, let me explain. It basically consists of two operations: Where and Select. First, each object is checked to be of a given class and then this object is cast to that class so you can iterate directly using a FOR .. IN loop only over the objects you want to. Of course doing that for TObject makes no sense (as in example) … but well … that was an example.

Well, that’s all for today,
Have Fun!

DeHL 0.8.1

DeHL

I’ve just released the version 0.8.1 of DeHL. The downloads can be found on this page and changelog on this page.

This is mostly a fix release with only one major feature – Cloning (in DeHL.Cloning). The rest of the changes are either bug fixes or janitorial changes.

Have Fun!

Here you go — DeHL 0.8

DeHL

This is going to be a short one. After months of no releases, here it is: DeHL 0.8 (see changelog for the list of changes on this release). As I mentioned previously, this release will only work on Delphi 2010, since the number of changes required to support serialization was quite big.

I must confess, this is the first time in my programming career that I had to interact with serialization (excluding the times when the frameworks do that for you). I had to learn quite a bit and changed my internal design three times.

So, here’s an example how to serialize a TFormatSettings structure into binary format:

var
  LBinFile: TFileStream;
  LBinSerializer: TBinarySerializer<TFormatSettings>;
  LSettings: TFormatSettings;
begin
  { Obtain current thread's format settings }
  GetFormatSettings(GetThreadLocale(), LSettings);

  { Create a serializer and a file stream }
  LBinSerializer := TBinarySerializer<TFormatSettings>.Create();
  LBinFile := TFileStream.Create('dump_obj.bin', fmCreate);

  { Serialize the structure }
  try
    LBinSerializer.Serialize(LSettings, LBinFile);
  finally
    LBinFile.Free;
    LBinSerializer.Free;
  end;
end;

… and here’s an example how to deserialize it:

var
  LBinFile: TFileStream;
  LBinSerializer: TBinarySerializer<TFormatSettings>;
  LSettings: TFormatSettings;
begin
  { Create a serializer and a file stream }
  LBinSerializer := TBinarySerializer<TFormatSettings>.Create();
  LBinFile := TFileStream.Create('dump_obj.bin', fmOpenRead);

  { Deserialize the structure }
  try
    LBinSerializer.Deserialize(LSettings, LBinFile);
  finally
    LBinFile.Free;
    LBinSerializer.Free;
  end;
end;

Note: I have written quite a few unit tests to support the new changes, but most certainly there are hidden bugs. If you find one please report it here.

Other Note: I exhausted my idea jar regarding new features. If you have an idea please do not hesitate to drop me a comment or an email.

Have Fun!