rtti.inc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Michael Van Canneyt
  4. member of the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { Run-Time type information routines }
  12. { The RTTI is implemented through a series of constants : }
  13. Const
  14. tkUnknown = 0;
  15. tkInteger = 1;
  16. tkChar = 2;
  17. tkEnumeration = 3;
  18. tkFloat = 4;
  19. tkSet = 5;
  20. tkMethod = 6;
  21. tkSString = 7;
  22. tkString = tkSString;
  23. tkLString = 8;
  24. tkAString = 9;
  25. tkWString = 10;
  26. tkVariant = 11;
  27. tkArray = 12;
  28. tkRecord = 13;
  29. tkInterface = 14;
  30. tkClass = 15;
  31. tkObject = 16;
  32. tkWChar = 17;
  33. tkBool = 18;
  34. tkInt64 = 19;
  35. tkQWord = 20;
  36. tkDynArray = 21;
  37. type
  38. TRTTIProc=procedure(Data,TypeInfo:Pointer);
  39. procedure RecordRTTI(Data,TypeInfo:Pointer;rttiproc:TRTTIProc);
  40. {
  41. A record is designed as follows :
  42. 1 : tkrecord
  43. 2 : Length of name string (n);
  44. 3 : name string;
  45. 3+n : record size;
  46. 7+n : number of elements (N)
  47. 11+n : N times : Pointer to type info
  48. Offset in record
  49. }
  50. var
  51. Temp : pbyte;
  52. namelen : byte;
  53. count,
  54. offset,
  55. i : longint;
  56. info : pointer;
  57. begin
  58. Temp:=PByte(TypeInfo);
  59. inc(Temp);
  60. { Skip Name }
  61. namelen:=Temp^;
  62. inc(temp,namelen+1);
  63. temp:=aligntoptr(temp);
  64. { Skip size }
  65. inc(Temp,4);
  66. { Element count }
  67. Count:=PLongint(Temp)^;
  68. inc(Temp,sizeof(Count));
  69. { Process elements }
  70. for i:=1 to count Do
  71. begin
  72. Info:=PPointer(Temp)^;
  73. inc(Temp,sizeof(Info));
  74. Offset:=PLongint(Temp)^;
  75. inc(Temp,sizeof(Offset));
  76. rttiproc (Data+Offset,Info);
  77. end;
  78. end;
  79. procedure ArrayRTTI(Data,TypeInfo:Pointer;rttiproc:TRTTIProc);
  80. {
  81. An array is designed as follows :
  82. 1 : tkArray;
  83. 2 : length of name string (n);
  84. 3 : NAme string
  85. 3+n : Element Size
  86. 7+n : Number of elements
  87. 11+n : Pointer to type of elements
  88. }
  89. var
  90. Temp : pbyte;
  91. namelen : byte;
  92. count,
  93. size,
  94. i : SizeInt;
  95. info : pointer;
  96. begin
  97. Temp:=PByte(TypeInfo);
  98. inc(Temp);
  99. { Skip Name }
  100. namelen:=Temp^;
  101. inc(temp,namelen+1);
  102. temp:=aligntoptr(temp);
  103. { Element size }
  104. size:=PSizeInt(Temp)^;
  105. inc(Temp,sizeof(Size));
  106. { Element count }
  107. Count:=PSizeInt(Temp)^;
  108. inc(Temp,sizeof(Count));
  109. Info:=PPointer(Temp)^;
  110. inc(Temp,sizeof(Info));
  111. { Process elements }
  112. for I:=0 to Count-1 do
  113. rttiproc(Data+(I*size),Info);
  114. end;
  115. Procedure fpc_Initialize (Data,TypeInfo : pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[Public,Alias : 'FPC_INITIALIZE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  116. begin
  117. case PByte(TypeInfo)^ of
  118. tkAstring,tkWstring,tkInterface,tkDynArray:
  119. PPchar(Data)^:=Nil;
  120. tkArray:
  121. arrayrtti(data,typeinfo,@int_initialize);
  122. tkObject,
  123. tkRecord:
  124. recordrtti(data,typeinfo,@int_initialize);
  125. {$ifdef HASVARIANT}
  126. tkVariant:
  127. variant_init(PVarData(Data)^);
  128. {$endif HASVARIANT}
  129. end;
  130. end;
  131. Procedure fpc_finalize (Data,TypeInfo: Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[Public,Alias : 'FPC_FINALIZE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  132. begin
  133. case PByte(TypeInfo)^ of
  134. tkAstring :
  135. begin
  136. fpc_AnsiStr_Decr_Ref(PPointer(Data)^);
  137. PPointer(Data)^:=nil;
  138. end;
  139. tkWstring :
  140. begin
  141. fpc_WideStr_Decr_Ref(PPointer(Data)^);
  142. PPointer(Data)^:=nil;
  143. end;
  144. tkArray :
  145. arrayrtti(data,typeinfo,@int_finalize);
  146. tkObject,
  147. tkRecord:
  148. recordrtti(data,typeinfo,@int_finalize);
  149. tkInterface:
  150. begin
  151. Intf_Decr_Ref(PPointer(Data)^);
  152. PPointer(Data)^:=nil;
  153. end;
  154. tkDynArray:
  155. fpc_dynarray_decr_ref(PPointer(Data)^,TypeInfo);
  156. {$ifdef HASVARIANT}
  157. tkVariant:
  158. variant_clear(PVarData(Data)^);
  159. {$endif HASVARIANT}
  160. end;
  161. end;
  162. Procedure fpc_Addref (Data,TypeInfo : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif} [Public,alias : 'FPC_ADDREF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  163. begin
  164. case PByte(TypeInfo)^ of
  165. tkAstring :
  166. fpc_AnsiStr_Incr_Ref(PPointer(Data)^);
  167. tkWstring :
  168. fpc_WideStr_Incr_Ref(PPointer(Data)^);
  169. tkArray :
  170. arrayrtti(data,typeinfo,@int_addref);
  171. tkobject,
  172. tkrecord :
  173. recordrtti(data,typeinfo,@int_addref);
  174. tkDynArray:
  175. fpc_dynarray_incr_ref(PPointer(Data)^);
  176. tkInterface:
  177. Intf_Incr_Ref(PPointer(Data)^);
  178. {$ifdef HASVARIANT}
  179. tkVariant:
  180. variant_addref(pvardata(Data)^);
  181. {$endif HASVARIANT}
  182. end;
  183. end;
  184. { alias for internal use }
  185. { we use another name else the compiler gets puzzled because of the wrong forward def }
  186. procedure fpc_systemDecRef (Data, TypeInfo : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[external name 'FPC_DECREF'];
  187. Procedure fpc_DecRef (Data, TypeInfo : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[Public,alias : 'FPC_DECREF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  188. begin
  189. case PByte(TypeInfo)^ of
  190. { see AddRef for comment about below construct (JM) }
  191. tkAstring:
  192. fpc_AnsiStr_Decr_Ref(PPointer(Data)^);
  193. tkWstring:
  194. fpc_WideStr_Decr_Ref(PPointer(Data)^);
  195. tkArray:
  196. arrayrtti(data,typeinfo,@fpc_systemDecRef);
  197. tkobject,
  198. tkrecord:
  199. recordrtti(data,typeinfo,@fpc_systemDecRef);
  200. tkDynArray:
  201. fpc_dynarray_decr_ref(PPointer(Data)^,TypeInfo);
  202. tkInterface:
  203. Intf_Decr_Ref(PPointer(Data)^);
  204. {$ifdef HASVARIANT}
  205. tkVariant:
  206. variant_clear(pvardata(data)^);
  207. {$endif HASVARIANT}
  208. end;
  209. end;
  210. procedure fpc_finalize_array(data,typeinfo : pointer;count,size : longint); [Public,Alias:'FPC_FINALIZEARRAY']; {$ifdef hascompilerproc} compilerproc; {$endif}
  211. var
  212. i : longint;
  213. begin
  214. for i:=0 to count-1 do
  215. int_finalize(data+size*i,typeinfo);
  216. end;