sysencoding.inc 21 KB

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