sysencoding.inc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. {
  2. *********************************************************************
  3. Copyright (C) 2012 Paul Ishenin,
  4. member of the Free Pascal Development Team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. *********************************************************************
  11. }
  12. {$ifndef VER2_4}
  13. { TEncoding }
  14. class function TEncoding.GetANSI: TEncoding;
  15. begin
  16. EnterCriticalSection(FLock);
  17. try
  18. if not Assigned(FStandardEncodings[seAnsi]) then
  19. FStandardEncodings[seAnsi] := TMBCSEncoding.Create(DefaultSystemCodePage);
  20. finally
  21. LeaveCriticalSection(FLock);
  22. end;
  23. Result := FStandardEncodings[seAnsi];
  24. end;
  25. function TEncoding.GetAnsiBytes(const S: string): TBytes;
  26. begin
  27. Result := GetAnsiBytes(S, 1, Length(S));
  28. end;
  29. function TEncoding.GetAnsiBytes(const S: string; CharIndex, CharCount: Integer
  30. ): TBytes;
  31. begin
  32. Result := GetAnsiBytes(Pointer(@S[CharIndex]), CharCount);
  33. end;
  34. function TEncoding.GetAnsiString(const Bytes: TBytes): string;
  35. begin
  36. Result := GetAnsiString(Bytes, 0, Length(Bytes));
  37. end;
  38. function TEncoding.GetAnsiString(const Bytes: TBytes; ByteIndex,
  39. ByteCount: Integer): string;
  40. begin
  41. Result := GetAnsiString(Pointer(@Bytes[ByteIndex]), ByteCount);
  42. SetCodePage(RawByteString(Result), DefaultSystemCodePage, False);
  43. end;
  44. class function TEncoding.GetASCII: TEncoding;
  45. begin
  46. EnterCriticalSection(FLock);
  47. try
  48. if not Assigned(FStandardEncodings[seAscii]) then
  49. FStandardEncodings[seAscii] := TMBCSEncoding.Create(CP_ASCII);
  50. finally
  51. LeaveCriticalSection(FLock);
  52. end;
  53. Result := FStandardEncodings[seAscii];
  54. end;
  55. class function TEncoding.GetBigEndianUnicode: TEncoding;
  56. begin
  57. EnterCriticalSection(FLock);
  58. try
  59. if not Assigned(FStandardEncodings[seBigEndianUnicode]) then
  60. FStandardEncodings[seBigEndianUnicode] := TBigEndianUnicodeEncoding.Create;
  61. finally
  62. LeaveCriticalSection(FLock);
  63. end;
  64. Result := FStandardEncodings[seBigEndianUnicode];
  65. end;
  66. class function TEncoding.GetDefault: TEncoding;
  67. begin
  68. Result := GetANSI;
  69. end;
  70. class function TEncoding.GetUnicode: TEncoding;
  71. begin
  72. EnterCriticalSection(FLock);
  73. try
  74. if not Assigned(FStandardEncodings[seUnicode]) then
  75. FStandardEncodings[seUnicode] := TUnicodeEncoding.Create;
  76. finally
  77. LeaveCriticalSection(FLock);
  78. end;
  79. Result := FStandardEncodings[seUnicode];
  80. end;
  81. class function TEncoding.GetUTF7: TEncoding;
  82. begin
  83. EnterCriticalSection(FLock);
  84. try
  85. if not Assigned(FStandardEncodings[seUTF7]) then
  86. FStandardEncodings[seUTF7] := TUTF7Encoding.Create;
  87. finally
  88. LeaveCriticalSection(FLock);
  89. end;
  90. Result := FStandardEncodings[seUTF7];
  91. end;
  92. class function TEncoding.GetUTF8: TEncoding;
  93. begin
  94. EnterCriticalSection(FLock);
  95. try
  96. if not Assigned(FStandardEncodings[seUTF8]) then
  97. FStandardEncodings[seUTF8] := TUTF8Encoding.Create;
  98. finally
  99. LeaveCriticalSection(FLock);
  100. end;
  101. Result := FStandardEncodings[seUTF8];
  102. end;
  103. class procedure TEncoding.FreeEncodings;
  104. var
  105. E: TStandardEncoding;
  106. begin
  107. EnterCriticalSection(FLock);
  108. try
  109. for E := Low(FStandardEncodings) to High(FStandardEncodings) do
  110. FStandardEncodings[E].Free;
  111. finally
  112. LeaveCriticalSection(FLock);
  113. end;
  114. end;
  115. class constructor TEncoding.Create;
  116. var
  117. E: TStandardEncoding;
  118. begin
  119. for E := Low(FStandardEncodings) to High(FStandardEncodings) do
  120. FStandardEncodings[E] := nil;
  121. InitCriticalSection(FLock);
  122. end;
  123. class destructor TEncoding.Destroy;
  124. begin
  125. FreeEncodings;
  126. DoneCriticalSection(FLock);
  127. end;
  128. function TEncoding.Clone: TEncoding;
  129. begin
  130. Result := nil;
  131. end;
  132. class function TEncoding.Convert(Source, Destination: TEncoding;
  133. const Bytes: TBytes): TBytes;
  134. begin
  135. Result := Destination.GetBytes(Source.GetChars(Bytes));
  136. end;
  137. class function TEncoding.Convert(Source, Destination: TEncoding;
  138. const Bytes: TBytes; StartIndex, Count: Integer): TBytes;
  139. begin
  140. Result := Destination.GetBytes(Source.GetChars(Bytes, StartIndex, Count));
  141. end;
  142. class function TEncoding.IsStandardEncoding(AEncoding: TEncoding): Boolean;
  143. var
  144. Encoding: TEncoding;
  145. begin
  146. if Assigned(AEncoding) then
  147. for Encoding in FStandardEncodings do
  148. if Encoding = AEncoding then
  149. Exit(True);
  150. Result := False;
  151. end;
  152. class function TEncoding.GetBufferEncoding(const Buffer: TBytes; var AEncoding: TEncoding): Integer;
  153. begin
  154. Result := GetBufferEncoding(Buffer, AEncoding, Default);
  155. end;
  156. class function TEncoding.GetBufferEncoding(const Buffer: TBytes;
  157. var AEncoding: TEncoding; ADefaultEncoding: TEncoding): Integer;
  158. function CheckEncoding(AEncoding: TEncoding; out ByteCount: Integer): Boolean;
  159. var
  160. Preamble: TBytes;
  161. begin
  162. Preamble := AEncoding.GetPreamble;
  163. ByteCount := Length(Preamble);
  164. Result := (Length(Buffer) >= ByteCount) and (ByteCount > 0);
  165. if Result then
  166. Result := CompareMem(@Preamble[0], @Buffer[0], ByteCount);
  167. end;
  168. begin
  169. if Assigned(AEncoding) then
  170. begin
  171. if not CheckEncoding(AEncoding, Result) then
  172. Result := 0;
  173. end
  174. else
  175. if CheckEncoding(Unicode, Result) then
  176. AEncoding := Unicode
  177. else
  178. if CheckEncoding(BigEndianUnicode, Result) then
  179. AEncoding := BigEndianUnicode
  180. else
  181. if CheckEncoding(UTF8, Result) then
  182. AEncoding := UTF8
  183. else
  184. begin
  185. AEncoding := ADefaultEncoding;
  186. Result := 0;
  187. end;
  188. end;
  189. function TEncoding.GetByteCount(const Chars: TUnicodeCharArray): Integer;
  190. begin
  191. Result := GetByteCount(Chars, 0, Length(Chars));
  192. end;
  193. function TEncoding.GetByteCount(const Chars: TUnicodeCharArray; CharIndex,
  194. CharCount: Integer): Integer;
  195. begin
  196. if (CharCount < 0) or (Length(Chars) < CharCount + CharIndex) then
  197. raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
  198. if (CharIndex < 0) then
  199. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  200. Result := GetByteCount(@Chars[CharIndex], CharCount);
  201. end;
  202. function TEncoding.GetByteCount(const S: UnicodeString): Integer;
  203. begin
  204. Result := GetByteCount(PUnicodeChar(S), Length(S));
  205. end;
  206. function TEncoding.GetByteCount(const S: UnicodeString; CharIndex, CharCount: Integer): Integer;
  207. begin
  208. if (CharCount < 0) or (Length(S) < CharCount + CharIndex) then
  209. raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
  210. if (CharIndex < 1) then
  211. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  212. Result := GetByteCount(@S[CharIndex], CharCount);
  213. end;
  214. function TEncoding.GetBytes(const Chars: TUnicodeCharArray): TBytes;
  215. begin
  216. SetLength(Result, GetByteCount(Chars));
  217. GetBytes(@Chars[0], Length(Chars), @Result[0], Length(Result));
  218. end;
  219. function TEncoding.GetBytes(const Chars: TUnicodeCharArray; CharIndex,
  220. CharCount: Integer): TBytes;
  221. begin
  222. if (CharCount < 0) or (Length(Chars) < CharCount + CharIndex) then
  223. raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
  224. if (CharIndex < 0) then
  225. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  226. SetLength(Result, GetByteCount(Chars, CharIndex, CharCount));
  227. GetBytes(@Chars[CharIndex], CharCount, @Result[0], Length(Result));
  228. end;
  229. function TEncoding.GetBytes(const Chars: TUnicodeCharArray; CharIndex,
  230. CharCount: Integer; const Bytes: TBytes; ByteIndex: Integer): Integer;
  231. var
  232. ByteLen: Integer;
  233. begin
  234. ByteLen := Length(Bytes);
  235. if (ByteLen = 0) and (CharCount > 0) then
  236. raise EEncodingError.Create(SInvalidDestinationArray);
  237. if (ByteIndex < 0) or (ByteLen < ByteIndex) then
  238. raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
  239. if (CharCount < 0) or (Length(Chars) < CharCount + CharIndex) then
  240. raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
  241. if (CharIndex < 0) then
  242. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  243. Result := GetBytes(@Chars[CharIndex], CharCount, @Bytes[ByteIndex], ByteLen - ByteIndex);
  244. end;
  245. function TEncoding.GetBytes(const S: UnicodeString): TBytes;
  246. begin
  247. SetLength(Result, GetByteCount(S));
  248. GetBytes(@S[1], Length(S), @Result[0], Length(Result));
  249. end;
  250. function TEncoding.GetBytes(const S: UnicodeString; CharIndex, CharCount: Integer;
  251. const Bytes: TBytes; ByteIndex: Integer): Integer;
  252. var
  253. ByteLen: Integer;
  254. begin
  255. ByteLen := Length(Bytes);
  256. if (ByteLen = 0) and (CharCount > 0) then
  257. raise EEncodingError.Create(SInvalidDestinationArray);
  258. if (ByteIndex < 0) or (ByteLen < ByteIndex) then
  259. raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
  260. if (CharCount < 0) or (Length(S) < CharCount + CharIndex) then
  261. raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
  262. if (CharIndex < 1) then
  263. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  264. Result := GetBytes(@S[CharIndex], CharCount, @Bytes[ByteIndex], ByteLen - ByteIndex);
  265. end;
  266. function TEncoding.GetCharCount(const Bytes: TBytes): Integer;
  267. begin
  268. Result := GetCharCount(@Bytes[0], Length(Bytes));
  269. end;
  270. function TEncoding.GetCharCount(const Bytes: TBytes; ByteIndex,
  271. ByteCount: Integer): Integer;
  272. begin
  273. if (ByteIndex < 0) or (Length(Bytes) < ByteIndex) then
  274. raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
  275. Result := GetCharCount(@Bytes[ByteIndex], ByteCount);
  276. end;
  277. function TEncoding.GetChars(const Bytes: TBytes): TUnicodeCharArray;
  278. begin
  279. SetLength(Result, GetCharCount(Bytes));
  280. GetChars(@Bytes[0], Length(Bytes), @Result[0], Length(Result));
  281. end;
  282. function TEncoding.GetChars(const Bytes: TBytes; ByteIndex, ByteCount: Integer): TUnicodeCharArray;
  283. begin
  284. if (ByteIndex < 0) or (Length(Bytes) < ByteIndex) then
  285. raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
  286. SetLength(Result, GetCharCount(Bytes, ByteIndex, ByteCount));
  287. GetChars(@Bytes[ByteIndex], ByteCount, @Result[0], Length(Result));
  288. end;
  289. function TEncoding.GetChars(const Bytes: TBytes; ByteIndex, ByteCount: Integer;
  290. const Chars: TUnicodeCharArray; CharIndex: Integer): Integer;
  291. var
  292. CharLen: Integer;
  293. begin
  294. if (ByteIndex < 0) or (Length(Bytes) <= ByteIndex) then
  295. raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
  296. CharLen := Length(Chars);
  297. if (CharIndex < 0) or (CharLen <= CharIndex) then
  298. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  299. Result := GetChars(@Bytes[ByteIndex], ByteCount, @Chars[CharIndex], CharLen - CharIndex);
  300. end;
  301. class function TEncoding.GetEncoding(CodePage: Integer): TEncoding;
  302. begin
  303. case CodePage of
  304. CP_UTF16: Result := TUnicodeEncoding.Create;
  305. CP_UTF16BE: Result := TBigEndianUnicodeEncoding.Create;
  306. CP_UTF7: Result := TUTF7Encoding.Create;
  307. CP_UTF8: Result := TUTF8Encoding.Create;
  308. else
  309. Result := TMBCSEncoding.Create(CodePage);
  310. end;
  311. end;
  312. class function TEncoding.GetEncoding(const EncodingName: UnicodeString): TEncoding;
  313. var
  314. ACodePage: TSystemCodePage;
  315. begin
  316. ACodePage := CodePageNameToCodePage(AnsiString(EncodingName));
  317. if ACodePage = $FFFF then
  318. raise EEncodingError.CreateFmt(SNotValidCodePageName, [EncodingName]);
  319. Result := TMBCSEncoding.Create(ACodePage);
  320. end;
  321. function TEncoding.GetString(const Bytes: TBytes): UnicodeString;
  322. var
  323. Chars: TUnicodeCharArray;
  324. begin
  325. Chars := GetChars(Bytes);
  326. SetString(Result, PUnicodeChar(Chars), Length(Chars));
  327. end;
  328. function TEncoding.GetString(const Bytes: TBytes; ByteIndex, ByteCount: Integer): UnicodeString;
  329. var
  330. Chars: TUnicodeCharArray;
  331. begin
  332. Chars := GetChars(Bytes, ByteIndex, ByteCount);
  333. SetString(Result, PUnicodeChar(Chars), Length(Chars));
  334. end;
  335. { TMBCSEncoding }
  336. function TMBCSEncoding.GetByteCount(Chars: PUnicodeChar; CharCount: Integer): Integer;
  337. var
  338. S: RawByteString;
  339. begin
  340. widestringmanager.Unicode2AnsiMoveProc(Chars, S, CodePage, CharCount);
  341. Result := Length(S);
  342. end;
  343. function TMBCSEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer; Bytes: PByte;
  344. ByteCount: Integer): Integer;
  345. var
  346. S: RawByteString;
  347. begin
  348. widestringmanager.Unicode2AnsiMoveProc(Chars, S, CodePage, CharCount);
  349. Result := Length(S);
  350. if ByteCount < Result then
  351. Result := ByteCount;
  352. if Result > 0 then
  353. Move(S[1], Bytes[0], Result);
  354. end;
  355. function TMBCSEncoding.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer;
  356. var
  357. U: UnicodeString;
  358. begin
  359. widestringmanager.Ansi2UnicodeMoveProc(PChar(Bytes), CodePage, U, ByteCount);
  360. Result := Length(U);
  361. end;
  362. function TMBCSEncoding.GetChars(Bytes: PByte; ByteCount: Integer; Chars: PUnicodeChar;
  363. CharCount: Integer): Integer;
  364. var
  365. U: UnicodeString;
  366. begin
  367. widestringmanager.Ansi2UnicodeMoveProc(PChar(Bytes), CodePage, U, ByteCount);
  368. Result := Length(U);
  369. if CharCount < Result then
  370. Result := CharCount;
  371. if Result > 0 then
  372. Move(U[1], Chars[0], Result * SizeOf(UnicodeChar));
  373. end;
  374. function TMBCSEncoding.GetCodePage: Cardinal;
  375. begin
  376. Result := FCodePage;
  377. end;
  378. function TMBCSEncoding.GetEncodingName: UnicodeString;
  379. begin
  380. Result := UnicodeString(CodePageToCodePageName(CodePage));
  381. end;
  382. constructor TMBCSEncoding.Create;
  383. begin
  384. Create(DefaultSystemCodePage, 0, 0);
  385. end;
  386. constructor TMBCSEncoding.Create(ACodePage: Integer);
  387. begin
  388. Create(ACodePage, 0, 0);
  389. end;
  390. constructor TMBCSEncoding.Create(ACodePage, MBToWCharFlags,
  391. WCharToMBFlags: Integer);
  392. begin
  393. FCodePage := ACodePage;
  394. FMBToWCharFlags := MBToWCharFlags;
  395. FWCharToMBFlags := WCharToMBFlags;
  396. end;
  397. function TMBCSEncoding.Clone: TEncoding;
  398. begin
  399. Result := TMBCSEncoding.Create(FCodePage, FMBToWCharFlags, FWCharToMBFlags);
  400. end;
  401. function TMBCSEncoding.GetAnsiBytes(Chars: PChar; CharCount: Integer): TBytes;
  402. var
  403. S: RawByteString;
  404. begin
  405. SetString(S, Chars, CharCount);
  406. SetCodePage(S, DefaultSystemCodePage, False);
  407. SetCodePage(S, GetCodePage, True);
  408. SetLength(Result, Length(S));
  409. if Length(S)>0 then
  410. Move(S[1], Result[0], Length(S));
  411. end;
  412. function TMBCSEncoding.GetAnsiString(Bytes: PByte; ByteCount: Integer): string;
  413. begin
  414. SetString(Result, Pointer(Bytes), ByteCount);
  415. SetCodePage(RawByteString(Result), GetCodePage, False);
  416. SetCodePage(RawByteString(Result), DefaultSystemCodePage, True);
  417. end;
  418. function TMBCSEncoding.GetMaxByteCount(CharCount: Integer): Integer;
  419. begin
  420. Result := CharCount;
  421. end;
  422. function TMBCSEncoding.GetMaxCharCount(ByteCount: Integer): Integer;
  423. begin
  424. Result := ByteCount;
  425. end;
  426. function TMBCSEncoding.GetPreamble: TBytes;
  427. begin
  428. Result := nil;
  429. end;
  430. { TUTF7Encoding }
  431. constructor TUTF7Encoding.Create;
  432. begin
  433. inherited Create(CP_UTF7);
  434. FIsSingleByte := False;
  435. end;
  436. function TUTF7Encoding.Clone: TEncoding;
  437. begin
  438. Result := TUTF7Encoding.Create;
  439. end;
  440. function TUTF7Encoding.GetMaxByteCount(CharCount: Integer): Integer;
  441. begin
  442. Result := CharCount * 3 + 2;
  443. end;
  444. function TUTF7Encoding.GetMaxCharCount(ByteCount: Integer): Integer;
  445. begin
  446. Result := ByteCount;
  447. end;
  448. { TUTF8Encoding }
  449. constructor TUTF8Encoding.Create;
  450. begin
  451. inherited Create(CP_UTF8);
  452. FIsSingleByte := False;
  453. end;
  454. function TUTF8Encoding.Clone: TEncoding;
  455. begin
  456. Result := TUTF8Encoding.Create;
  457. end;
  458. function TUTF8Encoding.GetMaxByteCount(CharCount: Integer): Integer;
  459. begin
  460. Result := CharCount * 3;
  461. end;
  462. function TUTF8Encoding.GetMaxCharCount(ByteCount: Integer): Integer;
  463. begin
  464. Result := ByteCount;
  465. end;
  466. function TUTF8Encoding.GetPreamble: TBytes;
  467. begin
  468. SetLength(Result, 3);
  469. Result[0] := $EF;
  470. Result[1] := $BB;
  471. Result[2] := $BF;
  472. end;
  473. { TUnicodeEncoding }
  474. function TUnicodeEncoding.GetByteCount(Chars: PUnicodeChar; CharCount: Integer): Integer;
  475. begin
  476. Result := CharCount * SizeOf(UnicodeChar);
  477. end;
  478. function TUnicodeEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer;
  479. Bytes: PByte; ByteCount: Integer): Integer;
  480. begin
  481. Result := CharCount * SizeOf(UnicodeChar);
  482. if ByteCount < Result then
  483. Result := ByteCount;
  484. if Result > 0 then
  485. Move(Chars[0], Bytes[0], Result);
  486. end;
  487. function TUnicodeEncoding.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer;
  488. begin
  489. Result := ByteCount div SizeOf(UnicodeChar);
  490. end;
  491. function TUnicodeEncoding.GetChars(Bytes: PByte; ByteCount: Integer;
  492. Chars: PUnicodeChar; CharCount: Integer): Integer;
  493. begin
  494. Result := ByteCount div 2;
  495. if CharCount < Result then
  496. Result := CharCount;
  497. Move(Bytes[0], Chars[0], Result * SizeOf(UnicodeChar));
  498. end;
  499. function TUnicodeEncoding.GetCodePage: Cardinal;
  500. begin
  501. Result := CP_UTF16;
  502. end;
  503. function TUnicodeEncoding.GetEncodingName: UnicodeString;
  504. begin
  505. Result := UnicodeString(CodePageToCodePageName(CodePage));
  506. end;
  507. constructor TUnicodeEncoding.Create;
  508. begin
  509. inherited Create;
  510. FIsSingleByte := False;
  511. FMaxCharSize := SizeOf(UnicodeChar);
  512. end;
  513. function TUnicodeEncoding.Clone: TEncoding;
  514. begin
  515. Result := TUnicodeEncoding.Create;
  516. end;
  517. function TUnicodeEncoding.GetAnsiBytes(Chars: PChar; CharCount: Integer
  518. ): TBytes;
  519. var
  520. U: UnicodeString;
  521. begin
  522. widestringmanager.Ansi2UnicodeMoveProc(Chars, DefaultSystemCodePage, U, CharCount);
  523. SetLength(Result, Length(U)*SizeOf(UnicodeChar));
  524. if Length(Result)>0 then
  525. Move(U[1], Result[0], Length(Result));
  526. end;
  527. function TUnicodeEncoding.GetAnsiString(Bytes: PByte; ByteCount: Integer
  528. ): string;
  529. begin
  530. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Bytes), RawByteString(Result), DefaultSystemCodePage, ByteCount div SizeOf(UnicodeChar));
  531. end;
  532. function TUnicodeEncoding.GetMaxByteCount(CharCount: Integer): Integer;
  533. begin
  534. Result := CharCount * SizeOf(UnicodeChar);
  535. end;
  536. function TUnicodeEncoding.GetMaxCharCount(ByteCount: Integer): Integer;
  537. begin
  538. Result := ByteCount div SizeOf(UnicodeChar);
  539. end;
  540. function TUnicodeEncoding.GetPreamble: TBytes;
  541. begin
  542. SetLength(Result, 2);
  543. Result[0] := $FF;
  544. Result[1] := $FE;
  545. end;
  546. { TBigEndianUnicodeEncoding }
  547. function TBigEndianUnicodeEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer;
  548. Bytes: PByte; ByteCount: Integer): Integer;
  549. var
  550. LastByte: PByte;
  551. begin
  552. Result := CharCount * SizeOf(UnicodeChar);
  553. if ByteCount < Result then
  554. Result := ByteCount;
  555. LastByte := @Bytes[Result];
  556. while Bytes < LastByte do
  557. begin
  558. Bytes^ := Hi(Word(Chars^));
  559. inc(Bytes);
  560. if Bytes < LastByte then
  561. Bytes^ := Lo(Word(Chars^));
  562. inc(Bytes);
  563. inc(Chars);
  564. end;
  565. end;
  566. function TBigEndianUnicodeEncoding.GetChars(Bytes: PByte; ByteCount: Integer;
  567. Chars: PUnicodeChar; CharCount: Integer): Integer;
  568. var
  569. LastChar: PUnicodeChar;
  570. begin
  571. Result := ByteCount div SizeOf(UnicodeChar);
  572. if CharCount < Result then
  573. Result := CharCount;
  574. LastChar := @Chars[Result];
  575. while Chars < LastChar do
  576. begin
  577. Chars^ := UnicodeChar(Bytes[1] + Bytes[0] shl 8);
  578. inc(Bytes, SizeOf(UnicodeChar));
  579. inc(Chars);
  580. end;
  581. end;
  582. function TBigEndianUnicodeEncoding.GetCodePage: Cardinal;
  583. begin
  584. Result := CP_UTF16BE;
  585. end;
  586. function TBigEndianUnicodeEncoding.GetEncodingName: UnicodeString;
  587. begin
  588. Result := UnicodeString(CodePageToCodePageName(CodePage));
  589. end;
  590. function TBigEndianUnicodeEncoding.Clone: TEncoding;
  591. begin
  592. Result := TBigEndianUnicodeEncoding.Create;
  593. end;
  594. function TBigEndianUnicodeEncoding.GetAnsiBytes(Chars: PChar; CharCount: Integer
  595. ): TBytes;
  596. begin
  597. Result := TEncoding.Unicode.GetAnsiBytes(Chars, CharCount);
  598. Swap(Result);
  599. end;
  600. function TBigEndianUnicodeEncoding.GetAnsiString(Bytes: PByte;
  601. ByteCount: Integer): string;
  602. var
  603. B: TBytes;
  604. begin
  605. if ByteCount=0 then
  606. Exit('');
  607. SetLength(B, ByteCount);
  608. Move(Bytes^, B[0], ByteCount);
  609. Swap(B);
  610. Result := TEncoding.Unicode.GetAnsiString(PByte(@B[0]), ByteCount);
  611. end;
  612. function TBigEndianUnicodeEncoding.GetPreamble: TBytes;
  613. begin
  614. SetLength(Result, 2);
  615. Result[0] := $FE;
  616. Result[1] := $FF;
  617. end;
  618. procedure TBigEndianUnicodeEncoding.Swap(var B: TBytes);
  619. var
  620. LastB, I: Integer;
  621. C: Byte;
  622. begin
  623. LastB := Length(B)-1;
  624. I := 0;
  625. while I < LastB do
  626. begin
  627. C := B[I];
  628. B[I] := B[I+1];
  629. B[I+1] := C;
  630. Inc(I, 2);
  631. end;
  632. end;
  633. {$endif VER2_4}