Dienstag, 26. Februar 2008

Delphi/C++ Builder vs .NET and C#

Lately I was looking for a nice GUI front-end for MySql and also for Sqlite. MySql now comes with several GUI Tools, including MySql Query Browser which is supposed to do exactly what I need - except, that it doesn't.
Some features simply aren't just there - what about clicking in data cell to edit its value? Too advanced to be required from a application being developed for at least two years or even more? And I was thinking that Database GUI editors were all about editing data.

Than I tried the open source HediSql. It is truly awesome! Given the enormous competition in the field, and official GUI from MySql itself these guyes just rock!
It gives you everything that you need; it is fast, responsible and nice to work with. Keep up the good work! What about Sqlite support?

It was clear that it is native application - it just worked too smooth and had too small memory footprint to be developed with .NET.
A wanted to look at the source and to my surprise it wasn't in C++, it was Delphi!
That really got me thinking - some of the best software products, that I have used - BSPlayer, Skype, HeidiSql, TestComplete- just to name a few, aren't developed in a mainstream language like C++ or C#, but in Deplhi. I even was told, that the initial version of the eBay ISAPI was also developed in Delphi.
But there is more - a lot of bussines applications, that really make a lot of money for their developers are also developed also in Delphi.

We had a presentation at work from a partner software company, which product works with ours. He talked all day long and he could show us just a small part the application features. It was really good and he developed it all by himself. Guess what development platform he is using - Delphi.

Well I don't know why Microsoft can't pull this off with all the billions they are putting in to their development platform. .NET is really good, I love developing software with it, but I hate using .NET products, because they are slow. Not too slow if the developers did a good job, but a lot slower than anything native.

I know that there is no market for Delphi developers and I know that Java and .NET jobs are all around the place, but Delphi and C++ Builder are better for developing user software.

So if you are looking for career opportunities - go .NET or J2EE. But if you want to develop a software product and sell it successfully - Deplhi and C++ Builder are the way to go.

I wish I had the courage to use this platform way myself.

memccpy considered harmful ( if you don't know how to use it)

Ever heard of the memccpy function?

It is very similar to memcpy, but it will stop copying if given delimiter character is encountered. So that's a nice feature - let's just use it instead of memcpy everywhere!

Except that you must pay extreme attention to what are you actually copying, and what kind of delimiter character are you using. Copying text strings and using line feed '\n' as delimiter is fine, but copying mac addresses, and using '\n' as delimiter, as a coworker did, is not.
But why, you may ask. Well because the '\n' character, 0x0a in hex, is pretty valid byte to come in a mac address. And guess what - if you use memccpy to copy a mac address and use '\n' as delimiter, it is going the get truncated! And because the target buffer is already allocated with certain size and filled with some random data, that may also be valid for mac address, this kind of error may go unnoticed for a long time.

This brings up the question of the data representation, that you are using and how well you understand it, and also the quality of the interface definitions of common C functions and stuff like:

if(strcmp(str1, str2)) {
/*
if you are expecting to get here
if str1 and str2 are the same,
you are in for a surprise
*/
}


Otherwise remember it also very important to always check the return values, that you are getting and event more important also: test, test, test

Montag, 25. Februar 2008

GUIDs, their representation and Base64

Everyone knows what a GUID is - 128 bit number, that is supposed to be global unique and it is used for identifier for different types of objects, COM objects most notably.

Usually they are formatted as hex string like {F7F052A2-8BC7-4b84-8330-228BCA8A6E19}. A tool for creating guids can is guuidgen.exe, there are also System.Guid class and CoCreateGuid API.
Sometimes GUIDs have to be formatted more compactly, for instance in the IFC Specification GUIDs have to be formatted as Base64, making them string with 22 characters length.
Sadly the base64 encoding is non-compatible with the .NET implementation, which makes it a hard task to convert System.Guid object to required format.
IFC Base64 is using 0-9A-Za-z_$ characters and .NET implementation is using something like A-Za-z0-9 for encoding table.
There is some sample C code on the ifc wiki site, so I went for the easy solution - make a dll and call it from .NET.
The problems with this approach kept comming one after another - mostly dll was not always found in Web scenario, due to deployment issues. But there are also other possible hurles - 64bit migration, deployment on Mono and so on.
So I needed a pure managed implementation of Base64 encoding for GUIDs.
Some googleing brought me to sample code, that I adjusted it to the spec and here is the solution:


public class Managed {

public static string GetId(Guid guid) {
return ToBase64String(guid.ToByteArray());
}

public static string GetId() {
return ToBase64String(Guid.NewGuid().ToByteArray());
}

public static readonly char[] base64Chars = new char[]
{ '0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',
'_','$' };

public static string ToBase64String(byte[] value) {
int numBlocks;
int padBytes;

if ((value.Length % 3) == 0) {
numBlocks = value.Length / 3;
padBytes = 0;
} else {
numBlocks = 1 + (value.Length / 3);
padBytes = 3 - (value.Length % 3);
}
if (padBytes < 0 || padBytes > 3)
throw new ApplicationException("Fatal logic error in padding code");


byte[] newValue = new byte[numBlocks * 3];
for (int i = 0; i < value.Length; ++i)
newValue[i] = value[i];

byte[] resultBytes = new byte[numBlocks * 4];
char[] resultChars = new char[numBlocks * 4];

for (int i = 0; i < numBlocks; i++) {
resultBytes[i * 4 + 0] =
(byte)((newValue[i * 3 + 0] & 0xFC) >> 2);
resultBytes[i * 4 + 1] =
(byte)((newValue[i * 3 + 0] & 0x03) << 4 |
(newValue[i * 3 + 1] & 0xF0) >> 4);
resultBytes[i * 4 + 2] =
(byte)((newValue[i * 3 + 1] & 0x0F) << 2 |
(newValue[i * 3 + 2] & 0xC0) >> 6);
resultBytes[i * 4 + 3] =
(byte)((newValue[i * 3 + 2] & 0x3F));
}

for (int i = 0; i < numBlocks * 4; ++i)
resultChars[i] = base64Chars[resultBytes[i]];

string s = new string(resultChars);
return s.Substring(0, 22);
}
}


So if you have to encode something as Base64 or deal with GUIDs with one way or another - this may be helpful to you.
Original code by James McCaffrey

Hello World!

Hello everyone!

This is my first blog post! This blog is going to be about software development problems that I encounter at work and their solutions. I am mostly working with the .NET platform and C#, but there will also be bunch of other stuff like C++ and its pitfalls, Java, VB, VB.NET and nifty gritty Windows Installer MSI tricks and a lot more.
I hope this will be a nice trip and I will be glad if this is helpful to someone.