IdCoder.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. $Log$
  13. Rev 1.18 27.08.2004 22:03:20 Andreas Hausladen
  14. Optimized encoders
  15. speed optimization ("const" for string parameters)
  16. Rev 1.17 7/23/04 7:00:14 PM RLebeau
  17. Added extra exception handling to DecodeString() and Encode()
  18. Rev 1.16 2004.06.14 9:23:06 PM czhower
  19. Bug fix.
  20. Rev 1.15 22/05/2004 12:05:20 CCostelloe
  21. Bug fix
  22. Rev 1.14 2004.05.20 1:39:20 PM czhower
  23. Last of the IdStream updates
  24. Rev 1.13 2004.05.20 11:37:08 AM czhower
  25. IdStreamVCL
  26. Rev 1.12 2004.05.20 11:13:10 AM czhower
  27. More IdStream conversions
  28. Rev 1.11 2004.05.19 3:06:48 PM czhower
  29. IdStream / .NET fix
  30. Rev 1.10 2004.02.03 5:44:56 PM czhower
  31. Name changes
  32. Rev 1.9 1/27/2004 3:58:16 PM SPerry
  33. StringStream ->IdStringStream
  34. Rev 1.8 27/1/2004 1:57:58 PM SGrobety
  35. Additional bug fix
  36. Rev 1.6 11/10/2003 7:39:22 PM BGooijen
  37. Did all todo's ( TStream to TIdStream mainly )
  38. Rev 1.5 2003.10.02 10:52:48 PM czhower
  39. .Net
  40. Rev 1.4 2003.06.24 12:02:08 AM czhower
  41. Coders now decode properly again.
  42. Rev 1.3 2003.06.13 6:57:08 PM czhower
  43. Speed improvement
  44. Rev 1.2 2003.06.13 3:41:18 PM czhower
  45. Optimizaitions.
  46. Rev 1.1 2003.06.13 2:24:06 PM czhower
  47. Speed improvement
  48. Rev 1.0 11/14/2002 02:14:30 PM JPMugaas
  49. }
  50. unit IdCoder;
  51. interface
  52. {$i IdCompilerDefines.inc}
  53. uses
  54. Classes,
  55. IdBaseComponent,
  56. IdGlobal;
  57. type
  58. TIdEncoder = class(TIdBaseComponent)
  59. public
  60. function Encode(const AIn: string; AByteEncoding: IIdTextEncoding = nil
  61. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  62. ): string; overload;
  63. procedure Encode(const AIn: string; ADestStrings: TStrings; AByteEncoding: IIdTextEncoding = nil
  64. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  65. ); overload;
  66. procedure Encode(const AIn: string; ADestStream: TStream; AByteEncoding: IIdTextEncoding = nil
  67. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  68. ); overload;
  69. function Encode(ASrcStream: TStream; const ABytes: Integer = -1): string; overload;
  70. procedure Encode(ASrcStream: TStream; ADestStrings: TStrings; const ABytes: Integer = -1); overload;
  71. procedure Encode(ASrcStream: TStream; ADestStream: TStream; const ABytes: Integer = -1); overload; virtual; abstract;
  72. class function EncodeString(const AIn: string; AByteEncoding: IIdTextEncoding = nil
  73. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  74. ): string; overload;
  75. class procedure EncodeString(const AIn: string; ADestStrings: TStrings;
  76. AByteEncoding: IIdTextEncoding = nil
  77. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  78. ); overload;
  79. class procedure EncodeString(const AIn: string; ADestStream: TStream;
  80. AByteEncoding: IIdTextEncoding = nil
  81. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  82. ); overload;
  83. class function EncodeBytes(const ABytes: TIdBytes): string; overload;
  84. class procedure EncodeBytes(const ABytes: TIdBytes; ADestStrings: TStrings); overload;
  85. class procedure EncodeBytes(const ABytes: TIdBytes; ADestStream: TStream); overload;
  86. class function EncodeStream(ASrcStream: TStream; const ABytes: Integer = -1): string; overload;
  87. class procedure EncodeStream(ASrcStream: TStream; ADestStrings: TStrings; const ABytes: Integer = -1); overload;
  88. class procedure EncodeStream(ASrcStream: TStream; ADestStream: TStream; const ABytes: Integer = -1); overload;
  89. end;
  90. TIdEncoderClass = class of TIdEncoder;
  91. TIdDecoder = class(TIdBaseComponent)
  92. protected
  93. FStream: TStream;
  94. public
  95. procedure DecodeBegin(ADestStream: TStream); virtual;
  96. procedure DecodeEnd; virtual;
  97. procedure Decode(const AIn: string); overload;
  98. procedure Decode(ASrcStream: TStream; const ABytes: Integer = -1); overload; virtual; abstract;
  99. class function DecodeString(const AIn: string; AByteEncoding: IIdTextEncoding = nil
  100. {$IFDEF STRING_IS_ANSI}; ADestEncoding: IIdTextEncoding = nil{$ENDIF}
  101. ): string;
  102. class function DecodeBytes(const AIn: string): TIdBytes;
  103. class procedure DecodeStream(const AIn: string; ADestStream: TStream);
  104. end;
  105. TIdDecoderClass = class of TIdDecoder;
  106. implementation
  107. uses
  108. IdGlobalProtocols, SysUtils;
  109. { TIdDecoder }
  110. procedure TIdDecoder.DecodeBegin(ADestStream: TStream);
  111. begin
  112. FStream := ADestStream;
  113. end;
  114. procedure TIdDecoder.DecodeEnd;
  115. begin
  116. FStream := nil;
  117. end;
  118. procedure TIdDecoder.Decode(const AIn: string);
  119. var
  120. LStream: TMemoryStream;
  121. LEncoding: IIdTextEncoding;
  122. begin
  123. LStream := TMemoryStream.Create;
  124. try
  125. LEncoding := IndyTextEncoding_8Bit;
  126. WriteStringToStream(LStream, AIn, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
  127. LEncoding := nil;
  128. LStream.Position := 0;
  129. Decode(LStream);
  130. finally
  131. LStream.Free;
  132. end;
  133. end;
  134. class function TIdDecoder.DecodeString(const AIn: string; AByteEncoding: IIdTextEncoding = nil
  135. {$IFDEF STRING_IS_ANSI}; ADestEncoding: IIdTextEncoding = nil{$ENDIF}
  136. ): string;
  137. var
  138. LStream: TMemoryStream;
  139. begin
  140. LStream := TMemoryStream.Create;
  141. try
  142. DecodeStream(AIn, LStream);
  143. LStream.Position := 0;
  144. EnsureEncoding(AByteEncoding, enc8Bit);
  145. Result := ReadStringFromStream(LStream, -1, AByteEncoding{$IFDEF STRING_IS_ANSI}, ADestEncoding{$ENDIF});
  146. finally
  147. LStream.Free;
  148. end;
  149. end;
  150. class function TIdDecoder.DecodeBytes(const AIn: string): TIdBytes;
  151. var
  152. LStream: TMemoryStream;
  153. begin
  154. Result := nil;
  155. LStream := TMemoryStream.Create;
  156. try
  157. DecodeStream(AIn, LStream);
  158. LStream.Position := 0;
  159. ReadTIdBytesFromStream(LStream, Result, -1);
  160. finally
  161. FreeAndNil(LStream);
  162. end;
  163. end;
  164. class procedure TIdDecoder.DecodeStream(const AIn: string; ADestStream: TStream);
  165. var
  166. LDecoder: TIdDecoder;
  167. begin
  168. LDecoder := Create(nil);
  169. try
  170. LDecoder.DecodeBegin(ADestStream);
  171. try
  172. LDecoder.Decode(AIn);
  173. finally
  174. LDecoder.DecodeEnd;
  175. end;
  176. finally
  177. LDecoder.Free;
  178. end;
  179. end;
  180. { TIdEncoder }
  181. function TIdEncoder.Encode(const AIn: string; AByteEncoding: IIdTextEncoding = nil
  182. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  183. ): string;
  184. var
  185. LStream: TMemoryStream;
  186. begin
  187. if AIn <> '' then begin
  188. LStream := TMemoryStream.Create;
  189. try
  190. EnsureEncoding(AByteEncoding, enc8Bit);
  191. WriteStringToStream(LStream, AIn, AByteEncoding{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF});
  192. LStream.Position := 0;
  193. Result := Encode(LStream);
  194. finally
  195. FreeAndNil(LStream);
  196. end;
  197. end else begin
  198. Result := '';
  199. end;
  200. end;
  201. procedure TIdEncoder.Encode(const AIn: string; ADestStrings: TStrings;
  202. AByteEncoding: IIdTextEncoding = nil
  203. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  204. );
  205. var
  206. LStream: TMemoryStream;
  207. begin
  208. LStream := TMemoryStream.Create;
  209. try
  210. EnsureEncoding(AByteEncoding, enc8Bit);
  211. WriteStringToStream(LStream, AIn, AByteEncoding{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF});
  212. LStream.Position := 0;
  213. Encode(LStream, ADestStrings);
  214. finally
  215. FreeAndNil(LStream);
  216. end;
  217. end;
  218. procedure TIdEncoder.Encode(const AIn: string; ADestStream: TStream;
  219. AByteEncoding: IIdTextEncoding = nil
  220. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  221. );
  222. var
  223. LStream: TMemoryStream;
  224. begin
  225. LStream := TMemoryStream.Create;
  226. try
  227. EnsureEncoding(AByteEncoding, enc8Bit);
  228. WriteStringToStream(LStream, AIn, AByteEncoding{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF});
  229. LStream.Position := 0;
  230. Encode(LStream, ADestStream);
  231. finally
  232. FreeAndNil(LStream);
  233. end;
  234. end;
  235. function TIdEncoder.Encode(ASrcStream: TStream; const ABytes: Integer = -1) : string;
  236. var
  237. LStream: TMemoryStream;
  238. begin
  239. LStream := TMemoryStream.Create;
  240. try
  241. Encode(ASrcStream, LStream, ABytes);
  242. LStream.Position := 0;
  243. Result := ReadStringFromStream(LStream, -1, IndyTextEncoding_8Bit);
  244. finally
  245. FreeAndNil(LStream);
  246. end;
  247. end;
  248. procedure TIdEncoder.Encode(ASrcStream: TStream; ADestStrings: TStrings; const ABytes: Integer = -1);
  249. var
  250. LStream: TMemoryStream;
  251. begin
  252. ADestStrings.Clear;
  253. // TODO: provide an Encode() implementation that can save its output directly
  254. // to ADestStrings without having to waste memory encoding the data entirely
  255. // to memory first. In Delphi 2009+ in particular, TStrings.LoadFromStream()
  256. // wastes a lot of memory handling large streams...
  257. LStream := TMemoryStream.Create;
  258. try
  259. Encode(ASrcStream, LStream, ABytes);
  260. LStream.Position := 0;
  261. ADestStrings.LoadFromStream(LStream);
  262. finally
  263. FreeAndNil(LStream);
  264. end;
  265. end;
  266. class function TIdEncoder.EncodeString(const AIn: string; AByteEncoding: IIdTextEncoding = nil
  267. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  268. ): string;
  269. var
  270. LEncoder: TIdEncoder;
  271. begin
  272. LEncoder := Create(nil);
  273. try
  274. Result := LEncoder.Encode(AIn, AByteEncoding{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF});
  275. finally
  276. LEncoder.Free;
  277. end;
  278. end;
  279. class procedure TIdEncoder.EncodeString(const AIn: string; ADestStrings: TStrings;
  280. AByteEncoding: IIdTextEncoding = nil
  281. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  282. );
  283. var
  284. LEncoder: TIdEncoder;
  285. begin
  286. LEncoder := Create(nil);
  287. try
  288. LEncoder.Encode(AIn, ADestStrings, AByteEncoding{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF});
  289. finally
  290. LEncoder.Free;
  291. end;
  292. end;
  293. class procedure TIdEncoder.EncodeString(const AIn: string; ADestStream: TStream;
  294. AByteEncoding: IIdTextEncoding = nil
  295. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  296. );
  297. var
  298. LEncoder: TIdEncoder;
  299. begin
  300. LEncoder := Create(nil);
  301. try
  302. LEncoder.Encode(AIn, ADestStream, AByteEncoding{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF});
  303. finally
  304. LEncoder.Free;
  305. end;
  306. end;
  307. class function TIdEncoder.EncodeBytes(const ABytes: TIdBytes): string;
  308. var
  309. LStream: TMemoryStream;
  310. begin
  311. if ABytes <> nil then begin
  312. LStream := TMemoryStream.Create;
  313. try
  314. WriteTIdBytesToStream(LStream, ABytes);
  315. LStream.Position := 0;
  316. Result := EncodeStream(LStream);
  317. finally
  318. FreeAndNil(LStream);
  319. end;
  320. end else begin
  321. Result := '';
  322. end;
  323. end;
  324. class procedure TIdEncoder.EncodeBytes(const ABytes: TIdBytes; ADestStrings: TStrings);
  325. var
  326. LStream: TMemoryStream;
  327. begin
  328. if ABytes <> nil then begin
  329. LStream := TMemoryStream.Create;
  330. try
  331. WriteTIdBytesToStream(LStream, ABytes);
  332. LStream.Position := 0;
  333. EncodeStream(LStream, ADestStrings);
  334. finally
  335. FreeAndNil(LStream);
  336. end;
  337. end;
  338. end;
  339. class procedure TIdEncoder.EncodeBytes(const ABytes: TIdBytes; ADestStream: TStream);
  340. var
  341. LStream: TMemoryStream;
  342. begin
  343. if ABytes <> nil then begin
  344. LStream := TMemoryStream.Create;
  345. try
  346. WriteTIdBytesToStream(LStream, ABytes);
  347. LStream.Position := 0;
  348. EncodeStream(LStream, ADestStream);
  349. finally
  350. FreeAndNil(LStream);
  351. end;
  352. end;
  353. end;
  354. class function TIdEncoder.EncodeStream(ASrcStream: TStream; const ABytes: Integer = -1): string;
  355. var
  356. LEncoder: TIdEncoder;
  357. begin
  358. if ASrcStream <> nil then begin
  359. LEncoder := Create(nil);
  360. try
  361. Result := LEncoder.Encode(ASrcStream, ABytes);
  362. finally
  363. LEncoder.Free;
  364. end;
  365. end else begin
  366. Result := '';
  367. end;
  368. end;
  369. class procedure TIdEncoder.EncodeStream(ASrcStream: TStream; ADestStrings: TStrings; const ABytes: Integer = -1);
  370. var
  371. LEncoder: TIdEncoder;
  372. begin
  373. if ASrcStream <> nil then begin
  374. LEncoder := Create(nil);
  375. try
  376. LEncoder.Encode(ASrcStream, ADestStrings, ABytes);
  377. finally
  378. LEncoder.Free;
  379. end;
  380. end;
  381. end;
  382. class procedure TIdEncoder.EncodeStream(ASrcStream: TStream; ADestStream: TStream; const ABytes: Integer = -1);
  383. var
  384. LEncoder: TIdEncoder;
  385. begin
  386. if ASrcStream <> nil then begin
  387. LEncoder := Create(nil);
  388. try
  389. LEncoder.Encode(ASrcStream, ADestStream, ABytes);
  390. finally
  391. LEncoder.Free;
  392. end;
  393. end;
  394. end;
  395. end.