Explorar o código

* I've found that libc on Android does not implement widechar case functions such as towupper(). Such functions are just wrappers over regular char functions. Therefore the whole cwstring unit is useless for Android. For now I've added stub cwstring unit for Android and reverted all Android specific changes in unix/cwstring.pp. Later, Unicode manager for Androud should be implemented using libicuuc, which is default Android lib.

git-svn-id: branches/targetandroid@23301 -
yury %!s(int64=12) %!d(string=hai) anos
pai
achega
7322164c0a
Modificáronse 3 ficheiros con 291 adicións e 84 borrados
  1. 1 0
      .gitattributes
  2. 275 0
      rtl/android/cwstring.pp
  3. 15 84
      rtl/unix/cwstring.pp

+ 1 - 0
.gitattributes

@@ -7221,6 +7221,7 @@ rtl/android/Makefile svneol=native#text/plain
 rtl/android/Makefile.fpc svneol=native#text/plain
 rtl/android/arm/dllprt0.as svneol=native#text/plain
 rtl/android/arm/prt0.as svneol=native#text/plain
+rtl/android/cwstring.pp svneol=native#text/plain
 rtl/android/i386/dllprt0.as svneol=native#text/plain
 rtl/android/i386/prt0.as svneol=native#text/plain
 rtl/android/jvm/Makefile svneol=native#text/plain

+ 275 - 0
rtl/android/cwstring.pp

