2
0

sysencoding.inc 23 KB

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