[Back to STREAMS SWAG index] [Back to Main SWAG index] [Original]
{
Streams : stream su aree di memoria.
}
unit Streams;
{$V-}
{$IFDEF Final} { Remove debug code for final version}
{$D-,I-,L-,R-,S-,G+}
{$ELSE}
{$D+,I+,L+,R+,S+}
{$ENDIF}
interface
uses
Objects,
Strings,
Arit;
{--------------------- Classe TMemStream : stream su aree di memoria (< 64KB) }
type
PMemStream = ^TMemStream;
TMemStream = object(TStream)
constructor Init(BlockPtr : PChar; BlockSize : word);
destructor Done; virtual;
function GetPos : longint; virtual;
function GetSize : longint; virtual;
procedure Read(var Buf; Count : word); virtual;
procedure Seek(Pos : longint); virtual;
procedure Truncate; virtual;
procedure Write(var Buf; Count : word); virtual;
private
StartPtr,CurPtr : PChar;
Size : word;
end;
{------------------ Classe TBigMemStream : stream su aree di memoria (> 64KB) }
type
TLongRec = record
case integer of
0 : (L : longint);
1 : (LoW : word;
HiW : word);
end;
PBigMemStream = ^TBigMemStream;
TBigMemStream = object(TStream)
constructor Init(BlockPtr : PChar; BlockSize : longint);
destructor Done; virtual;
function GetPos : longint; virtual;
function GetSize : longint; virtual;
procedure Read(var Buf; Count : word); virtual;
procedure Seek(Pos : longint); virtual;
procedure Truncate; virtual;
procedure Write(var Buf; Count : word); virtual;
private
MemOfs : word;
MemSeg : word;
CurPos : TLongRec;
Size : longint;
end;
{------------------------------------------- Classe TBuffer : buffer dinamici }
type
PBuffer = ^TBuffer;
TBuffer = object(TObject)
Size,Len,AllocSize : word;
BufPtr : PChar;
constructor Init(StartSize,Alloc : word);
destructor Done; virtual;
function GetLen : word;
function GetBuffer : PChar;
procedure Append(const Buf; Count : word);
procedure Insert(var Buf; Count : word; Pos : word);
procedure AppendChar(C : char);
procedure AppendStr(S : PChar);
procedure Overwrite(var Buf; Count : word; Pos : word);
procedure Reset;
procedure Truncate(NewLen : word);
procedure Delete(From,N : word);
private
procedure Realloc(NewLen : word);
end;
{--------------- Classe TAllocStream : stream di scrittura su buffer dinamici }
type
PAllocStream = ^TAllocStream;
TAllocStream = object(TStream)
constructor Init(StartSize,Alloc : word);
destructor Done; virtual;
function GetPos : longint; virtual;
function GetSize : longint; virtual;
procedure Seek(Pos : longint); virtual;
procedure Truncate; virtual;
procedure Write(var Buf; Count : word); virtual;
function GetBuffer : PChar;
private
CurPos : word;
Buffer : TBuffer;
end;
{----------------- Classe TSCollection : collection non ordinate di stringhe }
type
PSCollection = ^TSCollection;
TSCollection = object(TCollection)
procedure FreeItem(Item : pointer); virtual;
end;
{-------------------------- Classe TErrCollection : gestione error metodo At }
type
PErrCollection = ^TErrCollection;
TErrCollection = object(TCollection)
procedure Error(Code,Info : integer); virtual;
end;
implementation {==============================================================}
uses
WinTypes,
WinProcs;
{----------------- Metodi di TMemStream : stream su aree di memoria (< 64 KB) }
constructor TMemStream.Init(BlockPtr : PChar; BlockSize : word);
begin
inherited Init;
StartPtr := BlockPtr;
CurPtr := BlockPtr;
Size := BlockSize;
end; { Init }
destructor TMemStream.Done;
begin
StartPtr := nil;
CurPtr := nil;
Size := 0;
inherited Done;
end; { Done }
function TMemStream.GetPos : longint;
begin
GetPos := CurPtr-StartPtr;
end; { GetPos }
function TMemStream.GetSize : longint;
begin
GetSize := Size;
end; { GetSize }
procedure TMemStream.Read(var Buf; Count : word);
begin
if Status = stOk then begin
if (CurPtr-StartPtr)+Count > Size then begin
FillChar(Buf,Count,0);
Error(stReadError,0);
end else begin
move(CurPtr^,Buf,Count);
inc(CurPtr,Count);
end;
end;
end; { Read }
procedure TMemStream.Seek(Pos : longint);
begin
if Pos >= Size then Error(stReadError,0)
else CurPtr := StartPtr+Pos;
end; { Seek }
procedure TMemStream.Truncate;
begin
CurPtr := StartPtr;
end; { Truncate }
procedure TMemStream.Write(var Buf; Count : word);
begin
if Status = stOk then begin
if (CurPtr-StartPtr)+Count > Size then
Error(stWriteError,0)
else begin
move(Buf,CurPtr^,Count);
inc(CurPtr,Count);
end;
end;
end; { Write }
{-------------- Metodi di TBigMemStream : stream su aree di memoria (> 64 KB) }
procedure AHIncr; far; external 'KERNEL' index 114;
constructor TBigMemStream.Init(BlockPtr : PChar; BlockSize : longint);
begin
TStream.Init;
MemSeg := Seg(BlockPtr^);
MemOfs := Ofs(BlockPtr^);
CurPos.L := 0;
Size := BlockSize;
end; { Init }
destructor TBigMemStream.Done;
begin
MemSeg := 0;
MemOfs := 0;
CurPos.L := 0;
Size := 0;
end; { Done }
function TBigMemStream.GetPos : longint;
begin
GetPos := CurPos.L;
end; { GetPos }
function TBigMemStream.GetSize : longint;
begin
GetSize := Size;
end; { GetSize }
procedure TBigMemStream.Read(var Buf; Count : word);
var
CurPtr : pointer;
BufPtr : PChar;
MaxCount : longint;
begin
if Status = stOk then begin
if CurPos.L+Count > Size then begin
FillChar(Buf,Count,0);
Error(stReadError,0);
end else begin
CurPtr := Ptr(MemSeg+CurPos.HiW*Ofs(AHIncr),MemOfs+CurPos.LoW);
BufPtr := @Buf;
MaxCount := 65536-CurPos.LoW;
if Count > MaxCount then begin
move(CurPtr^,Buf,MaxCount);
inc(CurPos.L,MaxCount);
dec(Count,MaxCount);
inc(BufPtr,MaxCount);
CurPtr := Ptr(MemSeg+CurPos.HiW*Ofs(AHIncr),MemOfs+CurPos.LoW);
end;
move(CurPtr^,BufPtr^,Count);
inc(CurPos.L,Count);
end;
end;
end; { Read }
procedure TBigMemStream.Seek(Pos : longint);
begin
if Pos >= Size then Error(stReadError,0)
else CurPos.L := Pos;
end; { Seek }
procedure TBigMemStream.Truncate;
begin
CurPos.L := 0;
end; { Truncate }
procedure TBigMemStream.Write(var Buf; Count : word);
var
CurPtr : pointer;
BufPtr : PChar;
MaxCount : longint;
begin
if Status = stOk then begin
if CurPos.L+Count > Size then
Error(stWriteError,0)
else begin
CurPtr := Ptr(MemSeg+CurPos.HiW*Ofs(AHIncr),MemOfs+CurPos.LoW);
BufPtr := @Buf;
MaxCount := 65536-CurPos.LoW;
if Count > MaxCount then begin
move(Buf,CurPtr^,MaxCount);
inc(CurPos.L,MaxCount);
dec(Count,MaxCount);
inc(BufPtr,MaxCount);
CurPtr := Ptr(MemSeg+CurPos.HiW*Ofs(AHIncr),MemOfs+CurPos.LoW);
end;
move(BufPtr^,CurPtr^,Count);
inc(CurPos.L,Count);
end;
end;
end; { Write }
{---------------------------------------------------------- Metodi di TBuffer }
constructor TBuffer.Init(StartSize,Alloc : word);
begin
Size := StartSize;
AllocSize := Max(16,Alloc);
Len := 0;
if Size = 0 then BufPtr := nil
else begin
GetMem(BufPtr,Size);
FillChar(BufPtr^,Size,0);
end;
end; { Init }
destructor TBuffer.Done;
begin
if BufPtr <> nil then FreeMem(BufPtr,Size);
end; { Done }
function TBuffer.GetLen : word;
begin
GetLen := Len;
end; { GetLen }
function TBuffer.GetBuffer : PChar;
begin
GetBuffer := BufPtr;
end; { GetBuffer }
procedure TBuffer.Realloc(NewLen : word);
var
Temp : PChar;
begin
NewLen := ((NewLen+AllocSize) div AllocSize)*AllocSize;
GetMem(Temp,NewLen);
FillChar(Temp^,NewLen,#0);
if BufPtr <> nil then begin
move(BufPtr^,Temp^,Min(Len,NewLen));
FreeMem(BufPtr,Size);
end;
if (NewLen > Len) then FillChar(Temp[Len],NewLen-Len,#0);
BufPtr := Temp;
Size := NewLen;
end; { Realloc }
procedure TBuffer.Append(const Buf; Count : word);
begin
if Len+Count >= Size then Realloc(Len+Count+1);
move(Buf,BufPtr[Len],Count);
inc(Len,Count);
end; { Append }
procedure TBuffer.Insert(var Buf; Count : word; Pos : word);
begin
if InRange(Pos,0,Len) then begin
if Len+Count >= Size then Realloc(Len+Count+1);
if Len > Pos then move(BufPtr[Pos],BufPtr[Pos+Count],Len-Pos);
move(Buf,BufPtr[Pos],Count);
inc(Len,Count);
end;
end; { Insert }
procedure TBuffer.AppendChar(C : char);
begin
if Len+1 >= Size then Realloc(Len+2);
BufPtr[Len] := C;
inc(Len);
end; { AppendChar }
procedure TBuffer.AppendStr(S : PChar);
begin
if S <> nil then Append(S^,StrLen(S));
end; { AppendStr }
procedure TBuffer.Overwrite(var Buf; Count : word; Pos : word);
begin
if InRange(Pos,0,pred(Len)) then begin
Count := Min(Count,Len-Pos);
move(Buf,BufPtr[Pos],Count);
end;
end; { Overwrite }
procedure TBuffer.Reset;
begin
Len := 0;
FillChar(BufPtr^,Size,#0);
end; { Reset }
procedure TBuffer.Truncate(NewLen : word);
begin
if NewLen < Len then begin
if Size-NewLen > AllocSize then Realloc(NewLen);
Len := NewLen;
FillChar(BufPtr[Len],Size-Len,#0);
end;
end; { Truncate }
procedure TBuffer.Delete(From,N : word);
var
Last : word;
begin
if (From < Len) and (N > 0) then begin
Last := From+N;
if Last < Len then move(BufPtr[Last],BufPtr[From],succ(Len-Last));
Truncate(Len-N);
end;
end; { Delete }
{----------------------------------------------------- Metodi di TAllocStream }
constructor TAllocStream.Init(StartSize,Alloc : word);
begin
inherited Init;
Buffer.Init(StartSize,Alloc);
CurPos := 0;
end; { Init }
destructor TAllocStream.Done;
begin
Buffer.Done;
inherited Done;
end; { Done }
function TAllocStream.GetPos : longint;
begin
GetPos := CurPos;
end; { GetPos }
function TAllocStream.GetSize : longint;
begin
GetSize := Buffer.GetLen;
end; { GetSize }
procedure TAllocStream.Seek(Pos : longint);
begin
if (Pos > Buffer.GetLen) or (Pos < 0) then Error(stWriteError,0)
else CurPos := Pos;
end; { Seek }
procedure TAllocStream.Truncate;
begin
if CurPos < Buffer.GetLen then Buffer.Truncate(succ(CurPos));
end; { Truncate }
procedure TAllocStream.Write(var Buf; Count : word);
var
Len : word;
B : array[0..65000] of char absolute Buf;
begin
if Status = stOk then begin
Len := Buffer.GetLen;
if CurPos >= Len then Buffer.Append(Buf,Count)
else begin
Buffer.Overwrite(Buf,Min(Count,Len-CurPos),CurPos);
if Count > Len-CurPos then
Buffer.Append(B[Len-CurPos],Count-Len+CurPos);
end;
inc(CurPos,Count);
end;
end; { Write }
function TAllocStream.GetBuffer : PChar;
begin
GetBuffer := Buffer.GetBuffer;
end; { GetBuffer }
{----------------- Classe TSCollection : collection non ordinate di stringhe }
procedure TSCollection.FreeItem(Item : pointer);
begin
StrDispose(PChar(Item));
end; { FreeItem }
{-------------------------- Classe TErrCollection : gestione error metodo At }
procedure TErrCollection.Error(Code,Info : integer);
var
ErrDesc : record
ErrCode : integer;
ErrPosHi : word;
ErrPosLo : word;
ErrIndex : integer;
ErrCount : integer;
end;
Buffer : array[0..80] of char;
begin
asm
mov cx,[BP+20]
mov bx,[BP+22]
verr bx
je @1
mov bx,$FFFF
mov cx,bx
jmp @2
@1:
mov es,bx
mov bx,word ptr es:0
@2:
mov ErrDesc.ErrPosLo,cx
mov ErrDesc.ErrPosHi,bx
end;
ErrDesc.ErrCode := 212-Code;
ErrDesc.ErrIndex := Info;
ErrDesc.ErrCount := Count;
WVSPrintF(Buffer,'Runtime error %d at %04X:%04X with index %d; Count=%d',ErrDesc);
MessageBox(0,Buffer,nil,mb_Ok or mb_SystemModal);
halt(0);
end; { Error }
{----------------------------------------------------------------------- Main }
end. { unit Streams }
[Back to STREAMS SWAG index] [Back to Main SWAG index] [Original]