@@ -0,0 +1,275 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2013 by Yury Sidorov,
+    member of the Free Pascal development team.
+
+    Wide string support for Android
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ **********************************************************************}
+
+{$mode objfpc}
+{$inline on}
+{$implicitexceptions off}
+
+unit cwstring;
+
+interface
+
+procedure SetCWidestringManager;
+
+implementation
+
+procedure Wide2AnsiMove(source:pwidechar; var dest:RawByteString; cp:TSystemCodePage; len:SizeInt);
+var
+  i : SizeInt;
+  hs : RawByteString;
+begin
+  dest:='';
+  if len = 0 then
+    exit;
+  if (cp = CP_UTF8) or (cp = CP_ACP) then
+    begin
+      // Only UTF-8 is supported for Android
+      SetLength(hs,len*3);
+      i:=UnicodeToUtf8(pchar(hs),length(hs)+1,source,len);
+      if i > 0 then
+        begin
+          SetLength(hs,i-1);
+          dest:=hs;
+        end;
+    end
+  else
+    DefaultUnicode2AnsiMove(source,dest,DefaultSystemCodePage,len);
+end;
+
+procedure Ansi2WideMove(source:pchar; cp:TSystemCodePage; var dest:widestring; len:SizeInt);
+var
+  i : SizeInt;
+  hs : UnicodeString;
+begin
+  // Only UTF-8 is supported for Android
+  dest:='';
+  if len = 0 then
+    exit;
+  if (cp = CP_UTF8) or (cp = CP_ACP) then
+    begin
+      SetLength(hs,len);
+      i:=Utf8ToUnicode(PUnicodeChar(hs),length(hs)+1,pchar(source),len);
+      if i>0 then
+        begin
+          SetLength(hs,i-1);
+          dest:=hs;
+        end
+      else
+        dest:='';
+    end
+  else
+    DefaultAnsi2UnicodeMove(source,DefaultSystemCodePage,dest,len);
+end;
+
+function UpperWideString(const s : WideString) : WideString;
+begin
+  // Not implemented
+  Result:=UpCase(AnsiString(s));
+end;
+
+function LowerWideString(const s : WideString) : WideString;
+begin
+  // Not implemented
+  Result:=LowerCase(AnsiString(s));
+end;
+
+function _CompareStr(const S1, S2: ansistring): Integer;
+var count, count1, count2: integer;
+begin
+  result := 0;
+  Count1 := Length(S1);
+  Count2 := Length(S2);
+  if Count1>Count2 then
+    Count:=Count2
+  else
+    Count:=Count1;
+  result := CompareByte(PChar(S1)^,PChar(S2)^,Count);
+  if result=0 then
+    result:=Count1-Count2;
+end;
+
+function CompareWideString(const s1, s2 : WideString) : PtrInt;
+begin
+  // Not implemented
+  Result:=_CompareStr(s1, s2);
+end;
+
+function CompareTextWideString(const s1, s2 : WideString): PtrInt;
+begin
+  // Not implemented
+  Result:=_CompareStr(LowerCase(AnsiString(s1)), LowerCase(AnsiString(s2)));
+end;
+
+function UpperAnsiString(const s : AnsiString) : AnsiString;
+begin
+  // Not implemented
+  Result:=UpCase(s);
+end;
+
+function LowerAnsiString(const s : AnsiString) : AnsiString;
+begin
+  // Not implemented
+  Result:=LowerCase(s);
+end;
+
+function CharLengthPChar(const Str: PChar): PtrInt;
+begin
+  // Not implemented
+  Result:=Length(Str);
+end;
+
+function CodePointLength(const Str: PChar; maxlookahead: ptrint): PtrInt;
+begin
+  // Not implemented
+  Result:=Length(Str);
+end;
+
+function CompareStrAnsiString(const s1, s2: ansistring): PtrInt;
+begin
+  // Not implemented
+  Result:=_CompareStr(s1, s2);
+end;
+
+function StrCompAnsi(s1,s2 : PChar): PtrInt;
+begin
+  // Not implemented
+  Result:=_CompareStr(s1, s2);
+end;
+
+function AnsiCompareText(const S1, S2: ansistring): PtrInt;
+begin
+  // Not implemented
+  Result:=_CompareStr(LowerCase(s1), LowerCase(s2));
+end;
+
+function AnsiStrIComp(S1, S2: PChar): PtrInt;
+begin
+  // Not implemented
+  Result:=_CompareStr(LowerCase(s1), LowerCase(s2));
+end;
+
+function AnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
+begin
+  // Not implemented
+  Result:=_CompareStr(Copy(s1, 1, MaxLen), Copy(s2, 1, MaxLen));
+end;
+
+function AnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
+begin
+  // Not implemented
+  Result:=_CompareStr(LowerCase(Copy(s1, 1, MaxLen)), LowerCase(Copy(s2, 1, MaxLen)));
+end;
+
+function AnsiStrLower(Str: PChar): PChar;
+var
+  temp: ansistring;
+begin
+  // Not implemented
+  temp:=loweransistring(str);
+  Move(PChar(temp)^, Str, Length(temp));
+  Result:=Str;
+end;
+
+function AnsiStrUpper(Str: PChar): PChar;
+var
+  temp: ansistring;
+begin
+  // Not implemented
+  temp:=upperansistring(str);
+  Move(PChar(temp)^, Str, Length(temp));
+  Result:=Str;
+end;
+
+function GetStandardCodePage(const stdcp: TStandardCodePageEnum): TSystemCodePage;
+begin
+  Result := CP_UTF8; // Android has only UTF-8
+end;
+
+{$ifdef FPC_HAS_CPSTRING}
+{$i textrec.inc}
+procedure SetStdIOCodePage(var T: Text); inline;
+begin
+  case TextRec(T).Mode of
+    fmInput:TextRec(T).CodePage:=GetStandardCodePage(scpConsoleInput);
+    fmOutput:TextRec(T).CodePage:=GetStandardCodePage(scpConsoleOutput);
+  end;
+end;
+
+procedure SetStdIOCodePages; inline;
+begin
+  SetStdIOCodePage(Input);
+  SetStdIOCodePage(Output);
+  SetStdIOCodePage(ErrOutput);
+  SetStdIOCodePage(StdOut);
+  SetStdIOCodePage(StdErr);
+end;
+{$endif FPC_HAS_CPSTRING}
+
+Procedure SetCWideStringManager;
+Var
+  CWideStringManager : TUnicodeStringManager;
+begin
+  CWideStringManager:=widestringmanager;
+  With CWideStringManager do
+    begin
+      Wide2AnsiMoveProc:=@Wide2AnsiMove;
+      Ansi2WideMoveProc:=@Ansi2WideMove;
+
+      UpperWideStringProc:=@UpperWideString;
+      LowerWideStringProc:=@LowerWideString;
+
+      CompareWideStringProc:=@CompareWideString;
+      CompareTextWideStringProc:=@CompareTextWideString;
+
+      CharLengthPCharProc:=@CharLengthPChar;
+      CodePointLengthProc:=@CodePointLength;
+
+      UpperAnsiStringProc:=@UpperAnsiString;
+      LowerAnsiStringProc:=@LowerAnsiString;
+      CompareStrAnsiStringProc:=@CompareStrAnsiString;
+      CompareTextAnsiStringProc:=@AnsiCompareText;
+      StrCompAnsiStringProc:=@StrCompAnsi;
+      StrICompAnsiStringProc:=@AnsiStrIComp;
+      StrLCompAnsiStringProc:=@AnsiStrLComp;
+      StrLICompAnsiStringProc:=@AnsiStrLIComp;
+      StrLowerAnsiStringProc:=@AnsiStrLower;
+      StrUpperAnsiStringProc:=@AnsiStrUpper;
+      { Unicode }
+      Unicode2AnsiMoveProc:=@Wide2AnsiMove;
+      Ansi2UnicodeMoveProc:=@Ansi2WideMove;
+      UpperUnicodeStringProc:=@UpperWideString;
+      LowerUnicodeStringProc:=@LowerWideString;
+      CompareUnicodeStringProc:=@CompareWideString;
+      CompareTextUnicodeStringProc:=@CompareTextWideString;
+      { CodePage }
+      GetStandardCodePageProc:=@GetStandardCodePage;
+    end;
+  SetUnicodeStringManager(CWideStringManager);
+end;
+
+{$ifndef android}
+var
+  iconvlib:TLibHandle;
+{$endif android}
+
+initialization
+  SetCWideStringManager;
+  { set the DefaultSystemCodePage }
+  DefaultSystemCodePage:=GetStandardCodePage(scpAnsi);
+  SetStdIOCodePages;
+
+finalization
+
+end.

