IdCoder.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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): string; overload;
  61. procedure Encode(const AIn: string; ADestStrings: TStrings; AByteEncoding: IIdTextEncoding = nil); overload;
  62. procedure Encode(const AIn: string; ADestStream: TStream; AByteEncoding: IIdTextEncoding = nil); overload;
  63. function Encode(ASrcStream: TStream; const ABytes: Integer = -1): string; overload;
  64. procedure Encode(ASrcStream: TStream; ADestStrings: TStrings; const ABytes: Integer = -1); overload;
  65. procedure Encode(ASrcStream: TStream; ADestStream: TStream; const ABytes: Integer = -1); overload; virtual; abstract;
  66. class function EncodeString(const AIn: string; AByteEncoding: IIdTextEncoding = nil): string; overload;
  67. class procedure EncodeString(const AIn: string; ADestStrings: TStrings; AByteEncoding: IIdTextEncoding = nil); overload;
  68. class procedure EncodeString(const AIn: string; ADestStream: TStream; AByteEncoding: IIdTextEncoding = nil); overload;
  69. class function EncodeBytes(const ABytes: TIdBytes): string; overload;
  70. class procedure EncodeBytes(const ABytes: TIdBytes; ADestStrings: TStrings); overload;
  71. class procedure EncodeBytes(const ABytes: TIdBytes; ADestStream: TStream); overload;
  72. class function EncodeStream(ASrcStream: TStream; const ABytes: Integer = -1): string; overload;
  73. class procedure EncodeStream(ASrcStream: TStream; ADestStrings: TStrings; const ABytes: Integer = -1); overload;
  74. class procedure EncodeStream(ASrcStream: TStream; ADestStream: TStream; const ABytes: Integer = -1); overload;
  75. end;
  76. TIdEncoderClass = class of TIdEncoder;
  77. TIdDecoder = class(TIdBaseComponent)
  78. protected
  79. FStream: TStream;
  80. public
  81. procedure DecodeBegin(ADestStream: TStream); virtual;
  82. procedure DecodeEnd; virtual;
  83. procedure Decode(const AIn: string); overload;
  84. procedure Decode(ASrcStream: TStream; const ABytes: Integer = -1); overload; virtual; abstract;
  85. class function DecodeString(const AIn: string; AByteEncoding: IIdTextEncoding = nil): string;
  86. class function DecodeBytes(const AIn: string): TIdBytes;
  87. class procedure DecodeStream(const AIn: string; ADestStream: TStream);
  88. end;
  89. TIdDecoderClass = class of TIdDecoder;
  90. implementation
  91. uses
  92. IdGlobalProtocols, SysUtils;
  93. { TIdDecoder }
  94. procedure TIdDecoder.DecodeBegin(ADestStream: TStream);
  95. begin
  96. FStream := ADestStream;
  97. end;
  98. procedure TIdDecoder.DecodeEnd;
  99. begin
  100. FStream := nil;
  101. end;
  102. procedure TIdDecoder.Decode(const AIn: string);
  103. var
  104. LStream: TMemoryStream;
  105. begin
  106. LStream := TMemoryStream.Create;
  107. try
  108. WriteStringToStream(LStream, AIn, IndyTextEncoding_8Bit);
  109. LStream.Position := 0;
  110. Decode(LStream);
  111. finally
  112. LStream.Free;
  113. end;
  114. end;
  115. class function TIdDecoder.DecodeString(const AIn: string; AByteEncoding: IIdTextEncoding = nil): string;
  116. var
  117. LStream: TMemoryStream;
  118. begin
  119. LStream := TMemoryStream.Create;
  120. try
  121. DecodeStream(AIn, LStream);
  122. LStream.Position := 0;
  123. EnsureEncoding(AByteEncoding, enc8Bit);
  124. Result := ReadStringFromStream(LStream, -1, AByteEncoding);
  125. finally
  126. LStream.Free;
  127. end;
  128. end;
  129. class function TIdDecoder.DecodeBytes(const AIn: string): TIdBytes;
  130. var
  131. LStream: TMemoryStream;
  132. begin
  133. Result := nil;
  134. LStream := TMemoryStream.Create;
  135. try
  136. DecodeStream(AIn, LStream);
  137. LStream.Position := 0;
  138. ReadTIdBytesFromStream(LStream, Result, -1);
  139. finally
  140. LStream.Free;
  141. end;
  142. end;
  143. class procedure TIdDecoder.DecodeStream(const AIn: string; ADestStream: TStream);
  144. var
  145. LDecoder: TIdDecoder;
  146. begin
  147. LDecoder := Create(nil);
  148. try
  149. LDecoder.DecodeBegin(ADestStream);
  150. try
  151. LDecoder.Decode(AIn);
  152. finally
  153. LDecoder.DecodeEnd;
  154. end;
  155. finally
  156. LDecoder.Free;
  157. end;
  158. end;
  159. { TIdEncoder }
  160. function TIdEncoder.Encode(const AIn: string; AByteEncoding: IIdTextEncoding = nil): string;
  161. var
  162. LStream: TMemoryStream;
  163. begin
  164. if AIn <> '' then begin
  165. LStream := TMemoryStream.Create;
  166. try
  167. EnsureEncoding(AByteEncoding, enc8Bit);
  168. WriteStringToStream(LStream, AIn, AByteEncoding);
  169. LStream.Position := 0;
  170. Result := Encode(LStream);
  171. finally
  172. LStream.Free;
  173. end;
  174. end else begin
  175. Result := '';
  176. end;
  177. end;
  178. procedure TIdEncoder.Encode(const AIn: string; ADestStrings: TStrings; AByteEncoding: IIdTextEncoding = nil);
  179. var
  180. LStream: TMemoryStream;
  181. begin
  182. LStream := TMemoryStream.Create;
  183. try
  184. EnsureEncoding(AByteEncoding, enc8Bit);
  185. WriteStringToStream(LStream, AIn, AByteEncoding);
  186. LStream.Position := 0;
  187. Encode(LStream, ADestStrings);
  188. finally
  189. LStream.Free;
  190. end;
  191. end;
  192. procedure TIdEncoder.Encode(const AIn: string; ADestStream: TStream; AByteEncoding: IIdTextEncoding = nil);
  193. var
  194. LStream: TMemoryStream;
  195. begin
  196. LStream := TMemoryStream.Create;
  197. try
  198. EnsureEncoding(AByteEncoding, enc8Bit);
  199. WriteStringToStream(LStream, AIn, AByteEncoding);
  200. LStream.Position := 0;
  201. Encode(LStream, ADestStream);
  202. finally
  203. LStream.Free;
  204. end;
  205. end;
  206. function TIdEncoder.Encode(ASrcStream: TStream; const ABytes: Integer = -1) : string;
  207. var
  208. LStream: TMemoryStream;
  209. begin
  210. LStream := TMemoryStream.Create;
  211. try
  212. Encode(ASrcStream, LStream, ABytes);
  213. LStream.Position := 0;
  214. Result := ReadStringFromStream(LStream, -1, IndyTextEncoding_8Bit);
  215. finally
  216. LStream.Free;
  217. end;
  218. end;
  219. procedure TIdEncoder.Encode(ASrcStream: TStream; ADestStrings: TStrings; const ABytes: Integer = -1);
  220. var
  221. LStream: TMemoryStream;
  222. begin
  223. ADestStrings.Clear;
  224. // TODO: provide an Encode() implementation that can save its output directly
  225. // to ADestStrings without having to waste memory encoding the data entirely
  226. // to memory first. In Delphi 2009+ in particular, TStrings.LoadFromStream()
  227. // wastes a lot of memory handling large streams...
  228. LStream := TMemoryStream.Create;
  229. try
  230. Encode(ASrcStream, LStream, ABytes);
  231. LStream.Position := 0;
  232. ADestStrings.LoadFromStream(LStream);
  233. finally
  234. LStream.Free;
  235. end;
  236. end;
  237. class function TIdEncoder.EncodeString(const AIn: string; AByteEncoding: IIdTextEncoding = nil): string;
  238. var
  239. LEncoder: TIdEncoder;
  240. begin
  241. LEncoder := Create(nil);
  242. try
  243. Result := LEncoder.Encode(AIn, AByteEncoding);
  244. finally
  245. LEncoder.Free;
  246. end;
  247. end;
  248. class procedure TIdEncoder.EncodeString(const AIn: string; ADestStrings: TStrings; AByteEncoding: IIdTextEncoding = nil);
  249. var
  250. LEncoder: TIdEncoder;
  251. begin
  252. LEncoder := Create(nil);
  253. try
  254. LEncoder.Encode(AIn, ADestStrings, AByteEncoding);
  255. finally
  256. LEncoder.Free;
  257. end;
  258. end;
  259. class procedure TIdEncoder.EncodeString(const AIn: string; ADestStream: TStream; AByteEncoding: IIdTextEncoding = nil);
  260. var
  261. LEncoder: TIdEncoder;
  262. begin
  263. LEncoder := Create(nil);
  264. try
  265. LEncoder.Encode(AIn, ADestStream, AByteEncoding);
  266. finally
  267. LEncoder.Free;
  268. end;
  269. end;
  270. class function TIdEncoder.EncodeBytes(const ABytes: TIdBytes): string;
  271. var
  272. LStream: TIdMemoryBufferStream;
  273. begin
  274. if ABytes <> nil then begin
  275. LStream := TIdMemoryBufferStream.Create(PByte(ABytes), Length(ABytes));
  276. try
  277. Result := EncodeStream(LStream);
  278. finally
  279. LStream.Free;
  280. end;
  281. end else begin
  282. Result := '';
  283. end;
  284. end;
  285. class procedure TIdEncoder.EncodeBytes(const ABytes: TIdBytes; ADestStrings: TStrings);
  286. var
  287. LStream: TIdMemoryBufferStream;
  288. begin
  289. if ABytes <> nil then begin
  290. LStream := TIdMemoryBufferStream.Create(PByte(ABytes), Length(ABytes));
  291. try
  292. EncodeStream(LStream, ADestStrings);
  293. finally
  294. LStream.Free;
  295. end;
  296. end;
  297. end;
  298. class procedure TIdEncoder.EncodeBytes(const ABytes: TIdBytes; ADestStream: TStream);
  299. var
  300. LStream: TIdMemoryBufferStream;
  301. begin
  302. if ABytes <> nil then begin
  303. LStream := TIdMemoryBufferStream.Create(PByte(ABytes), Length(ABytes));
  304. try
  305. EncodeStream(LStream, ADestStream);
  306. finally
  307. LStream.Free;
  308. end;
  309. end;
  310. end;
  311. class function TIdEncoder.EncodeStream(ASrcStream: TStream; const ABytes: Integer = -1): string;
  312. var
  313. LEncoder: TIdEncoder;
  314. begin
  315. if ASrcStream <> nil then begin
  316. LEncoder := Create(nil);
  317. try
  318. Result := LEncoder.Encode(ASrcStream, ABytes);
  319. finally
  320. LEncoder.Free;
  321. end;
  322. end else begin
  323. Result := '';
  324. end;
  325. end;
  326. class procedure TIdEncoder.EncodeStream(ASrcStream: TStream; ADestStrings: TStrings; const ABytes: Integer = -1);
  327. var
  328. LEncoder: TIdEncoder;
  329. begin
  330. if ASrcStream <> nil then begin
  331. LEncoder := Create(nil);
  332. try
  333. LEncoder.Encode(ASrcStream, ADestStrings, ABytes);
  334. finally
  335. LEncoder.Free;
  336. end;
  337. end;
  338. end;
  339. class procedure TIdEncoder.EncodeStream(ASrcStream: TStream; ADestStream: TStream; const ABytes: Integer = -1);
  340. var
  341. LEncoder: TIdEncoder;
  342. begin
  343. if ASrcStream <> nil then begin
  344. LEncoder := Create(nil);
  345. try
  346. LEncoder.Encode(ASrcStream, ADestStream, ABytes);
  347. finally
  348. LEncoder.Free;
  349. end;
  350. end;
  351. end;
  352. end.