Recent

Author Topic: Reading variant from a stream  (Read 3393 times)

Renat.Su

  • Full Member
  • ***
  • Posts: 232
    • Renat.Su
Re: Reading variant from a stream
« Reply #15 on: February 24, 2018, 04:05:50 pm »
So stupid ... Apparently, only the first 16 bytes are significant?
That's what ASerge already pointed out in his first post.
I look stupid, inattentively read it  :-[

ASerge

  • Hero Member
  • *****
  • Posts: 2246
Re: Reading variant from a stream
« Reply #16 on: February 24, 2018, 06:43:03 pm »
An example of safer use of Variant with streams:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$APPTYPE CONSOLE}
  3.  
  4. uses SysUtils, Classes, Variants;
  5.  
  6. type
  7.   TStreamWithVariant = class helper for TStream
  8.     function ReadVariant: Variant;
  9.     procedure WriteVariant(const Value: Variant);
  10.   end;
  11.  
  12. function TStreamWithVariant.ReadVariant: Variant;
  13.  
  14.   function ReadPWideChar: PWideChar;
  15.   var
  16.     Len: Cardinal;
  17.     U: UnicodeString = '';
  18.   begin
  19.     Len := ReadDWord;
  20.     if Len > 0 then
  21.     begin
  22.       SetLength(U, Len);
  23.       ReadBuffer(Pointer(U)^, Len * SizeOf(WideChar));
  24.     end;
  25.     Result := StringToOleStr(U);
  26.   end;
  27.  
  28.   procedure ReadString(var V: TVarData);
  29.   begin
  30.     V.VString := nil;
  31.     string(V.VString) := ReadAnsiString;
  32.   end;
  33.  
  34. var
  35.   V: TVarData absolute Result;
  36. begin
  37.   VarClear(Result);
  38.   V.VType := ReadWord;
  39.   if (V.VType and not varTypeMask) <> 0 then // (varByRef or varArray)
  40.     Exit;  // not supported yet - ignore
  41.   case V.VType of
  42.     varEmpty, varNull, varUnknown:
  43.        { All done };
  44.     varBoolean, varShortInt, varByte:
  45.       V.VByte := ReadByte;
  46.     varSmallInt, varWord:
  47.       V.VWord := ReadWord;
  48.     varInteger, varSingle, varError, varLongWord:
  49.       V.VLongWord := ReadDWord;
  50.     varDouble, varDate, varCurrency, varInt64, varQword{, varWord64, varUint64}:
  51.       V.VQword := ReadQWord;
  52.     varString:
  53.       ReadString(V);
  54.     varOleStr:
  55.       V.VOleStr := ReadPWideChar;
  56.     varDispatch, varAny, varRecord:
  57.       { not Supported - ignore };
  58.   else
  59.     Assert(True, 'Unknown Variant type');
  60.   end;
  61. end;
  62.  
  63. procedure TStreamWithVariant.WriteVariant(const Value: Variant);
  64.  
  65.   procedure WritePWideChar(P: PWideChar);
  66.   var
  67.     Len: Cardinal;
  68.   begin
  69.     Len := Length(P);
  70.     WriteDWord(Len);
  71.     if Len > 0 then
  72.       WriteBuffer(P^, Len * SizeOf(WideChar));
  73.   end;
  74.  
  75. var
  76.   V: TVarData absolute Value;
  77. begin
  78.   WriteWord(V.VType);
  79.   if (V.VType and not varTypeMask) <> 0 then // (varByRef or varArray)
  80.     Exit;  // not supported yet - ignore
  81.   case V.VType of
  82.     varEmpty, varNull, varUnknown:
  83.        { All done };
  84.     varBoolean, varShortInt, varByte:
  85.       WriteByte(V.VByte);
  86.     varSmallInt, varWord:
  87.       WriteWord(V.VWord);
  88.     varInteger, varSingle, varError, varLongWord:
  89.       WriteDWord(V.VLongWord);
  90.     varDouble, varDate, varCurrency, varInt64, varQword{, varWord64, varUint64}:
  91.       WriteQWord(V.VQword);
  92.     varString:
  93.       WriteAnsiString(string(V.VString));
  94.     varOleStr:
  95.       WritePWideChar(V.VOleStr);
  96.     varDispatch, varAny, varRecord:
  97.       { not Supported - ignore };
  98.   else
  99.     Assert(True, 'Unknown Variant type');
  100.   end;
  101. end;
  102.  
  103. var
  104.   Stream: TMemoryStream;
  105.   Data: Variant;
  106.   i: Integer;
  107. begin
  108.   Data := VarArrayOf(['1111', 22, 3333, 4444444444444, 55.55, PWideChar('6666'), 7e77, Now]);
  109.   Stream := TMemoryStream.Create;
  110.   try
  111.     for i := VarArrayLowBound(Data, 1) to VarArrayHighBound(Data, 1) do
  112.       Stream.WriteVariant(Data[i]);
  113.     Stream.Position := 0;
  114.     for i := VarArrayLowBound(Data, 1) to VarArrayHighBound(Data, 1) do
  115.       Writeln(Stream.ReadVariant);
  116.   finally
  117.     Stream.Free;
  118.   end;
  119.   Readln;
  120. end.

 

TinyPortal © 2005-2018