typinfo.pp 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081
  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. {$ifdef FPC_RTTI_PACKSET1}
  23. { for Delphi compatibility }
  24. {$packset 1}
  25. {$endif}
  26. // if you change one of the following enumeration types
  27. // you have also to change the compiler in an appropriate way !
  28. TTypeKind = (tkUnknown,tkInteger,tkChar,tkEnumeration,tkFloat,
  29. tkSet,tkMethod,tkSString,tkLString,tkAString,
  30. tkWString,tkVariant,tkArray,tkRecord,tkInterface,
  31. tkClass,tkObject,tkWChar,tkBool,tkInt64,tkQWord,
  32. tkDynArray,tkInterfaceRaw,tkProcVar,tkUString,tkUChar,
  33. tkHelper);
  34. TOrdType = (otSByte,otUByte,otSWord,otUWord,otSLong,otULong);
  35. {$ifndef FPUNONE}
  36. TFloatType = (ftSingle,ftDouble,ftExtended,ftComp,ftCurr);
  37. {$endif}
  38. TMethodKind = (mkProcedure,mkFunction,mkConstructor,mkDestructor,
  39. mkClassProcedure,mkClassFunction,mkClassConstructor,
  40. mkClassDestructor,mkOperatorOverload);
  41. TParamFlag = (pfVar,pfConst,pfArray,pfAddress,pfReference,pfOut);
  42. TParamFlags = set of TParamFlag;
  43. TIntfFlag = (ifHasGuid,ifDispInterface,ifDispatch,ifHasStrGUID);
  44. TIntfFlags = set of TIntfFlag;
  45. TIntfFlagsBase = set of TIntfFlag;
  46. // don't rely on integer values of TCallConv since it includes all conventions
  47. // which both delphi and fpc support. In the future delphi can support more and
  48. // fpc own conventions will be shifted/reordered accordinly
  49. TCallConv = (ccReg, ccCdecl, ccPascal, ccStdCall, ccSafeCall,
  50. ccCppdecl, ccFar16, ccOldFPCCall, ccInternProc,
  51. ccSysCall, ccSoftFloat, ccMWPascal);
  52. {$MINENUMSIZE DEFAULT}
  53. const
  54. ptField = 0;
  55. ptStatic = 1;
  56. ptVirtual = 2;
  57. ptConst = 3;
  58. tkString = tkSString;
  59. type
  60. TTypeKinds = set of TTypeKind;
  61. ShortStringBase = string[255];
  62. PVmtFieldEntry = ^TVmtFieldEntry;
  63. TVmtFieldEntry =
  64. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  65. packed
  66. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  67. record
  68. FieldOffset: PtrUInt;
  69. TypeIndex: Word;
  70. Name: ShortString;
  71. end;
  72. PVmtFieldTable = ^TVmtFieldTable;
  73. TVmtFieldTable =
  74. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  75. packed
  76. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  77. record
  78. Count: Word;
  79. ClassTab: Pointer;
  80. { should be array[Word] of TFieldInfo; but
  81. Elements have variant size! force at least proper alignment }
  82. Fields: array[0..0] of TVmtFieldEntry
  83. end;
  84. {$PACKRECORDS 1}
  85. TTypeInfo = record
  86. Kind : TTypeKind;
  87. Name : ShortString;
  88. // here the type data follows as TTypeData record
  89. end;
  90. PTypeInfo = ^TTypeInfo;
  91. PPTypeInfo = ^PTypeInfo;
  92. {$PACKRECORDS C}
  93. PTypeData = ^TTypeData;
  94. TTypeData =
  95. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  96. packed
  97. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  98. record
  99. case TTypeKind of
  100. tkUnKnown,tkLString,tkWString,tkAString,tkVariant,tkUString:
  101. ();
  102. tkInteger,tkChar,tkEnumeration,tkWChar,tkSet:
  103. (OrdType : TOrdType;
  104. case TTypeKind of
  105. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar : (
  106. MinValue,MaxValue : Longint;
  107. case TTypeKind of
  108. tkEnumeration:
  109. (
  110. BaseType : PTypeInfo;
  111. NameList : ShortString;
  112. {EnumUnitName: ShortString;})
  113. );
  114. tkSet:
  115. (CompType : PTypeInfo)
  116. );
  117. {$ifndef FPUNONE}
  118. tkFloat:
  119. (FloatType : TFloatType);
  120. {$endif}
  121. tkSString:
  122. (MaxLength : Byte);
  123. tkClass:
  124. (ClassType : TClass;
  125. ParentInfo : PTypeInfo;
  126. PropCount : SmallInt;
  127. AttributeCount : byte;
  128. UnitName : ShortString
  129. // here the attributes follow as array of TAttributeProc
  130. // followed by the properties as array of TPropInfo
  131. );
  132. tkHelper:
  133. (HelperParent : PTypeInfo;
  134. ExtendedInfo : PTypeInfo;
  135. HelperProps : SmallInt;
  136. HelperUnit : ShortString
  137. // here the properties follow as array of TPropInfo
  138. );
  139. tkMethod:
  140. (MethodKind : TMethodKind;
  141. ParamCount : Byte;
  142. ParamList : array[0..1023] of Char
  143. {in reality ParamList is a array[1..ParamCount] of:
  144. record
  145. Flags : TParamFlags;
  146. ParamName : ShortString;
  147. TypeName : ShortString;
  148. end;
  149. followed by
  150. ResultType : ShortString // for mkFunction, mkClassFunction only
  151. ResultTypeRef : PPTypeInfo; // for mkFunction, mkClassFunction only
  152. CC : TCallConv;
  153. ParamTypeRefs : array[1..ParamCount] of PPTypeInfo;}
  154. );
  155. tkInt64:
  156. (MinInt64Value, MaxInt64Value: Int64);
  157. tkQWord:
  158. (MinQWordValue, MaxQWordValue: QWord);
  159. tkInterface:
  160. (
  161. IntfParent: PTypeInfo;
  162. IntfFlags : TIntfFlagsBase;
  163. GUID: TGUID;
  164. IntfUnit: ShortString;
  165. );
  166. tkInterfaceRaw:
  167. (
  168. RawIntfParent: PTypeInfo;
  169. RawIntfFlags : TIntfFlagsBase;
  170. IID: TGUID;
  171. RawIntfUnit: ShortString;
  172. IIDStr: ShortString;
  173. );
  174. tkDynArray:
  175. (
  176. elSize : PtrUInt;
  177. elType2 : PPTypeInfo;
  178. varType : Longint;
  179. elType : PPTypeInfo;
  180. DynUnitName: ShortStringBase
  181. );
  182. end;
  183. // unsed, just for completeness
  184. TPropData =
  185. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  186. packed
  187. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  188. record
  189. PropCount : Word;
  190. PropList : record _alignmentdummy : ptrint; end;
  191. end;
  192. {$PACKRECORDS 1}
  193. PPropInfo = ^TPropInfo;
  194. TPropInfo = packed record
  195. PropType : PTypeInfo;
  196. GetProc : Pointer;
  197. SetProc : Pointer;
  198. StoredProc : Pointer;
  199. Index : Integer;
  200. Default : Longint;
  201. NameIndex : SmallInt;
  202. // contains the type of the Get/Set/Storedproc, see also ptxxx
  203. // bit 0..1 GetProc
  204. // 2..3 SetProc
  205. // 4..5 StoredProc
  206. // 6 : true, constant index property
  207. PropProcs : Byte;
  208. AttributeCount : byte;
  209. Name : ShortString;
  210. end;
  211. TProcInfoProc = Procedure(PropInfo : PPropInfo) of object;
  212. TAttributeProc = function : TObject;
  213. PAttributeProcList = ^TAttributeProcList;
  214. TAttributeProcList = array[0..255] of TAttributeProc;
  215. PPropList = ^TPropList;
  216. TPropList = array[0..65535] of PPropInfo;
  217. TClassAttributeData = record
  218. AttributeCount: byte;
  219. AttributesList: TAttributeProcList;
  220. end;
  221. PClassAttributeData = ^TClassAttributeData;
  222. TExtRTTIData = record
  223. TypeData: PTypeInfo;
  224. AttributeData: PClassAttributeData;
  225. end;
  226. PExtRTTIData = ^TExtRTTIData;
  227. const
  228. tkAny = [Low(TTypeKind)..High(TTypeKind)];
  229. tkMethods = [tkMethod];
  230. tkProperties = tkAny-tkMethods-[tkUnknown];
  231. // general property handling
  232. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  233. Function GetPropInfo(TypeInfo: PTypeInfo;const PropName: string): PPropInfo;
  234. Function GetPropInfo(TypeInfo: PTypeInfo;const PropName: string; AKinds: TTypeKinds): PPropInfo;
  235. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  236. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  237. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  238. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  239. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  240. Function FindPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  241. Function FindPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  242. Function FindPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  243. Procedure GetPropInfos(TypeInfo: PTypeInfo; PropList: PPropList);
  244. Function GetPropList(TypeInfo: PTypeInfo; TypeKinds: TTypeKinds; PropList: PPropList; Sorted: boolean = true): longint;
  245. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  246. function GetPropList(AClass: TClass; out PropList: PPropList): Integer;
  247. function GetPropList(Instance: TObject; out PropList: PPropList): Integer;
  248. // Property information routines.
  249. Function IsStoredProp(Instance: TObject;PropInfo : PPropInfo) : Boolean;
  250. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  251. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  252. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  253. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  254. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  255. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  256. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  257. // subroutines to read/write properties
  258. Function GetOrdProp(Instance: TObject; PropInfo : PPropInfo) : Int64;
  259. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  260. Procedure SetOrdProp(Instance: TObject; PropInfo : PPropInfo; Value : Int64);
  261. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  262. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  263. Function GetEnumProp(Instance: TObject; const PropInfo: PPropInfo): string;
  264. Procedure SetEnumProp(Instance: TObject; const PropName: string;const Value: string);
  265. Procedure SetEnumProp(Instance: TObject; const PropInfo: PPropInfo;const Value: string);
  266. Function GetSetProp(Instance: TObject; const PropName: string): string;
  267. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  268. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  269. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  270. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  271. Function GetStrProp(Instance: TObject; PropInfo : PPropInfo) : Ansistring;
  272. Function GetStrProp(Instance: TObject; const PropName: string): string;
  273. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  274. Procedure SetStrProp(Instance: TObject; PropInfo : PPropInfo; const Value : Ansistring);
  275. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  276. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  277. Procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  278. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  279. Function GetUnicodeStrProp(Instance: TObject; PropInfo: PPropInfo): UnicodeString;
  280. Function GetUnicodeStrProp(Instance: TObject; const PropName: string): UnicodeString;
  281. Procedure SetUnicodeStrProp(Instance: TObject; const PropName: string; const Value: UnicodeString);
  282. Procedure SetUnicodeStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: UnicodeString);
  283. {$ifndef FPUNONE}
  284. Function GetFloatProp(Instance: TObject; PropInfo : PPropInfo) : Extended;
  285. Function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  286. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  287. Procedure SetFloatProp(Instance: TObject; PropInfo : PPropInfo; Value : Extended);
  288. {$endif}
  289. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  290. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  291. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo): TObject;
  292. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo; MinClass: TClass): TObject;
  293. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  294. Procedure SetObjectProp(Instance: TObject; PropInfo: PPropInfo; Value: TObject);
  295. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  296. Function GetObjectPropClass(AClass: TClass; const PropName: string): TClass;
  297. Function GetMethodProp(Instance: TObject; PropInfo: PPropInfo) : TMethod;
  298. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  299. Procedure SetMethodProp(Instance: TObject; PropInfo: PPropInfo; const Value : TMethod);
  300. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  301. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  302. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  303. Procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  304. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  305. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  306. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  307. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  308. Function GetVariantProp(Instance: TObject; PropInfo : PPropInfo): Variant;
  309. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  310. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  311. Procedure SetVariantProp(Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  312. function GetInterfaceProp(Instance: TObject; const PropName: string): IInterface;
  313. function GetInterfaceProp(Instance: TObject; PropInfo: PPropInfo): IInterface;
  314. procedure SetInterfaceProp(Instance: TObject; const PropName: string; const Value: IInterface);
  315. procedure SetInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: IInterface);
  316. function GetRawInterfaceProp(Instance: TObject; const PropName: string): Pointer;
  317. function GetRawInterfaceProp(Instance: TObject; PropInfo: PPropInfo): Pointer;
  318. procedure SetRawInterfaceProp(Instance: TObject; const PropName: string; const Value: Pointer);
  319. procedure SetRawInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: Pointer);
  320. // Extended RTTI
  321. function GetExtRTTIData(TypeInfo : PTypeInfo) : PExtRTTIData;
  322. function GetPropAttributeProclist(PropInfo: PPropInfo): PAttributeProcList;
  323. function GetPropAttribute(PropInfo: PPropInfo; AttributeNr: byte): TObject;
  324. function GetClassAttributeCount(ExtRTTIData: PExtRTTIData): byte;
  325. function GetClassAttributeProclist(ExtRTTIData: PExtRTTIData): PAttributeProcList;
  326. function GetClassAttribute(ExtRTTIData: PExtRTTIData; AttributeNr: byte): TObject;
  327. // Auxiliary routines, which may be useful
  328. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  329. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  330. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  331. function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean) : String;
  332. function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  333. function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  334. function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  335. function StringToSet(TypeInfo: PTypeInfo; const Value: string): Integer;
  336. const
  337. BooleanIdents: array[Boolean] of String = ('False', 'True');
  338. DotSep: String = '.';
  339. Type
  340. EPropertyError = Class(Exception);
  341. TGetPropValue = Function (Instance: TObject; const PropName: string; PreferStrings: Boolean) : Variant;
  342. TSetPropValue = Procedure (Instance: TObject; const PropName: string; const Value: Variant);
  343. TGetVariantProp = Function (Instance: TObject; PropInfo : PPropInfo): Variant;
  344. TSetVariantProp = Procedure (Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  345. EPropertyConvertError = class(Exception); // Not used (yet), but defined for compatibility.
  346. Const
  347. OnGetPropValue : TGetPropValue = Nil;
  348. OnSetPropValue : TSetPropValue = Nil;
  349. OnGetVariantprop : TGetVariantProp = Nil;
  350. OnSetVariantprop : TSetVariantProp = Nil;
  351. Implementation
  352. uses rtlconsts;
  353. type
  354. PMethod = ^TMethod;
  355. { ---------------------------------------------------------------------
  356. Auxiliary methods
  357. ---------------------------------------------------------------------}
  358. function aligntoptr(p : pointer) : pointer;inline;
  359. begin
  360. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  361. result:=align(p,sizeof(p));
  362. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  363. result:=p;
  364. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  365. end;
  366. function GetExtRTTIData(TypeInfo: PTypeInfo): PExtRTTIData;
  367. var
  368. p: pointer;
  369. begin
  370. p := pointer(TypeInfo) - sizeof(p);
  371. result := PExtRTTIData(pointer(p)^);
  372. end;
  373. function GetPropAttributeProclist(PropInfo: PPropInfo): PAttributeProcList;
  374. begin
  375. if PropInfo^.AttributeCount=0 then
  376. result := nil
  377. else
  378. begin
  379. Result:=PAttributeProcList(aligntoptr(pointer(@PropInfo^.Name)+byte(PropInfo^.Name[0])+1));
  380. end;
  381. end;
  382. function GetPropAttribute(PropInfo: PPropInfo; AttributeNr: byte): TObject;
  383. var
  384. AttributeProcList: PAttributeProcList;
  385. begin
  386. if AttributeNr>=PropInfo^.AttributeCount then
  387. result := nil
  388. else
  389. begin
  390. AttributeProcList := GetPropAttributeProclist(PropInfo);
  391. result := AttributeProcList^[AttributeNr]();
  392. end;
  393. end;
  394. function GetClassAttributeCount(ExtRTTIData: PExtRTTIData): byte;
  395. begin
  396. if not assigned(ExtRTTIData^.AttributeData) then
  397. result := 0
  398. else
  399. result := ExtRTTIData^.AttributeData^.AttributeCount;
  400. end;
  401. function GetClassAttributeProclist(ExtRTTIData: PExtRTTIData): PAttributeProcList;
  402. begin
  403. if GetClassAttributeCount(ExtRTTIData) = 0 then
  404. result := nil
  405. else
  406. result := @ExtRTTIData^.AttributeData^.AttributesList;
  407. end;
  408. function GetClassAttribute(ExtRTTIData: PExtRTTIData; AttributeNr: byte): TObject;
  409. var
  410. AttributeProcList: PAttributeProcList;
  411. begin
  412. if AttributeNr>=GetClassAttributeCount(ExtRTTIData) then
  413. result := nil
  414. else
  415. begin
  416. AttributeProcList := GetClassAttributeProclist(ExtRTTIData);
  417. result := AttributeProcList^[AttributeNr]();
  418. end;
  419. end;
  420. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  421. Var PS : PShortString;
  422. PT : PTypeData;
  423. begin
  424. PT:=GetTypeData(TypeInfo);
  425. if TypeInfo^.Kind=tkBool then
  426. begin
  427. case Value of
  428. 0,1:
  429. Result:=BooleanIdents[Boolean(Value)];
  430. else
  431. Result:='';
  432. end;
  433. end
  434. else
  435. begin
  436. PS:=@PT^.NameList;
  437. dec(Value,PT^.MinValue);
  438. While Value>0 Do
  439. begin
  440. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  441. Dec(Value);
  442. end;
  443. Result:=PS^;
  444. end;
  445. end;
  446. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  447. Var PS : PShortString;
  448. PT : PTypeData;
  449. Count : longint;
  450. sName: shortstring;
  451. begin
  452. If Length(Name)=0 then
  453. exit(-1);
  454. sName := Name;
  455. PT:=GetTypeData(TypeInfo);
  456. Count:=0;
  457. Result:=-1;
  458. if TypeInfo^.Kind=tkBool then
  459. begin
  460. If CompareText(BooleanIdents[false],Name)=0 then
  461. result:=0
  462. else if CompareText(BooleanIdents[true],Name)=0 then
  463. result:=1;
  464. end
  465. else
  466. begin
  467. PS:=@PT^.NameList;
  468. While (Result=-1) and (PByte(PS)^<>0) do
  469. begin
  470. If ShortCompareText(PS^, sName) = 0 then
  471. Result:=Count+PT^.MinValue;
  472. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  473. Inc(Count);
  474. end;
  475. end;
  476. end;
  477. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  478. var
  479. PS: PShortString;
  480. PT: PTypeData;
  481. Count: SizeInt;
  482. begin
  483. PT:=GetTypeData(enum1);
  484. if enum1^.Kind=tkBool then
  485. Result:=2
  486. else
  487. begin
  488. Count:=0;
  489. Result:=0;
  490. PS:=@PT^.NameList;
  491. While (PByte(PS)^<>0) do
  492. begin
  493. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  494. Inc(Count);
  495. end;
  496. { the last string is the unit name }
  497. Result := Count - 1;
  498. end;
  499. end;
  500. Function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  501. begin
  502. Result:=SetToString(PropInfo^.PropType,Value,Brackets);
  503. end;
  504. Function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean) : String;
  505. type
  506. tsetarr = bitpacked array[0..31] of 0..1;
  507. Var
  508. I : Integer;
  509. PTI : PTypeInfo;
  510. begin
  511. {$if defined(FPC_BIG_ENDIAN)}
  512. { On big endian systems, set element 0 is in the most significant bit,
  513. and the same goes for the elements of bitpacked arrays there. }
  514. case GetTypeData(TypeInfo)^.OrdType of
  515. otSByte,otUByte: Value:=Value shl 24;
  516. otSWord,otUWord: Value:=Value shl 16;
  517. end;
  518. {$endif}
  519. PTI:=GetTypeData(TypeInfo)^.CompType;
  520. Result:='';
  521. For I:=0 to SizeOf(Integer)*8-1 do
  522. begin
  523. if (tsetarr(Value)[i]<>0) then
  524. begin
  525. If Result='' then
  526. Result:=GetEnumName(PTI,i)
  527. else
  528. Result:=Result+','+GetEnumName(PTI,I);
  529. end;
  530. end;
  531. if Brackets then
  532. Result:='['+Result+']';
  533. end;
  534. Function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  535. begin
  536. Result:=SetToString(PropInfo,Value,False);
  537. end;
  538. Const
  539. SetDelim = ['[',']',',',' '];
  540. Function GetNextElement(Var S : String) : String;
  541. Var
  542. J : Integer;
  543. begin
  544. J:=1;
  545. Result:='';
  546. If Length(S)>0 then
  547. begin
  548. While (J<=Length(S)) and Not (S[j] in SetDelim) do
  549. Inc(j);
  550. Result:=Copy(S,1,j-1);
  551. Delete(S,1,j);
  552. end;
  553. end;
  554. Function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  555. begin
  556. Result:=StringToSet(PropInfo^.PropType,Value);
  557. end;
  558. Function StringToSet(TypeInfo: PTypeInfo; const Value: string): Integer;
  559. Var
  560. S,T : String;
  561. I : Integer;
  562. PTI : PTypeInfo;
  563. begin
  564. Result:=0;
  565. PTI:=GetTypeData(TypeInfo)^.Comptype;
  566. S:=Value;
  567. I:=1;
  568. If Length(S)>0 then
  569. begin
  570. While (I<=Length(S)) and (S[i] in SetDelim) do
  571. Inc(I);
  572. Delete(S,1,i-1);
  573. end;
  574. While (S<>'') do
  575. begin
  576. T:=GetNextElement(S);
  577. if T<>'' then
  578. begin
  579. I:=GetEnumValue(PTI,T);
  580. if (I<0) then
  581. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [T]);
  582. Result:=Result or (1 shl i);
  583. end;
  584. end;
  585. end;
  586. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  587. begin
  588. GetTypeData:=PTypeData(aligntoptr(PTypeData(pointer(TypeInfo)+2+PByte(pointer(TypeInfo)+1)^)));
  589. end;
  590. { ---------------------------------------------------------------------
  591. Basic Type information functions.
  592. ---------------------------------------------------------------------}
  593. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  594. var
  595. hp : PTypeData;
  596. i : longint;
  597. p : shortstring;
  598. pd : ^TPropData;
  599. begin
  600. P:=PropName; // avoid Ansi<->short conversion in a loop
  601. while Assigned(TypeInfo) do
  602. begin
  603. // skip the name
  604. hp:=GetTypeData(Typeinfo);
  605. // the class info rtti the property rtti follows immediatly
  606. pd:=aligntoptr(pointer(pointer(@hp^.UnitName)+Length(hp^.UnitName)+1));
  607. // also skip the attribute-information
  608. pd:=aligntoptr(pointer(pd)+(hp^.AttributeCount*sizeof(TAttributeProc)));
  609. Result:=PPropInfo(@pd^.PropList);
  610. for i:=1 to pd^.PropCount do
  611. begin
  612. // found a property of that name ?
  613. if ShortCompareText(Result^.Name, P) = 0 then
  614. exit;
  615. // skip to next property
  616. Result:=PPropInfo(aligntoptr(pointer(@Result^.Name)+byte(Result^.Name[0])+(result^.AttributeCount*SizeOf(TAttributeProc))+1));
  617. end;
  618. // parent class
  619. Typeinfo:=hp^.ParentInfo;
  620. end;
  621. Result:=Nil;
  622. end;
  623. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; Akinds : TTypeKinds) : PPropInfo;
  624. begin
  625. Result:=GetPropInfo(TypeInfo,PropName);
  626. If (Akinds<>[]) then
  627. If (Result<>Nil) then
  628. If Not (Result^.PropType^.Kind in AKinds) then
  629. Result:=Nil;
  630. end;
  631. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  632. begin
  633. Result:=GetPropInfo(PTypeInfo(AClass.ClassInfo),PropName,AKinds);
  634. end;
  635. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  636. begin
  637. Result:=GetPropInfo(Instance.ClassType,PropName,AKinds);
  638. end;
  639. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  640. begin
  641. Result:=GetPropInfo(Instance,PropName,[]);
  642. end;
  643. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  644. begin
  645. Result:=GetPropInfo(AClass,PropName,[]);
  646. end;
  647. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  648. begin
  649. result:=GetPropInfo(Instance, PropName);
  650. if Result=nil then
  651. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  652. end;
  653. Function FindPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  654. begin
  655. result:=GetPropInfo(Instance, PropName, AKinds);
  656. if Result=nil then
  657. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  658. end;
  659. Function FindPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  660. begin
  661. result:=GetPropInfo(AClass, PropName);
  662. if result=nil then
  663. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  664. end;
  665. Function FindPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  666. begin
  667. result:=GetPropInfo(AClass, PropName, AKinds);
  668. if result=nil then
  669. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  670. end;
  671. Function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean;
  672. type
  673. TBooleanIndexFunc=function(Index:integer):boolean of object;
  674. TBooleanFunc=function:boolean of object;
  675. var
  676. AMethod : TMethod;
  677. begin
  678. case (PropInfo^.PropProcs shr 4) and 3 of
  679. ptfield:
  680. Result:=PBoolean(Pointer(Instance)+PtrUInt(PropInfo^.StoredProc))^;
  681. ptconst:
  682. Result:=LongBool(PropInfo^.StoredProc);
  683. ptstatic,
  684. ptvirtual:
  685. begin
  686. if (PropInfo^.PropProcs shr 4) and 3=ptstatic then
  687. AMethod.Code:=PropInfo^.StoredProc
  688. else
  689. AMethod.Code:=ppointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.StoredProc))^;
  690. AMethod.Data:=Instance;
  691. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  692. Result:=TBooleanIndexFunc(AMethod)(PropInfo^.Index)
  693. else
  694. Result:=TBooleanFunc(AMethod)();
  695. end;
  696. end;
  697. end;
  698. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  699. {
  700. Store Pointers to property information in the list pointed
  701. to by proplist. PRopList must contain enough space to hold ALL
  702. properties.
  703. }
  704. Var
  705. TD : PTypeData;
  706. TP : PPropInfo;
  707. Count : Longint;
  708. begin
  709. // Get this objects TOTAL published properties count
  710. TD:=GetTypeData(TypeInfo);
  711. // Clear list
  712. FillChar(PropList^,TD^.PropCount*sizeof(Pointer),0);
  713. repeat
  714. TD:=GetTypeData(TypeInfo);
  715. // published properties count for this object
  716. TP:=aligntoptr(PPropInfo(aligntoptr((Pointer(@TD^.UnitName)+Length(TD^.UnitName)+1))));
  717. // skip the attribute-info if available
  718. TP:=aligntoptr(pointer(TP)+(TD^.AttributeCount*sizeof(TAttributeProc)));
  719. Count:=PWord(TP)^;
  720. // Now point TP to first propinfo record.
  721. Inc(Pointer(TP),SizeOF(Word));
  722. tp:=aligntoptr(tp);
  723. While Count>0 do
  724. begin
  725. // Don't overwrite properties with the same name
  726. if PropList^[TP^.NameIndex]=nil then
  727. PropList^[TP^.NameIndex]:=TP;
  728. // Point to TP next propinfo record.
  729. // Located at Name[Length(Name)+1] !
  730. TP:=aligntoptr(PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+(TP^.AttributeCount*SizeOf(TAttributeProc))+1));
  731. Dec(Count);
  732. end;
  733. TypeInfo:=TD^.Parentinfo;
  734. until TypeInfo=nil;
  735. end;
  736. Procedure InsertProp (PL : PProplist;PI : PPropInfo; Count : longint);
  737. Var
  738. I : Longint;
  739. begin
  740. I:=0;
  741. While (I<Count) and (PI^.Name>PL^[I]^.Name) do
  742. Inc(I);
  743. If I<Count then
  744. Move(PL^[I], PL^[I+1], (Count - I) * SizeOf(Pointer));
  745. PL^[I]:=PI;
  746. end;
  747. Procedure InsertPropnosort (PL : PProplist;PI : PPropInfo; Count : longint);
  748. begin
  749. PL^[Count]:=PI;
  750. end;
  751. Type TInsertProp = Procedure (PL : PProplist;PI : PPropInfo; Count : longint);
  752. //Const InsertProps : array[false..boolean] of TInsertProp = (InsertPropNoSort,InsertProp);
  753. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
  754. {
  755. Store Pointers to property information OF A CERTAIN KIND in the list pointed
  756. to by proplist. PRopList must contain enough space to hold ALL
  757. properties.
  758. }
  759. Var
  760. TempList : PPropList;
  761. PropInfo : PPropinfo;
  762. I,Count : longint;
  763. DoInsertProp : TInsertProp;
  764. begin
  765. if sorted then
  766. DoInsertProp:=@InsertProp
  767. else
  768. DoInsertProp:=@InsertPropnosort;
  769. Result:=0;
  770. Count:=GetTypeData(TypeInfo)^.Propcount;
  771. If Count>0 then
  772. begin
  773. GetMem(TempList,Count*SizeOf(Pointer));
  774. Try
  775. GetPropInfos(TypeInfo,TempList);
  776. For I:=0 to Count-1 do
  777. begin
  778. PropInfo:=TempList^[i];
  779. If PropInfo^.PropType^.Kind in TypeKinds then
  780. begin
  781. If (PropList<>Nil) then
  782. DoInsertProp(PropList,PropInfo,Result);
  783. Inc(Result);
  784. end;
  785. end;
  786. finally
  787. FreeMem(TempList,Count*SizeOf(Pointer));
  788. end;
  789. end;
  790. end;
  791. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  792. begin
  793. result:=GetTypeData(TypeInfo)^.Propcount;
  794. if result>0 then
  795. begin
  796. getmem(PropList,result*sizeof(pointer));
  797. GetPropInfos(TypeInfo,PropList);
  798. end
  799. else
  800. PropList:=Nil;
  801. end;
  802. function GetPropList(AClass: TClass; out PropList: PPropList): Integer;
  803. begin
  804. Result := GetPropList(PTypeInfo(AClass.ClassInfo), PropList);
  805. end;
  806. function GetPropList(Instance: TObject; out PropList: PPropList): Integer;
  807. begin
  808. Result := GetPropList(Instance.ClassType, PropList);
  809. end;
  810. { ---------------------------------------------------------------------
  811. Property access functions
  812. ---------------------------------------------------------------------}
  813. { ---------------------------------------------------------------------
  814. Ordinal properties
  815. ---------------------------------------------------------------------}
  816. Function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Int64;
  817. type
  818. TGetInt64ProcIndex=function(index:longint):Int64 of object;
  819. TGetInt64Proc=function():Int64 of object;
  820. TGetIntegerProcIndex=function(index:longint):longint of object;
  821. TGetIntegerProc=function:longint of object;
  822. TGetWordProcIndex=function(index:longint):word of object;
  823. TGetWordProc=function:word of object;
  824. TGetByteProcIndex=function(index:longint):Byte of object;
  825. TGetByteProc=function:Byte of object;
  826. var
  827. TypeInfo: PTypeInfo;
  828. AMethod : TMethod;
  829. DataSize: Integer;
  830. OrdType: TOrdType;
  831. Signed: Boolean;
  832. begin
  833. Result:=0;
  834. TypeInfo := PropInfo^.PropType;
  835. Signed := false;
  836. DataSize := 4;
  837. case TypeInfo^.Kind of
  838. {$ifdef cpu64}
  839. tkInterface,
  840. tkInterfaceRaw,
  841. tkDynArray,
  842. tkClass:
  843. DataSize:=8;
  844. {$endif cpu64}
  845. tkChar, tkBool:
  846. DataSize:=1;
  847. tkWChar:
  848. DataSize:=2;
  849. tkSet,
  850. tkEnumeration,
  851. tkInteger:
  852. begin
  853. OrdType:=GetTypeData(TypeInfo)^.OrdType;
  854. case OrdType of
  855. otSByte,otUByte: DataSize := 1;
  856. otSWord,otUWord: DataSize := 2;
  857. end;
  858. Signed := OrdType in [otSByte,otSWord,otSLong];
  859. end;
  860. tkInt64 :
  861. begin
  862. DataSize:=8;
  863. Signed:=true;
  864. end;
  865. tkQword :
  866. begin
  867. DataSize:=8;
  868. Signed:=false;
  869. end;
  870. end;
  871. case (PropInfo^.PropProcs) and 3 of
  872. ptfield:
  873. if Signed then begin
  874. case DataSize of
  875. 1: Result:=PShortInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  876. 2: Result:=PSmallInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  877. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  878. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  879. end;
  880. end else begin
  881. case DataSize of
  882. 1: Result:=PByte(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  883. 2: Result:=PWord(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  884. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  885. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  886. end;
  887. end;
  888. ptstatic,
  889. ptvirtual :
  890. begin
  891. if (PropInfo^.PropProcs and 3)=ptStatic then
  892. AMethod.Code:=PropInfo^.GetProc
  893. else
  894. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  895. AMethod.Data:=Instance;
  896. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then begin
  897. case DataSize of
  898. 1: Result:=TGetByteProcIndex(AMethod)(PropInfo^.Index);
  899. 2: Result:=TGetWordProcIndex(AMethod)(PropInfo^.Index);
  900. 4: Result:=TGetIntegerProcIndex(AMethod)(PropInfo^.Index);
  901. 8: result:=TGetInt64ProcIndex(AMethod)(PropInfo^.Index)
  902. end;
  903. end else begin
  904. case DataSize of
  905. 1: Result:=TGetByteProc(AMethod)();
  906. 2: Result:=TGetWordProc(AMethod)();
  907. 4: Result:=TGetIntegerProc(AMethod)();
  908. 8: result:=TGetInt64Proc(AMethod)();
  909. end;
  910. end;
  911. if Signed then begin
  912. case DataSize of
  913. 1: Result:=ShortInt(Result);
  914. 2: Result:=SmallInt(Result);
  915. end;
  916. end;
  917. end;
  918. end;
  919. end;
  920. Procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;Value : Int64);
  921. type
  922. TSetInt64ProcIndex=procedure(index:longint;i:Int64) of object;
  923. TSetInt64Proc=procedure(i:Int64) of object;
  924. TSetIntegerProcIndex=procedure(index,i:longint) of object;
  925. TSetIntegerProc=procedure(i:longint) of object;
  926. var
  927. DataSize: Integer;
  928. AMethod : TMethod;
  929. begin
  930. if PropInfo^.PropType^.Kind in [tkInt64,tkQword
  931. { why do we have to handle classes here, see also below? (FK) }
  932. {$ifdef cpu64}
  933. ,tkInterface
  934. ,tkInterfaceRaw
  935. ,tkDynArray
  936. ,tkClass
  937. {$endif cpu64}
  938. ] then
  939. DataSize := 8
  940. else
  941. DataSize := 4;
  942. if not(PropInfo^.PropType^.Kind in [tkInt64,tkQword,tkClass]) then
  943. begin
  944. { cut off unnecessary stuff }
  945. case GetTypeData(PropInfo^.PropType)^.OrdType of
  946. otSWord,otUWord:
  947. begin
  948. Value:=Value and $ffff;
  949. DataSize := 2;
  950. end;
  951. otSByte,otUByte:
  952. begin
  953. Value:=Value and $ff;
  954. DataSize := 1;
  955. end;
  956. end;
  957. end;
  958. case (PropInfo^.PropProcs shr 2) and 3 of
  959. ptfield:
  960. case DataSize of
  961. 1: PByte(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Byte(Value);
  962. 2: PWord(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Word(Value);
  963. 4: PLongint(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Longint(Value);
  964. 8: PInt64(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  965. end;
  966. ptstatic,
  967. ptvirtual :
  968. begin
  969. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  970. AMethod.Code:=PropInfo^.SetProc
  971. else
  972. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  973. AMethod.Data:=Instance;
  974. if datasize=8 then
  975. begin
  976. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  977. TSetInt64ProcIndex(AMethod)(PropInfo^.Index,Value)
  978. else
  979. TSetInt64Proc(AMethod)(Value);
  980. end
  981. else
  982. begin
  983. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  984. TSetIntegerProcIndex(AMethod)(PropInfo^.Index,Value)
  985. else
  986. TSetIntegerProc(AMethod)(Value);
  987. end;
  988. end;
  989. end;
  990. end;
  991. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  992. begin
  993. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  994. end;
  995. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  996. begin
  997. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  998. end;
  999. Function GetEnumProp(Instance: TObject; Const PropInfo: PPropInfo): string;
  1000. begin
  1001. Result:=GetEnumName(PropInfo^.PropType, GetOrdProp(Instance, PropInfo));
  1002. end;
  1003. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  1004. begin
  1005. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  1006. end;
  1007. Procedure SetEnumProp(Instance: TObject; const PropName: string; const Value: string);
  1008. begin
  1009. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  1010. end;
  1011. Procedure SetEnumProp(Instance: TObject; Const PropInfo : PPropInfo; const Value: string);
  1012. Var
  1013. PV : Longint;
  1014. begin
  1015. If PropInfo<>Nil then
  1016. begin
  1017. PV:=GetEnumValue(PropInfo^.PropType, Value);
  1018. if (PV<0) then
  1019. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [Value]);
  1020. SetOrdProp(Instance, PropInfo,PV);
  1021. end;
  1022. end;
  1023. { ---------------------------------------------------------------------
  1024. Int64 wrappers
  1025. ---------------------------------------------------------------------}
  1026. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  1027. begin
  1028. Result:=GetOrdProp(Instance,PropInfo);
  1029. end;
  1030. procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  1031. begin
  1032. SetOrdProp(Instance,PropInfo,Value);
  1033. end;
  1034. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  1035. begin
  1036. Result:=GetInt64Prop(Instance,FindPropInfo(Instance,PropName));
  1037. end;
  1038. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  1039. begin
  1040. SetInt64Prop(Instance,FindPropInfo(Instance,PropName),Value);
  1041. end;
  1042. { ---------------------------------------------------------------------
  1043. Set properties
  1044. ---------------------------------------------------------------------}
  1045. Function GetSetProp(Instance: TObject; const PropName: string): string;
  1046. begin
  1047. Result:=GetSetProp(Instance,PropName,False);
  1048. end;
  1049. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  1050. begin
  1051. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName),Brackets);
  1052. end;
  1053. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  1054. begin
  1055. Result:=SetToString(PropInfo,GetOrdProp(Instance,PropInfo),Brackets);
  1056. end;
  1057. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  1058. begin
  1059. SetSetProp(Instance,FindPropInfo(Instance,PropName),Value);
  1060. end;
  1061. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  1062. begin
  1063. SetOrdProp(Instance,PropInfo,StringToSet(PropInfo,Value));
  1064. end;
  1065. { ---------------------------------------------------------------------
  1066. Object properties
  1067. ---------------------------------------------------------------------}
  1068. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  1069. begin
  1070. Result:=GetObjectProp(Instance,PropName,Nil);
  1071. end;
  1072. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  1073. begin
  1074. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName),MinClass);
  1075. end;
  1076. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo): TObject;
  1077. begin
  1078. Result:=GetObjectProp(Instance,PropInfo,Nil);
  1079. end;
  1080. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo; MinClass: TClass): TObject;
  1081. begin
  1082. {$ifdef cpu64}
  1083. Result:=TObject(GetInt64Prop(Instance,PropInfo));
  1084. {$else cpu64}
  1085. Result:=TObject(PtrInt(GetOrdProp(Instance,PropInfo)));
  1086. {$endif cpu64}
  1087. If (MinClass<>Nil) and (Result<>Nil) Then
  1088. If Not Result.InheritsFrom(MinClass) then
  1089. Result:=Nil;
  1090. end;
  1091. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  1092. begin
  1093. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  1094. end;
  1095. Procedure SetObjectProp(Instance: TObject; PropInfo : PPropInfo; Value: TObject);
  1096. begin
  1097. {$ifdef cpu64}
  1098. SetInt64Prop(Instance,PropInfo,Int64(Value));
  1099. {$else cpu64}
  1100. SetOrdProp(Instance,PropInfo,Integer(Value));
  1101. {$endif cpu64}
  1102. end;
  1103. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  1104. begin
  1105. Result:=GetTypeData(FindPropInfo(Instance,PropName,[tkClass])^.PropType)^.ClassType;
  1106. end;
  1107. Function GetObjectPropClass(AClass: TClass; const PropName: string): TClass;
  1108. begin
  1109. Result:=GetTypeData(FindPropInfo(AClass,PropName,[tkClass])^.PropType)^.ClassType;
  1110. end;
  1111. { ---------------------------------------------------------------------
  1112. Interface wrapprers
  1113. ---------------------------------------------------------------------}
  1114. function GetInterfaceProp(Instance: TObject; const PropName: string): IInterface;
  1115. begin
  1116. Result:=GetInterfaceProp(Instance,FindPropInfo(Instance,PropName));
  1117. end;
  1118. function GetInterfaceProp(Instance: TObject; PropInfo: PPropInfo): IInterface;
  1119. type
  1120. TGetInterfaceProc=function:IInterface of object;
  1121. TGetInterfaceProcIndex=function(index:longint):IInterface of object;
  1122. var
  1123. TypeInfo: PTypeInfo;
  1124. AMethod : TMethod;
  1125. begin
  1126. Result:=nil;
  1127. TypeInfo := PropInfo^.PropType;
  1128. case (PropInfo^.PropProcs) and 3 of
  1129. ptfield:
  1130. Result:=IInterface(PPointer(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^);
  1131. ptstatic,
  1132. ptvirtual :
  1133. begin
  1134. if (PropInfo^.PropProcs and 3)=ptStatic then
  1135. AMethod.Code:=PropInfo^.GetProc
  1136. else
  1137. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1138. AMethod.Data:=Instance;
  1139. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1140. Result:=TGetInterfaceProcIndex(AMethod)(PropInfo^.Index)
  1141. else
  1142. Result:=TGetInterfaceProc(AMethod)();
  1143. end;
  1144. end;
  1145. end;
  1146. procedure SetInterfaceProp(Instance: TObject; const PropName: string; const Value: IInterface);
  1147. begin
  1148. SetInterfaceProp(Instance,FindPropInfo(Instance,PropName),Value);
  1149. end;
  1150. procedure SetInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: IInterface);
  1151. type
  1152. TSetIntfStrProcIndex=procedure(index:longint;const i:IInterface) of object;
  1153. TSetIntfStrProc=procedure(i:IInterface) of object;
  1154. var
  1155. AMethod : TMethod;
  1156. begin
  1157. case Propinfo^.PropType^.Kind of
  1158. tkInterface:
  1159. begin
  1160. case (PropInfo^.PropProcs shr 2) and 3 of
  1161. ptField:
  1162. PInterface(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1163. ptstatic,
  1164. ptvirtual :
  1165. begin
  1166. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1167. AMethod.Code:=PropInfo^.SetProc
  1168. else
  1169. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1170. AMethod.Data:=Instance;
  1171. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1172. TSetIntfStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1173. else
  1174. TSetIntfStrProc(AMethod)(Value);
  1175. end;
  1176. end;
  1177. end;
  1178. tkInterfaceRaw:
  1179. Raise Exception.Create('Cannot set RAW interface from IUnknown interface');
  1180. end;
  1181. end;
  1182. { ---------------------------------------------------------------------
  1183. RAW (Corba) Interface wrapprers
  1184. ---------------------------------------------------------------------}
  1185. function GetRawInterfaceProp(Instance: TObject; const PropName: string): Pointer;
  1186. begin
  1187. Result:=GetRawInterfaceProp(Instance,FindPropInfo(Instance,PropName));
  1188. end;
  1189. function GetRawInterfaceProp(Instance: TObject; PropInfo: PPropInfo): Pointer;
  1190. begin
  1191. {$ifdef cpu64}
  1192. Result:=Pointer(GetInt64Prop(Instance,PropInfo));
  1193. {$else cpu64}
  1194. Result:=Pointer(PtrInt(GetOrdProp(Instance,PropInfo)));
  1195. {$endif cpu64}
  1196. end;
  1197. procedure SetRawInterfaceProp(Instance: TObject; const PropName: string; const Value: Pointer);
  1198. begin
  1199. SetRawInterfaceProp(Instance,FindPropInfo(Instance,PropName),Value);
  1200. end;
  1201. procedure SetRawInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: Pointer);
  1202. type
  1203. TSetPointerProcIndex=procedure(index:longint;const i:Pointer) of object;
  1204. TSetPointerProc=procedure(i:Pointer) of object;
  1205. var
  1206. AMethod : TMethod;
  1207. begin
  1208. case Propinfo^.PropType^.Kind of
  1209. tkInterfaceRaw:
  1210. begin
  1211. case (PropInfo^.PropProcs shr 2) and 3 of
  1212. ptField:
  1213. PPointer(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1214. ptstatic,
  1215. ptvirtual :
  1216. begin
  1217. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1218. AMethod.Code:=PropInfo^.SetProc
  1219. else
  1220. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1221. AMethod.Data:=Instance;
  1222. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1223. TSetPointerProcIndex(AMethod)(PropInfo^.Index,Value)
  1224. else
  1225. TSetPointerProc(AMethod)(Value);
  1226. end;
  1227. end;
  1228. end;
  1229. tkInterface:
  1230. Raise Exception.Create('Cannot set interface from RAW interface');
  1231. end;
  1232. end;
  1233. { ---------------------------------------------------------------------
  1234. String properties
  1235. ---------------------------------------------------------------------}
  1236. Function GetStrProp(Instance: TObject; PropInfo: PPropInfo): AnsiString;
  1237. type
  1238. TGetShortStrProcIndex=function(index:longint):ShortString of object;
  1239. TGetShortStrProc=function():ShortString of object;
  1240. TGetAnsiStrProcIndex=function(index:longint):AnsiString of object;
  1241. TGetAnsiStrProc=function():AnsiString of object;
  1242. var
  1243. AMethod : TMethod;
  1244. begin
  1245. Result:='';
  1246. case Propinfo^.PropType^.Kind of
  1247. tkWString:
  1248. Result:=GetWideStrProp(Instance,PropInfo);
  1249. tkUString :
  1250. Result := GetUnicodeStrProp(Instance,PropInfo);
  1251. tkSString:
  1252. begin
  1253. case (PropInfo^.PropProcs) and 3 of
  1254. ptField:
  1255. Result := PShortString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  1256. ptstatic,
  1257. ptvirtual :
  1258. begin
  1259. if (PropInfo^.PropProcs and 3)=ptStatic then
  1260. AMethod.Code:=PropInfo^.GetProc
  1261. else
  1262. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1263. AMethod.Data:=Instance;
  1264. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1265. Result:=TGetShortStrProcIndex(AMethod)(PropInfo^.Index)
  1266. else
  1267. Result:=TGetShortStrProc(AMethod)();
  1268. end;
  1269. end;
  1270. end;
  1271. tkAString:
  1272. begin
  1273. case (PropInfo^.PropProcs) and 3 of
  1274. ptField:
  1275. Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  1276. ptstatic,
  1277. ptvirtual :
  1278. begin
  1279. if (PropInfo^.PropProcs and 3)=ptStatic then
  1280. AMethod.Code:=PropInfo^.GetProc
  1281. else
  1282. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1283. AMethod.Data:=Instance;
  1284. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1285. Result:=TGetAnsiStrProcIndex(AMethod)(PropInfo^.Index)
  1286. else
  1287. Result:=TGetAnsiStrProc(AMethod)();
  1288. end;
  1289. end;
  1290. end;
  1291. end;
  1292. end;
  1293. Procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo; const Value : AnsiString);
  1294. type
  1295. TSetShortStrProcIndex=procedure(index:longint;const s:ShortString) of object;
  1296. TSetShortStrProc=procedure(const s:ShortString) of object;
  1297. TSetAnsiStrProcIndex=procedure(index:longint;s:AnsiString) of object;
  1298. TSetAnsiStrProc=procedure(s:AnsiString) of object;
  1299. var
  1300. AMethod : TMethod;
  1301. begin
  1302. case Propinfo^.PropType^.Kind of
  1303. tkWString:
  1304. SetWideStrProp(Instance,PropInfo,Value);
  1305. tkUString:
  1306. SetUnicodeStrProp(Instance,PropInfo,Value);
  1307. tkSString:
  1308. begin
  1309. case (PropInfo^.PropProcs shr 2) and 3 of
  1310. ptField:
  1311. PShortString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  1312. ptstatic,
  1313. ptvirtual :
  1314. begin
  1315. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1316. AMethod.Code:=PropInfo^.SetProc
  1317. else
  1318. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1319. AMethod.Data:=Instance;
  1320. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1321. TSetShortStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1322. else
  1323. TSetShortStrProc(AMethod)(Value);
  1324. end;
  1325. end;
  1326. end;
  1327. tkAString:
  1328. begin
  1329. case (PropInfo^.PropProcs shr 2) and 3 of
  1330. ptField:
  1331. PAnsiString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  1332. ptstatic,
  1333. ptvirtual :
  1334. begin
  1335. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1336. AMethod.Code:=PropInfo^.SetProc
  1337. else
  1338. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1339. AMethod.Data:=Instance;
  1340. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1341. TSetAnsiStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1342. else
  1343. TSetAnsiStrProc(AMethod)(Value);
  1344. end;
  1345. end;
  1346. end;
  1347. end;
  1348. end;
  1349. Function GetStrProp(Instance: TObject; const PropName: string): string;
  1350. begin
  1351. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  1352. end;
  1353. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  1354. begin
  1355. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1356. end;
  1357. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  1358. begin
  1359. Result:=GetWideStrProp(Instance, FindPropInfo(Instance, PropName));
  1360. end;
  1361. procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  1362. begin
  1363. SetWideStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1364. end;
  1365. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  1366. type
  1367. TGetWideStrProcIndex=function(index:longint):WideString of object;
  1368. TGetWideStrProc=function():WideString of object;
  1369. var
  1370. AMethod : TMethod;
  1371. begin
  1372. Result:='';
  1373. case Propinfo^.PropType^.Kind of
  1374. tkSString,tkAString:
  1375. Result:=GetStrProp(Instance,PropInfo);
  1376. tkUString :
  1377. Result := GetUnicodeStrProp(Instance,PropInfo);
  1378. tkWString:
  1379. begin
  1380. case (PropInfo^.PropProcs) and 3 of
  1381. ptField:
  1382. Result := PWideString(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1383. ptstatic,
  1384. ptvirtual :
  1385. begin
  1386. if (PropInfo^.PropProcs and 3)=ptStatic then
  1387. AMethod.Code:=PropInfo^.GetProc
  1388. else
  1389. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1390. AMethod.Data:=Instance;
  1391. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1392. Result:=TGetWideStrProcIndex(AMethod)(PropInfo^.Index)
  1393. else
  1394. Result:=TGetWideStrProc(AMethod)();
  1395. end;
  1396. end;
  1397. end;
  1398. end;
  1399. end;
  1400. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  1401. type
  1402. TSetWideStrProcIndex=procedure(index:longint;s:WideString) of object;
  1403. TSetWideStrProc=procedure(s:WideString) of object;
  1404. var
  1405. AMethod : TMethod;
  1406. begin
  1407. case Propinfo^.PropType^.Kind of
  1408. tkSString,tkAString:
  1409. SetStrProp(Instance,PropInfo,Value);
  1410. tkUString:
  1411. SetUnicodeStrProp(Instance,PropInfo,Value);
  1412. tkWString:
  1413. begin
  1414. case (PropInfo^.PropProcs shr 2) and 3 of
  1415. ptField:
  1416. PWideString(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1417. ptstatic,
  1418. ptvirtual :
  1419. begin
  1420. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1421. AMethod.Code:=PropInfo^.SetProc
  1422. else
  1423. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1424. AMethod.Data:=Instance;
  1425. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1426. TSetWideStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1427. else
  1428. TSetWideStrProc(AMethod)(Value);
  1429. end;
  1430. end;
  1431. end;
  1432. end;
  1433. end;
  1434. Function GetUnicodeStrProp(Instance: TObject; const PropName: string): UnicodeString;
  1435. begin
  1436. Result:=GetUnicodeStrProp(Instance, FindPropInfo(Instance, PropName));
  1437. end;
  1438. procedure SetUnicodeStrProp(Instance: TObject; const PropName: string; const Value: UnicodeString);
  1439. begin
  1440. SetUnicodeStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1441. end;
  1442. Function GetUnicodeStrProp(Instance: TObject; PropInfo: PPropInfo): UnicodeString;
  1443. type
  1444. TGetUnicodeStrProcIndex=function(index:longint):UnicodeString of object;
  1445. TGetUnicodeStrProc=function():UnicodeString of object;
  1446. var
  1447. AMethod : TMethod;
  1448. begin
  1449. Result:='';
  1450. case Propinfo^.PropType^.Kind of
  1451. tkSString,tkAString:
  1452. Result:=GetStrProp(Instance,PropInfo);
  1453. tkWString:
  1454. Result:=GetWideStrProp(Instance,PropInfo);
  1455. tkUString:
  1456. begin
  1457. case (PropInfo^.PropProcs) and 3 of
  1458. ptField:
  1459. Result := PUnicodeString(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1460. ptstatic,
  1461. ptvirtual :
  1462. begin
  1463. if (PropInfo^.PropProcs and 3)=ptStatic then
  1464. AMethod.Code:=PropInfo^.GetProc
  1465. else
  1466. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1467. AMethod.Data:=Instance;
  1468. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1469. Result:=TGetUnicodeStrProcIndex(AMethod)(PropInfo^.Index)
  1470. else
  1471. Result:=TGetUnicodeStrProc(AMethod)();
  1472. end;
  1473. end;
  1474. end;
  1475. end;
  1476. end;
  1477. Procedure SetUnicodeStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: UnicodeString);
  1478. type
  1479. TSetUnicodeStrProcIndex=procedure(index:longint;s:UnicodeString) of object;
  1480. TSetUnicodeStrProc=procedure(s:UnicodeString) of object;
  1481. var
  1482. AMethod : TMethod;
  1483. begin
  1484. case Propinfo^.PropType^.Kind of
  1485. tkSString,tkAString:
  1486. SetStrProp(Instance,PropInfo,Value);
  1487. tkWString:
  1488. SetWideStrProp(Instance,PropInfo,Value);
  1489. tkUString:
  1490. begin
  1491. case (PropInfo^.PropProcs shr 2) and 3 of
  1492. ptField:
  1493. PUnicodeString(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1494. ptstatic,
  1495. ptvirtual :
  1496. begin
  1497. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1498. AMethod.Code:=PropInfo^.SetProc
  1499. else
  1500. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1501. AMethod.Data:=Instance;
  1502. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1503. TSetUnicodeStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1504. else
  1505. TSetUnicodeStrProc(AMethod)(Value);
  1506. end;
  1507. end;
  1508. end;
  1509. end;
  1510. end;
  1511. {$ifndef FPUNONE}
  1512. { ---------------------------------------------------------------------
  1513. Float properties
  1514. ---------------------------------------------------------------------}
  1515. function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
  1516. type
  1517. TGetExtendedProc = function:Extended of object;
  1518. TGetExtendedProcIndex = function(Index: integer): Extended of object;
  1519. TGetDoubleProc = function:Double of object;
  1520. TGetDoubleProcIndex = function(Index: integer): Double of object;
  1521. TGetSingleProc = function:Single of object;
  1522. TGetSingleProcIndex = function(Index: integer):Single of object;
  1523. TGetCurrencyProc = function : Currency of object;
  1524. TGetCurrencyProcIndex = function(Index: integer) : Currency of object;
  1525. var
  1526. AMethod : TMethod;
  1527. begin
  1528. Result:=0.0;
  1529. case PropInfo^.PropProcs and 3 of
  1530. ptField:
  1531. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1532. ftSingle:
  1533. Result:=PSingle(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1534. ftDouble:
  1535. Result:=PDouble(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1536. ftExtended:
  1537. Result:=PExtended(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1538. ftcomp:
  1539. Result:=PComp(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1540. ftcurr:
  1541. Result:=PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1542. end;
  1543. ptStatic,
  1544. ptVirtual:
  1545. begin
  1546. if (PropInfo^.PropProcs and 3)=ptStatic then
  1547. AMethod.Code:=PropInfo^.GetProc
  1548. else
  1549. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1550. AMethod.Data:=Instance;
  1551. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1552. ftSingle:
  1553. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1554. Result:=TGetSingleProc(AMethod)()
  1555. else
  1556. Result:=TGetSingleProcIndex(AMethod)(PropInfo^.Index);
  1557. ftDouble:
  1558. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1559. Result:=TGetDoubleProc(AMethod)()
  1560. else
  1561. Result:=TGetDoubleProcIndex(AMethod)(PropInfo^.Index);
  1562. ftExtended:
  1563. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1564. Result:=TGetExtendedProc(AMethod)()
  1565. else
  1566. Result:=TGetExtendedProcIndex(AMethod)(PropInfo^.Index);
  1567. ftCurr:
  1568. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1569. Result:=TGetCurrencyProc(AMethod)()
  1570. else
  1571. Result:=TGetCurrencyProcIndex(AMethod)(PropInfo^.Index);
  1572. end;
  1573. end;
  1574. end;
  1575. end;
  1576. Procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo; Value : Extended);
  1577. type
  1578. TSetExtendedProc = procedure(const AValue: Extended) of object;
  1579. TSetExtendedProcIndex = procedure(Index: integer; AValue: Extended) of object;
  1580. TSetDoubleProc = procedure(const AValue: Double) of object;
  1581. TSetDoubleProcIndex = procedure(Index: integer; AValue: Double) of object;
  1582. TSetSingleProc = procedure(const AValue: Single) of object;
  1583. TSetSingleProcIndex = procedure(Index: integer; AValue: Single) of object;
  1584. TSetCurrencyProc = procedure(const AValue: Currency) of object;
  1585. TSetCurrencyProcIndex = procedure(Index: integer; AValue: Currency) of object;
  1586. Var
  1587. AMethod : TMethod;
  1588. begin
  1589. case (PropInfo^.PropProcs shr 2) and 3 of
  1590. ptfield:
  1591. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1592. ftSingle:
  1593. PSingle(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1594. ftDouble:
  1595. PDouble(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1596. ftExtended:
  1597. PExtended(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1598. {$ifdef FPC_COMP_IS_INT64}
  1599. ftComp:
  1600. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=trunc(Value);
  1601. {$else FPC_COMP_IS_INT64}
  1602. ftComp:
  1603. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Comp(Value);
  1604. {$endif FPC_COMP_IS_INT64}
  1605. ftCurr:
  1606. PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1607. end;
  1608. ptStatic,
  1609. ptVirtual:
  1610. begin
  1611. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1612. AMethod.Code:=PropInfo^.SetProc
  1613. else
  1614. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1615. AMethod.Data:=Instance;
  1616. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1617. ftSingle:
  1618. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1619. TSetSingleProc(AMethod)(Value)
  1620. else
  1621. TSetSingleProcIndex(AMethod)(PropInfo^.Index,Value);
  1622. ftDouble:
  1623. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1624. TSetDoubleProc(AMethod)(Value)
  1625. else
  1626. TSetDoubleProcIndex(AMethod)(PropInfo^.Index,Value);
  1627. ftExtended:
  1628. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1629. TSetExtendedProc(AMethod)(Value)
  1630. else
  1631. TSetExtendedProcIndex(AMethod)(PropInfo^.Index,Value);
  1632. ftCurr:
  1633. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1634. TSetCurrencyProc(AMethod)(Value)
  1635. else
  1636. TSetCurrencyProcIndex(AMethod)(PropInfo^.Index,Value);
  1637. end;
  1638. end;
  1639. end;
  1640. end;
  1641. function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  1642. begin
  1643. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName))
  1644. end;
  1645. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  1646. begin
  1647. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  1648. end;
  1649. {$endif}
  1650. { ---------------------------------------------------------------------
  1651. Method properties
  1652. ---------------------------------------------------------------------}
  1653. Function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
  1654. type
  1655. TGetMethodProcIndex=function(Index: Longint): TMethod of object;
  1656. TGetMethodProc=function(): TMethod of object;
  1657. var
  1658. value: PMethod;
  1659. AMethod : TMethod;
  1660. begin
  1661. Result.Code:=nil;
  1662. Result.Data:=nil;
  1663. case (PropInfo^.PropProcs) and 3 of
  1664. ptfield:
  1665. begin
  1666. Value:=PMethod(Pointer(Instance)+PtrUInt(PropInfo^.GetProc));
  1667. if Value<>nil then
  1668. Result:=Value^;
  1669. end;
  1670. ptstatic,
  1671. ptvirtual :
  1672. begin
  1673. if (PropInfo^.PropProcs and 3)=ptStatic then
  1674. AMethod.Code:=PropInfo^.GetProc
  1675. else
  1676. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1677. AMethod.Data:=Instance;
  1678. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1679. Result:=TGetMethodProcIndex(AMethod)(PropInfo^.Index)
  1680. else
  1681. Result:=TGetMethodProc(AMethod)();
  1682. end;
  1683. end;
  1684. end;
  1685. Procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo; const Value : TMethod);
  1686. type
  1687. TSetMethodProcIndex=procedure(index:longint;p:TMethod) of object;
  1688. TSetMethodProc=procedure(p:TMethod) of object;
  1689. var
  1690. AMethod : TMethod;
  1691. begin
  1692. case (PropInfo^.PropProcs shr 2) and 3 of
  1693. ptfield:
  1694. PMethod(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^ := Value;
  1695. ptstatic,
  1696. ptvirtual :
  1697. begin
  1698. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1699. AMethod.Code:=PropInfo^.SetProc
  1700. else
  1701. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1702. AMethod.Data:=Instance;
  1703. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1704. TSetMethodProcIndex(AMethod)(PropInfo^.Index,Value)
  1705. else
  1706. TSetMethodProc(AMethod)(Value);
  1707. end;
  1708. end;
  1709. end;
  1710. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  1711. begin
  1712. Result:=GetMethodProp(Instance,FindPropInfo(Instance,PropName));
  1713. end;
  1714. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  1715. begin
  1716. SetMethodProp(Instance,FindPropInfo(Instance,PropName),Value);
  1717. end;
  1718. { ---------------------------------------------------------------------
  1719. Variant properties
  1720. ---------------------------------------------------------------------}
  1721. Procedure CheckVariantEvent(P : Pointer);
  1722. begin
  1723. If (P=Nil) then
  1724. Raise Exception.Create(SErrNoVariantSupport);
  1725. end;
  1726. Function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
  1727. begin
  1728. CheckVariantEvent(Pointer(OnGetVariantProp));
  1729. Result:=OnGetVariantProp(Instance,PropInfo);
  1730. end;
  1731. Procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo; const Value: Variant);
  1732. begin
  1733. CheckVariantEvent(Pointer(OnSetVariantProp));
  1734. OnSetVariantProp(Instance,PropInfo,Value);
  1735. end;
  1736. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  1737. begin
  1738. Result:=GetVariantProp(Instance,FindPropInfo(Instance,PropName));
  1739. end;
  1740. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  1741. begin
  1742. SetVariantprop(instance,FindpropInfo(Instance,PropName),Value);
  1743. end;
  1744. { ---------------------------------------------------------------------
  1745. All properties through variant.
  1746. ---------------------------------------------------------------------}
  1747. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  1748. begin
  1749. Result:=GetPropValue(Instance,PropName,True);
  1750. end;
  1751. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  1752. begin
  1753. CheckVariantEvent(Pointer(OnGetPropValue));
  1754. Result:=OnGetPropValue(Instance,PropName,PreferStrings)
  1755. end;
  1756. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  1757. begin
  1758. CheckVariantEvent(Pointer(OnSetPropValue));
  1759. OnSetPropValue(Instance,PropName,Value);
  1760. end;
  1761. { ---------------------------------------------------------------------
  1762. Easy access methods that appeared in Delphi 5
  1763. ---------------------------------------------------------------------}
  1764. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  1765. begin
  1766. Result:=GetPropInfo(Instance,PropName)<>Nil;
  1767. end;
  1768. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  1769. begin
  1770. Result:=GetPropInfo(AClass,PropName)<>Nil;
  1771. end;
  1772. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  1773. begin
  1774. Result:=PropType(Instance,PropName)=TypeKind
  1775. end;
  1776. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  1777. begin
  1778. Result:=PropType(AClass,PropName)=TypeKind
  1779. end;
  1780. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  1781. begin
  1782. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind;
  1783. end;
  1784. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  1785. begin
  1786. Result:=FindPropInfo(AClass,PropName)^.PropType^.Kind;
  1787. end;
  1788. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  1789. begin
  1790. Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
  1791. end;
  1792. end.