2
0

sysencoding.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  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. if not Assigned(FStandardEncodings[seAnsi]) then
  17. FStandardEncodings[seAnsi] := TMBCSEncoding.Create(DefaultSystemCodePage);
  18. Result := FStandardEncodings[seAnsi];
  19. end;
  20. class function TEncoding.GetASCII: TEncoding;
  21. begin
  22. if not Assigned(FStandardEncodings[seAscii]) then
  23. FStandardEncodings[seAscii] := TMBCSEncoding.Create(CP_ASCII);
  24. Result := FStandardEncodings[seAscii];
  25. end;
  26. class function TEncoding.GetBigEndianUnicode: TEncoding;
  27. begin
  28. if not Assigned(FStandardEncodings[seBigEndianUnicode]) then
  29. FStandardEncodings[seBigEndianUnicode] := TBigEndianUnicodeEncoding.Create;
  30. Result := FStandardEncodings[seBigEndianUnicode];
  31. end;
  32. class function TEncoding.GetDefault: TEncoding;
  33. begin
  34. Result := GetANSI;
  35. end;
  36. class function TEncoding.GetUnicode: TEncoding;
  37. begin
  38. if not Assigned(FStandardEncodings[seUnicode]) then
  39. FStandardEncodings[seUnicode] := TUnicodeEncoding.Create;
  40. Result := FStandardEncodings[seUnicode];
  41. end;
  42. class function TEncoding.GetUTF7: TEncoding;
  43. begin
  44. if not Assigned(FStandardEncodings[seUTF7]) then
  45. FStandardEncodings[seUTF7] := TUTF7Encoding.Create;
  46. Result := FStandardEncodings[seUTF7];
  47. end;
  48. class function TEncoding.GetUTF8: TEncoding;
  49. begin
  50. if not Assigned(FStandardEncodings[seUTF8]) then
  51. FStandardEncodings[seUTF8] := TUTF8Encoding.Create;
  52. Result := FStandardEncodings[seUTF8];
  53. end;
  54. class procedure TEncoding.FreeEncodings;
  55. var
  56. E: TStandardEncoding;
  57. begin
  58. for E := Low(FStandardEncodings) to High(FStandardEncodings) do
  59. FStandardEncodings[E].Free;
  60. end;
  61. class constructor TEncoding.Create;
  62. var
  63. E: TStandardEncoding;
  64. begin
  65. for E := Low(FStandardEncodings) to High(FStandardEncodings) do
  66. FStandardEncodings[E] := nil;
  67. end;
  68. class destructor TEncoding.Destroy;
  69. begin
  70. FreeEncodings;
  71. end;
  72. function TEncoding.Clone: TEncoding;
  73. begin
  74. Result := nil;
  75. end;
  76. class function TEncoding.Convert(Source, Destination: TEncoding;
  77. const Bytes: TBytes): TBytes;
  78. begin
  79. Result := Destination.GetBytes(Source.GetChars(Bytes));
  80. end;
  81. class function TEncoding.Convert(Source, Destination: TEncoding;
  82. const Bytes: TBytes; StartIndex, Count: Integer): TBytes;
  83. begin
  84. Result := Destination.GetBytes(Source.GetChars(Bytes, StartIndex, Count));
  85. end;
  86. class function TEncoding.IsStandardEncoding(AEncoding: TEncoding): Boolean;
  87. var
  88. Encoding: TEncoding;
  89. begin
  90. if Assigned(AEncoding) then
  91. for Encoding in FStandardEncodings do
  92. if Encoding = AEncoding then
  93. Exit(True);
  94. Result := False;
  95. end;
  96. class function TEncoding.GetBufferEncoding(const Buffer: TBytes; var AEncoding: TEncoding): Integer;
  97. begin
  98. Result := GetBufferEncoding(Buffer, AEncoding, Default);
  99. end;
  100. class function TEncoding.GetBufferEncoding(const Buffer: TBytes;
  101. var AEncoding: TEncoding; ADefaultEncoding: TEncoding): Integer;
  102. function CheckEncoding(AEncoding: TEncoding; out ByteCount: Integer): Boolean;
  103. var
  104. Preamble: TBytes;
  105. begin
  106. Preamble := AEncoding.GetPreamble;
  107. ByteCount := Length(Preamble);
  108. Result := (Length(Buffer) >= ByteCount) and (ByteCount > 0);
  109. if Result then
  110. Result := CompareMem(@Preamble[0], @Buffer[0], ByteCount);
  111. end;
  112. begin
  113. if Assigned(AEncoding) then
  114. begin
  115. if not CheckEncoding(AEncoding, Result) then
  116. Result := 0;
  117. end
  118. else
  119. if CheckEncoding(Unicode, Result) then
  120. AEncoding := Unicode
  121. else
  122. if CheckEncoding(BigEndianUnicode, Result) then
  123. AEncoding := BigEndianUnicode
  124. else
  125. if CheckEncoding(UTF8, Result) then
  126. AEncoding := UTF8
  127. else
  128. begin
  129. AEncoding := ADefaultEncoding;
  130. Result := 0;
  131. end;
  132. end;
  133. function TEncoding.GetByteCount(const Chars: TUnicodeCharArray): Integer;
  134. begin
  135. Result := GetByteCount(Chars, 0, Length(Chars));
  136. end;
  137. function TEncoding.GetByteCount(const Chars: TUnicodeCharArray; CharIndex,
  138. CharCount: Integer): Integer;
  139. begin
  140. if (CharCount < 0) or (Length(Chars) < CharCount + CharIndex) then
  141. raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
  142. if (CharIndex < 0) then
  143. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  144. Result := GetByteCount(@Chars[CharIndex], CharCount);
  145. end;
  146. function TEncoding.GetByteCount(const S: UnicodeString): Integer;
  147. begin
  148. Result := GetByteCount(PUnicodeChar(S), Length(S));
  149. end;
  150. function TEncoding.GetByteCount(const S: UnicodeString; CharIndex, CharCount: Integer): Integer;
  151. begin
  152. if (CharCount < 0) or (Length(S) < CharCount + CharIndex) then
  153. raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
  154. if (CharIndex < 1) then
  155. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  156. Result := GetByteCount(@S[CharIndex], CharCount);
  157. end;
  158. function TEncoding.GetBytes(const Chars: TUnicodeCharArray): TBytes;
  159. begin
  160. SetLength(Result, GetByteCount(Chars));
  161. GetBytes(@Chars[0], Length(Chars), @Result[0], Length(Result));
  162. end;
  163. function TEncoding.GetBytes(const Chars: TUnicodeCharArray; CharIndex,
  164. CharCount: Integer): TBytes;
  165. begin
  166. if (CharCount < 0) or (Length(Chars) < CharCount + CharIndex) then
  167. raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
  168. if (CharIndex < 0) then
  169. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  170. SetLength(Result, GetByteCount(Chars, CharIndex, CharCount));
  171. GetBytes(@Chars[CharIndex], CharCount, @Result[0], Length(Result));
  172. end;
  173. function TEncoding.GetBytes(const Chars: TUnicodeCharArray; CharIndex,
  174. CharCount: Integer; const Bytes: TBytes; ByteIndex: Integer): Integer;
  175. var
  176. ByteLen: Integer;
  177. begin
  178. ByteLen := Length(Bytes);
  179. if (ByteLen = 0) and (CharCount > 0) then
  180. raise EEncodingError.Create(SInvalidDestinationArray);
  181. if (ByteIndex < 0) or (ByteLen < ByteIndex) then
  182. raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
  183. if (CharCount < 0) or (Length(Chars) < CharCount + CharIndex) then
  184. raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
  185. if (CharIndex < 0) then
  186. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  187. Result := GetBytes(@Chars[CharIndex], CharCount, @Bytes[ByteIndex], ByteLen - ByteIndex);
  188. end;
  189. function TEncoding.GetBytes(const S: UnicodeString): TBytes;
  190. begin
  191. SetLength(Result, GetByteCount(S));
  192. GetBytes(@S[1], Length(S), @Result[0], Length(Result));
  193. end;
  194. function TEncoding.GetBytes(const S: UnicodeString; CharIndex, CharCount: Integer;
  195. const Bytes: TBytes; ByteIndex: Integer): Integer;
  196. var
  197. ByteLen: Integer;
  198. begin
  199. ByteLen := Length(Bytes);
  200. if (ByteLen = 0) and (CharCount > 0) then
  201. raise EEncodingError.Create(SInvalidDestinationArray);
  202. if (ByteIndex < 0) or (ByteLen < ByteIndex) then
  203. raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
  204. if (CharCount < 0) or (Length(S) < CharCount + CharIndex) then
  205. raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
  206. if (CharIndex < 1) then
  207. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  208. Result := GetBytes(@S[CharIndex], CharCount, @Bytes[ByteIndex], ByteLen - ByteIndex);
  209. end;
  210. function TEncoding.GetCharCount(const Bytes: TBytes): Integer;
  211. begin
  212. Result := GetCharCount(@Bytes[0], Length(Bytes));
  213. end;
  214. function TEncoding.GetCharCount(const Bytes: TBytes; ByteIndex,
  215. ByteCount: Integer): Integer;
  216. begin
  217. if (ByteIndex < 0) or (Length(Bytes) < ByteIndex) then
  218. raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
  219. Result := GetCharCount(@Bytes[ByteIndex], ByteCount);
  220. end;
  221. function TEncoding.GetChars(const Bytes: TBytes): TUnicodeCharArray;
  222. begin
  223. SetLength(Result, GetCharCount(Bytes));
  224. GetChars(@Bytes[0], Length(Bytes), @Result[0], Length(Result));
  225. end;
  226. function TEncoding.GetChars(const Bytes: TBytes; ByteIndex, ByteCount: Integer): TUnicodeCharArray;
  227. begin
  228. if (ByteIndex < 0) or (Length(Bytes) < ByteIndex) then
  229. raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
  230. SetLength(Result, GetCharCount(Bytes, ByteIndex, ByteCount));
  231. GetChars(@Bytes[ByteIndex], ByteCount, @Result[0], Length(Result));
  232. end;
  233. function TEncoding.GetChars(const Bytes: TBytes; ByteIndex, ByteCount: Integer;
  234. const Chars: TUnicodeCharArray; CharIndex: Integer): Integer;
  235. var
  236. CharLen: Integer;
  237. begin
  238. if (ByteIndex < 0) or (Length(Bytes) <= ByteIndex) then
  239. raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
  240. CharLen := Length(Chars);
  241. if (CharIndex < 0) or (CharLen <= CharIndex) then
  242. raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
  243. Result := GetChars(@Bytes[ByteIndex], ByteCount, @Chars[CharIndex], CharLen - CharIndex);
  244. end;
  245. class function TEncoding.GetEncoding(CodePage: Integer): TEncoding;
  246. begin
  247. case CodePage of
  248. CP_UTF16: Result := TUnicodeEncoding.Create;
  249. CP_UTF16BE: Result := TBigEndianUnicodeEncoding.Create;
  250. CP_UTF7: Result := TUTF7Encoding.Create;
  251. CP_UTF8: Result := TUTF8Encoding.Create;
  252. else
  253. Result := TMBCSEncoding.Create(CodePage);
  254. end;
  255. end;
  256. class function TEncoding.GetEncoding(const EncodingName: UnicodeString): TEncoding;
  257. var
  258. ACodePage: TSystemCodePage;
  259. begin
  260. ACodePage := CodePageNameToCodePage(AnsiString(EncodingName));
  261. if ACodePage = $FFFF then
  262. raise EEncodingError.CreateFmt(SNotValidCodePageName, [EncodingName]);
  263. Result := TMBCSEncoding.Create(ACodePage);
  264. end;
  265. function TEncoding.GetString(const Bytes: TBytes): UnicodeString;
  266. var
  267. Chars: TUnicodeCharArray;
  268. begin
  269. Chars := GetChars(Bytes);
  270. SetString(Result, PUnicodeChar(Chars), Length(Chars));
  271. end;
  272. function TEncoding.GetString(const Bytes: TBytes; ByteIndex, ByteCount: Integer): UnicodeString;
  273. var
  274. Chars: TUnicodeCharArray;
  275. begin
  276. Chars := GetChars(Bytes, ByteIndex, ByteCount);
  277. SetString(Result, PUnicodeChar(Chars), Length(Chars));
  278. end;
  279. { TMBCSEncoding }
  280. function TMBCSEncoding.GetByteCount(Chars: PUnicodeChar; CharCount: Integer): Integer;
  281. var
  282. S: RawByteString;
  283. begin
  284. widestringmanager.Unicode2AnsiMoveProc(Chars, S, CodePage, CharCount);
  285. Result := Length(S);
  286. end;
  287. function TMBCSEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer; Bytes: PByte;
  288. ByteCount: Integer): Integer;
  289. var
  290. S: RawByteString;
  291. begin
  292. widestringmanager.Unicode2AnsiMoveProc(Chars, S, CodePage, CharCount);
  293. Result := Length(S);
  294. if ByteCount < Result then
  295. Result := ByteCount;
  296. if Result > 0 then
  297. Move(S[1], Bytes[0], Result);
  298. end;
  299. function TMBCSEncoding.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer;
  300. var
  301. U: UnicodeString;
  302. begin
  303. widestringmanager.Ansi2UnicodeMoveProc(PChar(Bytes), CodePage, U, ByteCount);
  304. Result := Length(U);
  305. end;
  306. function TMBCSEncoding.GetChars(Bytes: PByte; ByteCount: Integer; Chars: PUnicodeChar;
  307. CharCount: Integer): Integer;
  308. var
  309. U: UnicodeString;
  310. begin
  311. widestringmanager.Ansi2UnicodeMoveProc(PChar(Bytes), CodePage, U, ByteCount);
  312. Result := Length(U);
  313. if CharCount < Result then
  314. Result := CharCount;
  315. if Result > 0 then
  316. Move(U[1], Chars[0], Result * SizeOf(UnicodeChar));
  317. end;
  318. function TMBCSEncoding.GetCodePage: Cardinal;
  319. begin
  320. Result := FCodePage;
  321. end;
  322. function TMBCSEncoding.GetEncodingName: UnicodeString;
  323. begin
  324. Result := UnicodeString(CodePageToCodePageName(CodePage));
  325. end;
  326. constructor TMBCSEncoding.Create;
  327. begin
  328. Create(DefaultSystemCodePage, 0, 0);
  329. end;
  330. constructor TMBCSEncoding.Create(ACodePage: Integer);
  331. begin
  332. Create(ACodePage, 0, 0);
  333. end;
  334. constructor TMBCSEncoding.Create(ACodePage, MBToWCharFlags,
  335. WCharToMBFlags: Integer);
  336. begin
  337. FCodePage := ACodePage;
  338. FMBToWCharFlags := MBToWCharFlags;
  339. FWCharToMBFlags := WCharToMBFlags;
  340. end;
  341. function TMBCSEncoding.Clone: TEncoding;
  342. begin
  343. Result := TMBCSEncoding.Create(FCodePage, FMBToWCharFlags, FWCharToMBFlags);
  344. end;
  345. function TMBCSEncoding.GetMaxByteCount(CharCount: Integer): Integer;
  346. begin
  347. Result := CharCount;
  348. end;
  349. function TMBCSEncoding.GetMaxCharCount(ByteCount: Integer): Integer;
  350. begin
  351. Result := ByteCount;
  352. end;
  353. function TMBCSEncoding.GetPreamble: TBytes;
  354. begin
  355. Result := nil;
  356. end;
  357. { TUTF7Encoding }
  358. constructor TUTF7Encoding.Create;
  359. begin
  360. inherited Create(CP_UTF7);
  361. FIsSingleByte := False;
  362. end;
  363. function TUTF7Encoding.Clone: TEncoding;
  364. begin
  365. Result := TUTF7Encoding.Create;
  366. end;
  367. function TUTF7Encoding.GetMaxByteCount(CharCount: Integer): Integer;
  368. begin
  369. Result := CharCount * 3 + 2;
  370. end;
  371. function TUTF7Encoding.GetMaxCharCount(ByteCount: Integer): Integer;
  372. begin
  373. Result := ByteCount;
  374. end;
  375. { TUTF8Encoding }
  376. constructor TUTF8Encoding.Create;
  377. begin
  378. inherited Create(CP_UTF8);
  379. FIsSingleByte := False;
  380. end;
  381. function TUTF8Encoding.Clone: TEncoding;
  382. begin
  383. Result := TUTF8Encoding.Create;
  384. end;
  385. function TUTF8Encoding.GetMaxByteCount(CharCount: Integer): Integer;
  386. begin
  387. Result := CharCount * 3;
  388. end;
  389. function TUTF8Encoding.GetMaxCharCount(ByteCount: Integer): Integer;
  390. begin
  391. Result := ByteCount;
  392. end;
  393. function TUTF8Encoding.GetPreamble: TBytes;
  394. begin
  395. SetLength(Result, 3);
  396. Result[0] := $EF;
  397. Result[1] := $BB;
  398. Result[2] := $BF;
  399. end;
  400. { TUnicodeEncoding }
  401. function TUnicodeEncoding.GetByteCount(Chars: PUnicodeChar; CharCount: Integer): Integer;
  402. begin
  403. Result := CharCount * SizeOf(UnicodeChar);
  404. end;
  405. function TUnicodeEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer;
  406. Bytes: PByte; ByteCount: Integer): Integer;
  407. begin
  408. Result := CharCount * SizeOf(UnicodeChar);
  409. if ByteCount < Result then
  410. Result := ByteCount;
  411. if Result > 0 then
  412. Move(Chars[0], Bytes[0], Result);
  413. end;
  414. function TUnicodeEncoding.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer;
  415. begin
  416. Result := ByteCount div SizeOf(UnicodeChar);
  417. end;
  418. function TUnicodeEncoding.GetChars(Bytes: PByte; ByteCount: Integer;
  419. Chars: PUnicodeChar; CharCount: Integer): Integer;
  420. begin
  421. Result := ByteCount div 2;
  422. if CharCount < Result then
  423. Result := CharCount;
  424. Move(Bytes[0], Chars[0], Result * SizeOf(UnicodeChar));
  425. end;
  426. function TUnicodeEncoding.GetCodePage: Cardinal;
  427. begin
  428. Result := CP_UTF16;
  429. end;
  430. function TUnicodeEncoding.GetEncodingName: UnicodeString;
  431. begin
  432. Result := UnicodeString(CodePageToCodePageName(CodePage));
  433. end;
  434. constructor TUnicodeEncoding.Create;
  435. begin
  436. inherited Create;
  437. FIsSingleByte := False;
  438. FMaxCharSize := SizeOf(UnicodeChar);
  439. end;
  440. function TUnicodeEncoding.Clone: TEncoding;
  441. begin
  442. Result := TUnicodeEncoding.Create;
  443. end;
  444. function TUnicodeEncoding.GetMaxByteCount(CharCount: Integer): Integer;
  445. begin
  446. Result := CharCount * SizeOf(UnicodeChar);
  447. end;
  448. function TUnicodeEncoding.GetMaxCharCount(ByteCount: Integer): Integer;
  449. begin
  450. Result := ByteCount div SizeOf(UnicodeChar);
  451. end;
  452. function TUnicodeEncoding.GetPreamble: TBytes;
  453. begin
  454. SetLength(Result, 2);
  455. Result[0] := $FF;
  456. Result[1] := $FE;
  457. end;
  458. { TBigEndianUnicodeEncoding }
  459. function TBigEndianUnicodeEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer;
  460. Bytes: PByte; ByteCount: Integer): Integer;
  461. var
  462. LastByte: PByte;
  463. begin
  464. Result := CharCount * SizeOf(UnicodeChar);
  465. if ByteCount < Result then
  466. Result := ByteCount;
  467. LastByte := @Bytes[Result];
  468. while Bytes < LastByte do
  469. begin
  470. Bytes^ := Hi(Word(Chars^));
  471. inc(Bytes);
  472. if Bytes < LastByte then
  473. Bytes^ := Lo(Word(Chars^));
  474. inc(Bytes);
  475. inc(Chars);
  476. end;
  477. end;
  478. function TBigEndianUnicodeEncoding.GetChars(Bytes: PByte; ByteCount: Integer;
  479. Chars: PUnicodeChar; CharCount: Integer): Integer;
  480. var
  481. LastChar: PUnicodeChar;
  482. begin
  483. Result := ByteCount div SizeOf(UnicodeChar);
  484. if CharCount < Result then
  485. Result := CharCount;
  486. LastChar := @Chars[Result];
  487. while Chars <= LastChar do
  488. begin
  489. Chars^ := UnicodeChar(Bytes[1] + Bytes[0] shl 8);
  490. inc(Bytes, SizeOf(UnicodeChar));
  491. inc(Chars);
  492. end;
  493. end;
  494. function TBigEndianUnicodeEncoding.GetCodePage: Cardinal;
  495. begin
  496. Result := CP_UTF16BE;
  497. end;
  498. function TBigEndianUnicodeEncoding.GetEncodingName: UnicodeString;
  499. begin
  500. Result := UnicodeString(CodePageToCodePageName(CodePage));
  501. end;
  502. function TBigEndianUnicodeEncoding.Clone: TEncoding;
  503. begin
  504. Result := TBigEndianUnicodeEncoding.Create;
  505. end;
  506. function TBigEndianUnicodeEncoding.GetPreamble: TBytes;
  507. begin
  508. SetLength(Result, 2);
  509. Result[0] := $FE;
  510. Result[1] := $FF;
  511. end;
  512. {$endif VER2_4}