I have to use an old unit that uses ansistring, ansichar et al on Android, previously built on Delphi 2007, so I'm working on making it compatible with XE7.
I've come across several lines that would have put an empty string into an AnsiString, like so: FAnsiString := ''
, but now that AnsiString is an array of bytes(FAnsiString : array of Byte
) I get the message E2010 incompatible types.
I've tried to parse it by creating a type for the array (type TArrayOfByte = array of Byte
) and trying to parse it like so: FAnsiString := TArrayOfByte ('')
.
But then I get E2089 Invalid TypeCast.
How can I make it work correctly?
An simplification of how it should work is below. Basically I want a function that returns an array of bytes. Depending on the arguments, the result of that function should be an empty string.
{$ifdef android}
type AnsiString = array of Byte;
{$endif}
function FooBar(arguments) : AnsiString
begin
if false then
Result := '';
end;
Delphi strings and dynamic arrays both contain a nil
pointer when they are empty. So this:
var
FAnsiString: AnsiString;
FAnsiString := '';
Is effectively doing this behind the scenes:
// FAnsiString := '';
if Pointer(FAnsiString) <> nil then
begin
// decrement reference count, if 0 then free memory ...
Pointer(FAnsiString) := nil;
end;
Dynamic arrays do the exact same thing. This:
var
FAnsiString: array of Byte;
FAnsiString := nil;
// Alternatively:
// SetLength(FAnsiString, 0);
Is effectively doing the same thing as the AnsiString
cleanup behind the scenes:
// FAnsiString := nil;
if Pointer(FAnsiString) <> nil then
begin
// decrement reference count, if 0 then free memory ...
Pointer(FAnsiString) := nil;
end;
Both AnsiString
and dynamic arrays are compiler-managed ref-counted types. They are both auto-initialized to nil
.
Likewise, AnsiString
comparisons for empty strings:
var
FAnsiString: AnsiString;
if FAnsiString = '' then
...
if FAnsiString <> '' then
Are effectively just checking for a nil
pointer:
if Pointer(FAnsiString) = nil then
...
if Pointer(FAnsiString) <> nil then
Same with dynamic arrays, only you can do it without a typecast:
var
FAnsiString: array of byte;
if FAnsiString = nil then
...
if FAnsiString <> nil then
The alternative is to use Length()
and SetLength()
, which works for both strings and dynamic arrays:
var
FAnsiString: AnsiString;
if Length(FAnsiString) = 0 then
...
if Length(FAnsiString) <> 0 then
...
SetLength(FAnsiString, 0);
var
FAnsiString: array of byte;
if Length(FAnsiString) = 0 then
...
if Length(FAnsiString) <> 0 then
...
SetLength(FAnsiString, 0);
And, of course, there is always Andreas Hausladen's patch to enable AnsiString
in the mobile compilers:
The Return of the Byte-Strings
System.ByteStrings support for XE5 Update 2 (and XE6 and XE7)