[Back to WIN-OS2 SWAG index]  [Back to Main SWAG index]  [Original]

{
        Useful for transferring  objects which have been registered to the clipboard or any global memory situation.
        Also could be used to make a copy of any streamable object. Merely stream the object to memory and then
        re-instantiate a new object through the use of a TStream.Get. Solves the
        problem of passing objects to another program because it removes any method pointer info.

        NOTE: This works only for streams which are not larger than 64K. In order
                                to make this work for larger streams you have to ensure that your
                                writes and puts (and gets and reads...) don't straddle each 64K boundary.
                                I haven't added the pointer math to this unit yet.
}

{ Author Robert Warren CIS ID 70303,537 }

Unit MemStream;

interface

        Uses WinTypes,WinProcs, WObjects;

        type

                PMemStream = ^TMemStream;
                TMemStream = object(TStream)

                                Handle: Word;
                                Address: Pointer;
                                Size: Longint;       { allocated size }
                                Position: Longint;   { current position in stream }
                                AllocFlags: LongInt; { flags required when allocating / reallocating }
                                FreeMemory: Boolean; { Flag indicating whether to free global
                                                                                                                         memory when disposing of object }

                        constructor Init(AllocSize: Longint; Flags: LongInt; FreeMem: Boolean);
                        constructor InitWithHandle(aHandle: THandle; Flags: LongInt; FreeMem: Boolean);
                        destructor Done; virtual;
                        function GetPos: Longint; virtual;
                        procedure Grow(howMuch: LongInt); virtual;
                        function GetSize: Longint; virtual;
                        procedure Read(var Buf; Count: Word); virtual;
                        procedure Write(var Buf; Count: Word); virtual;
                        procedure Seek(Pos: Longint); virtual;
                        procedure Truncate; virtual;
                end;

implementation

{
 creates a memory stream of given size using the flags. The FreeMem argument
 is used to determine whether to delete the global block of memory when the
 object is disposed of. Sometime you don't want to delete the block if for
 example it has been placed in the clipboard or passed using DDE.
}
constructor TMemStream.Init(AllocSize: Longint; Flags: LongInt;FreeMem: Boolean);
begin
 TStream.Init;
 Handle:=GlobalAlloc( Flags, AllocSize);
 Address:=GlobalLock(Handle); { so much for real mode }
 Size:=AllocSize;
 Position:=0;
 FreeMemory:= FreeMem;
end;

{
 same as above but allows for the creation of a object given an already
 allocated memory block. Perhaps some data FROM a clipboard
}
constructor TMemStream.InitWithHandle(aHandle: THandle; Flags: LongInt;FreeMem: Boolean);
begin
 TStream.Init;
 Size:=GlobalSize(Handle);
 Address:=GlobalLock(Handle);
 Position:=0;
 FreeMemory:= FreeMem;
end;


destructor TMemStream.Done;
begin
 TStream.Done;
 GlobalUnlock(Handle);
 If FreeMemory then GlobalFree(Handle);
end;

function TMemStream.GetPos: LongInt;
begin
        GetPos:=Position;
end;

function TMemStream.GetSize: LongInt;
begin
        GetSize:=Size;
end;


procedure TMemStream.Read(var Buf; Count: Word);
var
 varAddress: PChar;
 stAddress: PChar;
 i: LongInt;
begin
 varAddress:=@Buf;
 stAddress:=PChar(MakeLong(Position+LoWord(LongInt(Address)),HiWord(LongInt(Address))));
 for i:=0 to Count -1 do
         varAddress[i]:=stAddress[i];
 inc(Position,Count);
end;

procedure TMemStream.Grow(HowMuch: LongInt);
begin
 GlobalUnlock(Handle);
 Inc(Size,HowMuch);
 GlobalRealloc(Handle, Size, AllocFlags);
 GlobalLock(Handle);
end;

procedure TMemStream.Write(var Buf; Count: Word);
var
 varAddress: PChar;
 stAddress: PChar;
 i: LongInt;
 growSize: Integer;
begin

 if Position + Count >= Size then
         begin
                if count < 1023
                         then growSize:=1024
                         else growSize:=count + 1;

                Grow(growSize);
         end;

 varAddress:=@Buf;
 stAddress:=PChar(MakeLong(Position+LoWord(LongInt(Address)),HiWord(LongInt(Address))));
 for i:=0 to Count -1 do
         stAddress[i]:=varAddress[i];
 inc(Position,Count);
end;

procedure TMemStream.Seek(Pos: Longint);
begin
 Position:=Pos;
end;

procedure TMemStream.Truncate;
begin
        GlobalUnlock(Handle);
        GlobalReAlloc(Handle,Position,AllocFlags);
        Address:=GlobalLock(Handle);
        Size:=Position;
end;

end.


[Back to WIN-OS2 SWAG index]  [Back to Main SWAG index]  [Original]