{
    This file is part of Chentrah,
    Copyright (C) 2004-2008 Anton Rzheshevski (chebmaster@mail.ru).

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see http://www.gnu.org/licenses/

 **********************************************************************}

  function _HashesMatch(a, b: pResourceHash): longbool;
  begin
    if not Assigned(a) and not Assigned(b) then Exit(Yes); //nil+nil=true
    if not Assigned(a) or not Assigned(b) then Exit(No);
    Result:=Md5Match(TMd5Digest(a^), TMd5Digest(b^));
  end;



  function HashesMatch(a, b: pResourceHash): longbool; cdecl;
  begin
   try
    Result:=_HashesMatch(a, b);
   except
    ProcessGuardedException();
   end;
  end;

  procedure _GenHash (phash: PResourceHash);
  begin
    phash^.DateTime:=Now;
    phash^.Stamp:=GetTimeStamp;
  end;
  
  
  procedure GenHash (phash: PResourceHash); cdecl;
  begin
   try
    _GenHash(phash);
   except
    ProcessGuardedException();
   end;
  end;
  
 {
  function _ResIndByHash(ph: PResourceHash): integer;
  var
    i: integer;
  begin
    Result:=-1;
    For i:=0 to Res.High do
      if _HashesMatch(ph, Res[i]) then Exit(i);
  end;
}
  procedure _DeleteResRec (ind: integer); //inline;
  begin
    FreeMem(Res[ind]);
    if Res.High > ind then Res[ind]:=Res.Last;
    Res.Length:= Res.Length - 1;
  end;


  function _NewResRec: integer; //inline;
  begin
    Result:=Res.Add(GetMem(SizeOf(TRes)));
    FillChar(Res.Last^, SizeOf(TRes), 0);
    PRes(Res.Last)^.owner := CurrentOwner; //the index of the module it belongs to
  end;


  procedure StoreResource (phandle: pDWORD; phash: PResourceHash); cdecl;
  var
    i: integer;
  begin
   try
    i:=_NewResRec;
    PResourceHash(Res[i])^:=phash^;
    with PRes(Res[i])^ do begin
      Unclaimed:= Yes;
      Handle:=phandle^;
    end;
   except
    ProcessGuardedException();
   end;
  end;


 function ClaimResource (phash: PResourceHash): PRes; cdecl;
 var
   i: integer;
 begin
  try
   Result:=nil;
   For i:=0 to Res.High do
     if _HashesMatch(Res[i], phash) then begin
       Result:=Res[i];
       break
     end;
   except
    ProcessGuardedException();
   end;
 end;
 
procedure ClearResourceList(); cdecl;
var
  i: integer;
begin
 try
  i:=Res.High;
  repeat
    if PRes(Res[i])^.owner = CurrentOwner then _DeleteREsRec(i);
    dec(i);
  until i < 0;
   except
    ProcessGuardedException();
   end;
end;

var
  grri: integer = -1;


function GetFirstResource: PRes; cdecl;
begin
  grri:= -1;
  Result:=GetNextResource;
end;

function GetNextResource: PRes; cdecl;
begin
 try
  Result:=NIL;
  while grri < Res.High do begin
    inc(grri);
    if PRes(Res[grri])^.owner = CurrentOwner then begin
      Result:=Res[grri];
      Break;
    end;
  end;
   except
    ProcessGuardedException();
   end;
end;


procedure InitResourceManager;
var ii: integer;
begin
  Res:=TAOP.Create;
//  Res.Container:=No;
//  for ii:=1 to MAX_MODULE do ModuleCiMs[ii]:=nil;
  SetLength(ModuleCiMs, 1);
  ModuleCiMs[0]:= nil;
end;


function CgeGetCiMemoryStream (): pointer; cdecl;
begin
//addlog('CgeGetCiMemoryStream: CurrentOwner = %0',[CurrentOwner]);
 try
  if CurrentOwner > High(ModuleCiMs) then Raise Exception.Create('Invalid CurrentOwner ' + IntToStr(CurrentOwner));
  if (CurrentOwner > 0)
    then Result:=ModuleCiMs[CurrentOwner]
    else Result:= nil;
   except
    ProcessGuardedException();
   end;
