cwstring.pp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. procedure SetCWidestringManager;
  16. implementation
  17. {$linklib c}
  18. {$ifdef bsd}
  19. {$linklib iconv}
  20. {$endif bsd}
  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. {$ifdef linux}
  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. {$else linux}
  47. {$ifdef darwin}
  48. CODESET = 0;
  49. {$else darwin}
  50. {$error lookup the value of CODESET in /usr/include/langinfo.h for your OS }
  51. {$endif darwin}
  52. {$endif linux}
  53. { unicode encoding name }
  54. {$ifdef FPC_LITTLE_ENDIAN}
  55. unicode_encoding = 'UNICODELITTLE';
  56. {$else FPC_LITTLE_ENDIAN}
  57. unicode_encoding = 'UNICODEBIG';
  58. {$endif FPC_LITTLE_ENDIAN}
  59. type
  60. piconv_t = ^iconv_t;
  61. iconv_t = pointer;
  62. nl_item = longint;
  63. function nl_langinfo(__item:nl_item):pchar;cdecl;external;
  64. function iconv_open(__tocode:pchar; __fromcode:pchar):iconv_t;cdecl;external;
  65. function iconv(__cd:iconv_t; __inbuf:ppchar; __inbytesleft:psize_t; __outbuf:ppchar; __outbytesleft:psize_t):size_t;cdecl;external;
  66. function iconv_close(__cd:iconv_t):longint;cdecl;external;
  67. var
  68. iconv_ansi2wide,
  69. iconv_wide2ansi : iconv_t;
  70. procedure Wide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
  71. var
  72. outlength,
  73. outoffset,
  74. srclen,
  75. outleft : size_t;
  76. srcpos : pwidechar;
  77. destpos: pchar;
  78. mynil : pchar;
  79. my0 : size_t;
  80. begin
  81. mynil:=nil;
  82. my0:=0;
  83. { rought estimation }
  84. setlength(dest,len*3);
  85. outlength:=len*3;
  86. srclen:=len*2;
  87. srcpos:=source;
  88. destpos:=pchar(dest);
  89. outleft:=outlength;
  90. while iconv(iconv_wide2ansi,@srcpos,@srclen,@destpos,@outleft)=size_t(-1) do
  91. begin
  92. case fpgetCerrno of
  93. ESysEILSEQ:
  94. begin
  95. { skip and set to '?' }
  96. inc(srcpos);
  97. dec(srclen,2);
  98. destpos^:='?';
  99. inc(destpos);
  100. dec(outleft);
  101. { reset }
  102. iconv(iconv_wide2ansi,@mynil,@my0,@mynil,@my0);
  103. end;
  104. ESysE2BIG:
  105. begin
  106. outoffset:=destpos-pchar(dest);
  107. { extend }
  108. setlength(dest,outlength+len*3);
  109. inc(outleft,len*3);
  110. inc(outlength,len*3);
  111. { string could have been moved }
  112. destpos:=pchar(dest)+outoffset;
  113. end;
  114. else
  115. raise EConvertError.Create('iconv error');
  116. end;
  117. end;
  118. // truncate string
  119. setlength(dest,length(dest)-outleft);
  120. end;
  121. procedure Ansi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
  122. var
  123. outlength,
  124. outoffset,
  125. outleft : size_t;
  126. srcpos,
  127. destpos: pchar;
  128. mynil : pchar;
  129. my0 : size_t;
  130. begin
  131. mynil:=nil;
  132. my0:=0;
  133. // extra space
  134. outlength:=len+1;
  135. setlength(dest,outlength);
  136. outlength:=len+1;
  137. srcpos:=source;
  138. destpos:=pchar(dest);
  139. outleft:=outlength*2;
  140. while iconv(iconv_ansi2wide,@srcpos,@len,@destpos,@outleft)=size_t(-1) do
  141. begin
  142. case fpgetCerrno of
  143. ESysE2BIG:
  144. begin
  145. outoffset:=destpos-pchar(dest);
  146. { extend }
  147. setlength(dest,outlength+len);
  148. inc(outleft,len*2);
  149. inc(outlength,len);
  150. { string could have been moved }
  151. destpos:=pchar(dest)+outoffset;
  152. end;
  153. else
  154. raise EConvertError.Create('iconv error');
  155. end;
  156. end;
  157. // truncate string
  158. setlength(dest,length(dest)-outleft div 2);
  159. end;
  160. function LowerWideString(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(towlower(wint_t(s[i])));
  167. end;
  168. function UpperWideString(const s : WideString) : WideString;
  169. var
  170. i : SizeInt;
  171. begin
  172. SetLength(result,length(s));
  173. for i:=1 to length(s) do
  174. result[i]:=WideChar(towupper(wint_t(s[i])));
  175. end;
  176. function CompareWideString(const s1, s2 : WideString) : PtrInt;
  177. begin
  178. end;
  179. function CompareTextWideString(const s1, s2 : WideString): PtrInt;
  180. begin
  181. end;
  182. Var
  183. CWideStringManager : TWideStringManager;
  184. Procedure SetCWideStringManager;
  185. begin
  186. CWideStringManager:=widestringmanager;
  187. With CWideStringManager do
  188. begin
  189. Wide2AnsiMoveProc:=@Wide2AnsiMove;
  190. Ansi2WideMoveProc:=@Ansi2WideMove;
  191. UpperWideStringProc:=@UpperWideString;
  192. LowerWideStringProc:=@LowerWideString;
  193. {
  194. CompareWideStringProc
  195. CompareTextWideStringProc
  196. CharLengthPCharProc
  197. UpperAnsiStringProc
  198. LowerAnsiStringProc
  199. CompareStrAnsiStringProc
  200. CompareTextAnsiStringProc
  201. StrCompAnsiStringProc
  202. StrICompAnsiStringProc
  203. StrLCompAnsiStringProc
  204. StrLICompAnsiStringProc
  205. StrLowerAnsiStringProc
  206. StrUpperAnsiStringProc
  207. }
  208. end;
  209. SetWideStringManager(CWideStringManager);
  210. end;
  211. initialization
  212. SetCWideStringManager;
  213. { init conversion tables }
  214. iconv_wide2ansi:=iconv_open(nl_langinfo(CODESET),unicode_encoding);
  215. iconv_ansi2wide:=iconv_open(unicode_encoding,nl_langinfo(CODESET));
  216. finalization
  217. iconv_close(iconv_ansi2wide);
  218. end.