cwstring.pp 5.9 KB

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