Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2013-12

How to know the string type of a variable?

16 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Marcos Douglas

Hi,

Is possible to know what string type of a variable (AnsiString, UTF8String, RawByteString, etc)?

Eg:

=== BEGIN ===
procedure foo(s: string);
begin
  // if S is AnsiString then do something;
  // if S is UTF8String then do something;
end;
var
  AStr: AnsiString;
  U8Str: UTF8String;
foo(AStr);
foo(U8Str);

=== END ===

Regards,
Marcos Douglas

Michael Van Canneyt
to Marcos Douglas
Marcos Douglas wrote
Hi, Is possible to know what string type of a variable (AnsiString, UTF8String, RawByteString, etc)?

You can try

if TypeInfo(S)=TypeInfo(AnsiString) then

etc.

The following program

procedure t(S : String);
begin
   if typeinfo(s)=typeinfo(shortstring) then
     Writeln('ShortString')
   else
     Writeln('Ansistring');
end;
begin
   t('');
end.

Prints
ShortString
if compiled as-is (fpc mode), and prints
AnsiString
if compiled with -S2h (objfpc mode, string=ansistring)

Michael.

Marcos Douglas
to Michael Van Canneyt
Michael Van Canneyt wrote 32 lines
On Mon, 30 Dec 2013, Marcos Douglas wrote: > Hi, > > Is possible to know what string type of a variable (AnsiString, > UTF8String, RawByteString, etc)? You can try if TypeInfo(S)=TypeInfo(AnsiString) then etc. The following program procedure t(S : String); begin if typeinfo(s)=typeinfo(shortstring) then Writeln('ShortString') else Writeln('Ansistring'); end; begin t(''); end. Prints ShortString if compiled as-is (fpc mode), and prints AnsiString if compiled with -S2h (objfpc mode, string=ansistring)

TypeInfo!
I was trying using "type(s)", "s is AnsiString"... I forgot.

Thank you.

Marcos Douglas

Marcos Douglas
to Marcos Douglas: On Mon, Dec 30, 2013 at 9:41 AM, Michael Van Canneyt TypeInfo! I was trying using…
Marcos Douglas wrote 39 lines
On Mon, Dec 30, 2013 at 9:41 AM, Michael Van Canneyt wrote: > > > On Mon, 30 Dec 2013, Marcos Douglas wrote: > >> Hi, >> >> Is possible to know what string type of a variable (AnsiString, >> UTF8String, RawByteString, etc)? > > > You can try > > if TypeInfo(S)=TypeInfo(AnsiString) then > > etc. > > The following program > > procedure t(S : String); > > begin > if typeinfo(s)=typeinfo(shortstring) then > Writeln('ShortString') > else > Writeln('Ansistring'); end; > > begin > t(''); > end. > > Prints ShortString if compiled as-is (fpc mode), and prints AnsiString if > compiled with -S2h (objfpc mode, string=ansistring) TypeInfo! I was trying using "type(s)", "s is AnsiString"... I forgot. Thank you.

Well, didn't worked as I wanted.
For example, I know UTF8String is an AnsiString but the TypeInfo should catch UTF8String not AnsiString, doesn't?

See the code bellow:

=== BEGIN ===
procedure TForm1.Button1Click(Sender: TObject);
var
  AStr: AnsiString;
  U8Str: UTF8String;
  UniStr: UnicodeString;
  function  ShowType(S: string): string;
  begin
    if TypeInfo(S) = TypeInfo(AnsiString) then
      ShowMessage('AnsiString')
    else if TypeInfo(S) = TypeInfo(UTF8String) then
      ShowMessage('UTF8String')
    else if TypeInfo(S) = TypeInfo(UnicodeString) then
      ShowMessage('UnicodeString')
  end;
begin
  AStr := 'ábçdé';
  U8Str := 'ábçdé';
  UniStr := 'ábçdé';
  ShowType(AStr);
  ShowType(U8Str);
  ShowType(UniStr);
end;

=== END ===

The result is:
AnsiString
AnsiString
AnsiString

Regards,
Marcos Douglas

Michael Van Canneyt
to Marcos Douglas
Marcos Douglas wrote 44 lines
On Mon, Dec 30, 2013 at 9:48 AM, Marcos Douglas wrote: > On Mon, Dec 30, 2013 at 9:41 AM, Michael Van Canneyt > wrote: >> >> >> On Mon, 30 Dec 2013, Marcos Douglas wrote: >> >>> Hi, >>> >>> Is possible to know what string type of a variable (AnsiString, >>> UTF8String, RawByteString, etc)? >> >> >> You can try >> >> if TypeInfo(S)=TypeInfo(AnsiString) then >> >> etc. >> >> The following program >> >> procedure t(S : String); >> >> begin >> if typeinfo(s)=typeinfo(shortstring) then >> Writeln('ShortString') >> else >> Writeln('Ansistring'); end; >> >> begin >> t(''); >> end. >> >> Prints ShortString if compiled as-is (fpc mode), and prints AnsiString if >> compiled with -S2h (objfpc mode, string=ansistring) > > TypeInfo! > I was trying using "type(s)", "s is AnsiString"... I forgot. > > Thank you. Well, didn't worked as I wanted. For example, I know UTF8String is an AnsiString but the TypeInfo should catch UTF8String not AnsiString, doesn't?

