Results 1 to 3 of 3

Thread: Reading and writing Variants efficently?

  1. #1

    Reading and writing Variants efficently?

    Ok, I know how to do this, I am just hoping that there is an easier way before I write the long case statements required . Basically for my TTCPServer for SDL I want to add support for Variants. This means writing the size of the variant and then the data block. Why go through all this trouble and not just write a full sized variant? Simple effeciency on the pipe. If I can get away with writing 2 bytes (integer) instead of 255 bytes (string) then I'm better off. Not to mention that SizeOf doesn't work on AnsiString Variants .

    Seems like you used to be able to do something like:[pascal]
    var
    varData : Tvardata;
    varSize : Cardinal;
    varPtr : Pointer;
    begin
    varData := TVarData(V);
    varSize := varData.Size;
    varPtr := @varData.vbytes[0];
    end;[/pascal]

    But this doesn't seem to work any more, of course I'm a bit rusty on Variants. Right now I'm not looking at variant arrays, I know they require loops and scanning of the entire variant record type. Any ideas on an effecient way instead of hand coding every single frigging thing?

  2. #2

    Reading and writing Variants efficently?

    Ok, here is my first attempt (that fails). Can anyone spot what I'm doing wrong?

    [pascal]uses
    Variants;

    Function GetVariantSize(v : Variant): Integer;
    var
    vt: TVarType;
    Begin
    vt := TVarData(v).vtype;
    Result := -1;
    Case vt Of
    varSmallint : Result := Sizeof( SmallInt );
    varInteger : Result := Sizeof( Integer );
    varSingle : Result := Sizeof( Single );
    varDouble : Result := Sizeof( Double );
    varCurrency : Result := Sizeof( Currency );
    varDate : Result := Sizeof( TDateTime );
    //varOleStr : Result := Sizeof( Widestring );
    varDispatch : Result := Sizeof( Pointer );
    varError : Result := Sizeof( Cardinal );
    varBoolean : Result := Sizeof( WordBool );
    varVariant : Result := Sizeof( Variant );
    varUnknown : Result := Sizeof( Pointer );
    varShortInt : Result := Sizeof( ShortInt );
    varByte : Result := Sizeof( Byte );
    varWord : Result := Sizeof( Word );
    varLongWord : Result := Sizeof( LongWord );
    varInt64 : Result := Sizeof( Int64 );
    varOleStr,// : Result := Sizeof( Widestring );
    varString : Result := Length(AnsiString(v));
    End; { Case }
    End;

    { TForm1 }

    procedure TForm1.Button1Click(Sender: TObject);
    var
    v2,
    v : Variant;
    vd: TVarData;
    vt: tvartype;
    i : Integer;
    ms: TMemoryStream;
    procedure WriteBlock(p : Pointer; siz : Cardinal);
    begin
    ms.WriteBuffer(siz, sizeof(siz));
    ms.WriteBuffer(p, siz);
    end;
    procedure ReadBlock(p : Pointer);
    var
    siz : Cardinal;
    begin
    ms.ReadBuffer(siz, sizeof(siz));
    ms.ReadBuffer(p, siz);
    end;
    procedure WriteString(s:AnsiString);
    begin
    WriteBlock(@s[1], length(s));
    end;
    function ReadString : AnsiString;
    var
    siz : Cardinal;
    begin
    ms.ReadBuffer(siz, sizeof(siz));
    setlength(ReadString, siz);
    ms.ReadBuffer(ReadString[1], siz);
    end;
    begin
    v := 'asdf';//123;
    vd := TVarData(v);
    vt := vd.vtype;

    ms := TMemoryStream.Create;
    try
    WriteBlock(@vt, SizeOf(vt));
    case vt of
    varString, varOleStr : WriteString(v);
    else
    WriteBlock(@TVarData(v).vwords[0], GetVariantSize(v));
    end;

    ms.Position := 0;
    ReadBlock(@vt);
    case vt of
    varString, varOleStr : v2 := ReadString;
    else
    TVarData(v2).vType := vt;
    ReadBlock(@TVarData(v2).vwords[0]);
    end;
    Memo1.lines.Add(v2);
    finally
    ms.Free;
    end;
    end;
    [/pascal]

  3. #3

    Reading and writing Variants efficently?

    You need a couple of extra "^", this is working:

    [pascal]procedure TForm1.Button1Click(Sender: TObject);
    var
    v2,
    v : Variant;
    vd: TVarData;
    vt: tvartype;
    i : Integer;
    ms: TMemoryStream;
    procedure WriteBlock(p : Pointer; siz : Cardinal);
    begin
    ms.WriteBuffer(siz, sizeof(siz));
    ms.WriteBuffer(p^, siz);
    end;
    procedure ReadBlock(p : Pointer);
    var
    siz : Cardinal;
    begin
    ms.ReadBuffer(siz, sizeof(siz));
    ms.ReadBuffer(p^, siz);
    end;
    procedure WriteString(s:AnsiString);
    begin
    WriteBlock(@s[1], length(s));
    end;
    function ReadString : AnsiString;
    var
    siz : Cardinal;
    begin
    ms.ReadBuffer(siz, sizeof(siz));
    setlength(Result, siz);
    ms.ReadBuffer(Result[1], siz);
    end;
    begin
    v := 'asdf';//123;
    vd := TVarData(v);
    vt := vd.vtype;

    ms := TMemoryStream.Create;
    try
    WriteBlock(@vt, SizeOf(vt));
    case vt of
    varString, varOleStr : WriteString(v);
    else
    WriteBlock(@TVarData(v).vwords[0], GetVariantSize(v));
    end;

    ms.Position := 0;
    ReadBlock(@vt);
    case vt of
    varString, varOleStr : v2 := ReadString;
    else
    TVarData(v2).vType := vt;
    ReadBlock(@TVarData(v2).vwords[0]);
    end;
    Button1.Caption := v2;
    finally
    ms.Free;
    end;
    end;
    [/pascal]
    ZGameEditor - Develop 64kb games for Windows.
    Thrust for Vectrex - ROM-file and 6809 source code.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •