Browse Source

* Call management operators also for records with zero-size. For that purpose was changed function RTTISize. New name for RTTISize is RTTISizeAndOp. RTTISizeAndOp can return size of required type and information about existing management operators for that type in current context (to determine context is used enum TRTTIRecOpType which is passed also as parameter in RTTISizeAndOp). RTTISizeAndOp is used in fpc_initialize_array, fpc_finalize_array, fpc_addref_array and CopyArray.

git-svn-id: trunk@35451 -
maciej-izak 8 years ago
parent
commit
4154b4ca8a
1 changed files with 64 additions and 10 deletions
  1. 64 10
      rtl/inc/rtti.inc

+ 64 - 10
rtl/inc/rtti.inc

@@ -166,8 +166,15 @@ begin
 end;
 end;
 {$endif FPC_HAS_MANAGEMENT_OPERATORS}
 {$endif FPC_HAS_MANAGEMENT_OPERATORS}
 
 
+{$ifdef FPC_HAS_MANAGEMENT_OPERATORS}
+function RTTISizeAndOp(typeInfo: Pointer;
+  const expectedManagementOp: TRTTIRecOpType; out hasManagementOp: boolean): SizeInt;
+begin
+  hasManagementOp:=false;
+{$else FPC_HAS_MANAGEMENT_OPERATORS}
 function RTTISize(typeInfo: Pointer): SizeInt;
 function RTTISize(typeInfo: Pointer): SizeInt;
 begin
 begin
+{$endif FPC_HAS_MANAGEMENT_OPERATORS}
   case PByte(typeinfo)^ of
   case PByte(typeinfo)^ of
     tkAString,tkWString,tkUString,
     tkAString,tkWString,tkUString,
     tkInterface,tkDynarray:
     tkInterface,tkDynarray:
@@ -178,8 +185,26 @@ begin
 {$endif FPC_HAS_FEATURE_VARIANTS}
 {$endif FPC_HAS_FEATURE_VARIANTS}
     tkArray:
     tkArray:
       result:=RTTIArraySize(typeinfo);
       result:=RTTIArraySize(typeinfo);
+{$ifdef FPC_HAS_MANAGEMENT_OPERATORS}
+    tkObject:
+      result:=RTTIRecordSize(typeinfo);
+    tkRecord:
+      with RTTIRecordOp(typeInfo,typeInfo)^ do
+        begin
+          result:=Size;
+          hasManagementOp := Assigned(RecordOp);
+          if hasManagementOp then
+            case expectedManagementOp of
+              rotInitialize: hasManagementOp:=Assigned(RecordOp^.Initialize);
+              rotFinalize: hasManagementOp:=Assigned(RecordOp^.Finalize);
+              rotAddRef: hasManagementOp:=Assigned(RecordOp^.AddRef);
+              rotCopy: hasManagementOp:=Assigned(RecordOp^.Copy);
+            end;
+        end;
+{$else FPC_HAS_MANAGEMENT_OPERATORS}
     tkObject,tkRecord:
     tkObject,tkRecord:
       result:=RTTIRecordSize(typeinfo);
       result:=RTTIRecordSize(typeinfo);
+{$endif FPC_HAS_MANAGEMENT_OPERATORS}
   else
   else
     result:=-1;
     result:=-1;
   end;
   end;
@@ -517,31 +542,53 @@ end;
 
 
 procedure fpc_initialize_array(data,typeinfo : pointer;count : SizeInt); [public,alias:'FPC_INITIALIZE_ARRAY']; compilerproc;
 procedure fpc_initialize_array(data,typeinfo : pointer;count : SizeInt); [public,alias:'FPC_INITIALIZE_ARRAY']; compilerproc;
   var
   var
-     i, size : SizeInt;
+    i, size : SizeInt;
+{$ifdef FPC_HAS_MANAGEMENT_OPERATORS}
+    hasManagementOp: boolean;
+  begin
+    size:=RTTISizeAndOp(typeinfo, rotInitialize, hasManagementOp);
+    if (size>0) or hasManagementOp then
+{$else FPC_HAS_MANAGEMENT_OPERATORS}
   begin
   begin
