選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

232 行
6.6 KiB

  1. unit utsUtils;
  2. {$IFDEF FPC}
  3. {$mode delphi}{$H+}
  4. {$ENDIF}
  5. interface
  6. uses
  7. Classes, SysUtils, utsTypes;
  8. function tsStrAlloc(aSize: Cardinal): PWideChar;
  9. function tsStrNew(const aText: PWideChar): PWideChar;
  10. procedure tsStrDispose(const aText: PWideChar);
  11. function tsStrLength(aText: PWideChar): Cardinal;
  12. function tsStrCopy(aDst, aSrc: PWideChar): PWideChar;
  13. function tsAnsiToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar; const aCodePage: TtsCodePage; const aDefaultChar: WideChar): Integer;
  14. function tsISO_8859_1ToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar): Integer;
  15. function tsUTF8ToWide(aDst: PWideChar; const aSize: Integer; const aSrc: PAnsiChar; const aDefaultChar: WideChar): Integer;
  16. function tsUTFBE16ToWide(aDst: PWideChar; const aDstSize: Integer; aSrc: PByte; aSrcSize: Integer; const aDefaultChar: WideChar): Integer;
  17. function tsAnsiSBCDToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar; const aCodePage: TtsCodePage; const aDefaultChar: WideChar): Integer;
  18. implementation
  19. uses
  20. utsCodePages;
  21. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  22. function tsStrAlloc(aSize: Cardinal): PWideChar;
  23. begin
  24. aSize := (aSize + 1) shl 1;
  25. GetMem(result, aSize);
  26. FillChar(result^, aSize, 0);
  27. end;
  28. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  29. function tsStrNew(const aText: PWideChar): PWideChar;
  30. begin
  31. result := tsStrAlloc(tsStrLength(aText));
  32. tsStrCopy(result, aText);
  33. end;
  34. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  35. procedure tsStrDispose(const aText: PWideChar);
  36. begin
  37. FreeMem(aText);
  38. end;
  39. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  40. function tsStrLength(aText: PWideChar): Cardinal;
  41. begin
  42. result := 0;
  43. if Assigned(aText) then
  44. while (ord(aText^) <> 0) do begin
  45. inc(result);
  46. inc(aText);
  47. end;
  48. end;
  49. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  50. function tsStrCopy(aDst, aSrc: PWideChar): PWideChar;
  51. begin
  52. result := aDst;
  53. if Assigned(aDst) and Assigned(aSrc) then
  54. while ord(aSrc^) <> 0 do begin
  55. aDst^ := aSrc^;
  56. inc(aDst);
  57. inc(aSrc);
  58. end;
  59. end;
  60. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  61. function tsAnsiToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar;
  62. const aCodePage: TtsCodePage; const aDefaultChar: WideChar): Integer;
  63. begin
  64. result := 0;
  65. case aCodePage of
  66. tsUTF8:
  67. result := tsUTF8ToWide(aDst, aSize, aSrc, aDefaultChar);
  68. tsISO_8859_1:
  69. result := tsISO_8859_1ToWide(aDst, aSize, aSrc);
  70. else
  71. result := tsAnsiSBCDToWide(aDst, aSize, aSrc, aCodePage, aDefaultChar);
  72. end;
  73. end;
  74. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  75. function tsISO_8859_1ToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar): Integer;
  76. begin
  77. result := 0;
  78. if Assigned(aDst) and Assigned(aSrc) then
  79. while (ord(aSrc^) <> 0) and (result < aSize) do begin
  80. aDst^ := WideChar(aSrc^);
  81. inc(aDst);
  82. inc(aSrc);
  83. inc(result);
  84. end;
  85. end;
  86. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87. function tsUTF8ToWide(aDst: PWideChar; const aSize: Integer; const aSrc: PAnsiChar; const aDefaultChar: WideChar): Integer;
  88. procedure AddToDest(aCharCode: UInt64);
  89. begin
  90. if (aCharCode > $FFFF) then
  91. aCharCode := ord(aDefaultChar);
  92. PWord(aDst)^ := aCharCode;
  93. inc(aDst);
  94. result := result + 1;
  95. end;
  96. const
  97. STATE_STARTBYTE = 0;
  98. STATE_FOLLOWBYTE = 1;
  99. var
  100. cc: UInt64;
  101. len, state, c: Integer;
  102. p: PByte;
  103. tmp: Byte;
  104. begin
  105. result := 0;
  106. if not Assigned(aDst) or not Assigned(aSrc) or (aSize <= 0) then
  107. exit;
  108. c := 0;
  109. cc := 0;
  110. p := PByte(aSrc);
  111. len := Length(aSrc);
  112. state := STATE_STARTBYTE;
  113. while (len > 0) do begin
  114. case state of
  115. STATE_STARTBYTE: begin
  116. if (p^ and $80 = 0) then begin
  117. AddToDest(p^);
  118. end else if (p^ and $40 > 0) then begin
  119. tmp := p^;
  120. c := 0;
  121. while (tmp and $80) > 0 do begin
  122. inc(c);
  123. tmp := tmp shl 1;
  124. end;
  125. cc := p^ and ((1 shl (7 - c)) - 1);
  126. state := STATE_FOLLOWBYTE;
  127. c := c - 1;
  128. end;
  129. end;
  130. STATE_FOLLOWBYTE: begin
  131. if ((p^ and $C0) = $80) then begin
  132. cc := (cc shl 6) or (p^ and $3F);
  133. c := c - 1;
  134. if (c = 0) then begin
  135. AddToDest(cc);
  136. state := STATE_STARTBYTE;
  137. end;
  138. end else
  139. state := STATE_STARTBYTE;
  140. end;
  141. end;
  142. if (result >= aSize) then
  143. exit;
  144. inc(p);
  145. end;
  146. end;
  147. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  148. function tsUTFBE16ToWide(aDst: PWideChar; const aDstSize: Integer; aSrc: PByte; aSrcSize: Integer;
  149. const aDefaultChar: WideChar): Integer;
  150. var
  151. tmp: Word;
  152. procedure AddToDest(aCharCode: Word);
  153. begin
  154. if ((aCharCode and $D800) = $D800) or
  155. ((aCharCode and $DC00) = $DC00) then
  156. aCharCode := Ord(aDefaultChar);
  157. aDst^ := WideChar(aCharCode);
  158. inc(aDst, 1);
  159. result := result + 1;
  160. end;
  161. begin
  162. result := 0;
  163. while (aSrcSize > 1) and (aDstSize > 0) do begin
  164. {$IFDEF FPC}
  165. tmp := (aSrc^ shl 8) or (aSrc + 1)^;
  166. {$ELSE}
  167. tmp := (PByteArray(aSrc)[0] shl 8) or PByteArray(aSrc)[1];
  168. {$ENDIF}
  169. inc(aSrc, 2);
  170. dec(aSrcSize, 2);
  171. AddToDest(tmp);
  172. end;
  173. end;
  174. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  175. function tsAnsiSBCDToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar;
  176. const aCodePage: TtsCodePage; const aDefaultChar: WideChar): Integer;
  177. var
  178. tmp: WideChar;
  179. cp: PtsCodePageValues;
  180. begin
  181. result := 0;
  182. cp := ANSI_TO_WIDE_CODE_PAGE_LUT[aCodePage];
  183. if not Assigned(aDst) or
  184. not Assigned(aSrc) or
  185. not Assigned(cp) or
  186. (aSize < 0) then exit;
  187. while (Ord(aSrc^) <> 0) and (result < aSize) do begin
  188. tmp := WideChar(cp^[aSrc^]);
  189. if (ord(tmp) = 0) then begin
  190. if (ord(aDefaultChar) <> 0) then begin
  191. aDst^ := aDefaultChar;
  192. inc(aDst);
  193. end;
  194. end else begin
  195. aDst^ := tmp;
  196. inc(aDst);
  197. end;
  198. inc(aSrc);
  199. end;
  200. end;
  201. end.