Our SQLite3/mORMot Framework has 100% UNICODE compatibility, that
is compilation under Delphi 2009/2010/XE/XE2. The code has been deeply
rewritten and tested, in order to provide compatibility with the
String=UnicodeString
paradigm of these compilers. But the code
will also handle safely Unicode for older version, i.e. from Delphi 6 up to
Delphi 2007.
Since our framework is natively UTF-8 (this is the better character encoding for fast text - JSON - streaming/parsing and it is natively supported by the SQLite3 engine), we had to establish a secure way our framework used strings, in order to handle all versions of Delphi (even pre-Unicode versions, especially the Delphi 7 version we like so much), and provide compatibility with the Free Pascal Compiler.
Some string types have been defined, and used in the code for best
cross-compiler efficiency (avoiding most conversion between formats):
- RawUTF8
is used for every internal data usage, since both
SQLite3 and JSON do expect UTF-8 encoding;
- WinAnsiString
where WinAnsi-encoded
AnsiString
(code page 1252) are needed;
- Generic string
for i18n (e.g. in unit
SQLite3i18n
), i.e. text ready to be used within the VCL, as either
AnsiString
(for Delphi 2 to 2007) or UnicodeString
(for Delphi 2009/2010/XE/XE2);
- RawUnicode
in some technical places (e.g. direct Win32 *W() API
call in Delphi 7) - note: this type is NOT compatible with Delphi
2009/2010/XE/XE2 UnicodeString
;
- RawByteString
for byte storage (e.g. for
FileFromString()
function);
- SynUnicode
is the fastest available Unicode native
string type, depending on the compiler used (i.e. WideString
before Delphi 2009, and UnicodeString
since);
- Some special conversion functions to be used for Delphi 2009/2010/XE/XE2
UnicodeString
(defined inside $ifdef UNICODE...$endif
blocks);
- Never use AnsiString
directly, but one of the types above.
Note that RawUTF8
is the preferred string
type to
be used in our framework when defining textual properties in a
TSQLRecord
and for all internal data processing. It's only when
you're reaching the User Interface layer that you may convert explicitly the
RawUTF8
content into the generic VCL string
type,
using either the Language. UTF8ToString
method (from
SQLite3i18n.pas
unit) or the following function from
SynCommons.pas
:
/// convert any UTF-8 encoded String into a generic VCL Text // - it's prefered to use TLanguageFile.UTF8ToString() in SQLite3i18n, // which will handle full i18n of your application // - it will work as is with Delphi 2009/2010/XE/XE2 (direct unicode conversion) // - under older version of Delphi (no unicode), it will use the // current RTL codepage, as with WideString conversion (but without slow // WideString usage) function UTF8ToString(const Text: RawUTF8): string;
Of course, the StringToUTF8
method or function are available to
send back some text to the ORM layer.
A lot of dedicated conversion functions (including to/from numerical values)
are included in SynCommons.pas
. Those were optimized for speed and
multi-thread capabilities, and to avoid implicit conversions involving a
temporary string
variable.
In fact, this enforce the n-tier layered architecture of the project:
RawUTF8
is to be used at Storage and Business layers;string
type for the User Interface (at the VCL level).
Warnings during the compilation process are not allowed, especially under Unicode version of Delphi (e.g. Delphi 2010): all string conversion from the types above are made explicitly in the framework's code, to avoid any unattended data loss.
With such an implementation pattern, we keep all our code benefit from the strong typing feature of Delphi, whereas we can handle safely Unicode content even with older Ansi versions of Delphi.
Comments are welcome on our forum.