typinfo.pp 53 KB

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