Monthly Archives: April 2014

Ansi- and RawByteString for Delphi mobile

Do you want to use 8-bit strings on mobile platforms with all the nice old-fashioned features?

ORawByteString has been designed to make old code easily portable to mobile platforms – you only have to rename functions like “Copy” to “AnsiCopy”, that’s all.
With ORawByteString you can write code like this:

procedure TestAnsiString(const aOutputLines: TStrings);
  Raw: RawByteString;
  Wide: string;
  I: Integer;
  C: PAnsiChar;
  Raw := RawByteString('HEADET');
  Raw[AnsiLength(Raw)] := AnsiChar('R');//Raw = HEADER
  Wide := UTF8ToString(Raw);//convert "HEADER" from UTF-8 (ASCII) to UTF-16

  aOutputLines.Add(Wide);//output "HEADER"

  Raw := RawByteString(Wide);//CONVERT UTF-16 back into ASCII (without any codepage)
  I := Pos('H', Raw);//Fast search in RawByteString
  Raw := AnsiCopy(Raw, I, 3);//Use fast copy on RawByteString -> Raw = "HEA"
  Wide := String(Raw);//CONVERT ASCII to UTF-16 (without any codepage)

  C := PAnsiChar(Raw);//YOU CAN EVEN USE PAnsiChar!!!
  Raw := RawByteString(C);//AND convert PAnsiChar back to RawByteString/AnsiString

  C := PAnsiChar(Raw);
  aOutputLines.Add(String(C[2]));//output "A" (the third letter from C (PAnsiChar is always 0-based)

  AnsiDelete(Raw, 1, 1);//Fast delete in RawByteString -> Raw = "EA"
  AnsiInsert(RawByteString('x'), Raw, 2);//Fast insert -> Raw = "ExA"
  Raw := UpperCase(Raw);//Fast uppercase -> Raw = "EXA"
  aOutputLines.Add(String(Raw));//output "EXA"
  Raw := LowerCase(Raw);//Fast uppercase -> Raw = "exa"
  aOutputLines.Add(String(Raw));//output "exa"

ORawByteString.pas allows you to:

  1. use 8-bit AnsiString and RawByteString on mobile platforms.
  2. use 8-bit PAnsiChar on mobile platforms.
  3. use 8-bit AnsiChar on mobile platforms.
  4. use the same AnsiString code on desktop and mobile.
  5. -> no IDE hacking is needed :)

It features it’s own text functions like AnsiInsert(), AnsiCopy(), AnsiDelete(), AnsiLength(), Pos(), LowerCase() etc. to offer maximum performance.

And when we talk about performance: ORawByteString is in some scenarios a little bit slower than string on mobile platforms, but most of the test cases and an usual usage showed no significant performance drawbacks. String operations perform on ORawByteString as fast as on string.

ORawByteString features full copy-on-write, mutability and all string features you have always taken advantage of.

On the one hand ORawByteString is a technical exhibition on how you can use records with operators to create your own delphi type, but on the other hand it can also be useful since it’s not certain that 8-bit strings will be officially available on mobile platforms at some point.

License: MPL 1.1


Free() bug on mobile compilers

Some time ago, we discussed the Free/DisposeOf issue of new ARC Delphi objects in the Delphi plus group.
The problem is that Free() does not call the destructor directly any more. It sets the object reference to nil instead. When the reference count is 0, the destructor is called.

I am among those who don’t like this new compiler feature. Free could just do what DisposeOf does (call destructor and set the object to zombie state). So there is basically no need of DisposeOf.

Now, we have another argument for the DisposeOf/Free futility: under some circumstances, pending references can be created by the compiler itself (when the object reference is passed to the Result variable but not used at all). The programmer thinks that there are no references left and the destructor should get called but no, the destructor is not called indeed.

The same behaviour can be observed on desktop compilers too with all reference-counted types (strings, interfaces, dynamic arrays) but none of those types rely on an explicit destructor call, so it does not really matter.

Link to the QC:

Honestly, I just don’t see the point why I should call DisposeOf() now everywhere where I have called Free() for so many years…

Sample code to reproduce (call TestReferenceBug()):

  TMyObject = class(TInterfacedObject)
    destructor Destroy; override;

destructor TMyObject.Destroy;


function MyFunc(const aObj: TObject): TObject;
  Result := aObj;

procedure TestReferenceBug;
  xObj: TObject;
  xObj := TMyObject.Create;
    MyFunc(xObj);//"virtual" reference is created here
    xObj.Free;//xObj.Destroy is not called!!!

  ShowMessage('After try-finally-end');

end;//"virtual" reference is destroyed here -> call xObj.Destroy