-     size:=RTTISize(typeinfo);
-     if size>0 then
-       for i:=0 to count-1 do
-         int_initialize(data+size*i,typeinfo);
+    size:=RTTISize(typeInfo);
+    if size>0 then
+{$endif FPC_HAS_MANAGEMENT_OPERATORS}
+      for i:=0 to count-1 do
+        int_initialize(data+size*i,typeinfo);
   end;
   end;
 
 
 
 
 procedure fpc_finalize_array(data,typeinfo : pointer;count : SizeInt); [Public,Alias:'FPC_FINALIZE_ARRAY'];  compilerproc;
 procedure fpc_finalize_array(data,typeinfo : pointer;count : SizeInt); [Public,Alias:'FPC_FINALIZE_ARRAY'];  compilerproc;
   var
   var
      i, size: SizeInt;
      i, size: SizeInt;
+{$ifdef FPC_HAS_MANAGEMENT_OPERATORS}
+    hasManagementOp: boolean;
   begin
   begin
-     size:=RTTISize(typeinfo);
-     if size>0 then
-       for i:=0 to count-1 do
-         int_finalize(data+size*i,typeinfo);
+    size:=RTTISizeAndOp(typeinfo, rotFinalize, hasManagementOp);
+    if (size>0) or hasManagementOp then
+{$else FPC_HAS_MANAGEMENT_OPERATORS}
+  begin
+    size:=RTTISize(typeInfo);
+    if size>0 then
+{$endif FPC_HAS_MANAGEMENT_OPERATORS}
+      for i:=0 to count-1 do
+        int_finalize(data+size*i,typeinfo);
   end;
   end;
 
 
+
 procedure fpc_addref_array(data,typeinfo: pointer; count: SizeInt); [public,alias:'FPC_ADDREF_ARRAY']; compilerproc;
 procedure fpc_addref_array(data,typeinfo: pointer; count: SizeInt); [public,alias:'FPC_ADDREF_ARRAY']; compilerproc;
   var
   var
     i, size: SizeInt;
     i, size: SizeInt;
+{$ifdef FPC_HAS_MANAGEMENT_OPERATORS}
+    hasManagementOp: boolean;
   begin
   begin
-    size:=RTTISize(typeinfo);
+    size:=RTTISizeAndOp(typeinfo, rotAddRef, hasManagementOp);
+    if (size>0) or hasManagementOp then
+{$else FPC_HAS_MANAGEMENT_OPERATORS}
+  begin
+    size:=RTTISize(typeInfo);
     if size>0 then
     if size>0 then
+{$endif FPC_HAS_MANAGEMENT_OPERATORS}
       for i:=0 to count-1 do
       for i:=0 to count-1 do
         int_addref(data+size*i,typeinfo);
         int_addref(data+size*i,typeinfo);
   end;
   end;
@@ -566,9 +613,16 @@ procedure FinalizeArray(p, typeInfo: Pointer; count: SizeInt);
 procedure CopyArray(dest, source, typeInfo: Pointer; count: SizeInt);
 procedure CopyArray(dest, source, typeInfo: Pointer; count: SizeInt);
   var
   var
     i, size: SizeInt;
     i, size: SizeInt;
+{$ifdef FPC_HAS_MANAGEMENT_OPERATORS}
+    hasManagementOp: boolean;
+  begin
+    size:=RTTISizeAndOp(typeinfo, rotCopy, hasManagementOp);
+    if (size>0) or hasManagementOp then
+{$else FPC_HAS_MANAGEMENT_OPERATORS}
   begin
   begin
     size:=RTTISize(typeInfo);
     size:=RTTISize(typeInfo);
     if size>0 then
     if size>0 then
+{$endif FPC_HAS_MANAGEMENT_OPERATORS}
       for i:=0 to count-1 do
       for i:=0 to count-1 do
         fpc_Copy_internal(source+size*i, dest+size*i, typeInfo);
         fpc_Copy_internal(source+size*i, dest+size*i, typeInfo);
   end;
   end;