Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

145 linhas
3.9 KiB

  1. unit utsUtils;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils;
  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 tsISO_8859_1ToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar): Integer;
  12. function tsUTF8ToWide(aDst: PWideChar; const aSize: Integer; const aSrc: PAnsiChar; const aDefaultChar: WideChar): Integer;
  13. implementation
  14. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  15. function tsStrAlloc(aSize: Cardinal): PWideChar;
  16. begin
  17. aSize := (aSize + 1) shl 1;
  18. GetMem(result, aSize);
  19. FillChar(result^, aSize, 0);
  20. end;
  21. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  22. function tsStrNew(const aText: PWideChar): PWideChar;
  23. begin
  24. result := tsStrAlloc(tsStrLength(aText));
  25. tsStrCopy(result, aText);
  26. end;
  27. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  28. procedure tsStrDispose(const aText: PWideChar);
  29. begin
  30. FreeMem(aText);
  31. end;
  32. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  33. function tsStrLength(aText: PWideChar): Cardinal;
  34. begin
  35. result := 0;
  36. if Assigned(aText) then
  37. while (ord(aText^) <> 0) do begin
  38. inc(result);
  39. inc(aText);
  40. end;
  41. end;
  42. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  43. function tsStrCopy(aDst, aSrc: PWideChar): PWideChar;
  44. begin
  45. result := aDst;
  46. if Assigned(aDst) and Assigned(aSrc) then
  47. while ord(aSrc^) <> 0 do begin
  48. aDst^ := aSrc^;
  49. inc(aDst);
  50. inc(aSrc);
  51. end;
  52. end;
  53. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  54. function tsISO_8859_1ToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar): Integer;
  55. begin
  56. result := 0;
  57. if Assigned(aDst) and Assigned(aSrc) then
  58. while (ord(aSrc^) <> 0) do begin
  59. aDst^ := WideChar(aSrc^);
  60. inc(aDst);
  61. inc(aSrc);
  62. inc(result);
  63. end;
  64. end;
  65. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  66. function tsUTF8ToWide(aDst: PWideChar; const aSize: Integer; const aSrc: PAnsiChar; const aDefaultChar: WideChar): Integer;
  67. procedure AddToDest(aCharCode: UInt64);
  68. begin
  69. if (aCharCode > $FFFF) then
  70. aCharCode := ord(aDefaultChar);
  71. PWord(aDst)^ := aCharCode;
  72. inc(aDst);
  73. result := result + 1;
  74. end;
  75. const
  76. STATE_STARTBYTE = 0;
  77. STATE_FOLLOWBYTE = 1;
  78. var
  79. cc: QWord;
  80. len, state, c: Integer;
  81. p: PByte;
  82. tmp: Byte;
  83. begin
  84. result := 0;
  85. if not Assigned(aDst) or not Assigned(aSrc) or (aSize <= 0) then
  86. exit;
  87. p := PByte(aSrc);
  88. len := Length(aSrc);
  89. state := STATE_STARTBYTE;
  90. while (len > 0) do begin
  91. case state of
  92. STATE_STARTBYTE: begin
  93. if (p^ and %10000000 = 0) then begin
  94. AddToDest(p^);
  95. end else if (p^ and %01000000 > 0) then begin
  96. tmp := p^;
  97. c := 0;
  98. while (tmp and %10000000) > 0 do begin
  99. inc(c);
  100. tmp := tmp shl 1;
  101. end;
  102. cc := p^ and ((1 shl (7 - c)) - 1);
  103. state := STATE_FOLLOWBYTE;
  104. c := c - 1;
  105. end;
  106. end;
  107. STATE_FOLLOWBYTE: begin
  108. if ((p^ and %11000000) = %10000000) then begin
  109. cc := (cc shl 6) or (p^ and %00111111);
  110. c := c - 1;
  111. if (c = 0) then begin
  112. AddToDest(cc);
  113. state := STATE_STARTBYTE;
  114. end;
  115. end else
  116. state := STATE_STARTBYTE;
  117. end;
  118. end;
  119. if (result >= aSize) then
  120. exit;
  121. inc(p);
  122. end;
  123. end;
  124. end.