sysencoding.inc 22 KB

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