typinfo.pp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  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. { This unit provides the same Functionality as the TypInfo Unit }
  12. { of Delphi }
  13. unit typinfo;
  14. interface
  15. {$MODE objfpc}
  16. {$inline on}
  17. {$h+}
  18. uses SysUtils;
  19. // temporary types:
  20. type
  21. {$MINENUMSIZE 1 this saves a lot of memory }
  22. // if you change one of the following enumeration types
  23. // you have also to change the compiler in an appropriate way !
  24. TTypeKind = (tkUnknown,tkInteger,tkChar,tkEnumeration,
  25. tkFloat,tkSet,tkMethod,tkSString,tkLString,tkAString,
  26. tkWString,tkVariant,tkArray,tkRecord,tkInterface,
  27. tkClass,tkObject,tkWChar,tkBool,tkInt64,tkQWord,
  28. tkDynArray,tkInterfaceRaw);
  29. TOrdType = (otSByte,otUByte,otSWord,otUWord,otSLong,otULong);
  30. TFloatType = (ftSingle,ftDouble,ftExtended,ftComp,ftCurr);
  31. TMethodKind = (mkProcedure,mkFunction,mkConstructor,mkDestructor,
  32. mkClassProcedure, mkClassFunction);
  33. TParamFlag = (pfVar,pfConst,pfArray,pfAddress,pfReference,pfOut);
  34. TParamFlags = set of TParamFlag;
  35. TIntfFlag = (ifHasGuid,ifDispInterface,ifDispatch,ifHasStrGUID);
  36. TIntfFlags = set of TIntfFlag;
  37. TIntfFlagsBase = set of TIntfFlag;
  38. {$MINENUMSIZE DEFAULT}
  39. const
  40. ptField = 0;
  41. ptStatic = 1;
  42. ptVirtual = 2;
  43. ptConst = 3;
  44. tkString = tkSString;
  45. type
  46. TTypeKinds = set of TTypeKind;
  47. ShortStringBase = string[255];
  48. {$PACKRECORDS 1}
  49. TTypeInfo = record
  50. Kind : TTypeKind;
  51. Name : ShortString;
  52. // here the type data follows as TTypeData record
  53. end;
  54. PTypeInfo = ^TTypeInfo;
  55. PPTypeInfo = ^PTypeInfo;
  56. {$PACKRECORDS C}
  57. PTypeData = ^TTypeData;
  58. TTypeData =
  59. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  60. packed
  61. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  62. record
  63. case TTypeKind of
  64. tkUnKnown,tkLString,tkWString,tkAString,tkVariant:
  65. ();
  66. tkInteger,tkChar,tkEnumeration,tkWChar,tkSet:
  67. (OrdType : TOrdType;
  68. case TTypeKind of
  69. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar : (
  70. MinValue,MaxValue : Longint;
  71. case TTypeKind of
  72. tkEnumeration:
  73. (
  74. BaseType : PTypeInfo;
  75. NameList : ShortString)
  76. );
  77. tkSet:
  78. (CompType : PTypeInfo)
  79. );
  80. tkFloat:
  81. (FloatType : TFloatType);
  82. tkSString:
  83. (MaxLength : Byte);
  84. tkClass:
  85. (ClassType : TClass;
  86. ParentInfo : PTypeInfo;
  87. PropCount : SmallInt;
  88. UnitName : ShortString
  89. // here the properties follow as array of TPropInfo
  90. );
  91. tkMethod:
  92. (MethodKind : TMethodKind;
  93. ParamCount : Byte;
  94. ParamList : array[0..1023] of Char
  95. {in reality ParamList is a array[1..ParamCount] of:
  96. record
  97. Flags : TParamFlags;
  98. ParamName : ShortString;
  99. TypeName : ShortString;
  100. end;
  101. followed by
  102. ResultType : ShortString}
  103. );
  104. tkInt64:
  105. (MinInt64Value, MaxInt64Value: Int64);
  106. tkQWord:
  107. (MinQWordValue, MaxQWordValue: QWord);
  108. tkInterface:
  109. (
  110. IntfParent: PTypeInfo;
  111. IntfFlags : TIntfFlagsBase;
  112. GUID: TGUID;
  113. IntfUnit: ShortString;
  114. );
  115. tkInterfaceRaw:
  116. (
  117. RawIntfParent: PTypeInfo;
  118. RawIntfFlags : TIntfFlagsBase;
  119. IID: TGUID;
  120. RawIntfUnit: ShortString;
  121. IIDStr: ShortString;
  122. );
  123. tkDynArray:
  124. (
  125. elSize : PtrUInt;
  126. elType2 : PPTypeInfo;
  127. varType : Longint;
  128. elType : PPTypeInfo;
  129. DynUnitName: ShortStringBase
  130. );
  131. end;
  132. // unsed, just for completeness
  133. TPropData =
  134. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  135. packed
  136. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  137. record
  138. PropCount : Word;
  139. PropList : record _alignmentdummy : ptrint; end;
  140. end;
  141. {$PACKRECORDS 1}
  142. PPropInfo = ^TPropInfo;
  143. TPropInfo = packed record
  144. PropType : PTypeInfo;
  145. GetProc : Pointer;
  146. SetProc : Pointer;
  147. StoredProc : Pointer;
  148. Index : Integer;
  149. Default : Longint;
  150. NameIndex : SmallInt;
  151. // contains the type of the Get/Set/Storedproc, see also ptxxx
  152. // bit 0..1 GetProc
  153. // 2..3 SetProc
  154. // 4..5 StoredProc
  155. // 6 : true, constant index property
  156. PropProcs : Byte;
  157. Name : ShortString;
  158. end;
  159. TProcInfoProc = Procedure(PropInfo : PPropInfo) of object;
  160. PPropList = ^TPropList;
  161. TPropList = array[0..65535] of PPropInfo;
  162. const
  163. tkAny = [Low(TTypeKind)..High(TTypeKind)];
  164. tkMethods = [tkMethod];
  165. tkProperties = tkAny-tkMethods-[tkUnknown];
  166. // general property handling
  167. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  168. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  169. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; AKinds : TTypeKinds) : PPropInfo;
  170. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  171. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  172. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  173. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  174. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  175. Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
  176. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  177. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
  178. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  179. function GetPropList(AObject: TObject; out PropList: PPropList): Integer;
  180. // Property information routines.
  181. Function IsStoredProp(Instance: TObject;PropInfo : PPropInfo) : Boolean;
  182. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  183. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  184. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  185. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  186. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  187. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  188. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  189. // subroutines to read/write properties
  190. Function GetOrdProp(Instance: TObject; PropInfo : PPropInfo) : Int64;
  191. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  192. Procedure SetOrdProp(Instance: TObject; PropInfo : PPropInfo; Value : Int64);
  193. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  194. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  195. Function GetEnumProp(Instance: TObject; const PropInfo: PPropInfo): string;
  196. Procedure SetEnumProp(Instance: TObject; const PropName: string;const Value: string);
  197. Procedure SetEnumProp(Instance: TObject; const PropInfo: PPropInfo;const Value: string);
  198. Function GetSetProp(Instance: TObject; const PropName: string): string;
  199. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  200. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  201. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  202. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  203. Function GetStrProp(Instance: TObject; PropInfo : PPropInfo) : Ansistring;
  204. Function GetStrProp(Instance: TObject; const PropName: string): string;
  205. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  206. Procedure SetStrProp(Instance: TObject; PropInfo : PPropInfo; const Value : Ansistring);
  207. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  208. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  209. Procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  210. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  211. Function GetFloatProp(Instance: TObject; PropInfo : PPropInfo) : Extended;
  212. Function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  213. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  214. Procedure SetFloatProp(Instance: TObject; PropInfo : PPropInfo; Value : Extended);
  215. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  216. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  217. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo): TObject;
  218. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo; MinClass: TClass): TObject;
  219. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  220. Procedure SetObjectProp(Instance: TObject; PropInfo: PPropInfo; Value: TObject);
  221. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  222. Function GetMethodProp(Instance: TObject; PropInfo: PPropInfo) : TMethod;
  223. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  224. Procedure SetMethodProp(Instance: TObject; PropInfo: PPropInfo; const Value : TMethod);
  225. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  226. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  227. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  228. Procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  229. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  230. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  231. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  232. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  233. Function GetVariantProp(Instance: TObject; PropInfo : PPropInfo): Variant;
  234. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  235. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  236. Procedure SetVariantProp(Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  237. // Auxiliary routines, which may be useful
  238. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  239. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  240. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  241. function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean) : String;
  242. function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  243. function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  244. function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  245. function StringToSet(TypeInfo: PTypeInfo; const Value: string): Integer;
  246. const
  247. BooleanIdents: array[Boolean] of String = ('False', 'True');
  248. DotSep: String = '.';
  249. Type
  250. EPropertyError = Class(Exception);
  251. TGetPropValue = Function (Instance: TObject; const PropName: string; PreferStrings: Boolean) : Variant;
  252. TSetPropValue = Procedure (Instance: TObject; const PropName: string; const Value: Variant);
  253. TGetVariantProp = Function (Instance: TObject; PropInfo : PPropInfo): Variant;
  254. TSetVariantProp = Procedure (Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  255. Const
  256. OnGetPropValue : TGetPropValue = Nil;
  257. OnSetPropValue : TSetPropValue = Nil;
  258. OnGetVariantprop : TGetVariantProp = Nil;
  259. OnSetVariantprop : TSetVariantProp = Nil;
  260. Implementation
  261. uses rtlconsts;
  262. type
  263. PMethod = ^TMethod;
  264. { ---------------------------------------------------------------------
  265. Auxiliary methods
  266. ---------------------------------------------------------------------}
  267. function aligntoptr(p : pointer) : pointer;inline;
  268. begin
  269. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  270. result:=align(p,sizeof(p));
  271. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  272. result:=p;
  273. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  274. end;
  275. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  276. Var PS : PShortString;
  277. PT : PTypeData;
  278. begin
  279. PT:=GetTypeData(TypeInfo);
  280. // ^.BaseType);
  281. // If PT^.MinValue<0 then Value:=Ord(Value<>0); {map to 0/1}
  282. PS:=@PT^.NameList;
  283. While Value>0 Do
  284. begin
  285. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  286. Dec(Value);
  287. end;
  288. Result:=PS^;
  289. end;
  290. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  291. Var PS : PShortString;
  292. PT : PTypeData;
  293. Count : longint;
  294. sName: shortstring;
  295. begin
  296. If Length(Name)=0 then
  297. exit(-1);
  298. sName := Name;
  299. PT:=GetTypeData(TypeInfo);
  300. Count:=0;
  301. Result:=-1;
  302. PS:=@PT^.NameList;
  303. While (Result=-1) and (PByte(PS)^<>0) do
  304. begin
  305. If ShortCompareText(PS^, sName) = 0 then
  306. Result:=Count;
  307. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  308. Inc(Count);
  309. end;
  310. end;
  311. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  312. var
  313. PS: PShortString;
  314. PT: PTypeData;
  315. Count: SizeInt;
  316. begin
  317. PT:=GetTypeData(enum1);
  318. Count:=0;
  319. Result:=0;
  320. PS:=@PT^.NameList;
  321. While (PByte(PS)^<>0) do
  322. begin
  323. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  324. Inc(Count);
  325. end;
  326. Result := Count;
  327. end;
  328. Function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  329. begin
  330. Result:=SetToString(PropInfo^.PropType,Value,Brackets);
  331. end;
  332. Function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean) : String;
  333. {$ifdef FPC_NEW_BIGENDIAN_SETS}
  334. type
  335. tsetarr = bitpacked array[0..31] of 0..1;
  336. {$endif}
  337. Var
  338. I : Integer;
  339. PTI : PTypeInfo;
  340. begin
  341. {$if defined(FPC_NEW_BIGENDIAN_SETS) and defined(FPC_BIG_ENDIAN)}
  342. case GetTypeData(TypeInfo)^.OrdType of
  343. otSByte,otUByte: Value:=Value shl 24;
  344. otSWord,otUWord: Value:=Value shl 16;
  345. end;
  346. {$endif}
  347. PTI:=GetTypeData(TypeInfo)^.CompType;
  348. Result:='';
  349. For I:=0 to SizeOf(Integer)*8-1 do
  350. begin
  351. {$ifdef FPC_NEW_BIGENDIAN_SETS}
  352. if (tsetarr(Value)[i]<>0) then
  353. {$else}
  354. if ((Value and 1)<>0) then
  355. {$endif}
  356. begin
  357. If Result='' then
  358. Result:=GetEnumName(PTI,i)
  359. else
  360. Result:=Result+','+GetEnumName(PTI,I);
  361. end;
  362. {$ifndef FPC_NEW_BIGENDIAN_SETS}
  363. Value:=Value shr 1;
  364. {$endif FPC_NEW_BIGENDIAN_SETS}
  365. end;
  366. if Brackets then
  367. Result:='['+Result+']';
  368. end;
  369. Function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  370. begin
  371. Result:=SetToString(PropInfo,Value,False);
  372. end;
  373. Const
  374. SetDelim = ['[',']',',',' '];
  375. Function GetNextElement(Var S : String) : String;
  376. Var
  377. J : Integer;
  378. begin
  379. J:=1;
  380. Result:='';
  381. If Length(S)>0 then
  382. begin
  383. While (J<=Length(S)) and Not (S[j] in SetDelim) do
  384. Inc(j);
  385. Result:=Copy(S,1,j-1);
  386. Delete(S,1,j);
  387. end;
  388. end;
  389. Function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  390. begin
  391. Result:=StringToSet(PropInfo^.PropType,Value);
  392. end;
  393. Function StringToSet(TypeInfo: PTypeInfo; const Value: string): Integer;
  394. Var
  395. S,T : String;
  396. I : Integer;
  397. PTI : PTypeInfo;
  398. begin
  399. Result:=0;
  400. PTI:=GetTypeData(TypeInfo)^.Comptype;
  401. S:=Value;
  402. I:=1;
  403. If Length(S)>0 then
  404. begin
  405. While (I<=Length(S)) and (S[i] in SetDelim) do
  406. Inc(I);
  407. Delete(S,1,i-1);
  408. end;
  409. While (S<>'') do
  410. begin
  411. T:=GetNextElement(S);
  412. if T<>'' then
  413. begin
  414. I:=GetEnumValue(PTI,T);
  415. if (I<0) then
  416. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [T]);
  417. Result:=Result or (1 shl i);
  418. end;
  419. end;
  420. end;
  421. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  422. begin
  423. GetTypeData:=PTypeData(aligntoptr(PTypeData(pointer(TypeInfo)+2+PByte(pointer(TypeInfo)+1)^)));
  424. end;
  425. { ---------------------------------------------------------------------
  426. Basic Type information functions.
  427. ---------------------------------------------------------------------}
  428. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  429. var
  430. hp : PTypeData;
  431. i : longint;
  432. p : shortstring;
  433. pd : ^TPropData;
  434. begin
  435. P:=PropName; // avoid Ansi<->short conversion in a loop
  436. while Assigned(TypeInfo) do
  437. begin
  438. // skip the name
  439. hp:=GetTypeData(Typeinfo);
  440. // the class info rtti the property rtti follows immediatly
  441. pd:=aligntoptr(pointer(pointer(@hp^.UnitName)+Length(hp^.UnitName)+1));
  442. Result:=PPropInfo(@pd^.PropList);
  443. for i:=1 to pd^.PropCount do
  444. begin
  445. // found a property of that name ?
  446. if ShortCompareText(Result^.Name, P) = 0 then
  447. exit;
  448. // skip to next property
  449. Result:=PPropInfo(aligntoptr(pointer(@Result^.Name)+byte(Result^.Name[0])+1));
  450. end;
  451. // parent class
  452. Typeinfo:=hp^.ParentInfo;
  453. end;
  454. Result:=Nil;
  455. end;
  456. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; Akinds : TTypeKinds) : PPropInfo;
  457. begin
  458. Result:=GetPropInfo(TypeInfo,PropName);
  459. If (Akinds<>[]) then
  460. If (Result<>Nil) then
  461. If Not (Result^.PropType^.Kind in AKinds) then
  462. Result:=Nil;
  463. end;
  464. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  465. begin
  466. Result:=GetPropInfo(PTypeInfo(AClass.ClassInfo),PropName,AKinds);
  467. end;
  468. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  469. begin
  470. Result:=GetPropInfo(Instance.ClassType,PropName,AKinds);
  471. end;
  472. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  473. begin
  474. Result:=GetPropInfo(Instance,PropName,[]);
  475. end;
  476. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  477. begin
  478. Result:=GetPropInfo(AClass,PropName,[]);
  479. end;
  480. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  481. begin
  482. result:=GetPropInfo(Instance, PropName);
  483. if Result=nil then
  484. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  485. end;
  486. Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
  487. begin
  488. result:=GetPropInfo(AClass,PropName);
  489. if result=nil then
  490. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  491. end;
  492. Function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean;
  493. type
  494. TBooleanIndexFunc=function(Index:integer):boolean of object;
  495. TBooleanFunc=function:boolean of object;
  496. var
  497. AMethod : TMethod;
  498. begin
  499. case (PropInfo^.PropProcs shr 4) and 3 of
  500. ptfield:
  501. Result:=PBoolean(Pointer(Instance)+PtrUInt(PropInfo^.StoredProc))^;
  502. ptconst:
  503. Result:=LongBool(PropInfo^.StoredProc);
  504. ptstatic,
  505. ptvirtual:
  506. begin
  507. if (PropInfo^.PropProcs shr 4) and 3=ptstatic then
  508. AMethod.Code:=PropInfo^.StoredProc
  509. else
  510. AMethod.Code:=ppointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.StoredProc))^;
  511. AMethod.Data:=Instance;
  512. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  513. Result:=TBooleanIndexFunc(AMethod)(PropInfo^.Index)
  514. else
  515. Result:=TBooleanFunc(AMethod)();
  516. end;
  517. end;
  518. end;
  519. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  520. {
  521. Store Pointers to property information in the list pointed
  522. to by proplist. PRopList must contain enough space to hold ALL
  523. properties.
  524. }
  525. Var
  526. TD : PTypeData;
  527. TP : PPropInfo;
  528. Count : Longint;
  529. begin
  530. // Get this objects TOTAL published properties count
  531. TD:=GetTypeData(TypeInfo);
  532. // Clear list
  533. FillChar(PropList^,TD^.PropCount*sizeof(Pointer),0);
  534. repeat
  535. TD:=GetTypeData(TypeInfo);
  536. // published properties count for this object
  537. TP:=aligntoptr(PPropInfo(aligntoptr((Pointer(@TD^.UnitName)+Length(TD^.UnitName)+1))));
  538. Count:=PWord(TP)^;
  539. // Now point TP to first propinfo record.
  540. Inc(Pointer(TP),SizeOF(Word));
  541. tp:=aligntoptr(tp);
  542. While Count>0 do
  543. begin
  544. // Don't overwrite properties with the same name
  545. if PropList^[TP^.NameIndex]=nil then
  546. PropList^[TP^.NameIndex]:=TP;
  547. // Point to TP next propinfo record.
  548. // Located at Name[Length(Name)+1] !
  549. TP:=aligntoptr(PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+1));
  550. Dec(Count);
  551. end;
  552. TypeInfo:=TD^.Parentinfo;
  553. until TypeInfo=nil;
  554. end;
  555. Procedure InsertProp (PL : PProplist;PI : PPropInfo; Count : longint);
  556. Var
  557. I : Longint;
  558. begin
  559. I:=0;
  560. While (I<Count) and (PI^.Name>PL^[I]^.Name) do
  561. Inc(I);
  562. If I<Count then
  563. Move(PL^[I], PL^[I+1], (Count - I) * SizeOf(Pointer));
  564. PL^[I]:=PI;
  565. end;
  566. Procedure InsertPropnosort (PL : PProplist;PI : PPropInfo; Count : longint);
  567. begin
  568. PL^[Count]:=PI;
  569. end;
  570. Type TInsertProp = Procedure (PL : PProplist;PI : PPropInfo; Count : longint);
  571. //Const InsertProps : array[false..boolean] of TInsertProp = (InsertPropNoSort,InsertProp);
  572. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
  573. {
  574. Store Pointers to property information OF A CERTAIN KIND in the list pointed
  575. to by proplist. PRopList must contain enough space to hold ALL
  576. properties.
  577. }
  578. Var
  579. TempList : PPropList;
  580. PropInfo : PPropinfo;
  581. I,Count : longint;
  582. DoInsertProp : TInsertProp;
  583. begin
  584. if sorted then
  585. DoInsertProp:=@InsertProp
  586. else
  587. DoInsertProp:=@InsertPropnosort;
  588. Result:=0;
  589. Count:=GetTypeData(TypeInfo)^.Propcount;
  590. If Count>0 then
  591. begin
  592. GetMem(TempList,Count*SizeOf(Pointer));
  593. Try
  594. GetPropInfos(TypeInfo,TempList);
  595. For I:=0 to Count-1 do
  596. begin
  597. PropInfo:=TempList^[i];
  598. If PropInfo^.PropType^.Kind in TypeKinds then
  599. begin
  600. If (PropList<>Nil) then
  601. DoInsertProp(PropList,PropInfo,Result);
  602. Inc(Result);
  603. end;
  604. end;
  605. finally
  606. FreeMem(TempList,Count*SizeOf(Pointer));
  607. end;
  608. end;
  609. end;
  610. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  611. begin
  612. result:=GetTypeData(TypeInfo)^.Propcount;
  613. if result>0 then
  614. begin
  615. getmem(PropList,result*sizeof(pointer));
  616. GetPropInfos(TypeInfo,PropList);
  617. end;
  618. end;
  619. function GetPropList(AObject: TObject; out PropList: PPropList): Integer;
  620. begin
  621. Result := GetPropList(PTypeInfo(AObject.ClassInfo), PropList);
  622. end;
  623. { ---------------------------------------------------------------------
  624. Property access functions
  625. ---------------------------------------------------------------------}
  626. { ---------------------------------------------------------------------
  627. Ordinal properties
  628. ---------------------------------------------------------------------}
  629. Function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Int64;
  630. type
  631. TGetInt64ProcIndex=function(index:longint):Int64 of object;
  632. TGetInt64Proc=function():Int64 of object;
  633. TGetIntegerProcIndex=function(index:longint):longint of object;
  634. TGetIntegerProc=function:longint of object;
  635. TGetWordProcIndex=function(index:longint):word of object;
  636. TGetWordProc=function:word of object;
  637. TGetByteProcIndex=function(index:longint):Byte of object;
  638. TGetByteProc=function:Byte of object;
  639. var
  640. TypeInfo: PTypeInfo;
  641. AMethod : TMethod;
  642. DataSize: Integer;
  643. OrdType: TOrdType;
  644. Signed: Boolean;
  645. begin
  646. Result:=0;
  647. TypeInfo := PropInfo^.PropType;
  648. Signed := false;
  649. DataSize := 4;
  650. case TypeInfo^.Kind of
  651. {$ifdef cpu64}
  652. tkInterface,
  653. tkInterfaceRaw,
  654. tkDynArray,
  655. tkClass:
  656. DataSize:=8;
  657. {$endif cpu64}
  658. tkChar, tkBool:
  659. DataSize:=1;
  660. tkWChar:
  661. DataSize:=2;
  662. tkSet,
  663. tkEnumeration,
  664. tkInteger:
  665. begin
  666. OrdType:=GetTypeData(TypeInfo)^.OrdType;
  667. case OrdType of
  668. otSByte,otUByte: DataSize := 1;
  669. otSWord,otUWord: DataSize := 2;
  670. end;
  671. Signed := OrdType in [otSByte,otSWord,otSLong];
  672. end;
  673. tkInt64 :
  674. begin
  675. DataSize:=8;
  676. Signed:=true;
  677. end;
  678. tkQword :
  679. begin
  680. DataSize:=8;
  681. Signed:=false;
  682. end;
  683. end;
  684. case (PropInfo^.PropProcs) and 3 of
  685. ptfield:
  686. if Signed then begin
  687. case DataSize of
  688. 1: Result:=PShortInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  689. 2: Result:=PSmallInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  690. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  691. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  692. end;
  693. end else begin
  694. case DataSize of
  695. 1: Result:=PByte(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  696. 2: Result:=PWord(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  697. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  698. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  699. end;
  700. end;
  701. ptstatic,
  702. ptvirtual :
  703. begin
  704. if (PropInfo^.PropProcs and 3)=ptStatic then
  705. AMethod.Code:=PropInfo^.GetProc
  706. else
  707. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  708. AMethod.Data:=Instance;
  709. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then begin
  710. case DataSize of
  711. 1: Result:=TGetByteProcIndex(AMethod)(PropInfo^.Index);
  712. 2: Result:=TGetWordProcIndex(AMethod)(PropInfo^.Index);
  713. 4: Result:=TGetIntegerProcIndex(AMethod)(PropInfo^.Index);
  714. 8: result:=TGetInt64ProcIndex(AMethod)(PropInfo^.Index)
  715. end;
  716. end else begin
  717. case DataSize of
  718. 1: Result:=TGetByteProc(AMethod)();
  719. 2: Result:=TGetWordProc(AMethod)();
  720. 4: Result:=TGetIntegerProc(AMethod)();
  721. 8: result:=TGetInt64Proc(AMethod)();
  722. end;
  723. end;
  724. if Signed then begin
  725. case DataSize of
  726. 1: Result:=ShortInt(Result);
  727. 2: Result:=SmallInt(Result);
  728. end;
  729. end;
  730. end;
  731. end;
  732. end;
  733. Procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;Value : Int64);
  734. type
  735. TSetInt64ProcIndex=procedure(index:longint;i:Int64) of object;
  736. TSetInt64Proc=procedure(i:Int64) of object;
  737. TSetIntegerProcIndex=procedure(index,i:longint) of object;
  738. TSetIntegerProc=procedure(i:longint) of object;
  739. var
  740. DataSize: Integer;
  741. AMethod : TMethod;
  742. begin
  743. if PropInfo^.PropType^.Kind in [tkInt64,tkQword
  744. { why do we have to handle classes here, see also below? (FK) }
  745. {$ifdef cpu64}
  746. ,tkInterface
  747. ,tkInterfaceRaw
  748. ,tkDynArray
  749. ,tkClass
  750. {$endif cpu64}
  751. ] then
  752. DataSize := 8
  753. else
  754. DataSize := 4;
  755. if not(PropInfo^.PropType^.Kind in [tkInt64,tkQword,tkClass]) then
  756. begin
  757. { cut off unnecessary stuff }
  758. case GetTypeData(PropInfo^.PropType)^.OrdType of
  759. otSWord,otUWord:
  760. begin
  761. Value:=Value and $ffff;
  762. DataSize := 2;
  763. end;
  764. otSByte,otUByte:
  765. begin
  766. Value:=Value and $ff;
  767. DataSize := 1;
  768. end;
  769. end;
  770. end;
  771. case (PropInfo^.PropProcs shr 2) and 3 of
  772. ptfield:
  773. case DataSize of
  774. 1: PByte(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Byte(Value);
  775. 2: PWord(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Word(Value);
  776. 4: PLongint(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Longint(Value);
  777. 8: PInt64(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  778. end;
  779. ptstatic,
  780. ptvirtual :
  781. begin
  782. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  783. AMethod.Code:=PropInfo^.SetProc
  784. else
  785. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  786. AMethod.Data:=Instance;
  787. if datasize=8 then
  788. begin
  789. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  790. TSetInt64ProcIndex(AMethod)(PropInfo^.Index,Value)
  791. else
  792. TSetInt64Proc(AMethod)(Value);
  793. end
  794. else
  795. begin
  796. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  797. TSetIntegerProcIndex(AMethod)(PropInfo^.Index,Value)
  798. else
  799. TSetIntegerProc(AMethod)(Value);
  800. end;
  801. end;
  802. end;
  803. end;
  804. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  805. begin
  806. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  807. end;
  808. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  809. begin
  810. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  811. end;
  812. Function GetEnumProp(Instance: TObject; Const PropInfo: PPropInfo): string;
  813. begin
  814. Result:=GetEnumName(PropInfo^.PropType, GetOrdProp(Instance, PropInfo));
  815. end;
  816. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  817. begin
  818. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  819. end;
  820. Procedure SetEnumProp(Instance: TObject; const PropName: string; const Value: string);
  821. begin
  822. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  823. end;
  824. Procedure SetEnumProp(Instance: TObject; Const PropInfo : PPropInfo; const Value: string);
  825. Var
  826. PV : Longint;
  827. begin
  828. If PropInfo<>Nil then
  829. begin
  830. PV:=GetEnumValue(PropInfo^.PropType, Value);
  831. if (PV<0) then
  832. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [Value]);
  833. SetOrdProp(Instance, PropInfo,PV);
  834. end;
  835. end;
  836. { ---------------------------------------------------------------------
  837. Int64 wrappers
  838. ---------------------------------------------------------------------}
  839. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  840. begin
  841. Result:=GetOrdProp(Instance,PropInfo);
  842. end;
  843. procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  844. begin
  845. SetOrdProp(Instance,PropInfo,Value);
  846. end;
  847. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  848. begin
  849. Result:=GetInt64Prop(Instance,FindPropInfo(Instance,PropName));
  850. end;
  851. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  852. begin
  853. SetInt64Prop(Instance,FindPropInfo(Instance,PropName),Value);
  854. end;
  855. { ---------------------------------------------------------------------
  856. Set properties
  857. ---------------------------------------------------------------------}
  858. Function GetSetProp(Instance: TObject; const PropName: string): string;
  859. begin
  860. Result:=GetSetProp(Instance,PropName,False);
  861. end;
  862. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  863. begin
  864. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName),Brackets);
  865. end;
  866. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  867. begin
  868. Result:=SetToString(PropInfo,GetOrdProp(Instance,PropInfo),Brackets);
  869. end;
  870. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  871. begin
  872. SetSetProp(Instance,FindPropInfo(Instance,PropName),Value);
  873. end;
  874. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  875. begin
  876. SetOrdProp(Instance,PropInfo,StringToSet(PropInfo,Value));
  877. end;
  878. { ---------------------------------------------------------------------
  879. Object properties
  880. ---------------------------------------------------------------------}
  881. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  882. begin
  883. Result:=GetObjectProp(Instance,PropName,Nil);
  884. end;
  885. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  886. begin
  887. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName),MinClass);
  888. end;
  889. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo): TObject;
  890. begin
  891. Result:=GetObjectProp(Instance,PropInfo,Nil);
  892. end;
  893. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo; MinClass: TClass): TObject;
  894. begin
  895. {$ifdef cpu64}
  896. Result:=TObject(GetInt64Prop(Instance,PropInfo));
  897. {$else cpu64}
  898. Result:=TObject(PtrInt(GetOrdProp(Instance,PropInfo)));
  899. {$endif cpu64}
  900. If (MinClass<>Nil) and (Result<>Nil) Then
  901. If Not Result.InheritsFrom(MinClass) then
  902. Result:=Nil;
  903. end;
  904. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  905. begin
  906. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  907. end;
  908. Procedure SetObjectProp(Instance: TObject; PropInfo : PPropInfo; Value: TObject);
  909. begin
  910. {$ifdef cpu64}
  911. SetInt64Prop(Instance,PropInfo,Int64(Value));
  912. {$else cpu64}
  913. SetOrdProp(Instance,PropInfo,Integer(Value));
  914. {$endif cpu64}
  915. end;
  916. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  917. begin
  918. Result:=GetTypeData(FindPropInfo(Instance,PropName)^.PropType)^.ClassType;
  919. end;
  920. { ---------------------------------------------------------------------
  921. String properties
  922. ---------------------------------------------------------------------}
  923. Function GetStrProp(Instance: TObject; PropInfo: PPropInfo): AnsiString;
  924. type
  925. TGetShortStrProcIndex=function(index:longint):ShortString of object;
  926. TGetShortStrProc=function():ShortString of object;
  927. TGetAnsiStrProcIndex=function(index:longint):AnsiString of object;
  928. TGetAnsiStrProc=function():AnsiString of object;
  929. var
  930. AMethod : TMethod;
  931. begin
  932. Result:='';
  933. case Propinfo^.PropType^.Kind of
  934. tkWString:
  935. Result:=GetWideStrProp(Instance,PropInfo);
  936. tkSString:
  937. begin
  938. case (PropInfo^.PropProcs) and 3 of
  939. ptField:
  940. Result := PShortString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  941. ptstatic,
  942. ptvirtual :
  943. begin
  944. if (PropInfo^.PropProcs and 3)=ptStatic then
  945. AMethod.Code:=PropInfo^.GetProc
  946. else
  947. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  948. AMethod.Data:=Instance;
  949. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  950. Result:=TGetShortStrProcIndex(AMethod)(PropInfo^.Index)
  951. else
  952. Result:=TGetShortStrProc(AMethod)();
  953. end;
  954. end;
  955. end;
  956. tkAString:
  957. begin
  958. case (PropInfo^.PropProcs) and 3 of
  959. ptField:
  960. Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  961. ptstatic,
  962. ptvirtual :
  963. begin
  964. if (PropInfo^.PropProcs and 3)=ptStatic then
  965. AMethod.Code:=PropInfo^.GetProc
  966. else
  967. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  968. AMethod.Data:=Instance;
  969. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  970. Result:=TGetAnsiStrProcIndex(AMethod)(PropInfo^.Index)
  971. else
  972. Result:=TGetAnsiStrProc(AMethod)();
  973. end;
  974. end;
  975. end;
  976. end;
  977. end;
  978. Procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo; const Value : AnsiString);
  979. type
  980. TSetShortStrProcIndex=procedure(index:longint;const s:ShortString) of object;
  981. TSetShortStrProc=procedure(const s:ShortString) of object;
  982. TSetAnsiStrProcIndex=procedure(index:longint;s:AnsiString) of object;
  983. TSetAnsiStrProc=procedure(s:AnsiString) of object;
  984. var
  985. AMethod : TMethod;
  986. begin
  987. case Propinfo^.PropType^.Kind of
  988. tkWString:
  989. SetWideStrProp(Instance,PropInfo,Value);
  990. tkSString:
  991. begin
  992. case (PropInfo^.PropProcs shr 2) and 3 of
  993. ptField:
  994. PShortString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  995. ptstatic,
  996. ptvirtual :
  997. begin
  998. if (PropInfo^.PropProcs and 3)=ptStatic then
  999. AMethod.Code:=PropInfo^.SetProc
  1000. else
  1001. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1002. AMethod.Data:=Instance;
  1003. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1004. TSetShortStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1005. else
  1006. TSetShortStrProc(AMethod)(Value);
  1007. end;
  1008. end;
  1009. end;
  1010. tkAString:
  1011. begin
  1012. case (PropInfo^.PropProcs shr 2) and 3 of
  1013. ptField:
  1014. PAnsiString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  1015. ptstatic,
  1016. ptvirtual :
  1017. begin
  1018. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1019. AMethod.Code:=PropInfo^.SetProc
  1020. else
  1021. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1022. AMethod.Data:=Instance;
  1023. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1024. TSetAnsiStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1025. else
  1026. TSetAnsiStrProc(AMethod)(Value);
  1027. end;
  1028. end;
  1029. end;
  1030. end;
  1031. end;
  1032. Function GetStrProp(Instance: TObject; const PropName: string): string;
  1033. begin
  1034. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  1035. end;
  1036. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  1037. begin
  1038. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1039. end;
  1040. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  1041. begin
  1042. Result:=GetWideStrProp(Instance, FindPropInfo(Instance, PropName));
  1043. end;
  1044. procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  1045. begin
  1046. SetWideStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1047. end;
  1048. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  1049. type
  1050. TGetWideStrProcIndex=function(index:longint):WideString of object;
  1051. TGetWideStrProc=function():WideString of object;
  1052. var
  1053. AMethod : TMethod;
  1054. begin
  1055. Result:='';
  1056. case Propinfo^.PropType^.Kind of
  1057. tkSString,tkAString:
  1058. Result:=GetStrProp(Instance,PropInfo);
  1059. tkWString:
  1060. begin
  1061. case (PropInfo^.PropProcs) and 3 of
  1062. ptField:
  1063. Result := PWideString(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1064. ptstatic,
  1065. ptvirtual :
  1066. begin
  1067. if (PropInfo^.PropProcs and 3)=ptStatic then
  1068. AMethod.Code:=PropInfo^.GetProc
  1069. else
  1070. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1071. AMethod.Data:=Instance;
  1072. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1073. Result:=TGetWideStrProcIndex(AMethod)(PropInfo^.Index)
  1074. else
  1075. Result:=TGetWideStrProc(AMethod)();
  1076. end;
  1077. end;
  1078. end;
  1079. end;
  1080. end;
  1081. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  1082. type
  1083. TSetWideStrProcIndex=procedure(index:longint;s:WideString) of object;
  1084. TSetWideStrProc=procedure(s:WideString) of object;
  1085. var
  1086. AMethod : TMethod;
  1087. begin
  1088. case Propinfo^.PropType^.Kind of
  1089. tkSString,tkAString:
  1090. SetStrProp(Instance,PropInfo,Value);
  1091. tkWString:
  1092. begin
  1093. case (PropInfo^.PropProcs shr 2) and 3 of
  1094. ptField:
  1095. PWideString(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1096. ptstatic,
  1097. ptvirtual :
  1098. begin
  1099. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1100. AMethod.Code:=PropInfo^.SetProc
  1101. else
  1102. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1103. AMethod.Data:=Instance;
  1104. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1105. TSetWideStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1106. else
  1107. TSetWideStrProc(AMethod)(Value);
  1108. end;
  1109. end;
  1110. end;
  1111. end;
  1112. end;
  1113. { ---------------------------------------------------------------------
  1114. Float properties
  1115. ---------------------------------------------------------------------}
  1116. function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
  1117. type
  1118. TGetExtendedProc = function:Extended of object;
  1119. TGetExtendedProcIndex = function(Index: integer): Extended of object;
  1120. TGetDoubleProc = function:Double of object;
  1121. TGetDoubleProcIndex = function(Index: integer): Double of object;
  1122. TGetSingleProc = function:Single of object;
  1123. TGetSingleProcIndex = function(Index: integer):Single of object;
  1124. TGetCurrencyProc = function : Currency of object;
  1125. TGetCurrencyProcIndex = function(Index: integer) : Currency of object;
  1126. var
  1127. AMethod : TMethod;
  1128. begin
  1129. Result:=0.0;
  1130. case PropInfo^.PropProcs and 3 of
  1131. ptField:
  1132. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1133. ftSingle:
  1134. Result:=PSingle(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1135. ftDouble:
  1136. Result:=PDouble(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1137. ftExtended:
  1138. Result:=PExtended(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1139. ftcomp:
  1140. Result:=PComp(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1141. ftcurr:
  1142. Result:=PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1143. end;
  1144. ptStatic,
  1145. ptVirtual:
  1146. begin
  1147. if (PropInfo^.PropProcs and 3)=ptStatic then
  1148. AMethod.Code:=PropInfo^.GetProc
  1149. else
  1150. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1151. AMethod.Data:=Instance;
  1152. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1153. ftSingle:
  1154. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1155. Result:=TGetSingleProc(AMethod)()
  1156. else
  1157. Result:=TGetSingleProcIndex(AMethod)(PropInfo^.Index);
  1158. ftDouble:
  1159. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1160. Result:=TGetDoubleProc(AMethod)()
  1161. else
  1162. Result:=TGetDoubleProcIndex(AMethod)(PropInfo^.Index);
  1163. ftExtended:
  1164. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1165. Result:=TGetExtendedProc(AMethod)()
  1166. else
  1167. Result:=TGetExtendedProcIndex(AMethod)(PropInfo^.Index);
  1168. ftCurr:
  1169. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1170. Result:=TGetCurrencyProc(AMethod)()
  1171. else
  1172. Result:=TGetCurrencyProcIndex(AMethod)(PropInfo^.Index);
  1173. end;
  1174. end;
  1175. end;
  1176. end;
  1177. Procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo; Value : Extended);
  1178. type
  1179. TSetExtendedProc = procedure(const AValue: Extended) of object;
  1180. TSetExtendedProcIndex = procedure(Index: integer; AValue: Extended) of object;
  1181. TSetDoubleProc = procedure(const AValue: Double) of object;
  1182. TSetDoubleProcIndex = procedure(Index: integer; AValue: Double) of object;
  1183. TSetSingleProc = procedure(const AValue: Single) of object;
  1184. TSetSingleProcIndex = procedure(Index: integer; AValue: Single) of object;
  1185. TSetCurrencyProc = procedure(const AValue: Currency) of object;
  1186. TSetCurrencyProcIndex = procedure(Index: integer; AValue: Currency) of object;
  1187. Var
  1188. AMethod : TMethod;
  1189. begin
  1190. case (PropInfo^.PropProcs shr 2) and 3 of
  1191. ptfield:
  1192. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1193. ftSingle:
  1194. PSingle(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1195. ftDouble:
  1196. PDouble(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1197. ftExtended:
  1198. PExtended(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1199. {$ifdef FPC_COMP_IS_INT64}
  1200. ftComp:
  1201. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=trunc(Value);
  1202. {$else FPC_COMP_IS_INT64}
  1203. ftComp:
  1204. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Comp(Value);
  1205. {$endif FPC_COMP_IS_INT64}
  1206. ftCurr:
  1207. PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1208. end;
  1209. ptStatic,
  1210. ptVirtual:
  1211. begin
  1212. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1213. AMethod.Code:=PropInfo^.SetProc
  1214. else
  1215. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1216. AMethod.Data:=Instance;
  1217. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1218. ftSingle:
  1219. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1220. TSetSingleProc(AMethod)(Value)
  1221. else
  1222. TSetSingleProcIndex(AMethod)(PropInfo^.Index,Value);
  1223. ftDouble:
  1224. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1225. TSetDoubleProc(AMethod)(Value)
  1226. else
  1227. TSetDoubleProcIndex(AMethod)(PropInfo^.Index,Value);
  1228. ftExtended:
  1229. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1230. TSetExtendedProc(AMethod)(Value)
  1231. else
  1232. TSetExtendedProcIndex(AMethod)(PropInfo^.Index,Value);
  1233. ftCurr:
  1234. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1235. TSetCurrencyProc(AMethod)(Value)
  1236. else
  1237. TSetCurrencyProcIndex(AMethod)(PropInfo^.Index,Value);
  1238. end;
  1239. end;
  1240. end;
  1241. end;
  1242. function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  1243. begin
  1244. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName))
  1245. end;
  1246. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  1247. begin
  1248. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  1249. end;
  1250. { ---------------------------------------------------------------------
  1251. Method properties
  1252. ---------------------------------------------------------------------}
  1253. Function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
  1254. type
  1255. TGetMethodProcIndex=function(Index: Longint): TMethod of object;
  1256. TGetMethodProc=function(): TMethod of object;
  1257. var
  1258. value: PMethod;
  1259. AMethod : TMethod;
  1260. begin
  1261. Result.Code:=nil;
  1262. Result.Data:=nil;
  1263. case (PropInfo^.PropProcs) and 3 of
  1264. ptfield:
  1265. begin
  1266. Value:=PMethod(Pointer(Instance)+PtrUInt(PropInfo^.GetProc));
  1267. if Value<>nil then
  1268. Result:=Value^;
  1269. end;
  1270. ptstatic,
  1271. ptvirtual :
  1272. begin
  1273. if (PropInfo^.PropProcs and 3)=ptStatic then
  1274. AMethod.Code:=PropInfo^.GetProc
  1275. else
  1276. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1277. AMethod.Data:=Instance;
  1278. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1279. Result:=TGetMethodProcIndex(AMethod)(PropInfo^.Index)
  1280. else
  1281. Result:=TGetMethodProc(AMethod)();
  1282. end;
  1283. end;
  1284. end;
  1285. Procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo; const Value : TMethod);
  1286. type
  1287. TSetMethodProcIndex=procedure(index:longint;p:TMethod) of object;
  1288. TSetMethodProc=procedure(p:TMethod) of object;
  1289. var
  1290. AMethod : TMethod;
  1291. begin
  1292. case (PropInfo^.PropProcs shr 2) and 3 of
  1293. ptfield:
  1294. PMethod(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^ := Value;
  1295. ptstatic,
  1296. ptvirtual :
  1297. begin
  1298. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1299. AMethod.Code:=PropInfo^.SetProc
  1300. else
  1301. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1302. AMethod.Data:=Instance;
  1303. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1304. TSetMethodProcIndex(AMethod)(PropInfo^.Index,Value)
  1305. else
  1306. TSetMethodProc(AMethod)(Value);
  1307. end;
  1308. end;
  1309. end;
  1310. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  1311. begin
  1312. Result:=GetMethodProp(Instance,FindPropInfo(Instance,PropName));
  1313. end;
  1314. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  1315. begin
  1316. SetMethodProp(Instance,FindPropInfo(Instance,PropName),Value);
  1317. end;
  1318. { ---------------------------------------------------------------------
  1319. Variant properties
  1320. ---------------------------------------------------------------------}
  1321. Procedure CheckVariantEvent(P : Pointer);
  1322. begin
  1323. If (P=Nil) then
  1324. Raise Exception.Create(SErrNoVariantSupport);
  1325. end;
  1326. Function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
  1327. begin
  1328. CheckVariantEvent(Pointer(OnGetVariantProp));
  1329. Result:=OnGetVariantProp(Instance,PropInfo);
  1330. end;
  1331. Procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo; const Value: Variant);
  1332. begin
  1333. CheckVariantEvent(Pointer(OnSetVariantProp));
  1334. OnSetVariantProp(Instance,PropInfo,Value);
  1335. end;
  1336. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  1337. begin
  1338. Result:=GetVariantProp(Instance,FindPropInfo(Instance,PropName));
  1339. end;
  1340. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  1341. begin
  1342. SetVariantprop(instance,FindpropInfo(Instance,PropName),Value);
  1343. end;
  1344. { ---------------------------------------------------------------------
  1345. All properties through variant.
  1346. ---------------------------------------------------------------------}
  1347. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  1348. begin
  1349. Result:=GetPropValue(Instance,PropName,True);
  1350. end;
  1351. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  1352. begin
  1353. CheckVariantEvent(Pointer(OnGetPropValue));
  1354. Result:=OnGetPropValue(Instance,PropName,PreferStrings)
  1355. end;
  1356. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  1357. begin
  1358. CheckVariantEvent(Pointer(OnSetPropValue));
  1359. OnSetPropValue(Instance,PropName,Value);
  1360. end;
  1361. { ---------------------------------------------------------------------
  1362. Easy access methods that appeared in Delphi 5
  1363. ---------------------------------------------------------------------}
  1364. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  1365. begin
  1366. Result:=GetPropInfo(Instance,PropName)<>Nil;
  1367. end;
  1368. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  1369. begin
  1370. Result:=GetPropInfo(AClass,PropName)<>Nil;
  1371. end;
  1372. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  1373. begin
  1374. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind=TypeKind
  1375. end;
  1376. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  1377. begin
  1378. Result:=PropType(AClass,PropName)=TypeKind
  1379. end;
  1380. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  1381. begin
  1382. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind;
  1383. end;
  1384. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  1385. begin
  1386. Result:=FindPropInfo(AClass,PropName)^.PropType^.Kind;
  1387. end;
  1388. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  1389. begin
  1390. Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
  1391. end;
  1392. end.