summaryrefslogtreecommitdiff
path: root/plugins/MirandaNGHistoryToDB/MapStream.pas
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/MirandaNGHistoryToDB/MapStream.pas')
-rw-r--r--plugins/MirandaNGHistoryToDB/MapStream.pas185
1 files changed, 185 insertions, 0 deletions
diff --git a/plugins/MirandaNGHistoryToDB/MapStream.pas b/plugins/MirandaNGHistoryToDB/MapStream.pas
new file mode 100644
index 0000000000..af0b67409a
--- /dev/null
+++ b/plugins/MirandaNGHistoryToDB/MapStream.pas
@@ -0,0 +1,185 @@
+{ ############################################################################ }
+{ # # }
+{ # MirandaNG HistoryToDB Plugin v2.5 # }
+{ # # }
+{ # License: GPLv3 # }
+{ # # }
+{ # Author: Grigorev Michael (icq: 161867489, email: sleuthhound@gmail.com) # }
+{ # # }
+{ ############################################################################ }
+
+//*****************************************************************//
+// //
+// TMapStream //
+// Copyright© BrandsPatch LLC //
+// http://www.explainth.at //
+// //
+// All Rights Reserved //
+// //
+// Permission is granted to use, modify and redistribute //
+// the code in this Delphi unit on the condition that this //
+// notice is retained unchanged. //
+// //
+// BrandsPatch declines all responsibility for any losses, //
+// direct or indirect, that may arise as a result of using //
+// this code. //
+// //
+//*****************************************************************//
+unit MapStream;
+
+interface
+
+uses Windows, SysUtils, Classes, SyncObjs;
+
+const MAXINTMINUS = MAXINT - 1;
+
+type TMapBytes = array[0..MAXINTMINUS] of Byte;
+ PMapBytes = ^TMapBytes;
+
+type TMapStream = class(TObject)
+private
+ FHandle: THandle;
+ FPosition: Integer;
+ FSize: Integer;
+ FTimeOut: Integer;
+ procedure SetPosition(Value: Integer);
+ function CountGood(Count: Integer):Boolean;
+ function GrabEvent: Boolean;
+ procedure ReleaseEvent;
+protected
+ FEvent: TEvent;
+ FMemory: PMapBytes;
+public
+ property Position: Integer read FPosition write SetPosition;
+ constructor CreateEx(const AName: String; ASize,ATimeOut: Integer);
+ destructor Destroy; override;
+ function Clear: Boolean;
+ function CopyFrom(AStream: TStream;Count: Integer): Boolean;
+ function ReadBuffer(P: Pointer; Count: Integer): Boolean;
+ function WriteBuffer(P: Pointer; Count: Integer): Boolean;
+end;
+
+type ENoMapping = class(Exception);
+
+implementation
+
+// MapStream Create & Destroy
+constructor TMapStream.CreateEx(const AName:String;ASize,ATimeOut:Integer);
+begin
+ inherited Create;
+ FSize := ASize;
+ FTimeOut := ATimeOut;
+ if (FSize < 1) or (FSize > MAXINTMINUS) then FSize:=MAXWORD;
+ if (FTimeOut < 1) or (FTimeOut > 5000) then FTimeOut:=2000;
+ //2000ms timeout for safety
+ FHandle:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,FSize,PChar(AName));
+ //See the Windows Kernel32 CreateFileMapping function for information
+ if (FHandle = 0) then ENoMapping.Create(Format('%s file mapping failed.',[AName]))
+ else begin
+ FMemory:=MapViewOfFile(FHandle,FILE_MAP_ALL_ACCESS,0,0,0);
+
+ FEvent:=TEvent.Create(nil,True,True,Format('ExplainThat_%s_MAP',[AName]));
+ {1. map a view of the file mapping into the address
+ space of the parent application
+
+ 2. create an event to prevent simultaneous access
+ to the map by different apps. We try to make the
+ event name unique so we don't end up with a handle to
+ an unrelated event that already exists
+ }
+ end;
+end;
+
+destructor TMapStream.Destroy;
+begin
+ UnMapViewOfFile(FMemory);
+ CloseHandle(FHandle);
+ FEvent.Free;
+ inherited;
+end;
+
+function TMapStream.CountGood(Count:Integer):Boolean;
+begin
+ Result:=(FPosition + Count < FSize);
+end;
+
+function TMapStream.GrabEvent:Boolean;
+begin
+ Result:=True;
+ with FEvent do
+ begin
+ case WaitFor(FTimeOut) of
+ wrSignaled:ReSetEvent;
+ {locks the event for exclusive use by this app. Funny name, ReSetEvent, not
+ our choice!}
+ else Result:=False;
+ end;
+ end;
+end;
+
+procedure TMapStream.ReleaseEvent;
+begin
+ FEvent.SetEvent; //unlock the event so other apps can use it
+end;
+
+// MapStream Manipulation
+function TMapStream.Clear:Boolean;
+begin
+ if GrabEvent then
+ try
+ FillChar(FMemory^[0],FSize,0);
+ FPosition:=0;
+ Result:=True;
+ finally ReleaseEvent end else Result:=False;
+end;
+
+function TMapStream.CopyFrom(AStream:TStream;Count:Integer):Boolean;
+
+ function SizeGood:Boolean;
+ var i,ASize:Integer;
+ begin
+ ASize:=AStream.Size;
+ if (Count = 0) or (Count > ASize) then
+ begin
+ Count:=ASize;
+ AStream.Position:=0;
+ end;
+ Result:=(FPosition + Count < FSize);
+ {make sure the copy block is not too big. Incidentally, also make Count = 0
+ as in Delphi.TStream}
+ end;
+
+begin
+ if SizeGood and GrabEvent then
+ try
+ AStream.ReadBuffer(Byte(FMemory^[FPosition]),Count);
+ Result:=True;
+ finally ReleaseEvent end else Result:=False;
+end;
+
+function TMapStream.ReadBuffer(P:Pointer;Count:Integer):Boolean;
+begin
+ if CountGood(Count) and GrabEvent then
+ try
+ Move(FMemory^[FPosition],P^,Count);
+ inc(FPosition,Count);
+ Result:=True;
+ finally ReleaseEvent end else Result:=False;
+end;
+
+function TMapStream.WriteBuffer(P:Pointer;Count:Integer):Boolean;
+begin
+ if CountGood(Count) and GrabEvent then
+ try
+ Move(P^,FMemory^[FPosition],Count);
+ inc(FPosition,Count);
+ Result:=True;
+ finally ReleaseEvent end else Result:=False;
+end;
+
+procedure TMapStream.SetPosition(Value:Integer);
+begin
+ if (Value < FSize) and (Value >= 0) then FPosition:=Value;
+end;
+
+end.