end;

procedure CgeSetCiMemoryStream (s: pointer); cdecl;
begin
//addlog('CgeSetCiMemoryStream: CurrentOwner = %0',[CurrentOwner]);
 try
  if (CurrentOwner < 0) or (CurrentOwner > High(ModuleCiMs)) then Raise Exception.Create('Invalid CurrentOwner ' + IntToStr(CurrentOwner));
  ModuleCiMs[CurrentOwner]:=s;
 except
  ProcessGuardedException();
 end;
end;


{***********************************************************************}

{
procedure krah(i: integer);
begin
  try
    case i of
      1: raise Exception.create('TEST');
      2: Die('BOOM!');
      3: byte(nil^):=0;
    end;
  except
    raise Exception.create('Krah: ' + (ExceptObject as Exception).Message);
  end;

end;
}

function CgeCreateMemoryStream (): pointer; cdecl;
begin
 try
  Result:=Pointer(TMemoryStream.Create);
  // krah(3);
   except
    ProcessGuardedException();
   end;
end;


procedure CgeDeleteMemoryStream (s: pointer); cdecl;
begin
 try
  TMemoryStream(s).Free;
   except
    ProcessGuardedException();
   end;
end;


procedure CgeMemoryStreamLoadFromFile (s: pointer; name: PAnsiChar); cdecl;
begin
 try
  TMemoryStream(s).LoadFromFile(WideToAnsi(UnmangleFileName(name)));
   except
    ProcessGuardedException();
   end;
end;

procedure CgeMemoryStreamSaveToFile (s: pointer; name: PAnsiChar); cdecl;
begin
 try
  TMemoryStream(s).SaveToFile(WideToAnsi(UnmangleFileName(name)));
   except
    ProcessGuardedException();
   end;
end;


procedure CgeSeekMemoryStream (s: pointer; pos: integer); cdecl;
begin
 try
//  Assert(Assigned(s), 'Invalid memory stream handle');
//addlog(' size %0 ', [TMemoryStream(s).Size]);
  TMemoryStream(s).Seek(pos, soBeginning);
   except
    ProcessGuardedException();
   end;
end;


procedure CgeWriteToMemoryStream (s: pointer; buf: pointer; len: integer); cdecl;
begin
 try
  TMemoryStream(s).Write(buf^, len);
   except
    ProcessGuardedException();
   end;
end;


function CgeReadFromMemoryStream (s: pointer; buf: pointer; len: integer): integer; cdecl;
begin
 try
  Result:=TMemoryStream(s).Read(buf^, len);
   except
    ProcessGuardedException();
   end;
end;

procedure CgeWriteIntToMemoryStream (s: pointer; i: integer); cdecl;
begin
 try
  TMemoryStream(s).WriteDword(dword(i));
   except
    ProcessGuardedException();
   end;
end;


function CgeReadIntFromMemoryStream (s: pointer): integer; cdecl;
begin
 try
  Result:=integer(TMemoryStream(s).ReadDword);
   except
    ProcessGuardedException();
   end;
end;

function CgeGetMemoryStreamMem (s: pointer): pointer; cdecl;
begin
 try
  Result:=TMemoryStream(s).Memory;
   except
    ProcessGuardedException();
   end;
end;


function CgeGetMemoryStreamSize (s: pointer): integer; cdecl;
begin
 try
  Result:=integer(TMemoryStream(s).ReadDword);
   except
    ProcessGuardedException();
   end;
end;

function CgeGetHostMem (size: integer): pointer; cdecl;
begin
 try
  Result:=GetMem(size);
   except
    ProcessGuardedException();
   end;
end;

procedure CgeFreeHostMem (p: pointer); cdecl;
begin
 try
  FreeMem(p);
   except
    ProcessGuardedException();
   end;
end;

function CgeReallocHostMem (p: pointer; newsize: integer): pointer; cdecl;
begin
 try
  Result:=ReallocMem(p, newsize);
   except
    ProcessGuardedException();
   end;
end;





