Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

224 Zeilen
6.5 KiB

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