diff --git a/Packages/DXE2/X2Utils.dproj b/Packages/DXE2/X2Utils.dproj
index 7abff9a..b100617 100644
--- a/Packages/DXE2/X2Utils.dproj
+++ b/Packages/DXE2/X2Utils.dproj
@@ -9,8 +9,8 @@
13.4
True
Debug
- Win32
- 1
+ Win64
+ 3
Package
@@ -31,11 +31,29 @@
Base
true
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
true
Base
true
+
+ true
+ Cfg_2
+ true
+ true
+
true
Cfg_2
@@ -57,14 +75,20 @@
true
+ Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ $(DELPHIBIN64)
+ 1033
+ $(DELPHIBIN64)
+ $(DELPHILIB64)
X2Utils_Icon.ico
+ $(DELPHIBIN)
+ $(DELPHILIB)
+ $(DELPHIBIN)
X2Utils_Icon.ico
Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- true
1033
- CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
7.0
@@ -75,15 +99,21 @@
0
RELEASE;$(DCC_Define)
+
+ 1033
+
+
+ 1033
+
7.0
True
True
- $(DELPHILIB)
$(DELPHILIB)
$(DELPHILIB)
- $(DELPHIBIN)
- $(DELPHIBIN)
+
+
+ 1033
XE2
@@ -135,7 +165,7 @@
- False
+ True
True
diff --git a/Packages/DXE2/X2Utils.res b/Packages/DXE2/X2Utils.res
index e43db43..df7d058 100644
Binary files a/Packages/DXE2/X2Utils.res and b/Packages/DXE2/X2Utils.res differ
diff --git a/X2UtPersistXML.pas b/X2UtPersistXML.pas
index c403713..0717463 100644
--- a/X2UtPersistXML.pas
+++ b/X2UtPersistXML.pas
@@ -35,6 +35,7 @@ type
private
FFileName: String;
FConfiguration: IXMLConfiguration;
+ FIsReader: Boolean;
FSection: IXMLSection;
FSectionStack: TInterfaceList;
protected
@@ -71,6 +72,7 @@ type
property Configuration: IXMLConfiguration read FConfiguration;
+ property IsReader: Boolean read FIsReader;
property Section: IXMLSection read FSection;
property SectionStack: TInterfaceList read FSectionStack;
property FileName: String read FFileName;
@@ -132,6 +134,7 @@ begin
FSectionStack := TInterfaceList.Create;
FFileName := AFileName;
+ FIsReader := AIsReader;
if AIsReader then
FConfiguration := LoadConfiguration(AFileName)
@@ -170,7 +173,7 @@ begin
end;
end;
- if not Result then
+ if (not Result) and (not IsReader) then
begin
FSection := Section.section.Add;
FSection.name := AName;
diff --git a/XMLDataBindingUtils.pas b/XMLDataBindingUtils.pas
index 4bf6f9e..186293b 100644
--- a/XMLDataBindingUtils.pas
+++ b/XMLDataBindingUtils.pas
@@ -148,12 +148,6 @@ type
function MimeDecodeString(const S: AnsiString): AnsiString; forward;
procedure MimeEncodeStream(const InputStream: TStream; const OutputStream: TStream); forward;
procedure MimeDecodeStream(const InputStream: TStream; const OutputStream: TStream); forward;
- function MimeEncodedSize(const I: Cardinal): Cardinal; forward;
- function MimeDecodedSize(const I: Cardinal): Cardinal; forward;
- procedure MimeEncode(var InputBuffer; const InputByteCount: Cardinal; var OutputBuffer); forward;
- function MimeDecode(var InputBuffer; const InputBytesCount: Cardinal; var OutputBuffer): Cardinal; forward;
- function MimeDecodePartial(var InputBuffer; const InputBytesCount: Cardinal; var OutputBuffer; var ByteBuffer: Cardinal; var ByteBufferSpace: Cardinal): Cardinal; forward;
- function MimeDecodePartialEnd(var OutputBuffer; const ByteBuffer: Cardinal; const ByteBufferSpace: Cardinal): Cardinal; forward;
@@ -590,45 +584,65 @@ end;
{ --- JclMime implementation from here. }
-// Caution: For MimeEncodeStream and all other kinds of multi-buffered
-// Mime encodings (i.e. Files etc.), BufferSize must be set to a multiple of 3.
-// Even though the implementation of the Mime decoding routines below
-// do not require a particular buffer size, they work fastest with sizes of
-// multiples of four. The chosen size is a multiple of 3 and of 4 as well.
-// The following numbers are, in addition, also divisible by 1024:
-// $2400, $3000, $3C00, $4800, $5400, $6000, $6C00.
+type
+ {$IFDEF WIN64}
+ SizeInt = NativeInt;
+ TJclAddr = UInt64;
+ {$ELSE}
+ SizeInt = Integer;
+ TJclAddr = Cardinal;
+ {$ENDIF}
+
+ PByte4 = ^TByte4;
+ TByte4 = packed record
+ B1: Byte;
+ B2: Byte;
+ B3: Byte;
+ B4: Byte;
+ end;
+
+ PByte3 = ^TByte3;
+ TByte3 = packed record
+ B1: Byte;
+ B2: Byte;
+ B3: Byte;
+ end;
+
const
- BUFFER_SIZE = $3000;
- EqualSign = Byte('=');
+ MIME_ENCODED_LINE_BREAK = 76;
+ MIME_DECODED_LINE_BREAK = MIME_ENCODED_LINE_BREAK div 4 * 3;
+ MIME_BUFFER_SIZE = MIME_DECODED_LINE_BREAK * 3 * 4 * 4;
MIME_ENCODE_TABLE: array [0..63] of Byte = (
- 65, 66, 67, 68, 69, 70, 71, 72, // 00 - 07
- 73, 74, 75, 76, 77, 78, 79, 80, // 08 - 15
- 81, 82, 83, 84, 85, 86, 87, 88, // 16 - 23
- 89, 90, 97, 98, 99, 100, 101, 102, // 24 - 31
- 103, 104, 105, 106, 107, 108, 109, 110, // 32 - 39
- 111, 112, 113, 114, 115, 116, 117, 118, // 40 - 47
- 119, 120, 121, 122, 48, 49, 50, 51, // 48 - 55
- 52, 53, 54, 55, 56, 57, 43, 47); // 56 - 63
+ 065, 066, 067, 068, 069, 070, 071, 072, // 00 - 07
+ 073, 074, 075, 076, 077, 078, 079, 080, // 08 - 15
+ 081, 082, 083, 084, 085, 086, 087, 088, // 16 - 23
+ 089, 090, 097, 098, 099, 100, 101, 102, // 24 - 31
+ 103, 104, 105, 106, 107, 108, 109, 110, // 32 - 39
+ 111, 112, 113, 114, 115, 116, 117, 118, // 40 - 47
+ 119, 120, 121, 122, 048, 049, 050, 051, // 48 - 55
+ 052, 053, 054, 055, 056, 057, 043, 047); // 56 - 63
- MIME_DECODE_TABLE: array [Byte] of Cardinal = (
- 255, 255, 255, 255, 255, 255, 255, 255, // 00 - 07
- 255, 255, 255, 255, 255, 255, 255, 255, // 08 - 15
+ MIME_PAD_CHAR = Byte('=');
+
+ MIME_DECODE_TABLE: array [Byte] of Byte = (
+ 255, 255, 255, 255, 255, 255, 255, 255, // 0 - 7
+ 255, 255, 255, 255, 255, 255, 255, 255, // 8 - 15
255, 255, 255, 255, 255, 255, 255, 255, // 16 - 23
255, 255, 255, 255, 255, 255, 255, 255, // 24 - 31
255, 255, 255, 255, 255, 255, 255, 255, // 32 - 39
- 255, 255, 255, 62, 255, 255, 255, 63, // 40 - 47
- 52, 53, 54, 55, 56, 57, 58, 59, // 48 - 55
- 60, 61, 255, 255, 255, 255, 255, 255, // 56 - 63
- 255, 0, 1, 2, 3, 4, 5, 6, // 64 - 71
- 7, 8, 9, 10, 11, 12, 13, 14, // 72 - 79
- 15, 16, 17, 18, 19, 20, 21, 22, // 80 - 87
- 23, 24, 25, 255, 255, 255, 255, 255, // 88 - 95
- 255, 26, 27, 28, 29, 30, 31, 32, // 96 - 103
- 33, 34, 35, 36, 37, 38, 39, 40, // 104 - 111
- 41, 42, 43, 44, 45, 46, 47, 48, // 112 - 119
- 49, 50, 51, 255, 255, 255, 255, 255, // 120 - 127
+ 255, 255, 255, 062, 255, 255, 255, 063, // 40 - 47
+ 052, 053, 054, 055, 056, 057, 058, 059, // 48 - 55
+ 060, 061, 255, 255, 255, 255, 255, 255, // 56 - 63
+ 255, 000, 001, 002, 003, 004, 005, 006, // 64 - 71
+ 007, 008, 009, 010, 011, 012, 013, 014, // 72 - 79
+ 015, 016, 017, 018, 019, 020, 021, 022, // 80 - 87
+ 023, 024, 025, 255, 255, 255, 255, 255, // 88 - 95
+ 255, 026, 027, 028, 029, 030, 031, 032, // 96 - 103
+ 033, 034, 035, 036, 037, 038, 039, 040, // 104 - 111
+ 041, 042, 043, 044, 045, 046, 047, 048, // 112 - 119
+ 049, 050, 051, 255, 255, 255, 255, 255, // 120 - 127
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
@@ -646,259 +660,218 @@ const
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255);
-type
- PByte4 = ^TByte4;
- TByte4 = packed record
- B1: Byte;
- B2: Byte;
- B3: Byte;
- B4: Byte;
- end;
- PByte3 = ^TByte3;
- TByte3 = packed record
- B1: Byte;
- B2: Byte;
- B3: Byte;
- end;
-
-
-//------------------------------------------------------------------------------
-// Wrapper functions & procedures
-//------------------------------------------------------------------------------
-
-function MimeEncodeString(const S: AnsiString): AnsiString;
-var
- L: Cardinal;
+function MimeEncodedSize(const InputSize: SizeInt): SizeInt;
begin
- L := Length(S);
- if L > 0 then
- begin
- SetLength(Result, MimeEncodedSize(L));
- MimeEncode(PAnsiChar(S)^, L, PAnsiChar(Result)^);
- end
+ if InputSize > 0 then
+ Result := (InputSize + 2) div 3 * 4 + (InputSize - 1) div MIME_DECODED_LINE_BREAK * 2
else
- Result := '';
+ Result := InputSize;
end;
-//------------------------------------------------------------------------------
-function MimeDecodeString(const S: AnsiString): AnsiString;
-var
- ByteBuffer, ByteBufferSpace: Cardinal;
- L: Cardinal;
-begin
- L := Length(S);
- if L > 0 then
- begin
- SetLength(Result, MimeDecodedSize(L));
- ByteBuffer := 0;
- ByteBufferSpace := 4;
- L := MimeDecodePartial(PAnsiChar(S)^, L, PAnsiChar(Result)^, ByteBuffer, ByteBufferSpace);
- Inc(L, MimeDecodePartialEnd(PAnsiChar(Cardinal(Result) + L)^, ByteBuffer, ByteBufferSpace));
- SetLength(Result, L);
- end;
-end;
-
-//------------------------------------------------------------------------------
-
-procedure MimeEncodeStream(const InputStream: TStream; const OutputStream: TStream);
-var
- InputBuffer: array [0..BUFFER_SIZE - 1] of Byte;
- OutputBuffer: array [0..((BUFFER_SIZE + 2) div 3) * 4 - 1] of Byte;
- BytesRead: Integer;
-begin
- BytesRead := InputStream.Read(InputBuffer, SizeOf(InputBuffer));
- while BytesRead > 0 do
- begin
- MimeEncode(InputBuffer, BytesRead, OutputBuffer);
- OutputStream.Write(OutputBuffer, MimeEncodedSize(BytesRead));
- BytesRead := InputStream.Read(InputBuffer, SizeOf(InputBuffer));
- end;
-end;
-
-//------------------------------------------------------------------------------
-
-procedure MimeDecodeStream(const InputStream: TStream; const OutputStream: TStream);
-var
- ByteBuffer, ByteBufferSpace: Cardinal;
- InputBuffer: array [0..(BUFFER_SIZE + 3) div 4 * 3 - 1] of Byte;
- OutputBuffer: array [0..BUFFER_SIZE - 1] of Byte;
- BytesRead: Integer;
-begin
- ByteBuffer := 0;
- ByteBufferSpace := 4;
- BytesRead := InputStream.Read(InputBuffer, SizeOf(InputBuffer));
- while BytesRead > 0 do
- begin
- OutputStream.Write(OutputBuffer, MimeDecodePartial(InputBuffer, BytesRead, OutputBuffer, ByteBuffer, ByteBufferSpace));
- BytesRead := InputStream.Read(InputBuffer, SizeOf(InputBuffer));
- end;
- OutputStream.Write(OutputBuffer, MimeDecodePartialEnd(OutputBuffer, ByteBuffer, ByteBufferSpace));
-end;
-
-//------------------------------------------------------------------------------
-// Helper functions
-//------------------------------------------------------------------------------
-
-function MimeEncodedSize(const I: Cardinal): Cardinal;
-begin
- Result := (I + 2) div 3 * 4;
-end;
-
-//------------------------------------------------------------------------------
-
-function MimeDecodedSize(const I: Cardinal): Cardinal;
-begin
- Result := (I + 3) div 4 * 3;
-end;
-
-//------------------------------------------------------------------------------
-// Primary functions & procedures
-//------------------------------------------------------------------------------
-
-procedure MimeEncode(var InputBuffer; const InputByteCount: Cardinal; var OutputBuffer);
+procedure MimeEncodeFullLines(const InputBuffer; const InputByteCount: SizeInt; out OutputBuffer);
var
B: Cardinal;
- InMax3: Cardinal;
- InPtr, InLimitPtr: ^Byte;
+ InnerLimit, OuterLimit: TJclAddr;
+ InPtr: PByte3;
OutPtr: PByte4;
begin
- if InputByteCount <= 0 then
+ { Do we have enough input to encode a full line? }
+ if InputByteCount < MIME_DECODED_LINE_BREAK then
Exit;
InPtr := @InputBuffer;
- InMax3 := InputByteCount div 3 * 3;
- OutPTr := @OutputBuffer;
- Cardinal(InLimitPtr) := Cardinal(InPtr) + InMax3;
+ OutPtr := @OutputBuffer;
- while InPtr <> InLimitPtr do
+ InnerLimit := TJclAddr(InPtr);
+ Inc(InnerLimit, MIME_DECODED_LINE_BREAK);
+
+ OuterLimit := TJclAddr(InPtr);
+ Inc(OuterLimit, InputByteCount);
+
+ { Multiple line loop. }
+ repeat
+ { Single line loop. }
+ repeat
+ { Read 3 bytes from InputBuffer. }
+ B := InPtr^.B1;
+ B := B shl 8;
+ B := B or InPtr^.B2;
+ B := B shl 8;
+ B := B or InPtr^.B3;
+ Inc(InPtr);
+ { Write 4 bytes to OutputBuffer (in reverse order). }
+ OutPtr^.B4 := MIME_ENCODE_TABLE[B and $3F];
+ B := B shr 6;
+ OutPtr^.B3 := MIME_ENCODE_TABLE[B and $3F];
+ B := B shr 6;
+ OutPtr^.B2 := MIME_ENCODE_TABLE[B and $3F];
+ B := B shr 6;
+ OutPtr^.B1 := MIME_ENCODE_TABLE[B];
+ Inc(OutPtr);
+ until TJclAddr(InPtr) >= InnerLimit;
+
+ { Write line break (CRLF). }
+ OutPtr^.B1 := 13;
+ OutPtr^.B2 := 10;
+ Inc(TJclAddr(OutPtr), 2);
+
+ Inc(InnerLimit, MIME_DECODED_LINE_BREAK);
+ until InnerLimit > OuterLimit;
+end;
+
+
+procedure MimeEncodeNoCRLF(const InputBuffer; const InputByteCount: SizeInt; out OutputBuffer);
+var
+ B: Cardinal;
+ InnerLimit, OuterLimit: SizeInt;
+ InPtr: PByte3;
+ OutPtr: PByte4;
+begin
+ if InputByteCount = 0 then
+ Exit;
+
+ InPtr := @InputBuffer;
+ OutPtr := @OutputBuffer;
+
+ OuterLimit := InputByteCount div 3 * 3;
+
+ InnerLimit := TJclAddr(InPtr);
+ Inc(InnerLimit, OuterLimit);
+
+ { Last line loop. }
+ while TJclAddr(InPtr) < TJclAddr(InnerLimit) do
begin
- B := InPtr^;
+ { Read 3 bytes from InputBuffer. }
+ B := InPtr^.B1;
B := B shl 8;
- Inc(InPtr);
- B := B or InPtr^;
+ B := B or InPtr^.B2;
B := B shl 8;
+ B := B or InPtr^.B3;
Inc(InPtr);
- B := B or InPtr^;
- Inc(InPtr);
- // Write 4 bytes to OutputBuffer (in reverse order).
- OutPtr.B4 := MIME_ENCODE_TABLE[B and $3F];
+ { Write 4 bytes to OutputBuffer (in reverse order). }
+ OutPtr^.B4 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
- OutPtr.B3 := MIME_ENCODE_TABLE[B and $3F];
+ OutPtr^.B3 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
- OutPtr.B2 := MIME_ENCODE_TABLE[B and $3F];
+ OutPtr^.B2 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
- OutPtr.B1 := MIME_ENCODE_TABLE[B];
+ OutPtr^.B1 := MIME_ENCODE_TABLE[B];
Inc(OutPtr);
end;
- case InputByteCount - InMax3 of
+ { End of data & padding. }
+ case InputByteCount - OuterLimit of
1:
begin
- B := InPtr^;
+ B := InPtr^.B1;
B := B shl 4;
OutPtr.B2 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr.B1 := MIME_ENCODE_TABLE[B];
- OutPtr.B3 := EqualSign; // Fill remaining 2 bytes.
- OutPtr.B4 := EqualSign;
+ OutPtr.B3 := MIME_PAD_CHAR; { Pad remaining 2 bytes. }
+ OutPtr.B4 := MIME_PAD_CHAR;
end;
2:
begin
- B := InPtr^;
- Inc(InPtr);
+ B := InPtr^.B1;
B := B shl 8;
- B := B or InPtr^;
+ B := B or InPtr^.B2;
B := B shl 2;
OutPtr.B3 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
- OutPTr.b2 := MIME_ENCODE_TABLE[B and $3F];
+ OutPtr.B2 := MIME_ENCODE_TABLE[B and $3F];
B := B shr 6;
OutPtr.B1 := MIME_ENCODE_TABLE[B];
- OutPtr.B4 := EqualSign; // Fill remaining byte.
+ OutPtr.B4 := MIME_PAD_CHAR; { Pad remaining byte. }
end;
end;
end;
-//------------------------------------------------------------------------------
-function MimeDecode(var InputBuffer; const InputBytesCount: Cardinal; var OutputBuffer): Cardinal;
+procedure MimeEncode(const InputBuffer; const InputByteCount: SizeInt; out OutputBuffer);
var
- ByteBuffer, ByteBufferSpace: Cardinal;
+ IDelta, ODelta: SizeInt;
+ I, O: PByte;
begin
- ByteBuffer := 0;
- ByteBufferSpace := 4;
- Result := MimeDecodePartial(InputBuffer, InputBytesCount, OutputBuffer, ByteBuffer, ByteBufferSpace);
- Inc(Result, MimeDecodePartialEnd(PAnsiChar(Cardinal(OutputBuffer) + Result)^, ByteBuffer, ByteBufferSpace));
+ MimeEncodeFullLines(InputBuffer, InputByteCount, OutputBuffer);
+ IDelta := InputByteCount div MIME_DECODED_LINE_BREAK; // Number of lines processed so far.
+ ODelta := IDelta * (MIME_ENCODED_LINE_BREAK + 2);
+ IDelta := IDelta * MIME_DECODED_LINE_BREAK;
+ I := @InputBuffer;
+ Inc(I, IDelta);
+ O := @OutputBuffer;
+ Inc(O, ODelta);
+ MimeEncodeNoCRLF(I^, InputByteCount - IDelta, O^);
end;
-//------------------------------------------------------------------------------
-function MimeDecodePartial(var InputBuffer; const InputBytesCount: Cardinal;
- var OutputBuffer; var ByteBuffer: Cardinal; var ByteBufferSpace: Cardinal): Cardinal;
+function MimeDecodePartial(const InputBuffer; const InputByteCount: SizeInt; out OutputBuffer;
+ var ByteBuffer: Cardinal; var ByteBufferSpace: Cardinal): SizeInt;
var
- lByteBuffer, lByteBufferSpace, C: Cardinal;
- InPtr, InLimitPtr: ^Byte;
+ LByteBuffer, LByteBufferSpace, C: Cardinal;
+ InPtr, OuterLimit: PByte;
OutPtr: PByte3;
begin
- if InputBytesCount > 0 then
+ if InputByteCount > 0 then
begin
InPtr := @InputBuffer;
- Cardinal(InLimitPtr) := Cardinal(InPtr) + InputBytesCount;
+ OuterLimit := Pointer(TJclAddr(InPtr) + TJclAddr(InputByteCount));
OutPtr := @OutputBuffer;
- lByteBuffer := ByteBuffer;
- lByteBufferSpace := ByteBufferSpace;
- while InPtr <> InLimitPtr do
+ LByteBuffer := ByteBuffer;
+ LByteBufferSpace := ByteBufferSpace;
+ while InPtr <> OuterLimit do
begin
- C := MIME_DECODE_TABLE[InPtr^]; // Read from InputBuffer.
+ { Read from InputBuffer. }
+ C := MIME_DECODE_TABLE[InPtr^];
Inc(InPtr);
if C = $FF then
Continue;
+ LByteBuffer := LByteBuffer shl 6;
+ LByteBuffer := LByteBuffer or C;
+ Dec(LByteBufferSpace);
+ { Have we read 4 bytes from InputBuffer? }
+ if LByteBufferSpace <> 0 then
+ Continue;
- lByteBuffer := lByteBuffer shl 6;
- lByteBuffer := lByteBuffer or C;
- Dec(lByteBufferSpace);
- if lByteBufferSpace <> 0 then
- Continue; // Read 4 bytes from InputBuffer?
-
- OutPtr.B3 := Byte(lByteBuffer); // Write 3 bytes to OutputBuffer (in reverse order).
- lByteBuffer := lByteBuffer shr 8;
- OutPtr.B2 := Byte(lByteBuffer);
- lByteBuffer := lByteBuffer shr 8;
- OutPtr.B1 := Byte(lByteBuffer);
- lByteBuffer := 0;
+ { Write 3 bytes to OutputBuffer (in reverse order). }
+ OutPtr^.B3 := Byte(LByteBuffer);
+ LByteBuffer := LByteBuffer shr 8;
+ OutPtr^.B2 := Byte(LByteBuffer);
+ LByteBuffer := LByteBuffer shr 8;
+ OutPtr^.B1 := Byte(LByteBuffer);
+ LByteBuffer := 0;
Inc(OutPtr);
- lByteBufferSpace := 4;
+ LByteBufferSpace := 4;
end;
- ByteBuffer := lByteBuffer;
- ByteBufferSpace := lByteBufferSpace;
- Result := Cardinal(OutPtr) - Cardinal(@OutputBuffer);
+ ByteBuffer := LByteBuffer;
+ ByteBufferSpace := LByteBufferSpace;
+ Result := SizeInt(TJclAddr(OutPtr) - TJclAddr(@OutputBuffer));
end
else
Result := 0;
end;
-//------------------------------------------------------------------------------
-function MimeDecodePartialEnd(var OutputBuffer; const ByteBuffer: Cardinal;
- const ByteBufferSpace: Cardinal): Cardinal;
+function MimeDecodePartialEnd(out OutputBuffer; const ByteBuffer: Cardinal;
+ const ByteBufferSpace: Cardinal): SizeInt;
var
- lByteBuffer: Cardinal;
+ LByteBuffer: Cardinal;
begin
case ByteBufferSpace of
1:
begin
- lByteBuffer := ByteBuffer shr 2;
- PByte3(@OutputBuffer).B2 := Byte(lByteBuffer);
- lByteBuffer := lByteBuffer shr 8;
- PByte3(@OutputBuffer).B1 := Byte(lByteBuffer);
+ LByteBuffer := ByteBuffer shr 2;
+ PByte3(@OutputBuffer)^.B2 := Byte(LByteBuffer);
+ LByteBuffer := LByteBuffer shr 8;
+ PByte3(@OutputBuffer)^.B1 := Byte(LByteBuffer);
Result := 2;
end;
2:
begin
- lByteBuffer := ByteBuffer shr 4;
- PByte3(@OutputBuffer).B1 := Byte(lByteBuffer);
+ LByteBuffer := ByteBuffer shr 4;
+ PByte3(@OutputBuffer)^.B1 := Byte(LByteBuffer);
Result := 1;
end;
else
@@ -906,5 +879,106 @@ begin
end;
end;
+
+function MimeEncodeString(const S: AnsiString): AnsiString;
+var
+ L: SizeInt;
+begin
+ if S <> '' then
+ begin
+ L := Length(S);
+ SetLength(Result, MimeEncodedSize(L));
+ MimeEncode(PAnsiChar(S)^, L, PAnsiChar(Result)^);
+ end
+ else
+ Result := '';
+end;
+
+
+function MimeDecodedSize(const InputSize: SizeInt): SizeInt;
+begin
+ Result := (InputSize + 3) div 4 * 3;
+end;
+
+
+function MimeDecodeString(const S: AnsiString): AnsiString;
+var
+ ByteBuffer, ByteBufferSpace: Cardinal;
+ L: SizeInt;
+ P, R: PAnsiChar;
+begin
+ if S <> '' then
+ begin
+ L := Length(S);
+ SetLength(Result, MimeDecodedSize(L));
+ ByteBuffer := 0;
+ ByteBufferSpace := 4;
+ P := PAnsiChar(S);
+ R := PAnsiChar(Result);
+ L := MimeDecodePartial(P^, L, R^, ByteBuffer, ByteBufferSpace);
+ Inc(R, L);
+ Inc(L, MimeDecodePartialEnd(R^, ByteBuffer, ByteBufferSpace));
+ SetLength(Result, L);
+ end
+ else
+ Result := '';
+end;
+
+
+procedure MimeEncodeStream(const InputStream: TStream; const OutputStream: TStream);
+var
+ InputBuffer: array [0..MIME_BUFFER_SIZE - 1] of Byte;
+ OutputBuffer: array [0..(MIME_BUFFER_SIZE + 2) div 3 * 4 + MIME_BUFFER_SIZE div MIME_DECODED_LINE_BREAK * 2 - 1] of Byte;
+ BytesRead: SizeInt;
+ IDelta, ODelta: SizeInt;
+ I, O: PByte;
+begin
+ InputBuffer[0] := 0;
+ BytesRead := InputStream.Read(InputBuffer, SizeOf(InputBuffer));
+
+ while BytesRead = Length(InputBuffer) do
+ begin
+ MimeEncodeFullLines(InputBuffer, Length(InputBuffer), OutputBuffer);
+ OutputStream.Write(OutputBuffer, Length(OutputBuffer));
+ BytesRead := InputStream.Read(InputBuffer, Length(InputBuffer));
+ end;
+
+ MimeEncodeFullLines(InputBuffer, BytesRead, OutputBuffer);
+
+ IDelta := BytesRead div MIME_DECODED_LINE_BREAK; // Number of lines processed.
+ ODelta := IDelta * (MIME_ENCODED_LINE_BREAK + 2);
+ IDelta := IDelta * MIME_DECODED_LINE_BREAK;
+
+ I := @InputBuffer;
+ Inc(I, IDelta);
+ O := @OutputBuffer;
+ Inc(O, ODelta);
+
+ MimeEncodeNoCRLF(I^, BytesRead - IDelta, O^);
+
+ OutputStream.Write(OutputBuffer, MimeEncodedSize(BytesRead));
+end;
+
+
+procedure MimeDecodeStream(const InputStream: TStream; const OutputStream: TStream);
+var
+ ByteBuffer, ByteBufferSpace: Cardinal;
+ InputBuffer: array [0..MIME_BUFFER_SIZE - 1] of Byte;
+ OutputBuffer: array [0..(MIME_BUFFER_SIZE + 3) div 4 * 3 - 1] of Byte;
+ BytesRead: SizeInt;
+begin
+ ByteBuffer := 0;
+ ByteBufferSpace := 4;
+ InputBuffer[0] := 0;
+ BytesRead := InputStream.Read(InputBuffer, SizeOf(InputBuffer));
+
+ while BytesRead > 0 do
+ begin
+ OutputStream.Write(OutputBuffer, MimeDecodePartial(InputBuffer, BytesRead, OutputBuffer, ByteBuffer, ByteBufferSpace));
+ BytesRead := InputStream.Read(InputBuffer, Length(InputBuffer));
+ end;
+ OutputStream.Write(OutputBuffer, MimeDecodePartialEnd(OutputBuffer, ByteBuffer, ByteBufferSpace));
+end;
+
end.