No. You make a wrong assumption.

TypeInfo will return the DECLARED type of S.

Not the type that was actually passed when calling the routine: That has been converted to the declared type of S by the compiler even before the routine ShowType is called.

Michael.

Show quoted text 43 lines
See the code bellow: === BEGIN === procedure TForm1.Button1Click(Sender: TObject); var AStr: AnsiString; U8Str: UTF8String; UniStr: UnicodeString; function ShowType(S: string): string; begin if TypeInfo(S) = TypeInfo(AnsiString) then ShowMessage('AnsiString') else if TypeInfo(S) = TypeInfo(UTF8String) then ShowMessage('UTF8String') else if TypeInfo(S) = TypeInfo(UnicodeString) then ShowMessage('UnicodeString') end; begin AStr := 'ábçdé'; U8Str := 'ábçdé'; UniStr := 'ábçdé'; ShowType(AStr); ShowType(U8Str); ShowType(UniStr); end; === END === The result is: AnsiString AnsiString AnsiString Regards, Marcos Douglas _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Marcos Douglas
to Michael Van Canneyt
Michael Van Canneyt wrote 26 lines
On Mon, 30 Dec 2013, Marcos Douglas wrote: > On Mon, Dec 30, 2013 at 9:48 AM, Marcos Douglas wrote: >> >> On Mon, Dec 30, 2013 at 9:41 AM, Michael Van Canneyt >> wrote: >>> >>> >>> On Mon, 30 Dec 2013, Marcos Douglas wrote: >>> >>>> [...] > > Well, didn't worked as I wanted. > For example, I know UTF8String is an AnsiString but the TypeInfo > should catch UTF8String not AnsiString, doesn't? No. You make a wrong assumption. TypeInfo will return the DECLARED type of S. Not the type that was actually passed when calling the routine: That has been converted to the declared type of S by the compiler even before the routine ShowType is called.

You're right.
Well is there another way to do I showed before?
I want to create a record/object type to receive a "string" but I need to know which string type was before.

If I change the code (see below) to use Pointer type it works but I think this is won't help me.

=== BEGIN ===
procedure TForm1.Button1Click(Sender: TObject);
var
  AStr: AnsiString;
  U8Str: UTF8String;
  UniStr: UnicodeString;
  function ShowType(P: Pointer): string;
  begin
    if P = TypeInfo(AnsiString) then
      ShowMessage('AnsiString')
    else if P = TypeInfo(UTF8String) then
      ShowMessage('UTF8String')
    else if P = TypeInfo(UnicodeString) then
      ShowMessage('UnicodeString')
  end;
begin
  ShowType(TypeInfo(AStr));
  ShowType(TypeInfo(U8Str));
  ShowType(TypeInfo(UniStr));
end;
=== END ===

Regards,
Marcos Douglas

Michael Van Canneyt
to Marcos Douglas
Show quoted text 12 lines
> No. You make a wrong assumption. > > TypeInfo will return the DECLARED type of S. > > Not the type that was actually passed when calling the routine: > That has been converted to the declared type of S by the compiler even > before the routine ShowType is called. You're right. Well is there another way to do I showed before? I want to create a record/object type to receive a "string" but I need to know which string type was before.

There is no way.

If I change the code (see below) to use Pointer type it works but I think this is won't help me.

No, it will not help you.

One thing you can do is use overloading:

TStringType = (stAnsi,stUnicode,stUTF8);
Procedure DoSomeStringOperation(S : Pointer; AStringType : TStringType);
begin
   // Whatever
end;
Procedure DoSomeStringOperation(S : Ansistring);
begin
   DoSomeStringOperation(Pointer(S),stAnsi);
end;
Procedure DoSomeStringOperation(S : UnicodeString);
begin
   DoSomeStringOperation(Pointer(S),stUnicode);
end;
Procedure DoSomeStringOperation(S : UTF8String);
begin
   DoSomeStringOperation(Pointer(S),stUTF8);
end.

The compiler will choose the correct overloaded version, and you will know which one she picked.

But it would help to know what exactly you want to achieve.

Michael.

