sysencoding.inc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  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 := GetSystemEncoding;
  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. case CodePage of
  508. CP_UTF8:
  509. begin
  510. SetLength(Result, 3);
  511. Result[0] := $EF;
  512. Result[1] := $BB;
  513. Result[2] := $BF;
  514. end;
  515. CP_UTF16:
  516. begin
  517. SetLength(Result, 2);
  518. Result[0] := $FF;
  519. Result[1] := $FE;
  520. end;
  521. CP_UTF16BE:
  522. begin
  523. SetLength(Result, 2);
  524. Result[0] := $FE;
  525. Result[1] := $FF;
  526. end;
  527. else
  528. Result := nil;
  529. end;
  530. end;
  531. { TUTF7Encoding }
  532. constructor TUTF7Encoding.Create;
  533. begin
  534. inherited Create(CP_UTF7);
  535. FIsSingleByte := False;
  536. end;
  537. function TUTF7Encoding.Clone: TEncoding;
  538. begin
  539. Result := TUTF7Encoding.Create;
  540. end;
  541. function TUTF7Encoding.GetMaxByteCount(CharCount: Integer): Integer;
  542. begin
  543. Result := CharCount * 3 + 2;
  544. end;
  545. function TUTF7Encoding.GetMaxCharCount(ByteCount: Integer): Integer;
  546. begin
  547. Result := ByteCount;
  548. end;
  549. { TUTF8Encoding }
  550. constructor TUTF8Encoding.Create;
  551. begin
  552. inherited Create(CP_UTF8);
  553. FIsSingleByte := False;
  554. end;
  555. function TUTF8Encoding.Clone: TEncoding;
  556. begin
  557. Result := TUTF8Encoding.Create;
  558. end;
  559. function TUTF8Encoding.GetMaxByteCount(CharCount: Integer): Integer;
  560. begin
  561. Result := CharCount * 3;
  562. end;
  563. function TUTF8Encoding.GetMaxCharCount(ByteCount: Integer): Integer;
  564. begin
  565. Result := ByteCount;
  566. end;
  567. function TUTF8Encoding.GetPreamble: TBytes;
  568. begin
  569. SetLength(Result, 3);
  570. Result[0] := $EF;
  571. Result[1] := $BB;
  572. Result[2] := $BF;
  573. end;
  574. { TUnicodeEncoding }
  575. function TUnicodeEncoding.GetByteCount(Chars: PUnicodeChar; CharCount: Integer): Integer;
  576. begin
  577. Result := CharCount * SizeOf(UnicodeChar);
  578. end;
  579. function TUnicodeEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer;
  580. Bytes: PByte; ByteCount: Integer): Integer;
  581. begin
  582. Result := CharCount * SizeOf(UnicodeChar);
  583. if ByteCount < Result then
  584. Result := ByteCount;
  585. if Result > 0 then
  586. Move(Chars[0], Bytes[0], Result);
  587. end;
  588. function TUnicodeEncoding.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer;
  589. begin
  590. Result := ByteCount div SizeOf(UnicodeChar);
  591. end;
  592. function TUnicodeEncoding.GetChars(Bytes: PByte; ByteCount: Integer;
  593. Chars: PUnicodeChar; CharCount: Integer): Integer;
  594. begin
  595. Result := ByteCount div 2;
  596. if CharCount < Result then
  597. Result := CharCount;
  598. Move(Bytes[0], Chars[0], Result * SizeOf(UnicodeChar));
  599. end;
  600. function TUnicodeEncoding.GetCodePage: Cardinal;
  601. begin
  602. Result := CP_UTF16;
  603. end;
  604. function TUnicodeEncoding.GetEncodingName: UnicodeString;
  605. begin
  606. Result := UnicodeString(CodePageToCodePageName(CodePage));
  607. end;
  608. constructor TUnicodeEncoding.Create;
  609. begin
  610. inherited Create;
  611. FIsSingleByte := False;
  612. FMaxCharSize := SizeOf(UnicodeChar);
  613. end;
  614. function TUnicodeEncoding.Clone: TEncoding;
  615. begin
  616. Result := TUnicodeEncoding.Create;
  617. end;
  618. function TUnicodeEncoding.GetAnsiBytes(Chars: PChar; CharCount: Integer
  619. ): TBytes;
  620. var
  621. U: UnicodeString;
  622. begin
  623. widestringmanager.Ansi2UnicodeMoveProc(Chars, DefaultSystemCodePage, U, CharCount);
  624. SetLength(Result, Length(U)*SizeOf(UnicodeChar));
  625. if Length(Result)>0 then
  626. Move(U[1], Result[0], Length(Result));
  627. end;
  628. function TUnicodeEncoding.GetAnsiString(Bytes: PByte; ByteCount: Integer
  629. ): string;
  630. begin
  631. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Bytes), RawByteString(Result), DefaultSystemCodePage, ByteCount div SizeOf(UnicodeChar));
  632. end;
  633. function TUnicodeEncoding.GetMaxByteCount(CharCount: Integer): Integer;
  634. begin
  635. Result := CharCount * SizeOf(UnicodeChar);
  636. end;
  637. function TUnicodeEncoding.GetMaxCharCount(ByteCount: Integer): Integer;
  638. begin
  639. Result := ByteCount div SizeOf(UnicodeChar);
  640. end;
  641. function TUnicodeEncoding.GetPreamble: TBytes;
  642. begin
  643. SetLength(Result, 2);
  644. Result[0] := $FF;
  645. Result[1] := $FE;
  646. end;
  647. { TBigEndianUnicodeEncoding }
  648. function TBigEndianUnicodeEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer;
  649. Bytes: PByte; ByteCount: Integer): Integer;
  650. var
  651. LastByte: PByte;
  652. begin
  653. Result := CharCount * SizeOf(UnicodeChar);
  654. if ByteCount < Result then
  655. Result := ByteCount;
  656. LastByte := @Bytes[Result];
  657. while Bytes < LastByte do
  658. begin
  659. Bytes^ := Hi(Word(Chars^));
  660. inc(Bytes);
  661. if Bytes < LastByte then
  662. Bytes^ := Lo(Word(Chars^));
  663. inc(Bytes);
  664. inc(Chars);
  665. end;
  666. end;
  667. function TBigEndianUnicodeEncoding.GetChars(Bytes: PByte; ByteCount: Integer;
  668. Chars: PUnicodeChar; CharCount: Integer): Integer;
  669. var
  670. LastChar: PUnicodeChar;
  671. begin
  672. Result := ByteCount div SizeOf(UnicodeChar);
  673. if CharCount < Result then
  674. Result := CharCount;
  675. LastChar := @Chars[Result];
  676. while Chars < LastChar do
  677. begin
  678. Chars^ := UnicodeChar(Bytes[1] + Bytes[0] shl 8);
  679. inc(Bytes, SizeOf(UnicodeChar));
  680. inc(Chars);
  681. end;
  682. end;
  683. function TBigEndianUnicodeEncoding.GetCodePage: Cardinal;
  684. begin
  685. Result := CP_UTF16BE;
  686. end;
  687. function TBigEndianUnicodeEncoding.GetEncodingName: UnicodeString;
  688. begin
  689. Result := UnicodeString(CodePageToCodePageName(CodePage));
  690. end;
  691. function TBigEndianUnicodeEncoding.Clone: TEncoding;
  692. begin
  693. Result := TBigEndianUnicodeEncoding.Create;
  694. end;
  695. function TBigEndianUnicodeEncoding.GetAnsiBytes(Chars: PChar; CharCount: Integer
  696. ): TBytes;
  697. begin
  698. Result := TEncoding.Unicode.GetAnsiBytes(Chars, CharCount);
  699. Swap(Result);
  700. end;
  701. function TBigEndianUnicodeEncoding.GetAnsiString(Bytes: PByte;
  702. ByteCount: Integer): string;
  703. var
  704. B: TBytes;
  705. begin
  706. if ByteCount=0 then
  707. Exit('');
  708. SetLength(B, ByteCount);
  709. Move(Bytes^, B[0], ByteCount);
  710. Swap(B);
  711. Result := TEncoding.Unicode.GetAnsiString(PByte(@B[0]), ByteCount);
  712. end;
  713. function TBigEndianUnicodeEncoding.GetPreamble: TBytes;
  714. begin
  715. SetLength(Result, 2);
  716. Result[0] := $FE;
  717. Result[1] := $FF;
  718. end;
  719. procedure TBigEndianUnicodeEncoding.Swap(var B: TBytes);
  720. var
  721. LastB, I: Integer;
  722. C: Byte;
  723. begin
  724. LastB := Length(B)-1;
  725. I := 0;
  726. while I < LastB do
  727. begin
  728. C := B[I];
  729. B[I] := B[I+1];
  730. B[I+1] := C;
  731. Inc(I, 2);
  732. end;
  733. end;
  734. {$endif VER2_4}