sysencoding.inc 22 KB

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