cwstring.pp 6.5 KB

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