Working with Strings

Elements provides extensive support for delphi-compatible String types.

The DelphiString type is provided 1 for working with Delphi-style strings in Elements. It is an alias to either DelphiUnicodeString or DelphiAnsiString, depending on the Delphi version and whether it uses Ansi or Wide strings by default, and it is 100% memory compatible with the String types used by the Delphi libraries.

This means it can be passed into Delphi code wherever a string is expected, and strings returned from calls into Delphi will be returned as DelphiString (or explicitly one of the four string types discussed below, if the API is defined so).

DelphiString has the same usage semantics as strings have in Delphi. In particular this means:

  • Strings are essentially a zero-terminated C-type string, with extra metadata stored at their head.
  • Strings can be indexed one-based, and are mutable.
  • Strings use copy-on-write semantics for efficiency
  • While Strings are heap based, COW means they essentially can be treated as value types, where changes to a copy of the string do not affect the original.
  • Strings are compatible with and can (with caution) be used and passed as PChars
  • And lastly, Strings are reference counted and will be freed automatically.

Types of Strings

Island.DelphiSupport implements four distinct string types, matching the four types in Delphi itself.

  • DelphiUnicodeString – a UTF16 two-bytes-per-character string type that matches the above description. The default String type and aliased as DelphiString in Delphi 2009 and later.

  • DelphiAnsiString – a one-byte-per-character string type that matches the above description. The default String type and aliased as DelphiString in Delphi 2007 and earlier.

  • DelphiWideString – a UTF16 two-bytes-per-character string type is reference counted, does not use reference counting or copy-on-write semantics, but will still be automatically freed when it goes out of scope.

  • DelphiShortString – a legacy one-byte-per-character string type that is stack based and limited to 255 characters.

As mentioned above, DelphiString is an alias to either DelphiUnicodeString or DelphiAnsiString, depending on the Delphi version, so most commonly you will use that name, rather than the Unicode/Ansi variant, unless you want to explicitly choose a "non-default" string width.

Delphi.System.string is also defined, in Delphi.rtl, as an alias to either DelphiUnicodeString or DelphiAnsiString.

String APIs

Unlike on Delphi, where the String types are basically pointers, the above types are implemented as records, meaning they provide APIs (such as .Length) that can be called on the types.

Like strings in Delphi, they are not part of the TObject class hierarchy, and cannot be assigned to TObject-typed references. However, being records, they can be boxed to be part of the Island Object type tree. The can also seamlessly be cast to Island Strings (and, on Cocoa to NSString).

Delphi Strings can be indexed via an Integer offset or an Index, and can be concatenated using the + operator.

And of course Delphi Strings will work with all the String API functions provided by Delphi's RTL and other Delphi libraries

Interoperability

Do note that, by default, strings declared in Elements code – such as those created from literals – are still Island-level string types (RemObjects.Elements.System.String), part of the Island object model tree, and responding to the APIs available on that type.

This means that if you declare a variable such as

var x := 'Hello Island';

then x will be an Island String, not a Delphi String. However, the compiler will infer the right string type for literals, based on context, for example when passing strings to APIs, or assigning to a typed variable:

var x: DelphiString := 'Hello Delphi';
myStringList.Add('Delphi');

The Delphi String types also provide cast operators for seamlessly converting between the two types, so you can pass Island Strings directly into a Delphi API, or vice versa. But do note that these casts come with a copy cost.

var x := 'Hello Island';
myStringList.Add(x); // converts to DelphiString
x := myStringList[1]; // converts back to IslandString

Assigning or casting a Delphi String to/from an Island Object type variable will also convert it to an Island String object, rather than boxing it.

See Also


  1. as part of the Island.DelphiSupport library.