typinfo.pp 70 KB

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