cwstring.pp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2005 by Florian Klaempfl,
  4. member of the Free Pascal development team.
  5. libc based wide string support
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$mode objfpc}
  13. unit cwstring;
  14. interface
  15. {$ifdef HASWIDESTRING}
  16. procedure SetCWidestringManager;
  17. {$endif HASWIDESTRING}
  18. implementation
  19. {$ifdef HASWIDESTRING}
  20. {$linklib c}
  21. Uses
  22. BaseUnix,
  23. ctypes,
  24. unix,
  25. unixtype,
  26. sysutils,
  27. initc;
  28. { Case-mapping "arrays" }
  29. var
  30. AnsiUpperChars: AnsiString; // 1..255
  31. AnsiLowerChars: AnsiString; // 1..255
  32. WideUpperChars: WideString; // 1..65535
  33. WideLowerChars: WideString; // 1..65535
  34. { the following declarations are from the libc unit for linux so they
  35. might be very linux centric
  36. maybe this needs to be splitted in an os depend way later }
  37. function towlower(__wc:wint_t):wint_t;cdecl;external;
  38. function towupper(__wc:wint_t):wint_t;cdecl;external;
  39. function wcscoll(__s1:pwchar_t; __s2:pwchar_t):longint;cdecl;external;
  40. const
  41. __LC_CTYPE = 0;
  42. _NL_CTYPE_CLASS = (__LC_CTYPE shl 16);
  43. _NL_CTYPE_CODESET_NAME = (_NL_CTYPE_CLASS)+14;
  44. CODESET = _NL_CTYPE_CODESET_NAME;
  45. { unicode encoding name }
  46. {$ifdef FPC_LITTLE_ENDIAN}
  47. unicode_encoding = 'UNICODELITTLE';
  48. {$else FPC_LITTLE_ENDIAN}
  49. unicode_encoding = 'UNICODEBIG';
  50. {$endif FPC_LITTLE_ENDIAN}
  51. type
  52. piconv_t = ^iconv_t;
  53. iconv_t = pointer;
  54. nl_item = longint;
  55. function nl_langinfo(__item:nl_item):pchar;cdecl;external;
  56. function iconv_open(__tocode:pchar; __fromcode:pchar):iconv_t;cdecl;external;
  57. function iconv(__cd:iconv_t; __inbuf:ppchar; __inbytesleft:psize_t; __outbuf:ppchar; __outbytesleft:psize_t):size_t;cdecl;external;
  58. function iconv_close(__cd:iconv_t):longint;cdecl;external;
  59. var
  60. iconv_ansi2wide,
  61. iconv_wide2ansi : iconv_t;
  62. procedure Wide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
  63. var
  64. outlength,
  65. outoffset,
  66. srclen,
  67. outleft : size_t;
  68. srcpos : pwidechar;
  69. destpos: pchar;
  70. mynil : pchar;
  71. my0 : size_t;
  72. begin
  73. mynil:=nil;
  74. my0:=0;
  75. { rought estimation }
  76. setlength(dest,len*3);
  77. outlength:=len*3;
  78. srclen:=len*2;
  79. srcpos:=source;
  80. destpos:=pchar(dest);
  81. outleft:=outlength;
  82. while iconv(iconv_wide2ansi,@srcpos,@srclen,@destpos,@outleft)=size_t(-1) do
  83. begin
  84. case fpgetCerrno of
  85. ESysEILSEQ:
  86. begin
  87. { skip and set to '?' }
  88. inc(srcpos);
  89. dec(srclen,2);
  90. destpos^:='?';
  91. inc(destpos);
  92. dec(outleft);
  93. { reset }
  94. iconv(iconv_wide2ansi,@mynil,@my0,@mynil,@my0);
  95. end;
  96. ESysE2BIG:
  97. begin
  98. outoffset:=destpos-pchar(dest);
  99. { extend }
  100. setlength(dest,outlength+len*3);
  101. inc(outleft,len*3);
  102. inc(outlength,len*3);
  103. { string could have been moved }
  104. destpos:=pchar(dest)+outoffset;
  105. end;
  106. else
  107. raise EConvertError.Create('iconv error');
  108. end;
  109. end;
  110. // truncate string
  111. setlength(dest,length(dest)-outleft);
  112. end;
  113. procedure Ansi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
  114. var
  115. outlength,
  116. outoffset,
  117. outleft : size_t;
  118. srcpos,
  119. destpos: pchar;
  120. mynil : pchar;
  121. my0 : size_t;
  122. begin
  123. mynil:=nil;
  124. my0:=0;
  125. // extra space
  126. outlength:=len+1;
  127. setlength(dest,outlength);
  128. outlength:=len+1;
  129. srcpos:=source;
  130. destpos:=pchar(dest);
  131. outleft:=outlength*2;
  132. while iconv(iconv_ansi2wide,@srcpos,@len,@destpos,@outleft)=size_t(-1) do
  133. begin
  134. case fpgetCerrno of
  135. ESysE2BIG:
  136. begin
  137. outoffset:=destpos-pchar(dest);
  138. { extend }
  139. setlength(dest,outlength+len);
  140. inc(outleft,len*2);
  141. inc(outlength,len);
  142. { string could have been moved }
  143. destpos:=pchar(dest)+outoffset;
  144. end;
  145. else
  146. raise EConvertError.Create('iconv error');
  147. end;
  148. end;
  149. // truncate string
  150. setlength(dest,length(dest)-outleft div 2);
  151. end;
  152. function LowerWideString(const s : WideString) : WideString;
  153. var
  154. i : SizeInt;
  155. begin
  156. SetLength(result,length(s));
  157. for i:=1 to length(s) do
  158. result[i]:=WideChar(towlower(wint_t(s[i])));
  159. end;
  160. function UpperWideString(const s : WideString) : WideString;
  161. var
  162. i : SizeInt;
  163. begin
  164. SetLength(result,length(s));
  165. for i:=1 to length(s) do
  166. result[i]:=WideChar(towupper(wint_t(s[i])));
  167. end;
  168. function CompareWideString(const s1, s2 : WideString) : PtrInt;
  169. begin
  170. end;
  171. function CompareTextWideString(const s1, s2 : WideString): PtrInt;
  172. begin
  173. end;
  174. Var
  175. CWideStringManager : TWideStringManager;
  176. Procedure SetCWideStringManager;
  177. begin
  178. With CWideStringManager do
  179. begin
  180. Wide2AnsiMoveProc:=@Wide2AnsiMove;
  181. Ansi2WideMoveProc:=@Ansi2WideMove;
  182. UpperWideStringProc:=@UpperWideString;
  183. LowerWideStringProc:=@LowerWideString;
  184. {
  185. CompareWideStringProc
  186. CompareTextWideStringProc
  187. CharLengthPCharProc
  188. UpperAnsiStringProc
  189. LowerAnsiStringProc
  190. CompareStrAnsiStringProc
  191. CompareTextAnsiStringProc
  192. StrCompAnsiStringProc
  193. StrICompAnsiStringProc
  194. StrLCompAnsiStringProc
  195. StrLICompAnsiStringProc
  196. StrLowerAnsiStringProc
  197. StrUpperAnsiStringProc
  198. }
  199. end;
  200. SetWideStringManager(CWideStringManager);
  201. end;
  202. initialization
  203. SetCWideStringManager;
  204. { init conversion tables }
  205. iconv_wide2ansi:=iconv_open(nl_langinfo(CODESET),unicode_encoding);
  206. iconv_ansi2wide:=iconv_open(unicode_encoding,nl_langinfo(CODESET));
  207. finalization
  208. iconv_close(iconv_ansi2wide);
  209. end.
  210. {$endif HASWIDESTRING}