Marcos Douglas
to Michael Van Canneyt
Michael Van Canneyt wrote 26 lines
>> No. You make a wrong assumption. >> >> TypeInfo will return the DECLARED type of S. >> >> Not the type that was actually passed when calling the routine: >> That has been converted to the declared type of S by the compiler even >> before the routine ShowType is called. > > > You're right. > Well is there another way to do I showed before? > I want to create a record/object type to receive a "string" but I need > to know which string type was before. There is no way. > > If I change the code (see below) to use Pointer type it works but I > think this is won't help me. No, it will not help you.

Yes... Well, I was trying the easy way but not possible. :-)

Show quoted text 8 lines
One thing you can do is use overloading: [code] The compiler will choose the correct overloaded version, and you will know which one she picked. But it would help to know what exactly you want to achieve.

I had some ideas looking at your code. Thank you.

Regards,
Marcos Douglas

Marcos Douglas
to Juha Manninen
Juha Manninen wrote 12 lines
On Mon, Dec 30, 2013 at 2:35 PM, Marcos Douglas wrote: > Is possible to know what string type of a variable (AnsiString, > UTF8String, RawByteString, etc)? When UTF-8 encoded string is stored in AnsiString (as in LCL), this test should tell you if it actually is UTF-8 string: if Length(s) UTF8Length(s) then begin // UTF-8 end; It should allow a mixture of ansi- and UTF-8 strings in your data.

That is a good tip.
LazUTF8 unit have the IsASCII function (not public) too.

Thanks,
Marcos Douglas

Mattias Gaertner
to Juha Manninen: When UTF-8 encoded string is stored in AnsiString (as in LCL), this test should tell you…
Show quoted text 10 lines
On Mon, Dec 30, 2013 at 2:35 PM, Marcos Douglas wrote: > Is possible to know what string type of a variable (AnsiString, > UTF8String, RawByteString, etc)? When UTF-8 encoded string is stored in AnsiString (as in LCL), this test should tell you if it actually is UTF-8 string: if Length(s) UTF8Length(s) then begin // UTF-8 end;

This is wrong.
There is no test for UTF-8 versus 8-bit windows codepage. A good heuristic is this:

if FindInvalidUTF8Character(PChar(Pointer(s)),length(s))<0 then
  // UTF-8

Mattias

Ralf Quint
to Marco van de Voort: In our previous episode, Michael Van Canneyt said: Thank you, I saved it to my obfuscated…
Marco van de Voort wrote 15 lines
In our previous episode, Michael Van Canneyt said: > procedure t(S : String); > > begin > if typeinfo(s)=typeinfo(shortstring) then > Writeln('ShortString') > else > Writeln('Ansistring'); > end; > > begin > t(''); > end. Thank you, I saved it to my obfuscated Pascal mailfolder :-)

Yup, tagged this as "intersting" in my mail folder as well... 8-)

Hope that some little gem like this will make it somehow into the FPC documentation...

Ralf

---
This email is free from viruses and malware because avast! Antivirus protection is active. http://www.avast.com

Michael Van Canneyt
to Juha Manninen
Juha Manninen wrote 8 lines
On Mon, Dec 30, 2013 at 9:17 PM, Mattias Gaertner wrote: > if FindInvalidUTF8Character(PChar(Pointer(s)),length(s))<0 then > // UTF-8 Uhhh! I will be totally screwed when I must do a unicode conversion myself. What was this "PChar(Pointer(s))" again? PChar is a pointer, why does it need a double cast?

Pchar(Ansistring) has some special compiler treatment.

If you omit the double cast, pchar(S) will point to a #0 character for an empty string. If you include the double cast, PChar(Pointer(s)) is Nil for an empty string.

Michael.

Jürgen Hestermann
to Mattias Gaertner: On Mon, 30 Dec 2013 19:19:20 +0200 This is wrong. There is no test for UTF-8 versus 8-bit…
Mattias Gaertner wrote 16 lines
On Mon, 30 Dec 2013 19:19:20 +0200 Juha Manninen wrote: > On Mon, Dec 30, 2013 at 2:35 PM, Marcos Douglas wrote: >> Is possible to know what string type of a variable (AnsiString, >> UTF8String, RawByteString, etc)? > When UTF-8 encoded string is stored in AnsiString (as in LCL), this > test should tell you if it actually is UTF-8 string: > if Length(s) UTF8Length(s) then > begin > // UTF-8 > end; This is wrong. There is no test for UTF-8 versus 8-bit windows codepage. A good heuristic is this: if FindInvalidUTF8Character(PChar(Pointer(s)),length(s))<0 then // UTF-8

But as you wrote:
It is a heuristic.
It may fail.

I am beginning to realize why software is so buggy nowadays if it has to be based on heuristics...