From a212dbd74c3c097c692528db981eae6249519a53 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Sun, 16 Mar 2014 08:42:46 +0000 Subject: [PATCH] Added: Win64 compatibility Fixed: XML persist reader creating sections Fixed: new MIME implementation for XMLDataBindingUtils --- Packages/DXE2/X2Utils.dproj | 46 +++- Packages/DXE2/X2Utils.res | Bin 27432 -> 27432 bytes X2UtPersistXML.pas | 5 +- XMLDataBindingUtils.pas | 500 +++++++++++++++++++++--------------- 4 files changed, 329 insertions(+), 222 deletions(-) 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 e43db4316777713c6519ae16cb15f008273bfd66..df7d05824cab9f268c78f0458188fc0a779e7b37 100644 GIT binary patch delta 14 VcmZ2+jd8^_#tkajEX)iH3;- 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.