+ 15 - 84
rtl/unix/cwstring.pp

@@ -27,7 +27,7 @@ implementation
 
 {$linklib c}
 
-{$if not defined(linux) and not defined(solaris) and not defined(android)}  // Linux (and maybe glibc platforms in general), have iconv in glibc.
+{$if not defined(linux) and not defined(solaris)}  // Linux (and maybe glibc platforms in general), have iconv in glibc.
  {$if defined(haiku)}
    {$linklib textencoding}
    {$linklib locale}
@@ -81,18 +81,9 @@ function wctomb(s: pchar; wc: wchar_t): size_t; cdecl; external clib name 'wctom
 function mblen(const s: pchar; n: size_t): size_t; cdecl; external clib name 'mblen';
 {$endif beos}
 
-const
-{ en_US.UTF-8 needs maximally 6 chars, UCS-4/UTF-32 needs 4   }
-{ -> 10 should be enough? Should actually use MB_CUR_MAX, but }
-{ that's a libc macro mapped to internal functions/variables  }
-{ and thus not a stable external API on systems where libc    }
-{ breaks backwards compatibility every now and then           }
-  MB_CUR_MAX = 10;
-
-{$ifndef android} // There is no iconv on Android
 
 const
-{$if defined(linux) or defined(Android)}
+{$if defined(linux)}
   __LC_CTYPE = 0;
   LC_ALL = 6;
   _NL_CTYPE_CLASS = (__LC_CTYPE shl 16);
@@ -149,6 +140,13 @@ const
 {$endif AIX}
 {$endif  FPC_LITTLE_ENDIAN}
 
+{ en_US.UTF-8 needs maximally 6 chars, UCS-4/UTF-32 needs 4   }
+{ -> 10 should be enough? Should actually use MB_CUR_MAX, but }
+{ that's a libc macro mapped to internal functions/variables  }
+{ and thus not a stable external API on systems where libc    }
+{ breaks backwards compatibility every now and then           }
+  MB_CUR_MAX = 10;
+
 { Requests for iconvctl }
   ICONV_TRIVIALP          = 0; // int *argument
   ICONV_GET_TRANSLITERATE = 1; // int *argument
@@ -186,7 +184,10 @@ const
 {$endif}
 var 
   iconvctl:function(__cd:iconv_t; __request:cint; __argument:pointer):cint;cdecl;
-  
+
+procedure fpc_rangeerror; [external name 'FPC_RANGEERROR'];
+
+
 threadvar
   iconv_ansi2wide,
   iconv_wide2ansi : iconv_t;
@@ -198,6 +199,7 @@ threadvar
     threads }
   current_DefaultSystemCodePage: TSystemCodePage;
 
+
 {$i winiconv.inc}
 
 procedure InitThread;
@@ -496,60 +498,7 @@ procedure Ansi2WideMove(source:pchar; cp:TSystemCodePage; var dest:widestring; l
     if free_iconv then
       iconv_close(use_iconv);
   end;
-  
-{$else android}
 
-procedure Wide2AnsiMove(source:pwidechar; var dest:RawByteString; cp:TSystemCodePage; len:SizeInt);
-var
-  i : SizeInt;
-  hs : RawByteString;
-begin
-  dest:='';
-  if len = 0 then
-    exit;
-  if (cp = CP_UTF8) or (cp = CP_ACP) then
-    begin
-      // Only UTF-8 is supported for Android
-      SetLength(hs,len*3);
-      i:=UnicodeToUtf8(pchar(hs),length(hs)+1,source,len);
-      if i > 0 then
-        begin
-          SetLength(hs,i-1);
-          dest:=hs;
-        end;
-    end
-  else
-    DefaultUnicode2AnsiMove(source,dest,DefaultSystemCodePage,len);
-end;
-
-procedure Ansi2WideMove(source:pchar; cp:TSystemCodePage; var dest:widestring; len:SizeInt);
-var
-  i : SizeInt;
-  hs : UnicodeString;
-begin
-  // Only UTF-8 is supported for Android
-  dest:='';
-  if len = 0 then
-    exit;
-  if (cp = CP_UTF8) or (cp = CP_ACP) then
-    begin
-      SetLength(hs,len);
-      i:=Utf8ToUnicode(PUnicodeChar(hs),length(hs)+1,pchar(source),len);
-      if i>0 then
-        begin
-          SetLength(hs,i-1);
-          dest:=hs;
-        end
-      else
-        dest:='';
-    end
-  else
-    DefaultAnsi2UnicodeMove(source,DefaultSystemCodePage,dest,len);
-end;
-
-{$endif android}
-
-procedure fpc_rangeerror; [external name 'FPC_RANGEERROR'];
 
 function LowerWideString(const s : WideString) : WideString;
   var
@@ -1022,14 +971,9 @@ begin
 end;
 
 function GetStandardCodePage(const stdcp: TStandardCodePageEnum): TSystemCodePage;
-{$ifndef android}
 var
   langinfo: pchar;
-{$endif android}
 begin
-{$ifdef android}
-  Result := CP_UTF8; // Android has only UTF-8
-{$else}
   langinfo:=nl_langinfo(CODESET);
   { there's a bug in the Mac OS X 10.5 libc (based on FreeBSD's)
     that causes it to return an empty string of UTF-8 locales
@@ -1039,7 +983,6 @@ begin
      (langinfo^=#0) then
     langinfo:='UTF-8';
   Result := iconv2win(ansistring(langinfo));
-{$endif android}
 end;
 
 {$ifdef FPC_HAS_CPSTRING}
@@ -1091,13 +1034,8 @@ begin
       StrLICompAnsiStringProc:=@AnsiStrLIComp;
       StrLowerAnsiStringProc:=@AnsiStrLower;
       StrUpperAnsiStringProc:=@AnsiStrUpper;
-{$ifdef android}
-      ThreadInitProc:=nil;
-      ThreadFiniProc:=nil;
-{$else}
       ThreadInitProc:=@InitThread;
       ThreadFiniProc:=@FiniThread;
-{$endif android}
       { Unicode }
       Unicode2AnsiMoveProc:=@Wide2AnsiMove;
       Ansi2UnicodeMoveProc:=@Ansi2WideMove;
@@ -1111,14 +1049,12 @@ begin
   SetUnicodeStringManager(CWideStringManager);
 end;
 
-{$ifndef android}
 var
   iconvlib:TLibHandle;
-{$endif android}
 
 initialization
   SetCWideStringManager;
-{$ifndef android}
+
   { you have to call setlocale(LC_ALL,'') to initialise the langinfo stuff  }
   { with the information from the environment variables according to POSIX  }
   { (some OSes do this automatically, but e.g. Darwin and Solaris don't)    }
@@ -1128,7 +1064,6 @@ initialization
   iconvlib:=LoadLibrary(libprefix+libiconvname+'.'+SharedSuffix);
   if iconvlib<>0 then
     pointer(iconvctl):=GetProcAddress(iconvlib,iconvctlname);
-{$endif android}
 
   { set the DefaultSystemCodePage }
   DefaultSystemCodePage:=GetStandardCodePage(scpAnsi);
@@ -1137,16 +1072,12 @@ initialization
   SetStdIOCodePages;
   {$endif FPC_HAS_CPSTRING}
 
-{$ifndef android}
   { init conversion tables for main program }
   InitThread;
-{$endif android}
 finalization
-{$ifndef android}
   { fini conversion tables for main program }
   FiniThread;
   { unload iconv library }
   if iconvlib<>0 then
     FreeLibrary(iconvlib);
-{$endif android}
 end.