az01
az01

Reputation: 11

Newest Delphi compiler versions and String type compatibilty

I'm trying to make some String processing routines compatible with newest delphi version. I'm using Delphi2005 and 2007 but I'm not totally sure of the compatibility.

Here are a few samples, are they compatible with both the old and the new string type ? ( I'll use an imaginary STRING_UNICODE directive ).

  1. a Type definition:

    {$IFNDEF UNICODE_STRING}  
    TextBuffer = Array[0..13] Of Char;   
    {$ELSE}  
    TextBuffer = Array[0..13] Of WideChar;  
    {$ENDIF}
    

    Useless or not? Is the Char type (becomes what was) a WideChar before the Unicode String, or is there still a difference?

  2. a Function:

    Function RemoveBlanks(Text: String): String;  
    Var   
      i: integer;  
    Begin  
      result := '';  
      For i:= 0 To Length(Text) Do  
      Begin  
        {$IFNDEF UNICODE_STRING}   
        If Byte(Text[i]) < 21 Then Continue;   
        {$ELSE}  
        If Word(Text[i]) < 21 Then Continue;  
        {$ENDIF}  
        If Text[i] = ' ' Then Continue;    
        Result := Result + Text[i];  
      End;
    

    Is the Word() casting OK?

    Here there is also the ' ' problem. How is the space handled in Unicode version? Should I also use the directive to differentiate ' ' and ' ' or will the ' ' be automatically handled as a 2-byte blank?

  3. a line jump:

    NewLineBegin := CanReadText( aPTextBuffer, #13#10 );
    

    How is the the second argument (#13#10) interpreted in the Unicode version? Is it compatible? Will it be translated to the byte block 00130010? If not, then should the directive be used instead with the constant #0013#0010?

Upvotes: 1

Views: 451

Answers (3)

user422039
user422039

Reputation: 1458

Generic type Char becomes either fundamental type AnsiChar or fundamental type WideChar (read up on generic vs. fundamental types). BTW, there is UNICODE symbol $DEFINEd for you already, however there is no need to branch at all, until specific byte size is required.

Second part smells, scratch it completely. It is an abuse of typecasts and creates a need for conditional compilation artifically. To get unsigned integer character code of given Char use Ord() function instead (or as said in the other answer - use ordinal traits of Char type).

For the third part, character constants are of generic type Char already. Again, there is no need to worry about, #13 becomes either byte sized $0D or word sized $0D00 (remember about little endianess)

Upvotes: 1

Disillusioned
Disillusioned

Reputation: 14842

Compiler Directives

In general, I'd advise you to be very wary of compiler directives. They serve their purpose, but for general use, they should probably be avoided altogether.

The first problem is that you have to compile your app and test it twice, because it is fundamentally and/or subtly different for a directive on/off.

This situation get worse for each additional directive, because you usually have to permute the combinations:

D1 On, D2 On
D1 On, D2 Off
D1 Off, D2 On
D1 Off, D2 Off

3 directives is 8 permutations... etc.

Unicode Strings

Please see: Get ready for Delphi 2009 and up when developing with Delphi 7?
It has some nice answers for you to consider.

Question 1

As said, I advise against it. I also advise against for other reasons in my answer to the above mentioned question.

More specifically:

  • In Delphi <2009, both lines are different.
  • In Delphi >=2009 both lines are effectively the same.

Question 2

Not only is this ill advised for the same reasons as Question 1, but it actually has some subtle problems.

The more precise type of Text (String) is determined by your Delphi version. So:

  • In Delphi <2009, the else part of your conditional casts a single character to a Word. (Probably with no ill effect.)
  • In Delph >=2009, the if part of your conditional casts a double-byte character to a Byte. (With loss of information.)

Also, there are some special considerations, and new support classes for 'special' characters. You'll want to look into those. Refer to: How to identify unicode keys on key press?

Question 3

I'm pretty sure that #13 will be treated as a single character, so in Delphi >=2009 where Char == WideChar, that character will take up 2 bytes.

However, again look for Linebreak constants in Delphi. System.sLinebreak was probably introduced back in the Kylix days.

Upvotes: 1

David Heffernan
David Heffernan

Reputation: 613531

The first thing to do is read Marco Cantú's paper on Unicode: http://edn.embarcadero.com/article/38980

Question 1

Just use Char all the time with no conditional code and it will work in old and new.

Char is a special type that is an 8 bit type in old versions of Delphi and a 16 bit type in new Unicode versions.

Question 2

Char is an ordinal type so you can write if s[i]<#21.

You also need to start loops at 1 for strings since they use 1-based indexing.

Question 3

Writing #0013 is not needed, #13 is fine.

In short almost all well written code will need no changes.

Upvotes: 7

Related Questions