Browse Source

* Patch from mattias to handle GUID as record

michael 7 years ago
parent
commit
691d3d8bdc
4 changed files with 155 additions and 50 deletions
  1. 46 8
      packages/rtl/system.pas
  2. 107 40
      packages/rtl/sysutils.pas
  3. 1 1
      packages/rtl/types.pas
  4. 1 1
      packages/rtl/typinfo.pas

+ 46 - 8
packages/rtl/system.pas

@@ -1,6 +1,6 @@
 {
 {
     This file is part of the Pas2JS run time library.
     This file is part of the Pas2JS run time library.
-    Copyright (c) 2017 by Mattias Gaertner
+    Copyright (c) 2018 by Mattias Gaertner
 
 
     See the file COPYING.FPC, included in this distribution,
     See the file COPYING.FPC, included in this distribution,
     for details about the copyright.
     for details about the copyright.
@@ -66,10 +66,17 @@ type
   TTextLineBreakStyle = (tlbsLF,tlbsCRLF,tlbsCR);
   TTextLineBreakStyle = (tlbsLF,tlbsCRLF,tlbsCR);
 
 
 {*****************************************************************************
 {*****************************************************************************
-                            TObject, TClass
+            TObject, TClass, IUnknown, IInterface, TInterfacedObject
 *****************************************************************************}
 *****************************************************************************}
 type
 type
-  TGuid = string;
+  TGuid = record
+    D1: DWord;
+    D2: word;
+    D3: word;
+    D4: array[0..7] of byte;
+  end;
+  TGUIDString = string; // ToDo: use type string when supported by compiler
+
   TClass = class of TObject;
   TClass = class of TObject;
 
 
   { TObject }
   { TObject }
@@ -100,8 +107,9 @@ type
     procedure AfterConstruction; virtual;
     procedure AfterConstruction; virtual;
     procedure BeforeDestruction; virtual;
     procedure BeforeDestruction; virtual;
 
 
-    function GetInterface(const iidstr: String; out obj): boolean;
-    function GetInterfaceByStr(const iidstr: String; out obj) : boolean;
+    function GetInterface(const iid: TGuid; out obj): boolean;
+    function GetInterface(const iidstr: String; out obj): boolean; inline;
+    function GetInterfaceByStr(const iidstr: String; out obj): boolean;
     function GetInterfaceWeak(const iid: TGuid; out obj): boolean; // equal to GetInterface but the interface returned is not referenced
     function GetInterfaceWeak(const iid: TGuid; out obj): boolean; // equal to GetInterface but the interface returned is not referenced
 
 
     function Equals(Obj: TObject): boolean; virtual;
     function Equals(Obj: TObject): boolean; virtual;
@@ -184,8 +192,7 @@ const
   { for safe as operator support }
   { for safe as operator support }
   IObjectInstance: TGuid = '{D91C9AF4-3C93-420F-A303-BF5BA82BFD23}';
   IObjectInstance: TGuid = '{D91C9AF4-3C93-420F-A303-BF5BA82BFD23}';
 
 
-const
-  DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
+function GUIDToString(const GUID: TGUID): string; overload;
 
 
 {*****************************************************************************
 {*****************************************************************************
                             Init / Exit / ExitProc
                             Init / Exit / ExitProc
@@ -238,6 +245,9 @@ function Trunc(const A: Double): NativeInt;
 {*****************************************************************************
 {*****************************************************************************
                           String functions
                           String functions
 *****************************************************************************}
 *****************************************************************************}
+const
+  DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
+
 function Int(const A: Double): double;
 function Int(const A: Double): double;
 function Copy(const S: string; Index, Size: Integer): String; assembler; overload;
 function Copy(const S: string; Index, Size: Integer): String; assembler; overload;
 function Copy(const S: string; Index: Integer): String; assembler; overload;
 function Copy(const S: string; Index: Integer): String; assembler; overload;
@@ -282,6 +292,11 @@ asm
   return s1.toLowerCase() == s2.toLowerCase();
   return s1.toLowerCase() == s2.toLowerCase();
 end;
 end;
 
 
+function GUIDToString(const GUID: TGUID): string; assembler;
+asm
+  return rtl.guidrToStr(GUID);
+end;
+
 function ParamCount: Longint;
 function ParamCount: Longint;
 begin
 begin
   if Assigned(OnParamCount) then
   if Assigned(OnParamCount) then
@@ -706,6 +721,21 @@ begin
 
 
 end;
 end;
 
 
+function TObject.GetInterface(const iid: TGuid; out obj): boolean;
+begin
+  asm
+    var i = iid.$intf;
+    if (i){
+      i = rtl.getIntfG(this,i.$guid,2);
+      if (i){
+        obj.set(i);
+        return true;
+      }
+    }
+  end;
+  Result := GetInterfaceByStr(GUIDToString(iid),obj);
+end;
+
 function TObject.GetInterface(const iidstr: String; out obj): boolean;
 function TObject.GetInterface(const iidstr: String; out obj): boolean;
 begin
 begin
   Result := GetInterfaceByStr(iidstr,obj);
   Result := GetInterfaceByStr(iidstr,obj);
@@ -728,7 +758,15 @@ end;
 
 
 function TObject.GetInterfaceWeak(const iid: TGuid; out obj): boolean;
 function TObject.GetInterfaceWeak(const iid: TGuid; out obj): boolean;
 begin
 begin
-  Result:=GetInterfaceByStr(iid,obj);
+  Result:=GetInterface(iid,obj);
+  asm
+    if (Result){
+      var o = obj.get();
+      if (o.$kind==='com'){
+        o._Release();
+      }
+    }
+  end;
 end;
 end;
 
 
 function TObject.Equals(Obj: TObject): boolean;
 function TObject.Equals(Obj: TObject): boolean;

+ 107 - 40
packages/rtl/sysutils.pas

@@ -537,19 +537,27 @@ type
                                Interfaces
                                Interfaces
 *****************************************************************************}
 *****************************************************************************}
 
 
+const
+  GUID_NULL: TGuid = '{00000000-0000-0000-0000-000000000000}';
+
 function Supports(const Instance: IInterface; const AClass: TClass; out Obj): Boolean; overload;
 function Supports(const Instance: IInterface; const AClass: TClass; out Obj): Boolean; overload;
-function Supports(const Instance: TObject; const IID: String; out Intf): Boolean; overload;
+function Supports(const Instance: IInterface; const IID: TGuid; out Intf): Boolean; overload;
+function Supports(const Instance: TObject; const IID: TGuid; out Intf): Boolean; overload;
+function Supports(const Instance: TObject; const IID: TGuidString; out Intf): Boolean; overload;
 
 
 function Supports(const Instance: IInterface; const AClass: TClass): Boolean; overload;
 function Supports(const Instance: IInterface; const AClass: TClass): Boolean; overload;
-function Supports(const Instance: TObject; const IID: String): Boolean; overload;
+function Supports(const Instance: IInterface; const IID: TGuid): Boolean; overload;
+function Supports(const Instance: TObject; const IID: TGuid): Boolean; overload;
+function Supports(const Instance: TObject; const IID: TGuidString): Boolean; overload;
 
 
-function Supports(const AClass: TClass; const IID: String): Boolean; assembler; overload;
+function Supports(const AClass: TClass; const IID: TGuid): Boolean; overload;
+function Supports(const AClass: TClass; const IID: TGuidString): Boolean; overload;
 
 
-function TryStringToGUID(const S: string; out Guid: TGUID): Boolean;
-function StringToGUID(const S: string): TGUID;
-function GUIDToString(const GUID: TGUID): string;
-function IsEqualGUID(const guid1, guid2: TGUID): Boolean;
-function GuidCase(const GUID: TGUID; const List: array of TGuid): Integer;
+function TryStringToGUID(const s: string; out Guid: TGuid): Boolean;
+function StringToGUID(const S: string): TGuid;
+function GUIDToString(const guid: TGuid): string;
+function IsEqualGUID(const guid1, guid2: TGuid): Boolean;
+function GuidCase(const guid: TGuid; const List: array of TGuid): Integer;
 
 
 implementation
 implementation
 
 
@@ -3316,6 +3324,9 @@ begin
   Result:=Value;
   Result:=Value;
 end;
 end;
 
 
+{ ---------------------------------------------------------------------
+  Interface related
+  ---------------------------------------------------------------------}
 function Supports(const Instance: IInterface; const AClass: TClass; out Obj
 function Supports(const Instance: IInterface; const AClass: TClass; out Obj
   ): Boolean;
   ): Boolean;
 begin
 begin
@@ -3323,12 +3334,24 @@ begin
      and (TObject(Obj).InheritsFrom(AClass));
      and (TObject(Obj).InheritsFrom(AClass));
 end;
 end;
 
 
-function Supports(const Instance: TObject; const IID: String; out Intf
+function Supports(const Instance: IInterface; const IID: TGUID; out Intf
+  ): Boolean;
+begin
+  Result:=(Instance<>nil) and (Instance.QueryInterface(IID,Intf)=S_OK);
+end;
+
+function Supports(const Instance: TObject; const IID: TGUID; out Intf
   ): Boolean;
   ): Boolean;
 begin
 begin
   Result:=(Instance<>nil) and Instance.GetInterface(IID,Intf);
   Result:=(Instance<>nil) and Instance.GetInterface(IID,Intf);
 end;
 end;
 
 
+function Supports(const Instance: TObject; const IID: TGuidString; out Intf
+  ): Boolean;
+begin
+  Result:=(Instance<>nil) and Instance.GetInterfaceByStr(IID,Intf);
+end;
+
 function Supports(const Instance: IInterface; const AClass: TClass): Boolean;
 function Supports(const Instance: IInterface; const AClass: TClass): Boolean;
 var
 var
   Temp: TObject;
   Temp: TObject;
@@ -3336,30 +3359,71 @@ begin
   Result:=Supports(Instance,AClass,Temp);
   Result:=Supports(Instance,AClass,Temp);
 end;
 end;
 
 
-function Supports(const Instance: TObject; const IID: String): Boolean;
+function Supports(const Instance: IInterface; const IID: TGUID): Boolean;
 var
 var
-  Temp: TObject;
+  Temp: IInterface;
 begin
 begin
   Result:=Supports(Instance,IID,Temp);
   Result:=Supports(Instance,IID,Temp);
 end;
 end;
 
 
-function Supports(const AClass: TClass; const IID: String): Boolean; assembler;
-asm
-  if (!AClass) return false;
-  var maps = AClass.$intfmaps;
-  if (!maps) return false;
-  if (maps[IID]) return true;
-  return false;
+function Supports(const Instance: TObject; const IID: TGUID): Boolean;
+var
+  Temp: TJSObject;
+begin
+  Result:=Supports(Instance,IID,Temp);
+  asm
+    if (Temp && Temp.$kind==='com') Temp._Release();
+  end;
 end;
 end;
 
 
-function TryStringToGUID(const S: string; out Guid: TGUID): Boolean;
+function Supports(const Instance: TObject; const IID: TGuidString): Boolean;
+var
+  Temp: TJSObject;
+begin
+  Result:=Supports(Instance,IID,Temp);
+  asm
+    if (Temp && Temp.$kind==='com') Temp._Release();
+  end;
+end;
+
+function Supports(const AClass: TClass; const IID: TGUID): Boolean;
+var
+  maps: JSValue;
+begin
+  if AClass=nil then exit(false);
+  maps := TJSObject(AClass)['$intfmaps'];
+  if not maps then exit(false);
+  if TJSObject(maps)[GUIDToString(IID)] then exit(true);
+  Result:=false;
+end;
+
+function Supports(const AClass: TClass; const IID: TGuidString): Boolean;
+var
+  maps: JSValue;
+begin
+  if AClass=nil then exit(false);
+  maps := TJSObject(AClass)['$intfmaps'];
+  if not maps then exit(false);
+  if TJSObject(maps)[uppercase(IID)] then exit(true);
+  Result:=false;
+end;
+
+function TryStringToGUID(const s: string; out Guid: TGUID): Boolean;
 var
 var
   re: TJSRegexp;
   re: TJSRegexp;
 begin
 begin
-  if Length(S)<>38 then Exit(False);
+  if Length(s)<>38 then Exit(False);
   re:=TJSRegexp.new('^\{[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\}$');
   re:=TJSRegexp.new('^\{[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\}$');
-  Result:=re.test(S);
-  Guid:=S;
+  Result:=re.test(s);
+  if not Result then
+    begin
+    Guid.D1:=0;
+    exit;
+    end;
+  asm
+    rtl.strToGUIDR(s,Guid.get());
+  end;
+  Result:=true;
 end;
 end;
 
 
 function StringToGUID(const S: string): TGUID;
 function StringToGUID(const S: string): TGUID;
@@ -3368,20 +3432,25 @@ begin
     raise EConvertError.CreateFmt(SInvalidGUID, [S]);
     raise EConvertError.CreateFmt(SInvalidGUID, [S]);
 end;
 end;
 
 
-function GUIDToString(const GUID: TGUID): string;
+function GUIDToString(const guid: TGUID): string;
 begin
 begin
-  Result:=GUID;
+  Result:=System.GUIDToString(guid);
 end;
 end;
 
 
 function IsEqualGUID(const guid1, guid2: TGUID): Boolean;
 function IsEqualGUID(const guid1, guid2: TGUID): Boolean;
+var
+  i: integer;
 begin
 begin
-  Result:=SameText(guid1,guid2);
+  if (guid1.D1<>guid2.D1) or (guid1.D2<>guid2.D2) or (guid1.D3<>guid2.D3) then
+    exit(false);
+  for i:=0 to 7 do if guid1.D4[i]<>guid2.D4[i] then exit(false);
+  Result:=true;
 end;
 end;
 
 
-function GuidCase(const GUID: TGUID; const List: array of TGuid): Integer;
+function GuidCase(const guid: TGUID; const List: array of TGuid): Integer;
 begin
 begin
   for Result := High(List) downto 0 do
   for Result := High(List) downto 0 do
-    if IsEqualGUID(GUID, List[Result]) then
+    if IsEqualGUID(guid, List[Result]) then
       Exit;
       Exit;
   Result := -1;
   Result := -1;
 end;
 end;
@@ -3585,21 +3654,19 @@ end;
 
 
 
 
 function IntToHex(Value: NativeInt; Digits: integer): string;
 function IntToHex(Value: NativeInt; Digits: integer): string;
-
 const
 const
-   HexDigits = '0123456789ABCDEF';
-
+  HexDigits = '0123456789ABCDEF';
 begin
 begin
- If Digits=0 then
-   Digits:=1;
- Result:='';
- While Value>0 do
-   begin
-   result:=HexDigits[(value and 15)+1]+Result;
-   value := value shr 4;
-   end ;
- while (Length(Result)<Digits) do
-   Result:='0'+Result;
+  If Digits=0 then
+    Digits:=1;
+  Result:='';
+  While Value>0 do
+    begin
+    result:=HexDigits[(value and 15)+1]+Result;
+    value := value shr 4;
+    end ;
+  while (Length(Result)<Digits) do
+    Result:='0'+Result;
 end;
 end;
 
 
 { TFormatSettings }
 { TFormatSettings }

+ 1 - 1
packages/rtl/types.pas

@@ -1,6 +1,6 @@
 {
 {
     This file is part of the Pas2JS run time library.
     This file is part of the Pas2JS run time library.
-    Copyright (c) 2017 by Mattias Gaertner
+    Copyright (c) 2018 by Mattias Gaertner
 
 
     See the file COPYING.FPC, included in this distribution,
     See the file COPYING.FPC, included in this distribution,
     for details about the copyright.
     for details about the copyright.

+ 1 - 1
packages/rtl/typinfo.pas

@@ -1,6 +1,6 @@
 {
 {
     This file is part of the Pas2JS run time library.
     This file is part of the Pas2JS run time library.
-    Copyright (c) 2017 by Mattias Gaertner
+    Copyright (c) 2018 by Mattias Gaertner
 
 
     See the file COPYING.FPC, included in this distribution,
     See the file COPYING.FPC, included in this distribution,
     for details about the copyright.
     for details about the copyright.