typinfo.pp 115 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872
  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. {$IFNDEF FPC_DOTTEDUNITS}
  14. unit TypInfo;
  15. {$ENDIF FPC_DOTTEDUNITS}
  16. interface
  17. {$MODE objfpc}
  18. {$MODESWITCH AdvancedRecords}
  19. {$inline on}
  20. {$macro on}
  21. {$h+}
  22. {$IFDEF FPC_DOTTEDUNITS}
  23. uses System.SysUtils;
  24. {$ELSE FPC_DOTTEDUNITS}
  25. uses SysUtils;
  26. {$ENDIF FPC_DOTTEDUNITS}
  27. // temporary types:
  28. type
  29. {$MINENUMSIZE 1 this saves a lot of memory }
  30. {$ifdef FPC_RTTI_PACKSET1}
  31. { for Delphi compatibility }
  32. {$packset 1}
  33. {$endif}
  34. { this alias and the following constant aliases are for backwards
  35. compatibility before TTypeKind was moved to System unit }
  36. TTypeKind = System.TTypeKind;
  37. const
  38. tkUnknown = System.tkUnknown;
  39. tkInteger = System.tkInteger;
  40. tkChar = System.tkChar;
  41. tkEnumeration = System.tkEnumeration;
  42. tkFloat = System.tkFloat;
  43. tkSet = System.tkSet;
  44. tkMethod = System.tkMethod;
  45. tkSString = System.tkSString;
  46. tkLString = System.tkLString;
  47. tkAString = System.tkAString;
  48. tkWString = System.tkWString;
  49. tkVariant = System.tkVariant;
  50. tkArray = System.tkArray;
  51. tkRecord = System.tkRecord;
  52. tkInterface = System.tkInterface;
  53. tkClass = System.tkClass;
  54. tkObject = System.tkObject;
  55. tkWChar = System.tkWChar;
  56. tkBool = System.tkBool;
  57. tkInt64 = System.tkInt64;
  58. tkQWord = System.tkQWord;
  59. tkDynArray = System.tkDynArray;
  60. tkInterfaceRaw = System.tkInterfaceRaw;
  61. tkProcVar = System.tkProcVar;
  62. tkUString = System.tkUString;
  63. tkUChar = System.tkUChar;
  64. tkHelper = System.tkHelper;
  65. tkFile = System.tkFile;
  66. tkClassRef = System.tkClassRef;
  67. tkPointer = System.tkPointer;
  68. type
  69. TOrdType = (otSByte,otUByte,otSWord,otUWord,otSLong,otULong,otSQWord,otUQWord);
  70. {$ifndef FPUNONE}
  71. TFloatType = (ftSingle,ftDouble,ftExtended,ftComp,ftCurr);
  72. {$endif}
  73. TMethodKind = (mkProcedure,mkFunction,mkConstructor,mkDestructor,
  74. mkClassProcedure,mkClassFunction,mkClassConstructor,
  75. mkClassDestructor,mkOperatorOverload);
  76. TParamFlag = (pfVar,pfConst,pfArray,pfAddress,pfReference,pfOut,pfConstRef
  77. {$ifndef VER3_0},pfHidden,pfHigh,pfSelf,pfVmt,pfResult{$endif VER3_0}
  78. );
  79. TParamFlags = set of TParamFlag;
  80. TIntfFlag = (ifHasGuid,ifDispInterface,ifDispatch,ifHasStrGUID);
  81. TIntfFlags = set of TIntfFlag;
  82. TIntfFlagsBase = set of TIntfFlag;
  83. // don't rely on integer values of TCallConv since it includes all conventions
  84. // which both Delphi and FPC support. In the future Delphi can support more and
  85. // FPC's own conventions will be shifted/reordered accordingly
  86. TCallConv = (ccReg, ccCdecl, ccPascal, ccStdCall, ccSafeCall,
  87. ccCppdecl, ccFar16, ccOldFPCCall, ccInternProc,
  88. ccSysCall, ccSoftFloat, ccMWPascal);
  89. {$push}
  90. {$scopedenums on}
  91. TSubRegister = (
  92. None,
  93. Lo,
  94. Hi,
  95. Word,
  96. DWord,
  97. QWord,
  98. FloatSingle,
  99. FloatDouble,
  100. FloatQuad,
  101. MultiMediaSingle,
  102. MultiMediaDouble,
  103. MultiMediaWhole,
  104. MultiMediaX,
  105. MultiMediaY
  106. );
  107. TRegisterType = (
  108. Invalid,
  109. Int,
  110. FP,
  111. MMX,
  112. MultiMedia,
  113. Special,
  114. Address
  115. );
  116. {$pop}
  117. {$IF FPC_FULLVERSION>=30301}
  118. {$DEFINE HAVE_INVOKEHELPER}
  119. {$DEFINE HAVE_HIDDENTHUNKCLASS}
  120. {$ENDIF}
  121. {$MINENUMSIZE DEFAULT}
  122. const
  123. ptField = 0;
  124. ptStatic = 1;
  125. ptVirtual = 2;
  126. ptConst = 3;
  127. type
  128. TTypeKinds = set of TTypeKind;
  129. ShortStringBase = string[255];
  130. {$IFDEF HAVE_INVOKEHELPER}
  131. TInvokeHelper = procedure(Instance : Pointer; Args : PPointer);
  132. {$ENDIF}
  133. PParameterLocation = ^TParameterLocation;
  134. TParameterLocation =
  135. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  136. packed
  137. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  138. record
  139. private
  140. LocType: Byte;
  141. function GetRegType: TRegisterType; inline;
  142. function GetReference: Boolean; inline;
  143. function GetShiftVal: Int8; inline;
  144. public
  145. RegSub: TSubRegister;
  146. RegNumber: Word;
  147. { Stack offset if Reference, ShiftVal if not }
  148. Offset: SizeInt;
  149. { if Reference then the register is the index register otherwise the
  150. register in wihch (part of) the parameter resides }
  151. property Reference: Boolean read GetReference;
  152. property RegType: TRegisterType read GetRegType;
  153. { if Reference, otherwise 0 }
  154. property ShiftVal: Int8 read GetShiftVal;
  155. end;
  156. PParameterLocations = ^TParameterLocations;
  157. TParameterLocations =
  158. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  159. packed
  160. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  161. record
  162. private
  163. function GetLocation(aIndex: Byte): PParameterLocation; inline;
  164. function GetTail: Pointer; inline;
  165. public
  166. Count: Byte;
  167. property Location[Index: Byte]: PParameterLocation read GetLocation;
  168. property Tail: Pointer read GetTail;
  169. end;
  170. { The following three types are essentially copies from the TObject.FieldAddress
  171. function. If something is changed there, change it here as well }
  172. PVmtFieldClassTab = ^TVmtFieldClassTab;
  173. TVmtFieldClassTab =
  174. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  175. packed
  176. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  177. record
  178. Count: Word;
  179. ClassRef: array[0..0] of PClass;
  180. end;
  181. PVmtFieldEntry = ^TVmtFieldEntry;
  182. TVmtFieldEntry =
  183. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  184. packed
  185. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  186. record
  187. private
  188. function GetNext: PVmtFieldEntry; inline;
  189. function GetTail: Pointer; inline;
  190. public
  191. FieldOffset: SizeUInt;
  192. TypeIndex: Word;
  193. Name: ShortString;
  194. property Tail: Pointer read GetTail;
  195. property Next: PVmtFieldEntry read GetNext;
  196. end;
  197. PVmtFieldTable = ^TVmtFieldTable;
  198. TVmtFieldTable =
  199. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  200. packed
  201. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  202. record
  203. private
  204. function GetField(aIndex: Word): PVmtFieldEntry;
  205. public
  206. Count: Word;
  207. ClassTab: PVmtFieldClassTab;
  208. { should be array[Word] of TFieldInfo; but
  209. Elements have variant size! force at least proper alignment }
  210. Fields: array[0..0] of TVmtFieldEntry;
  211. property Field[aIndex: Word]: PVmtFieldEntry read GetField;
  212. end;
  213. {$PACKRECORDS 1}
  214. TTypeInfo = record
  215. Kind : TTypeKind;
  216. Name : ShortString;
  217. // here the type data follows as TTypeData record
  218. end;
  219. PTypeInfo = ^TTypeInfo;
  220. PPTypeInfo = ^PTypeInfo;
  221. PPropData = ^TPropData;
  222. { Note: these are only for backwards compatibility. New type references should
  223. only use PPTypeInfo directly! }
  224. {$ifdef ver3_0}
  225. {$define TypeInfoPtr := PTypeInfo}
  226. {$else}
  227. {$define TypeInfoPtr := PPTypeInfo}
  228. {$endif}
  229. {$PACKRECORDS C}
  230. {$if not defined(VER3_0) and not defined(VER3_2)}
  231. {$define PROVIDE_ATTR_TABLE}
  232. {$endif}
  233. TAttributeProc = function : TCustomAttribute;
  234. TAttributeEntry =
  235. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  236. packed
  237. {$endif}
  238. record
  239. AttrType: PPTypeInfo;
  240. AttrCtor: CodePointer;
  241. AttrProc: TAttributeProc;
  242. ArgLen: Word;
  243. ArgData: Pointer;
  244. end;
  245. {$ifdef CPU16}
  246. TAttributeEntryList = array[0..(High(SizeUInt) div SizeOf(TAttributeEntry))-1] of TAttributeEntry;
  247. {$else CPU16}
  248. TAttributeEntryList = array[0..$ffff] of TAttributeEntry;
  249. {$endif CPU16}
  250. TAttributeTable =
  251. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  252. packed
  253. {$endif}
  254. record
  255. AttributeCount: word;
  256. AttributesList: TAttributeEntryList;
  257. end;
  258. PAttributeTable = ^TAttributeTable;
  259. // members of TTypeData
  260. TArrayTypeData =
  261. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  262. packed
  263. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  264. record
  265. private
  266. function GetElType: PTypeInfo; inline;
  267. function GetDims(aIndex: Byte): PTypeInfo; inline;
  268. public
  269. property ElType: PTypeInfo read GetElType;
  270. property Dims[Index: Byte]: PTypeInfo read GetDims;
  271. public
  272. Size: SizeInt;
  273. ElCount: SizeInt;
  274. ElTypeRef: TypeInfoPtr;
  275. DimCount: Byte;
  276. DimsRef: array[0..255] of TypeInfoPtr;
  277. end;
  278. PManagedField = ^TManagedField;
  279. TManagedField =
  280. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  281. packed
  282. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  283. record
  284. private
  285. function GetTypeRef: PTypeInfo; inline;
  286. public
  287. property TypeRef: PTypeInfo read GetTypeRef;
  288. public
  289. TypeRefRef: TypeInfoPtr;
  290. FldOffset: SizeInt;
  291. end;
  292. PInitManagedField = ^TInitManagedField;
  293. TInitManagedField = TManagedField;
  294. PProcedureParam = ^TProcedureParam;
  295. TProcedureParam =
  296. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  297. packed
  298. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  299. record
  300. private
  301. function GetParamType: PTypeInfo; inline;
  302. function GetFlags: Byte; inline;
  303. public
  304. property ParamType: PTypeInfo read GetParamType;
  305. property Flags: Byte read GetFlags;
  306. public
  307. ParamFlags: TParamFlags;
  308. ParamTypeRef: TypeInfoPtr;
  309. Name: ShortString;
  310. end;
  311. PProcedureSignature = ^TProcedureSignature;
  312. TProcedureSignature =
  313. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  314. packed
  315. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  316. record
  317. private
  318. function GetResultType: PTypeInfo; inline;
  319. public
  320. property ResultType: PTypeInfo read GetResultType;
  321. public
  322. Flags: Byte;
  323. CC: TCallConv;
  324. ResultTypeRef: TypeInfoPtr;
  325. ParamCount: Byte;
  326. {Params: array[0..ParamCount - 1] of TProcedureParam;}
  327. function GetParam(ParamIndex: Integer): PProcedureParam;
  328. end;
  329. PVmtMethodParam = ^TVmtMethodParam;
  330. TVmtMethodParam =
  331. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  332. packed
  333. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  334. record
  335. private
  336. function GetTail: Pointer; inline;
  337. function GetNext: PVmtMethodParam; inline;
  338. function GetName: ShortString; inline;
  339. public
  340. ParamType: PPTypeInfo;
  341. Flags: TParamFlags;
  342. NamePtr: PShortString;
  343. ParaLocs: PParameterLocations;
  344. property Name: ShortString read GetName;
  345. property Tail: Pointer read GetTail;
  346. property Next: PVmtMethodParam read GetNext;
  347. end;
  348. PIntfMethodEntry = ^TIntfMethodEntry;
  349. TIntfMethodEntry =
  350. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  351. packed
  352. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  353. record
  354. private
  355. function GetParam(Index: Word): PVmtMethodParam;
  356. function GetResultLocs: PParameterLocations; inline;
  357. function GetTail: Pointer; inline;
  358. function GetNext: PIntfMethodEntry; inline;
  359. function GetName: ShortString; inline;
  360. public
  361. ResultType: PPTypeInfo;
  362. CC: TCallConv;
  363. Kind: TMethodKind;
  364. ParamCount: Word;
  365. StackSize: SizeInt;
  366. {$IFDEF HAVE_INVOKEHELPER}
  367. InvokeHelper : TInvokeHelper;
  368. {$ENDIF}
  369. NamePtr: PShortString;
  370. { Params: array[0..ParamCount - 1] of TVmtMethodParam }
  371. { ResultLocs: PParameterLocations (if ResultType != Nil) }
  372. property Name: ShortString read GetName;
  373. property Param[Index: Word]: PVmtMethodParam read GetParam;
  374. property ResultLocs: PParameterLocations read GetResultLocs;
  375. property Tail: Pointer read GetTail;
  376. property Next: PIntfMethodEntry read GetNext;
  377. end;
  378. PIntfMethodTable = ^TIntfMethodTable;
  379. TIntfMethodTable =
  380. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  381. packed
  382. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  383. record
  384. private
  385. function GetMethod(Index: Word): PIntfMethodEntry;
  386. public
  387. Count: Word;
  388. { $FFFF if there is no further info, or the value of Count }
  389. RTTICount: Word;
  390. { Entry: array[0..Count - 1] of TIntfMethodEntry }
  391. property Method[Index: Word]: PIntfMethodEntry read GetMethod;
  392. end;
  393. PVmtMethodEntry = ^TVmtMethodEntry;
  394. TVmtMethodEntry =
  395. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  396. packed
  397. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  398. record
  399. Name: PShortString;
  400. CodeAddress: CodePointer;
  401. end;
  402. PVmtMethodTable = ^TVmtMethodTable;
  403. TVmtMethodTable =
  404. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  405. packed
  406. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  407. record
  408. private
  409. function GetEntry(Index: LongWord): PVmtMethodEntry; inline;
  410. public
  411. Count: LongWord;
  412. property Entry[Index: LongWord]: PVmtMethodEntry read GetEntry;
  413. private
  414. Entries: array[0..0] of TVmtMethodEntry;
  415. end;
  416. TRecOpOffsetEntry =
  417. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  418. packed
  419. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  420. record
  421. ManagementOperator: CodePointer;
  422. FieldOffset: SizeUInt;
  423. end;
  424. TRecOpOffsetTable =
  425. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  426. packed
  427. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  428. record
  429. Count: LongWord;
  430. Entries: array[0..0] of TRecOpOffsetEntry;
  431. end;
  432. PRecOpOffsetTable = ^TRecOpOffsetTable;
  433. PRecInitData = ^TRecInitData;
  434. TRecInitData =
  435. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  436. packed
  437. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  438. record
  439. {$ifdef PROVIDE_ATTR_TABLE}
  440. AttributeTable : PAttributeTable;
  441. {$endif}
  442. case TTypeKind of
  443. tkRecord: (
  444. Terminator: Pointer;
  445. Size: Longint;
  446. {$ifndef VER3_0}
  447. InitOffsetOp: PRecOpOffsetTable;
  448. ManagementOp: Pointer;
  449. {$endif}
  450. ManagedFieldCount: Longint;
  451. { ManagedFields: array[0..ManagedFieldCount - 1] of TInitManagedField ; }
  452. );
  453. { include for proper alignment }
  454. tkInt64: (
  455. dummy : Int64
  456. );
  457. end;
  458. PInterfaceData = ^TInterfaceData;
  459. TInterfaceData =
  460. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  461. packed
  462. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  463. record
  464. private
  465. function GetUnitName: ShortString; inline;
  466. function GetPropertyTable: PPropData; inline;
  467. function GetMethodTable: PIntfMethodTable; inline;
  468. public
  469. property UnitName: ShortString read GetUnitName;
  470. property PropertyTable: PPropData read GetPropertyTable;
  471. property MethodTable: PIntfMethodTable read GetMethodTable;
  472. public
  473. {$ifdef PROVIDE_ATTR_TABLE}
  474. AttributeTable : PAttributeTable;
  475. {$endif}
  476. case TTypeKind of
  477. tkInterface: (
  478. Parent: PPTypeInfo;
  479. Flags: TIntfFlagsBase;
  480. GUID: TGUID;
  481. {$IFDEF HAVE_HIDDENTHUNKCLASS}
  482. ThunkClass : PPTypeInfo;
  483. {$ENDIF}
  484. UnitNameField: ShortString;
  485. { PropertyTable: TPropData }
  486. { MethodTable: TIntfMethodTable }
  487. );
  488. { include for proper alignment }
  489. tkInt64: (
  490. dummy : Int64
  491. );
  492. {$ifndef FPUNONE}
  493. tkFloat:
  494. (FloatType : TFloatType
  495. );
  496. {$endif}
  497. end;
  498. PInterfaceRawData = ^TInterfaceRawData;
  499. TInterfaceRawData =
  500. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  501. packed
  502. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  503. record
  504. private
  505. function GetUnitName: ShortString; inline;
  506. function GetIIDStr: ShortString; inline;
  507. function GetPropertyTable: PPropData; inline;
  508. function GetMethodTable: PIntfMethodTable; inline;
  509. public
  510. property UnitName: ShortString read GetUnitName;
  511. property IIDStr: ShortString read GetIIDStr;
  512. property PropertyTable: PPropData read GetPropertyTable;
  513. property MethodTable: PIntfMethodTable read GetMethodTable;
  514. public
  515. {$ifdef PROVIDE_ATTR_TABLE}
  516. AttributeTable : PAttributeTable;
  517. {$endif}
  518. case TTypeKind of
  519. tkInterface: (
  520. Parent: PPTypeInfo;
  521. Flags : TIntfFlagsBase;
  522. IID: TGUID;
  523. {$IFDEF HAVE_HIDDENTHUNKCLASS}
  524. ThunkClass : PPTypeInfo;
  525. {$ENDIF}
  526. UnitNameField: ShortString;
  527. { IIDStr: ShortString; }
  528. { PropertyTable: TPropData }
  529. );
  530. { include for proper alignment }
  531. tkInt64: (
  532. dummy : Int64
  533. );
  534. {$ifndef FPUNONE}
  535. tkFloat:
  536. (FloatType : TFloatType
  537. );
  538. {$endif}
  539. end;
  540. PClassData = ^TClassData;
  541. TClassData =
  542. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  543. packed
  544. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  545. record
  546. private
  547. function GetUnitName: ShortString; inline;
  548. function GetPropertyTable: PPropData; inline;
  549. public
  550. property UnitName: ShortString read GetUnitName;
  551. property PropertyTable: PPropData read GetPropertyTable;
  552. public
  553. {$ifdef PROVIDE_ATTR_TABLE}
  554. AttributeTable : PAttributeTable;
  555. {$endif}
  556. case TTypeKind of
  557. tkClass: (
  558. ClassType : TClass;
  559. Parent : PPTypeInfo;
  560. PropCount : SmallInt;
  561. UnitNameField : ShortString;
  562. { PropertyTable: TPropData }
  563. );
  564. { include for proper alignment }
  565. tkInt64: (
  566. dummy: Int64;
  567. );
  568. {$ifndef FPUNONE}
  569. tkFloat: (
  570. FloatType : TFloatType
  571. );
  572. {$endif}
  573. end;
  574. PTypeData = ^TTypeData;
  575. TTypeData =
  576. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  577. packed
  578. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  579. record
  580. private
  581. function GetBaseType: PTypeInfo; inline;
  582. function GetCompType: PTypeInfo; inline;
  583. function GetParentInfo: PTypeInfo; inline;
  584. {$ifndef VER3_0}
  585. function GetRecInitData: PRecInitData; inline;
  586. {$endif}
  587. function GetHelperParent: PTypeInfo; inline;
  588. function GetExtendedInfo: PTypeInfo; inline;
  589. function GetIntfParent: PTypeInfo; inline;
  590. function GetRawIntfParent: PTypeInfo; inline;
  591. function GetIIDStr: ShortString; inline;
  592. function GetElType: PTypeInfo; inline;
  593. function GetElType2: PTypeInfo; inline;
  594. function GetInstanceType: PTypeInfo; inline;
  595. function GetRefType: PTypeInfo; inline;
  596. public
  597. { tkEnumeration }
  598. property BaseType: PTypeInfo read GetBaseType;
  599. { tkSet }
  600. property CompType: PTypeInfo read GetCompType;
  601. { tkClass }
  602. property ParentInfo: PTypeInfo read GetParentInfo;
  603. { tkRecord }
  604. {$ifndef VER3_0}
  605. property RecInitData: PRecInitData read GetRecInitData;
  606. {$endif}
  607. { tkHelper }
  608. property HelperParent: PTypeInfo read GetHelperParent;
  609. property ExtendedInfo: PTypeInfo read GetExtendedInfo;
  610. { tkInterface }
  611. property IntfParent: PTypeInfo read GetIntfParent;
  612. { tkInterfaceRaw }
  613. property RawIntfParent: PTypeInfo read GetRawIntfParent;
  614. property IIDStr: ShortString read GetIIDStr;
  615. { tkDynArray }
  616. property ElType2: PTypeInfo read GetElType2;
  617. property ElType: PTypeInfo read GetElType;
  618. { tkClassRef }
  619. property InstanceType: PTypeInfo read GetInstanceType;
  620. { tkPointer }
  621. property RefType: PTypeInfo read GetRefType;
  622. public
  623. {$ifdef PROVIDE_ATTR_TABLE}
  624. AttributeTable : PAttributeTable;
  625. {$endif}
  626. case TTypeKind of
  627. tkUnKnown,tkLString,tkWString,tkVariant,tkUString:
  628. ();
  629. tkAString:
  630. (CodePage: Word);
  631. {$ifndef VER3_0}
  632. tkInt64,tkQWord,
  633. {$endif VER3_0}
  634. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar,tkSet:
  635. (OrdType : TOrdType;
  636. case TTypeKind of
  637. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar : (
  638. MinValue,MaxValue : Longint;
  639. case TTypeKind of
  640. tkEnumeration:
  641. (
  642. BaseTypeRef : TypeInfoPtr;
  643. NameList : ShortString;
  644. {EnumUnitName: ShortString;})
  645. );
  646. {$ifndef VER3_0}
  647. {tkBool with OrdType=otSQWord }
  648. tkInt64:
  649. (MinInt64Value, MaxInt64Value: Int64);
  650. {tkBool with OrdType=otUQWord }
  651. tkQWord:
  652. (MinQWordValue, MaxQWordValue: QWord);
  653. {$endif VER3_0}
  654. tkSet:
  655. (
  656. {$ifndef VER3_0}
  657. SetSize : SizeInt;
  658. {$endif VER3_0}
  659. CompTypeRef : TypeInfoPtr
  660. )
  661. );
  662. {$ifndef FPUNONE}
  663. tkFloat:
  664. (FloatType : TFloatType);
  665. {$endif}
  666. tkSString:
  667. (MaxLength : Byte);
  668. tkClass:
  669. (ClassType : TClass;
  670. ParentInfoRef : TypeInfoPtr;
  671. PropCount : SmallInt;
  672. UnitName : ShortString;
  673. // here the properties follow as array of TPropInfo
  674. );
  675. tkRecord:
  676. (
  677. {$ifndef VER3_0}
  678. RecInitInfo: Pointer; { points to TTypeInfo followed by init table }
  679. {$endif VER3_0}
  680. RecSize: Longint;
  681. case Boolean of
  682. False: (ManagedFldCount: Longint deprecated 'Use RecInitData^.ManagedFieldCount or TotalFieldCount depending on your use case');
  683. True: (TotalFieldCount: Longint);
  684. {ManagedFields: array[1..TotalFieldCount] of TManagedField}
  685. );
  686. tkHelper:
  687. (HelperParentRef : TypeInfoPtr;
  688. ExtendedInfoRef : TypeInfoPtr;
  689. HelperProps : SmallInt;
  690. HelperUnit : ShortString
  691. // here the properties follow as array of TPropInfo
  692. );
  693. tkMethod:
  694. (MethodKind : TMethodKind;
  695. ParamCount : Byte;
  696. case Boolean of
  697. False: (ParamList : array[0..1023] of AnsiChar);
  698. { dummy for proper alignment }
  699. True: (ParamListDummy : Word);
  700. {in reality ParamList is a array[1..ParamCount] of:
  701. record
  702. Flags : TParamFlags;
  703. ParamName : ShortString;
  704. TypeName : ShortString;
  705. end;
  706. followed by
  707. ResultType : ShortString // for mkFunction, mkClassFunction only
  708. ResultTypeRef : PPTypeInfo; // for mkFunction, mkClassFunction only
  709. CC : TCallConv;
  710. ParamTypeRefs : array[1..ParamCount] of PPTypeInfo;}
  711. );
  712. tkProcVar:
  713. (ProcSig: TProcedureSignature);
  714. {$ifdef VER3_0}
  715. tkInt64:
  716. (MinInt64Value, MaxInt64Value: Int64);
  717. tkQWord:
  718. (MinQWordValue, MaxQWordValue: QWord);
  719. {$endif VER3_0}
  720. tkInterface:
  721. (
  722. IntfParentRef: TypeInfoPtr;
  723. IntfFlags : TIntfFlagsBase;
  724. GUID: TGUID;
  725. ThunkClass : PPTypeInfo;
  726. IntfUnit: ShortString;
  727. { PropertyTable: TPropData }
  728. { MethodTable: TIntfMethodTable }
  729. );
  730. tkInterfaceRaw:
  731. (
  732. RawIntfParentRef: TypeInfoPtr;
  733. RawIntfFlags : TIntfFlagsBase;
  734. IID: TGUID;
  735. RawThunkClass : PPTypeInfo;
  736. RawIntfUnit: ShortString;
  737. { IIDStr: ShortString; }
  738. { PropertyTable: TPropData }
  739. );
  740. tkArray:
  741. (ArrayData: TArrayTypeData);
  742. tkDynArray:
  743. (
  744. elSize : PtrUInt;
  745. elType2Ref : TypeInfoPtr;
  746. varType : Longint;
  747. elTypeRef : TypeInfoPtr;
  748. DynUnitName: ShortStringBase
  749. );
  750. tkClassRef:
  751. (InstanceTypeRef: TypeInfoPtr);
  752. tkPointer:
  753. (RefTypeRef: TypeInfoPtr);
  754. end;
  755. PPropInfo = ^TPropInfo;
  756. TPropData =
  757. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  758. packed
  759. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  760. record
  761. private
  762. function GetProp(Index: Word): PPropInfo;
  763. function GetTail: Pointer; inline;
  764. public
  765. PropCount : Word;
  766. PropList : record _alignmentdummy : ptrint; end;
  767. property Prop[Index: Word]: PPropInfo read GetProp;
  768. property Tail: Pointer read GetTail;
  769. end;
  770. {$PACKRECORDS 1}
  771. TPropInfo = packed record
  772. private
  773. function GetPropType: PTypeInfo; inline;
  774. function GetTail: Pointer; inline;
  775. function GetNext: PPropInfo; inline;
  776. public
  777. PropTypeRef : TypeInfoPtr;
  778. GetProc : CodePointer;
  779. SetProc : CodePointer;
  780. StoredProc : CodePointer;
  781. Index : Longint;
  782. Default : Longint;
  783. NameIndex : SmallInt;
  784. // contains the type of the Get/Set/Storedproc, see also ptxxx
  785. // bit 0..1 GetProc
  786. // 2..3 SetProc
  787. // 4..5 StoredProc
  788. // 6 : true, constant index property
  789. PropProcs : Byte;
  790. {$ifdef PROVIDE_ATTR_TABLE}
  791. AttributeTable : PAttributeTable;
  792. {$endif}
  793. Name : ShortString;
  794. property PropType: PTypeInfo read GetPropType;
  795. property Tail: Pointer read GetTail;
  796. property Next: PPropInfo read GetNext;
  797. end;
  798. TProcInfoProc = Procedure(PropInfo : PPropInfo) of object;
  799. PPropList = ^TPropList;
  800. TPropList = array[0..{$ifdef cpu16}(32768 div sizeof(PPropInfo))-2{$else}65535{$endif}] of PPropInfo;
  801. const
  802. tkString = tkSString;
  803. tkProcedure = tkProcVar; // for compatibility with Delphi
  804. tkAny = [Low(TTypeKind)..High(TTypeKind)];
  805. tkMethods = [tkMethod];
  806. tkProperties = tkAny-tkMethods-[tkUnknown];
  807. // general property handling
  808. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  809. Function AlignTypeData(p : Pointer) : Pointer; inline;
  810. Function AlignTParamFlags(p : Pointer) : Pointer; inline;
  811. Function AlignPTypeInfo(p : Pointer) : Pointer; inline;
  812. Generic Function ConstParamIsRef<T>(aCallConv: TCallConv = ccReg): Boolean; inline;
  813. Function GetPropInfo(TypeInfo: PTypeInfo;const PropName: string): PPropInfo;
  814. Function GetPropInfo(TypeInfo: PTypeInfo;const PropName: string; AKinds: TTypeKinds): PPropInfo;
  815. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  816. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  817. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  818. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  819. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  820. Function FindPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  821. Function FindPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  822. Function FindPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  823. Procedure GetPropInfos(TypeInfo: PTypeInfo; PropList: PPropList);
  824. Function GetPropList(TypeInfo: PTypeInfo; TypeKinds: TTypeKinds; PropList: PPropList; Sorted: boolean = true): longint;
  825. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  826. function GetPropList(AClass: TClass; out PropList: PPropList): Integer;
  827. function GetPropList(Instance: TObject; out PropList: PPropList): Integer;
  828. // Property information routines.
  829. Function IsReadableProp(PropInfo : PPropInfo) : Boolean;
  830. Function IsReadableProp(Instance: TObject; const PropName: string): Boolean;
  831. Function IsReadableProp(AClass: TClass; const PropName: string): Boolean;
  832. Function IsWriteableProp(PropInfo : PPropInfo) : Boolean;
  833. Function IsWriteableProp(Instance: TObject; const PropName: string): Boolean;
  834. Function IsWriteableProp(AClass: TClass; const PropName: string): Boolean;
  835. Function IsStoredProp(Instance: TObject;PropInfo : PPropInfo) : Boolean;
  836. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  837. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  838. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  839. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  840. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  841. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  842. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  843. // subroutines to read/write properties
  844. Function GetOrdProp(Instance: TObject; PropInfo : PPropInfo) : Int64;
  845. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  846. Procedure SetOrdProp(Instance: TObject; PropInfo : PPropInfo; Value : Int64);
  847. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  848. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  849. Function GetEnumProp(Instance: TObject; const PropInfo: PPropInfo): string;
  850. Procedure SetEnumProp(Instance: TObject; const PropName: string;const Value: string);
  851. Procedure SetEnumProp(Instance: TObject; const PropInfo: PPropInfo;const Value: string);
  852. Function GetSetProp(Instance: TObject; const PropName: string): string;
  853. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  854. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  855. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  856. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  857. Function GetStrProp(Instance: TObject; PropInfo : PPropInfo) : Ansistring;
  858. Function GetStrProp(Instance: TObject; const PropName: string): string;
  859. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  860. Procedure SetStrProp(Instance: TObject; PropInfo : PPropInfo; const Value : Ansistring);
  861. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  862. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  863. Procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  864. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  865. Function GetUnicodeStrProp(Instance: TObject; PropInfo: PPropInfo): UnicodeString;
  866. Function GetUnicodeStrProp(Instance: TObject; const PropName: string): UnicodeString;
  867. Procedure SetUnicodeStrProp(Instance: TObject; const PropName: string; const Value: UnicodeString);
  868. Procedure SetUnicodeStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: UnicodeString);
  869. Function GetRawbyteStrProp(Instance: TObject; PropInfo: PPropInfo): RawByteString;
  870. Function GetRawByteStrProp(Instance: TObject; const PropName: string): RawByteString;
  871. Procedure SetRawByteStrProp(Instance: TObject; const PropName: string; const Value: RawByteString);
  872. Procedure SetRawByteStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: RawByteString);
  873. {$ifndef FPUNONE}
  874. Function GetFloatProp(Instance: TObject; PropInfo : PPropInfo) : Extended;
  875. Function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  876. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  877. Procedure SetFloatProp(Instance: TObject; PropInfo : PPropInfo; Value : Extended);
  878. {$endif}
  879. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  880. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  881. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo): TObject;
  882. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo; MinClass: TClass): TObject;
  883. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  884. Procedure SetObjectProp(Instance: TObject; PropInfo: PPropInfo; Value: TObject);
  885. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  886. Function GetObjectPropClass(AClass: TClass; const PropName: string): TClass;
  887. Function GetMethodProp(Instance: TObject; PropInfo: PPropInfo) : TMethod;
  888. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  889. Procedure SetMethodProp(Instance: TObject; PropInfo: PPropInfo; const Value : TMethod);
  890. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  891. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  892. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  893. Procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  894. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  895. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  896. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  897. Function GetPropValue(Instance: TObject; PropInfo: PPropInfo): Variant;
  898. Function GetPropValue(Instance: TObject; PropInfo: PPropInfo; PreferStrings: Boolean): Variant;
  899. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  900. Procedure SetPropValue(Instance: TObject; PropInfo: PPropInfo; const Value: Variant);
  901. Function GetVariantProp(Instance: TObject; PropInfo : PPropInfo): Variant;
  902. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  903. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  904. Procedure SetVariantProp(Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  905. function GetInterfaceProp(Instance: TObject; const PropName: string): IInterface;
  906. function GetInterfaceProp(Instance: TObject; PropInfo: PPropInfo): IInterface;
  907. procedure SetInterfaceProp(Instance: TObject; const PropName: string; const Value: IInterface);
  908. procedure SetInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: IInterface);
  909. function GetRawInterfaceProp(Instance: TObject; const PropName: string): Pointer;
  910. function GetRawInterfaceProp(Instance: TObject; PropInfo: PPropInfo): Pointer;
  911. procedure SetRawInterfaceProp(Instance: TObject; const PropName: string; const Value: Pointer);
  912. procedure SetRawInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: Pointer);
  913. function GetDynArrayProp(Instance: TObject; const PropName: string): Pointer;
  914. function GetDynArrayProp(Instance: TObject; PropInfo: PPropInfo): Pointer;
  915. procedure SetDynArrayProp(Instance: TObject; const PropName: string; const Value: Pointer);
  916. procedure SetDynArrayProp(Instance: TObject; PropInfo: PPropInfo; const Value: Pointer);
  917. // Extended RTTI
  918. function GetAttributeTable(TypeInfo: PTypeInfo): PAttributeTable;
  919. function GetPropAttribute(PropInfo: PPropInfo; AttributeNr: Word): TCustomAttribute; inline;
  920. function GetAttribute(AttributeTable: PAttributeTable; AttributeNr: Word): TCustomAttribute;
  921. {$IFDEF HAVE_INVOKEHELPER}
  922. procedure CallInvokeHelper(aTypeInfo : PTypeInfo; Instance: Pointer; const aMethod : String; aArgs : PPointer);
  923. {$ENDIF}
  924. // Auxiliary routines, which may be useful
  925. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  926. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  927. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  928. procedure AddEnumElementAliases(aTypeInfo: PTypeInfo; const aNames: array of string; aStartValue: Integer = 0);
  929. procedure RemoveEnumElementAliases(aTypeInfo: PTypeInfo);
  930. function GetEnumeratedAliasValue(aTypeInfo: PTypeInfo; const aName: string): Integer;
  931. function SetToArray(TypeInfo: PTypeInfo; Value: Pointer) : TBytes;
  932. function SetToArray(PropInfo: PPropInfo; Value: Pointer) : TBytes;
  933. function SetToArray(TypeInfo: PTypeInfo; Value: LongInt) : TBytes;
  934. function SetToArray(PropInfo: PPropInfo; Value: LongInt) : TBytes;
  935. function SetToString(TypeInfo: PTypeInfo; Value: LongInt; Brackets: Boolean) : String;
  936. function SetToString(PropInfo: PPropInfo; Value: LongInt; Brackets: Boolean) : String;
  937. function SetToString(PropInfo: PPropInfo; Value: LongInt) : String;
  938. function SetToString(TypeInfo: PTypeInfo; Value: Pointer; Brackets: Boolean = False) : String;
  939. function SetToString(PropInfo: PPropInfo; Value: Pointer; Brackets: Boolean = False) : String;
  940. function ArrayToSet(PropInfo: PPropInfo; const Value: array of Byte): LongInt;
  941. function ArrayToSet(TypeInfo: PTypeInfo; const Value: array of Byte): LongInt;
  942. procedure ArrayToSet(PropInfo: PPropInfo; const Value: array of Byte; Result: Pointer);
  943. procedure ArrayToSet(TypeInfo: PTypeInfo; const Value: array of Byte; Result: Pointer);
  944. function StringToSet(PropInfo: PPropInfo; const Value: string): LongInt;
  945. function StringToSet(TypeInfo: PTypeInfo; const Value: string): LongInt;
  946. procedure StringToSet(PropInfo: PPropInfo; const Value: String; Result: Pointer);
  947. procedure StringToSet(TypeInfo: PTypeInfo; const Value: String; Result: Pointer);
  948. const
  949. BooleanIdents: array[Boolean] of String = ('False', 'True');
  950. DotSep: String = '.';
  951. Type
  952. EPropertyError = Class(Exception);
  953. TGetPropValue = Function (Instance: TObject; PropInfo: PPropInfo; PreferStrings: Boolean) : Variant;
  954. TSetPropValue = Procedure (Instance: TObject; PropInfo: PPropInfo; const Value: Variant);
  955. TGetVariantProp = Function (Instance: TObject; PropInfo : PPropInfo): Variant;
  956. TSetVariantProp = Procedure (Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  957. EPropertyConvertError = class(Exception); // Not used (yet), but defined for compatibility.
  958. Const
  959. OnGetPropValue : TGetPropValue = Nil;
  960. OnSetPropValue : TSetPropValue = Nil;
  961. OnGetVariantprop : TGetVariantProp = Nil;
  962. OnSetVariantprop : TSetVariantProp = Nil;
  963. { for inlining }
  964. function DerefTypeInfoPtr(Info: TypeInfoPtr): PTypeInfo; inline;
  965. Implementation
  966. {$IFDEF FPC_DOTTEDUNITS}
  967. uses System.RtlConsts;
  968. {$ELSE FPC_DOTTEDUNITS}
  969. uses rtlconsts;
  970. {$ENDIF FPC_DOTTEDUNITS}
  971. type
  972. PMethod = ^TMethod;
  973. { ---------------------------------------------------------------------
  974. Auxiliary methods
  975. ---------------------------------------------------------------------}
  976. function aligntoptr(p : pointer) : pointer;inline;
  977. begin
  978. {$ifdef CPUM68K}
  979. result:=AlignTypeData(p);
  980. {$else CPUM68K}
  981. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  982. result:=align(p,sizeof(p));
  983. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  984. result:=p;
  985. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  986. {$endif CPUM68K}
  987. end;
  988. function DerefTypeInfoPtr(Info: TypeInfoPtr): PTypeInfo; inline;
  989. begin
  990. {$ifdef ver3_0}
  991. Result := Info;
  992. {$else}
  993. if not Assigned(Info) then
  994. Result := Nil
  995. else
  996. Result := Info^;
  997. {$endif}
  998. end;
  999. function GetAttributeTable(TypeInfo: PTypeInfo): PAttributeTable;
  1000. {$ifdef PROVIDE_ATTR_TABLE}
  1001. var
  1002. TD: PTypeData;
  1003. begin
  1004. TD := GetTypeData(TypeInfo);
  1005. Result:=TD^.AttributeTable;
  1006. {$else}
  1007. begin
  1008. Result:=Nil;
  1009. {$endif}
  1010. end;
  1011. function GetPropData(TypeInfo : PTypeInfo; TypeData: PTypeData) : PPropData; inline;
  1012. var
  1013. p: PtrUInt;
  1014. begin
  1015. p := PtrUInt(@TypeData^.UnitName) + SizeOf(TypeData^.UnitName[0]) + Length(TypeData^.UnitName);
  1016. Result := PPropData(aligntoptr(Pointer(p)));
  1017. end;
  1018. function GetAttribute(AttributeTable: PAttributeTable; AttributeNr: Word): TCustomAttribute;
  1019. begin
  1020. if (AttributeTable=nil) or (AttributeNr>=AttributeTable^.AttributeCount) then
  1021. result := nil
  1022. else
  1023. begin
  1024. result := AttributeTable^.AttributesList[AttributeNr].AttrProc();
  1025. end;
  1026. end;
  1027. function GetPropAttribute(PropInfo: PPropInfo; AttributeNr: Word): TCustomAttribute;
  1028. begin
  1029. {$ifdef PROVIDE_ATTR_TABLE}
  1030. Result := GetAttribute(PropInfo^.AttributeTable, AttributeNr);
  1031. {$else}
  1032. Result := Nil;
  1033. {$endif}
  1034. end;
  1035. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  1036. Var PS : PShortString;
  1037. PT : PTypeData;
  1038. begin
  1039. PT:=GetTypeData(TypeInfo);
  1040. if TypeInfo^.Kind=tkBool then
  1041. begin
  1042. case Value of
  1043. 0,1:
  1044. Result:=BooleanIdents[Boolean(Value)];
  1045. else
  1046. Result:='';
  1047. end;
  1048. end
  1049. else
  1050. begin
  1051. PS:=@PT^.NameList;
  1052. dec(Value,PT^.MinValue);
  1053. While Value>0 Do
  1054. begin
  1055. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  1056. Dec(Value);
  1057. end;
  1058. Result:=PS^;
  1059. end;
  1060. end;
  1061. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  1062. Var PS : PShortString;
  1063. PT : PTypeData;
  1064. Count : longint;
  1065. sName: shortstring;
  1066. begin
  1067. If Length(Name)=0 then
  1068. exit(-1);
  1069. sName := Name;
  1070. PT:=GetTypeData(TypeInfo);
  1071. Count:=0;
  1072. Result:=-1;
  1073. if TypeInfo^.Kind=tkBool then
  1074. begin
  1075. If CompareText(BooleanIdents[false],Name)=0 then
  1076. result:=0
  1077. else if CompareText(BooleanIdents[true],Name)=0 then
  1078. result:=1;
  1079. end
  1080. else
  1081. begin
  1082. PS:=@PT^.NameList;
  1083. While (Result=-1) and (PByte(PS)^<>0) do
  1084. begin
  1085. If ShortCompareText(PS^, sName) = 0 then
  1086. Result:=Count+PT^.MinValue;
  1087. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  1088. Inc(Count);
  1089. end;
  1090. if Result=-1 then
  1091. Result:=GetEnumeratedAliasValue(TypeInfo,Name);
  1092. end;
  1093. end;
  1094. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  1095. var
  1096. PS: PShortString;
  1097. begin
  1098. if enum1^.Kind=tkBool then
  1099. Result:=2
  1100. else
  1101. begin
  1102. { the last string is the unit name, so start at -1 }
  1103. PS:=@GetTypeData(enum1)^.NameList;
  1104. Result:=-1;
  1105. While (PByte(PS)^<>0) do
  1106. begin
  1107. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  1108. Inc(Result);
  1109. end;
  1110. end;
  1111. end;
  1112. Function SetToString(PropInfo: PPropInfo; Value: LongInt; Brackets: Boolean) : String;
  1113. begin
  1114. Result:=SetToString(PropInfo^.PropType, Value, Brackets);
  1115. end;
  1116. Function SetToString(TypeInfo: PTypeInfo; Value: LongInt; Brackets: Boolean) : String;
  1117. begin
  1118. {$if defined(FPC_BIG_ENDIAN)}
  1119. { correctly adjust packed sets that are smaller than 32-bit }
  1120. case GetTypeData(TypeInfo)^.OrdType of
  1121. otSByte,otUByte: Value := Value shl (SizeOf(Integer)*8-8);
  1122. otSWord,otUWord: Value := Value shl (SizeOf(Integer)*8-16);
  1123. end;
  1124. {$endif}
  1125. Result := SetToString(TypeInfo, @Value, Brackets);
  1126. end;
  1127. function SetToString(TypeInfo: PTypeInfo; Value: Pointer; Brackets: Boolean): String;
  1128. var
  1129. A: TBytes;
  1130. B: Byte;
  1131. PTI : PTypeInfo;
  1132. begin
  1133. PTI:=GetTypeData(TypeInfo)^.CompType;
  1134. A:=SetToArray(TypeInfo, Value);
  1135. Result := '';
  1136. for B in A do
  1137. If Result='' then
  1138. Result:=GetEnumName(PTI,B)
  1139. else
  1140. Result:=Result+','+GetEnumName(PTI,B);
  1141. if Brackets then
  1142. Result:='['+Result+']';
  1143. end;
  1144. Function SetToString(PropInfo: PPropInfo; Value: LongInt) : String;
  1145. begin
  1146. Result:=SetToString(PropInfo,Value,False);
  1147. end;
  1148. function SetToString(PropInfo: PPropInfo; Value: Pointer; Brackets: Boolean): String;
  1149. begin
  1150. Result := SetToString(PropInfo^.PropType, Value, Brackets);
  1151. end;
  1152. function SetToArray(TypeInfo: PTypeInfo; Value: Pointer) : TBytes;
  1153. type
  1154. tsetarr = bitpacked array[0..SizeOf(LongInt)*8-1] of 0..1;
  1155. Var
  1156. I,El,Els,Rem,V,Max : Integer;
  1157. PTD : PTypeData;
  1158. ValueArr : PLongInt;
  1159. begin
  1160. PTD := GetTypeData(TypeInfo);
  1161. ValueArr := PLongInt(Value);
  1162. Result:=[];
  1163. {$ifdef ver3_0}
  1164. case PTD^.OrdType of
  1165. otSByte, otUByte: begin
  1166. Els := 0;
  1167. Rem := 1;
  1168. end;
  1169. otSWord, otUWord: begin
  1170. Els := 0;
  1171. Rem := 2;
  1172. end;
  1173. otSLong, otULong: begin
  1174. Els := 1;
  1175. Rem := 0;
  1176. end;
  1177. end;
  1178. {$else}
  1179. Els := PTD^.SetSize div SizeOf(LongInt);
  1180. Rem := PTD^.SetSize mod SizeOf(LongInt);
  1181. {$endif}
  1182. {$ifdef ver3_0}
  1183. El := 0;
  1184. {$else}
  1185. for El := 0 to (PTD^.SetSize - 1) div SizeOf(LongInt) do
  1186. {$endif}
  1187. begin
  1188. if El = Els then
  1189. Max := Rem
  1190. else
  1191. Max := SizeOf(LongInt);
  1192. For I:=0 to Max*8-1 do
  1193. begin
  1194. if (tsetarr(ValueArr[El])[i]<>0) then
  1195. begin
  1196. V := I + SizeOf(LongInt) * 8 * El;
  1197. SetLength(Result, Length(Result)+1);
  1198. Result[High(Result)]:=V;
  1199. end;
  1200. end;
  1201. end;
  1202. end;
  1203. function SetToArray(PropInfo: PPropInfo; Value: Pointer) : TBytes;
  1204. begin
  1205. Result:=SetToArray(PropInfo^.PropType,Value);
  1206. end;
  1207. function SetToArray(TypeInfo: PTypeInfo; Value: LongInt) : TBytes;
  1208. begin
  1209. Result:=SetToArray(TypeInfo,@Value);
  1210. end;
  1211. function SetToArray(PropInfo: PPropInfo; Value: LongInt) : TBytes;
  1212. begin
  1213. Result:=SetToArray(PropInfo^.PropType,@Value);
  1214. end;
  1215. Const
  1216. SetDelim = ['[',']',',',' '];
  1217. Function GetNextElement(Var S : String) : String;
  1218. Var
  1219. J : Integer;
  1220. begin
  1221. J:=1;
  1222. Result:='';
  1223. If Length(S)>0 then
  1224. begin
  1225. While (J<=Length(S)) and Not (S[j] in SetDelim) do
  1226. Inc(j);
  1227. Result:=Copy(S,1,j-1);
  1228. Delete(S,1,j);
  1229. end;
  1230. end;
  1231. Function StringToSet(PropInfo: PPropInfo; const Value: string): LongInt;
  1232. begin
  1233. Result:=StringToSet(PropInfo^.PropType,Value);
  1234. end;
  1235. Function StringToSet(TypeInfo: PTypeInfo; const Value: string): LongInt;
  1236. begin
  1237. StringToSet(TypeInfo, Value, @Result);
  1238. {$if defined(FPC_BIG_ENDIAN)}
  1239. { correctly adjust packed sets that are smaller than 32-bit }
  1240. case GetTypeData(TypeInfo)^.OrdType of
  1241. otSByte,otUByte: Result := Result shr (SizeOf(Integer)*8-8);
  1242. otSWord,otUWord: Result := Result shr (SizeOf(Integer)*8-16);
  1243. end;
  1244. {$endif}
  1245. end;
  1246. procedure StringToSet(TypeInfo: PTypeInfo; const Value: String; Result: Pointer);
  1247. Var
  1248. S,T : String;
  1249. I, ElOfs, BitOfs : Integer;
  1250. PTD: PTypeData;
  1251. PTI : PTypeInfo;
  1252. A: TBytes;
  1253. begin
  1254. PTD:=GetTypeData(TypeInfo);
  1255. PTI:=PTD^.Comptype;
  1256. S:=Value;
  1257. I:=1;
  1258. If Length(S)>0 then
  1259. begin
  1260. While (I<=Length(S)) and (S[i] in SetDelim) do
  1261. Inc(I);
  1262. Delete(S,1,i-1);
  1263. end;
  1264. A:=[];
  1265. While (S<>'') do
  1266. begin
  1267. T:=GetNextElement(S);
  1268. if T<>'' then
  1269. begin
  1270. I:=GetEnumValue(PTI,T);
  1271. if (I<0) then
  1272. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [T]);
  1273. SetLength(A, Length(A)+1);
  1274. A[High(A)]:=I;
  1275. end;
  1276. end;
  1277. ArrayToSet(TypeInfo,A,Result);
  1278. end;
  1279. procedure StringToSet(PropInfo: PPropInfo; const Value: String; Result: Pointer);
  1280. begin
  1281. StringToSet(PropInfo^.PropType, Value, Result);
  1282. end;
  1283. Function ArrayToSet(PropInfo: PPropInfo; const Value: array of Byte): LongInt;
  1284. begin
  1285. Result:=ArrayToSet(PropInfo^.PropType,Value);
  1286. end;
  1287. Function ArrayToSet(TypeInfo: PTypeInfo; const Value: array of Byte): LongInt;
  1288. begin
  1289. ArrayToSet(TypeInfo, Value, @Result);
  1290. {$if defined(FPC_BIG_ENDIAN)}
  1291. { correctly adjust packed sets that are smaller than 32-bit }
  1292. case GetTypeData(TypeInfo)^.OrdType of
  1293. otSByte,otUByte: Result := Result shr (SizeOf(Integer)*8-8);
  1294. otSWord,otUWord: Result := Result shr (SizeOf(Integer)*8-16);
  1295. end;
  1296. {$endif}
  1297. end;
  1298. procedure ArrayToSet(TypeInfo: PTypeInfo; const Value: array of Byte; Result: Pointer);
  1299. Var
  1300. ElOfs, BitOfs : Integer;
  1301. PTD: PTypeData;
  1302. ResArr: PLongWord;
  1303. B: Byte;
  1304. begin
  1305. PTD:=GetTypeData(TypeInfo);
  1306. {$ifndef ver3_0}
  1307. FillChar(Result^, PTD^.SetSize, 0);
  1308. {$else}
  1309. PInteger(Result)^ := 0;
  1310. {$endif}
  1311. ResArr := PLongWord(Result);
  1312. for B in Value do
  1313. begin
  1314. ElOfs := B shr 5;
  1315. BitOfs := B and $1F;
  1316. {$ifdef FPC_BIG_ENDIAN}
  1317. { on Big Endian systems enum values start from the MSB, thus we need
  1318. to reverse the shift }
  1319. BitOfs := 31 - BitOfs;
  1320. {$endif}
  1321. ResArr[ElOfs] := ResArr[ElOfs] or (LongInt(1) shl BitOfs);
  1322. end;
  1323. end;
  1324. procedure ArrayToSet(PropInfo: PPropInfo; const Value: array of Byte; Result: Pointer);
  1325. begin
  1326. ArrayToSet(PropInfo^.PropType, Value, Result);
  1327. end;
  1328. Function AlignTypeData(p : Pointer) : Pointer;
  1329. {$packrecords c}
  1330. type
  1331. TAlignCheck = record
  1332. b : byte;
  1333. q : qword;
  1334. end;
  1335. {$packrecords default}
  1336. begin
  1337. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  1338. {$ifdef VER3_0}
  1339. Result:=Pointer(align(p,SizeOf(Pointer)));
  1340. {$else VER3_0}
  1341. Result:=Pointer(align(p,PtrInt(@TAlignCheck(nil^).q)))
  1342. {$endif VER3_0}
  1343. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  1344. Result:=p;
  1345. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  1346. end;
  1347. Function AlignTParamFlags(p : Pointer) : Pointer; inline;
  1348. {$packrecords c}
  1349. type
  1350. TAlignCheck = record
  1351. b : byte;
  1352. w : word;
  1353. end;
  1354. {$packrecords default}
  1355. begin
  1356. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  1357. Result:=Pointer(align(p,PtrInt(@TAlignCheck(nil^).w)))
  1358. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  1359. Result:=p;
  1360. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  1361. end;
  1362. Function AlignPTypeInfo(p : Pointer) : Pointer; inline;
  1363. {$packrecords c}
  1364. type
  1365. TAlignCheck = record
  1366. b : byte;
  1367. p : pointer;
  1368. end;
  1369. {$packrecords default}
  1370. begin
  1371. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  1372. Result:=Pointer(align(p,PtrInt(@TAlignCheck(nil^).p)))
  1373. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  1374. Result:=p;
  1375. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  1376. end;
  1377. Generic Function ConstParamIsRef<T>(aCallConv: TCallConv): Boolean;
  1378. Function SameAddrRegister(const aArg1: T; constref aArg2: T): Boolean; register;
  1379. begin
  1380. Result := @aArg1 = @aArg2;
  1381. end;
  1382. Function SameAddrCDecl(const aArg1: T; constref aArg2: T): Boolean; cdecl;
  1383. begin
  1384. Result := @aArg1 = @aArg2;
  1385. end;
  1386. {$if defined(cpui8086) or defined(cpui386)}
  1387. Function SameAddrPascal(const aArg1: T; constref aArg2: T): Boolean; pascal;
  1388. begin
  1389. Result := @aArg1 = @aArg2;
  1390. end;
  1391. {$endif}
  1392. Function SameAddrStdCall(const aArg1: T; constref aArg2: T): Boolean; stdcall;
  1393. begin
  1394. Result := @aArg1 = @aArg2;
  1395. end;
  1396. Function SameAddrCppDecl(const aArg1: T; constref aArg2: T): Boolean; cppdecl;
  1397. begin
  1398. Result := @aArg1 = @aArg2;
  1399. end;
  1400. {$if defined(cpui386)}
  1401. Function SameAddrOldFPCCall(const aArg1: T; constref aArg2: T): Boolean; oldfpccall;
  1402. begin
  1403. Result := @aArg1 = @aArg2;
  1404. end;
  1405. {$endif}
  1406. Function SameAddrMWPascal(const aArg1: T; constref aArg2: T): Boolean; mwpascal;
  1407. begin
  1408. Result := @aArg1 = @aArg2;
  1409. end;
  1410. var
  1411. v: T;
  1412. begin
  1413. v := Default(T);
  1414. case aCallConv of
  1415. ccReg:
  1416. Result := SameAddrRegister(v, v);
  1417. ccCdecl:
  1418. Result := SameAddrCDecl(v, v);
  1419. {$if defined(cpui386) or defined(cpui8086)}
  1420. ccPascal:
  1421. Result := SameAddrPascal(v, v);
  1422. {$endif}
  1423. {$if not defined(cpui386)}
  1424. ccOldFPCCall,
  1425. {$endif}
  1426. {$if not defined(cpui386) and not defined(cpui8086)}
  1427. ccPascal,
  1428. {$endif}
  1429. ccStdCall:
  1430. Result := SameAddrStdCall(v, v);
  1431. ccCppdecl:
  1432. Result := SameAddrCppDecl(v, v);
  1433. {$if defined(cpui386)}
  1434. ccOldFPCCall:
  1435. Result := SameAddrOldFPCCall(v, v);
  1436. {$endif}
  1437. ccMWPascal:
  1438. Result := SameAddrMWPascal(v, v);
  1439. else
  1440. raise EArgumentException.CreateFmt(SUnsupportedCallConv, [GetEnumName(PTypeInfo(TypeInfo(TCallConv)), Ord(aCallConv))]);
  1441. end;
  1442. end;
  1443. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  1444. begin
  1445. GetTypeData:=AlignTypeData(pointer(TypeInfo)+2+PByte(pointer(TypeInfo)+1)^);
  1446. end;
  1447. { ---------------------------------------------------------------------
  1448. Basic Type information functions.
  1449. ---------------------------------------------------------------------}
  1450. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  1451. var
  1452. hp : PTypeData;
  1453. i : longint;
  1454. p : shortstring;
  1455. pd : PPropData;
  1456. begin
  1457. P:=PropName; // avoid Ansi<->short conversion in a loop
  1458. while Assigned(TypeInfo) do
  1459. begin
  1460. // skip the name
  1461. hp:=GetTypeData(Typeinfo);
  1462. // the class info rtti the property rtti follows immediatly
  1463. pd := GetPropData(TypeInfo,hp);
  1464. Result:=PPropInfo(@pd^.PropList);
  1465. for i:=1 to pd^.PropCount do
  1466. begin
  1467. // found a property of that name ?
  1468. if ShortCompareText(Result^.Name, P) = 0 then
  1469. exit;
  1470. // skip to next property
  1471. Result:=PPropInfo(aligntoptr(pointer(@Result^.Name)+byte(Result^.Name[0])+1));
  1472. end;
  1473. // parent class
  1474. Typeinfo:=hp^.ParentInfo;
  1475. end;
  1476. Result:=Nil;
  1477. end;
  1478. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; Akinds : TTypeKinds) : PPropInfo;
  1479. begin
  1480. Result:=GetPropInfo(TypeInfo,PropName);
  1481. If (Akinds<>[]) then
  1482. If (Result<>Nil) then
  1483. If Not (Result^.PropType^.Kind in AKinds) then
  1484. Result:=Nil;
  1485. end;
  1486. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  1487. begin
  1488. Result:=GetPropInfo(PTypeInfo(AClass.ClassInfo),PropName,AKinds);
  1489. end;
  1490. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  1491. begin
  1492. Result:=GetPropInfo(Instance.ClassType,PropName,AKinds);
  1493. end;
  1494. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  1495. begin
  1496. Result:=GetPropInfo(Instance,PropName,[]);
  1497. end;
  1498. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  1499. begin
  1500. Result:=GetPropInfo(AClass,PropName,[]);
  1501. end;
  1502. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  1503. begin
  1504. result:=GetPropInfo(Instance, PropName);
  1505. if Result=nil then
  1506. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  1507. end;
  1508. Function FindPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  1509. begin
  1510. result:=GetPropInfo(Instance, PropName, AKinds);
  1511. if Result=nil then
  1512. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  1513. end;
  1514. Function FindPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  1515. begin
  1516. result:=GetPropInfo(AClass, PropName);
  1517. if result=nil then
  1518. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  1519. end;
  1520. Function FindPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds): PPropInfo;
  1521. begin
  1522. result:=GetPropInfo(AClass, PropName, AKinds);
  1523. if result=nil then
  1524. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  1525. end;
  1526. function IsReadableProp(PropInfo: PPropInfo): Boolean;
  1527. begin
  1528. Result:=(((PropInfo^.PropProcs) and 3) in [ptField,ptStatic,ptVirtual]);
  1529. end;
  1530. function IsReadableProp(Instance: TObject; const PropName: string): Boolean;
  1531. begin
  1532. Result:=IsReadableProp(FindPropInfo(Instance,PropName));
  1533. end;
  1534. function IsReadableProp(AClass: TClass; const PropName: string): Boolean;
  1535. begin
  1536. Result:=IsReadableProp(FindPropInfo(AClass,PropName));
  1537. end;
  1538. function IsWriteableProp(PropInfo: PPropInfo): Boolean;
  1539. begin
  1540. Result:=(((PropInfo^.PropProcs shr 2) and 3) in [ptField,ptStatic,ptVirtual]);
  1541. end;
  1542. function IsWriteableProp(Instance: TObject; const PropName: string): Boolean;
  1543. begin
  1544. Result:=IsWriteableProp(FindPropInfo(Instance,PropName));
  1545. end;
  1546. function IsWriteableProp(AClass: TClass; const PropName: string): Boolean;
  1547. begin
  1548. Result:=IsWriteableProp(FindPropInfo(AClass,PropName));
  1549. end;
  1550. Function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean;
  1551. type
  1552. TBooleanIndexFunc=function(Index:integer):boolean of object;
  1553. TBooleanFunc=function:boolean of object;
  1554. var
  1555. AMethod : TMethod;
  1556. begin
  1557. case (PropInfo^.PropProcs shr 4) and 3 of
  1558. ptField:
  1559. Result:=PBoolean(Pointer(Instance)+PtrUInt(PropInfo^.StoredProc))^;
  1560. ptConst:
  1561. Result:=LongBool(PropInfo^.StoredProc);
  1562. ptStatic,
  1563. ptVirtual:
  1564. begin
  1565. if (PropInfo^.PropProcs shr 4) and 3=ptstatic then
  1566. AMethod.Code:=PropInfo^.StoredProc
  1567. else
  1568. AMethod.Code:=pcodepointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.StoredProc))^;
  1569. AMethod.Data:=Instance;
  1570. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1571. Result:=TBooleanIndexFunc(AMethod)(PropInfo^.Index)
  1572. else
  1573. Result:=TBooleanFunc(AMethod)();
  1574. end;
  1575. end;
  1576. end;
  1577. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  1578. {
  1579. Store Pointers to property information in the list pointed
  1580. to by proplist. PRopList must contain enough space to hold ALL
  1581. properties.
  1582. }
  1583. Var
  1584. TD : PTypeData;
  1585. TP : PPropInfo;
  1586. Count : Longint;
  1587. begin
  1588. // Get this objects TOTAL published properties count
  1589. TD:=GetTypeData(TypeInfo);
  1590. // Clear list
  1591. FillChar(PropList^,TD^.PropCount*sizeof(Pointer),0);
  1592. repeat
  1593. TD:=GetTypeData(TypeInfo);
  1594. // published properties count for this object
  1595. TP:=PPropInfo(GetPropData(TypeInfo, TD));
  1596. Count:=PWord(TP)^;
  1597. // Now point TP to first propinfo record.
  1598. Inc(Pointer(TP),SizeOF(Word));
  1599. tp:=aligntoptr(tp);
  1600. While Count>0 do
  1601. begin
  1602. // Don't overwrite properties with the same name
  1603. if PropList^[TP^.NameIndex]=nil then
  1604. PropList^[TP^.NameIndex]:=TP;
  1605. // Point to TP next propinfo record.
  1606. // Located at Name[Length(Name)+1] !
  1607. TP:=aligntoptr(PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+1));
  1608. Dec(Count);
  1609. end;
  1610. TypeInfo:=TD^.Parentinfo;
  1611. until TypeInfo=nil;
  1612. end;
  1613. Procedure InsertProp (PL : PProplist;PI : PPropInfo; Count : longint);
  1614. Var
  1615. I : Longint;
  1616. begin
  1617. I:=0;
  1618. While (I<Count) and (PI^.Name>PL^[I]^.Name) do
  1619. Inc(I);
  1620. If I<Count then
  1621. Move(PL^[I], PL^[I+1], (Count - I) * SizeOf(Pointer));
  1622. PL^[I]:=PI;
  1623. end;
  1624. Procedure InsertPropnosort (PL : PProplist;PI : PPropInfo; Count : longint);
  1625. begin
  1626. PL^[Count]:=PI;
  1627. end;
  1628. Type TInsertProp = Procedure (PL : PProplist;PI : PPropInfo; Count : longint);
  1629. //Const InsertProps : array[false..boolean] of TInsertProp = (InsertPropNoSort,InsertProp);
  1630. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
  1631. {
  1632. Store Pointers to property information OF A CERTAIN KIND in the list pointed
  1633. to by proplist. PRopList must contain enough space to hold ALL
  1634. properties.
  1635. }
  1636. Var
  1637. TempList : PPropList;
  1638. PropInfo : PPropinfo;
  1639. I,Count : longint;
  1640. DoInsertProp : TInsertProp;
  1641. begin
  1642. if sorted then
  1643. DoInsertProp:=@InsertProp
  1644. else
  1645. DoInsertProp:=@InsertPropnosort;
  1646. Result:=0;
  1647. Count:=GetTypeData(TypeInfo)^.Propcount;
  1648. If Count>0 then
  1649. begin
  1650. GetMem(TempList,Count*SizeOf(Pointer));
  1651. Try
  1652. GetPropInfos(TypeInfo,TempList);
  1653. For I:=0 to Count-1 do
  1654. begin
  1655. PropInfo:=TempList^[i];
  1656. If PropInfo^.PropType^.Kind in TypeKinds then
  1657. begin
  1658. If (PropList<>Nil) then
  1659. DoInsertProp(PropList,PropInfo,Result);
  1660. Inc(Result);
  1661. end;
  1662. end;
  1663. finally
  1664. FreeMem(TempList,Count*SizeOf(Pointer));
  1665. end;
  1666. end;
  1667. end;
  1668. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  1669. begin
  1670. result:=GetTypeData(TypeInfo)^.Propcount;
  1671. if result>0 then
  1672. begin
  1673. getmem(PropList,result*sizeof(pointer));
  1674. GetPropInfos(TypeInfo,PropList);
  1675. end
  1676. else
  1677. PropList:=Nil;
  1678. end;
  1679. function GetPropList(AClass: TClass; out PropList: PPropList): Integer;
  1680. begin
  1681. Result := GetPropList(PTypeInfo(AClass.ClassInfo), PropList);
  1682. end;
  1683. function GetPropList(Instance: TObject; out PropList: PPropList): Integer;
  1684. begin
  1685. Result := GetPropList(Instance.ClassType, PropList);
  1686. end;
  1687. { ---------------------------------------------------------------------
  1688. Property access functions
  1689. ---------------------------------------------------------------------}
  1690. { ---------------------------------------------------------------------
  1691. Ordinal properties
  1692. ---------------------------------------------------------------------}
  1693. Function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Int64;
  1694. type
  1695. TGetInt64ProcIndex=function(index:longint):Int64 of object;
  1696. TGetInt64Proc=function():Int64 of object;
  1697. TGetIntegerProcIndex=function(index:longint):longint of object;
  1698. TGetIntegerProc=function:longint of object;
  1699. TGetWordProcIndex=function(index:longint):word of object;
  1700. TGetWordProc=function:word of object;
  1701. TGetByteProcIndex=function(index:longint):Byte of object;
  1702. TGetByteProc=function:Byte of object;
  1703. var
  1704. TypeInfo: PTypeInfo;
  1705. AMethod : TMethod;
  1706. DataSize: Integer;
  1707. OrdType: TOrdType;
  1708. Signed: Boolean;
  1709. begin
  1710. Result:=0;
  1711. TypeInfo := PropInfo^.PropType;
  1712. Signed := false;
  1713. DataSize := 4;
  1714. case TypeInfo^.Kind of
  1715. // We keep this for backwards compatibility, but internally it is no longer used.
  1716. {$ifdef cpu64}
  1717. tkInterface,
  1718. tkInterfaceRaw,
  1719. tkDynArray,
  1720. tkClass:
  1721. DataSize:=8;
  1722. {$endif cpu64}
  1723. tkChar, tkBool:
  1724. DataSize:=1;
  1725. tkWChar:
  1726. DataSize:=2;
  1727. tkSet,
  1728. tkEnumeration,
  1729. tkInteger:
  1730. begin
  1731. OrdType:=GetTypeData(TypeInfo)^.OrdType;
  1732. case OrdType of
  1733. otSByte,otUByte: DataSize := 1;
  1734. otSWord,otUWord: DataSize := 2;
  1735. end;
  1736. Signed := OrdType in [otSByte,otSWord,otSLong];
  1737. end;
  1738. tkInt64 :
  1739. begin
  1740. DataSize:=8;
  1741. Signed:=true;
  1742. end;
  1743. tkQword :
  1744. begin
  1745. DataSize:=8;
  1746. Signed:=false;
  1747. end;
  1748. end;
  1749. case (PropInfo^.PropProcs) and 3 of
  1750. ptField:
  1751. if Signed then begin
  1752. case DataSize of
  1753. 1: Result:=PShortInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1754. 2: Result:=PSmallInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1755. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1756. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1757. end;
  1758. end else begin
  1759. case DataSize of
  1760. 1: Result:=PByte(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1761. 2: Result:=PWord(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1762. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1763. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1764. end;
  1765. end;
  1766. ptStatic,
  1767. ptVirtual:
  1768. begin
  1769. if (PropInfo^.PropProcs and 3)=ptStatic then
  1770. AMethod.Code:=PropInfo^.GetProc
  1771. else
  1772. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1773. AMethod.Data:=Instance;
  1774. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then begin
  1775. case DataSize of
  1776. 1: Result:=TGetByteProcIndex(AMethod)(PropInfo^.Index);
  1777. 2: Result:=TGetWordProcIndex(AMethod)(PropInfo^.Index);
  1778. 4: Result:=TGetIntegerProcIndex(AMethod)(PropInfo^.Index);
  1779. 8: result:=TGetInt64ProcIndex(AMethod)(PropInfo^.Index)
  1780. end;
  1781. end else begin
  1782. case DataSize of
  1783. 1: Result:=TGetByteProc(AMethod)();
  1784. 2: Result:=TGetWordProc(AMethod)();
  1785. 4: Result:=TGetIntegerProc(AMethod)();
  1786. 8: result:=TGetInt64Proc(AMethod)();
  1787. end;
  1788. end;
  1789. if Signed then begin
  1790. case DataSize of
  1791. 1: Result:=ShortInt(Result);
  1792. 2: Result:=SmallInt(Result);
  1793. end;
  1794. end;
  1795. end;
  1796. else
  1797. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  1798. end;
  1799. end;
  1800. Procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;Value : Int64);
  1801. type
  1802. TSetInt64ProcIndex=procedure(index:longint;i:Int64) of object;
  1803. TSetInt64Proc=procedure(i:Int64) of object;
  1804. TSetIntegerProcIndex=procedure(index,i:longint) of object;
  1805. TSetIntegerProc=procedure(i:longint) of object;
  1806. var
  1807. DataSize: Integer;
  1808. AMethod : TMethod;
  1809. begin
  1810. if PropInfo^.PropType^.Kind in [tkInt64,tkQword
  1811. { why do we have to handle classes here, see also below? (FK) }
  1812. {$ifdef cpu64}
  1813. ,tkInterface
  1814. ,tkInterfaceRaw
  1815. ,tkDynArray
  1816. ,tkClass
  1817. {$endif cpu64}
  1818. ] then
  1819. DataSize := 8
  1820. else
  1821. DataSize := 4;
  1822. if not(PropInfo^.PropType^.Kind in [tkInt64,tkQword,tkClass,tkInterface,tkInterfaceRaw,tkDynArray]) then
  1823. begin
  1824. { cut off unnecessary stuff }
  1825. case GetTypeData(PropInfo^.PropType)^.OrdType of
  1826. otSWord,otUWord:
  1827. begin
  1828. Value:=Value and $ffff;
  1829. DataSize := 2;
  1830. end;
  1831. otSByte,otUByte:
  1832. begin
  1833. Value:=Value and $ff;
  1834. DataSize := 1;
  1835. end;
  1836. end;
  1837. end;
  1838. case (PropInfo^.PropProcs shr 2) and 3 of
  1839. ptField:
  1840. case DataSize of
  1841. 1: PByte(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Byte(Value);
  1842. 2: PWord(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Word(Value);
  1843. 4: PLongint(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Longint(Value);
  1844. 8: PInt64(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1845. end;
  1846. ptStatic,
  1847. ptVirtual:
  1848. begin
  1849. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1850. AMethod.Code:=PropInfo^.SetProc
  1851. else
  1852. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1853. AMethod.Data:=Instance;
  1854. if datasize=8 then
  1855. begin
  1856. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1857. TSetInt64ProcIndex(AMethod)(PropInfo^.Index,Value)
  1858. else
  1859. TSetInt64Proc(AMethod)(Value);
  1860. end
  1861. else
  1862. begin
  1863. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1864. TSetIntegerProcIndex(AMethod)(PropInfo^.Index,Value)
  1865. else
  1866. TSetIntegerProc(AMethod)(Value);
  1867. end;
  1868. end;
  1869. else
  1870. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  1871. end;
  1872. end;
  1873. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  1874. begin
  1875. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  1876. end;
  1877. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  1878. begin
  1879. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  1880. end;
  1881. Function GetEnumProp(Instance: TObject; Const PropInfo: PPropInfo): string;
  1882. begin
  1883. Result:=GetEnumName(PropInfo^.PropType, GetOrdProp(Instance, PropInfo));
  1884. end;
  1885. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  1886. begin
  1887. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  1888. end;
  1889. Procedure SetEnumProp(Instance: TObject; const PropName: string; const Value: string);
  1890. begin
  1891. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  1892. end;
  1893. Procedure SetEnumProp(Instance: TObject; Const PropInfo : PPropInfo; const Value: string);
  1894. Var
  1895. PV : Longint;
  1896. begin
  1897. If PropInfo<>Nil then
  1898. begin
  1899. PV:=GetEnumValue(PropInfo^.PropType, Value);
  1900. if (PV<0) then
  1901. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [Value]);
  1902. SetOrdProp(Instance, PropInfo,PV);
  1903. end;
  1904. end;
  1905. { ---------------------------------------------------------------------
  1906. Int64 wrappers
  1907. ---------------------------------------------------------------------}
  1908. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  1909. begin
  1910. Result:=GetOrdProp(Instance,PropInfo);
  1911. end;
  1912. procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  1913. begin
  1914. SetOrdProp(Instance,PropInfo,Value);
  1915. end;
  1916. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  1917. begin
  1918. Result:=GetInt64Prop(Instance,FindPropInfo(Instance,PropName));
  1919. end;
  1920. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  1921. begin
  1922. SetInt64Prop(Instance,FindPropInfo(Instance,PropName),Value);
  1923. end;
  1924. { ---------------------------------------------------------------------
  1925. Set properties
  1926. ---------------------------------------------------------------------}
  1927. Function GetSetProp(Instance: TObject; const PropName: string): string;
  1928. begin
  1929. Result:=GetSetProp(Instance,PropName,False);
  1930. end;
  1931. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  1932. begin
  1933. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName),Brackets);
  1934. end;
  1935. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  1936. begin
  1937. Result:=SetToString(PropInfo,GetOrdProp(Instance,PropInfo),Brackets);
  1938. end;
  1939. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  1940. begin
  1941. SetSetProp(Instance,FindPropInfo(Instance,PropName),Value);
  1942. end;
  1943. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  1944. begin
  1945. SetOrdProp(Instance,PropInfo,StringToSet(PropInfo,Value));
  1946. end;
  1947. { ---------------------------------------------------------------------
  1948. Pointer properties - internal only
  1949. ---------------------------------------------------------------------}
  1950. Function GetPointerProp(Instance: TObject; PropInfo : PPropInfo): Pointer;
  1951. Type
  1952. TGetPointerProcIndex = function (index:longint): Pointer of object;
  1953. TGetPointerProc = function (): Pointer of object;
  1954. var
  1955. AMethod : TMethod;
  1956. begin
  1957. case (PropInfo^.PropProcs) and 3 of
  1958. ptField:
  1959. Result := PPointer(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  1960. ptStatic,
  1961. ptVirtual:
  1962. begin
  1963. if (PropInfo^.PropProcs and 3)=ptStatic then
  1964. AMethod.Code:=PropInfo^.GetProc
  1965. else
  1966. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1967. AMethod.Data:=Instance;
  1968. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1969. Result:=TGetPointerProcIndex(AMethod)(PropInfo^.Index)
  1970. else
  1971. Result:=TGetPointerProc(AMethod)();
  1972. end;
  1973. else
  1974. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  1975. end;
  1976. end;
  1977. Procedure SetPointerProp(Instance: TObject; PropInfo : PPropInfo; Value: Pointer);
  1978. type
  1979. TSetPointerProcIndex = procedure(index: longint; p: pointer) of object;
  1980. TSetPointerProc = procedure(p: pointer) of object;
  1981. var
  1982. AMethod : TMethod;
  1983. begin
  1984. case (PropInfo^.PropProcs shr 2) and 3 of
  1985. ptField:
  1986. PPointer(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  1987. ptStatic,
  1988. ptVirtual:
  1989. begin
  1990. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1991. AMethod.Code:=PropInfo^.SetProc
  1992. else
  1993. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1994. AMethod.Data:=Instance;
  1995. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1996. TSetPointerProcIndex(AMethod)(PropInfo^.Index,Value)
  1997. else
  1998. TSetPointerProc(AMethod)(Value);
  1999. end;
  2000. else
  2001. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  2002. end;
  2003. end;
  2004. { ---------------------------------------------------------------------
  2005. Object properties
  2006. ---------------------------------------------------------------------}
  2007. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  2008. begin
  2009. Result:=GetObjectProp(Instance,PropName,Nil);
  2010. end;
  2011. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  2012. begin
  2013. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName),MinClass);
  2014. end;
  2015. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo): TObject;
  2016. begin
  2017. Result:=GetObjectProp(Instance,PropInfo,Nil);
  2018. end;
  2019. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo; MinClass: TClass): TObject;
  2020. begin
  2021. Result:=TObject(GetPointerProp(Instance,PropInfo));
  2022. If (MinClass<>Nil) and (Result<>Nil) Then
  2023. If Not Result.InheritsFrom(MinClass) then
  2024. Result:=Nil;
  2025. end;
  2026. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  2027. begin
  2028. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  2029. end;
  2030. Procedure SetObjectProp(Instance: TObject; PropInfo : PPropInfo; Value: TObject);
  2031. begin
  2032. SetPointerProp(Instance,PropInfo,Pointer(Value));
  2033. end;
  2034. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  2035. begin
  2036. Result:=GetTypeData(FindPropInfo(Instance,PropName,[tkClass])^.PropType)^.ClassType;
  2037. end;
  2038. Function GetObjectPropClass(AClass: TClass; const PropName: string): TClass;
  2039. begin
  2040. Result:=GetTypeData(FindPropInfo(AClass,PropName,[tkClass])^.PropType)^.ClassType;
  2041. end;
  2042. { ---------------------------------------------------------------------
  2043. Interface wrapprers
  2044. ---------------------------------------------------------------------}
  2045. function GetInterfaceProp(Instance: TObject; const PropName: string): IInterface;
  2046. begin
  2047. Result:=GetInterfaceProp(Instance,FindPropInfo(Instance,PropName));
  2048. end;
  2049. function GetInterfaceProp(Instance: TObject; PropInfo: PPropInfo): IInterface;
  2050. type
  2051. TGetInterfaceProc=function:IInterface of object;
  2052. TGetInterfaceProcIndex=function(index:longint):IInterface of object;
  2053. var
  2054. AMethod : TMethod;
  2055. begin
  2056. Result:=nil;
  2057. case (PropInfo^.PropProcs) and 3 of
  2058. ptField:
  2059. Result:=IInterface(PPointer(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^);
  2060. ptStatic,
  2061. ptVirtual:
  2062. begin
  2063. if (PropInfo^.PropProcs and 3)=ptStatic then
  2064. AMethod.Code:=PropInfo^.GetProc
  2065. else
  2066. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  2067. AMethod.Data:=Instance;
  2068. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2069. Result:=TGetInterfaceProcIndex(AMethod)(PropInfo^.Index)
  2070. else
  2071. Result:=TGetInterfaceProc(AMethod)();
  2072. end;
  2073. else
  2074. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  2075. end;
  2076. end;
  2077. procedure SetInterfaceProp(Instance: TObject; const PropName: string; const Value: IInterface);
  2078. begin
  2079. SetInterfaceProp(Instance,FindPropInfo(Instance,PropName),Value);
  2080. end;
  2081. procedure SetInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: IInterface);
  2082. type
  2083. TSetIntfStrProcIndex=procedure(index:longint;const i:IInterface) of object;
  2084. TSetIntfStrProc=procedure(i:IInterface) of object;
  2085. var
  2086. AMethod : TMethod;
  2087. begin
  2088. case Propinfo^.PropType^.Kind of
  2089. tkInterface:
  2090. begin
  2091. case (PropInfo^.PropProcs shr 2) and 3 of
  2092. ptField:
  2093. PInterface(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  2094. ptStatic,
  2095. ptVirtual:
  2096. begin
  2097. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  2098. AMethod.Code:=PropInfo^.SetProc
  2099. else
  2100. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  2101. AMethod.Data:=Instance;
  2102. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2103. TSetIntfStrProcIndex(AMethod)(PropInfo^.Index,Value)
  2104. else
  2105. TSetIntfStrProc(AMethod)(Value);
  2106. end;
  2107. else
  2108. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  2109. end;
  2110. end;
  2111. tkInterfaceRaw:
  2112. Raise Exception.Create('Cannot set RAW interface from IUnknown interface');
  2113. end;
  2114. end;
  2115. { ---------------------------------------------------------------------
  2116. RAW (Corba) Interface wrapprers
  2117. ---------------------------------------------------------------------}
  2118. function GetRawInterfaceProp(Instance: TObject; const PropName: string): Pointer;
  2119. begin
  2120. Result:=GetRawInterfaceProp(Instance,FindPropInfo(Instance,PropName));
  2121. end;
  2122. function GetRawInterfaceProp(Instance: TObject; PropInfo: PPropInfo): Pointer;
  2123. begin
  2124. Result:=GetPointerProp(Instance,PropInfo);
  2125. end;
  2126. procedure SetRawInterfaceProp(Instance: TObject; const PropName: string; const Value: Pointer);
  2127. begin
  2128. SetRawInterfaceProp(Instance,FindPropInfo(Instance,PropName),Value);
  2129. end;
  2130. procedure SetRawInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: Pointer);
  2131. begin
  2132. SetPointerProp(Instance,PropInfo,Value);
  2133. end;
  2134. { ---------------------------------------------------------------------
  2135. Dynamic array properties
  2136. ---------------------------------------------------------------------}
  2137. function GetDynArrayProp(Instance: TObject; const PropName: string): Pointer;
  2138. begin
  2139. Result:=GetDynArrayProp(Instance,FindPropInfo(Instance,PropName));
  2140. end;
  2141. function GetDynArrayProp(Instance: TObject; PropInfo: PPropInfo): Pointer;
  2142. type
  2143. { we need a dynamic array as that type is usually passed differently from
  2144. a plain pointer }
  2145. TDynArray=array of Byte;
  2146. TGetDynArrayProc=function:TDynArray of object;
  2147. TGetDynArrayProcIndex=function(index:longint):TDynArray of object;
  2148. var
  2149. AMethod : TMethod;
  2150. begin
  2151. Result:=nil;
  2152. if PropInfo^.PropType^.Kind<>tkDynArray then
  2153. Exit;
  2154. case (PropInfo^.PropProcs) and 3 of
  2155. ptField:
  2156. Result:=PPointer(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  2157. ptStatic,
  2158. ptVirtual:
  2159. begin
  2160. if (PropInfo^.PropProcs and 3)=ptStatic then
  2161. AMethod.Code:=PropInfo^.GetProc
  2162. else
  2163. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  2164. AMethod.Data:=Instance;
  2165. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2166. Result:=Pointer(TGetDynArrayProcIndex(AMethod)(PropInfo^.Index))
  2167. else
  2168. Result:=Pointer(TGetDynArrayProc(AMethod)());
  2169. end;
  2170. else
  2171. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  2172. end;
  2173. end;
  2174. procedure SetDynArrayProp(Instance: TObject; const PropName: string; const Value: Pointer);
  2175. begin
  2176. SetDynArrayProp(Instance,FindPropInfo(Instance,PropName),Value);
  2177. end;
  2178. procedure SetDynArrayProp(Instance: TObject; PropInfo: PPropInfo; const Value: Pointer);
  2179. type
  2180. { we need a dynamic array as that type is usually passed differently from
  2181. a plain pointer }
  2182. TDynArray=array of Byte;
  2183. TSetDynArrayProcIndex=procedure(index:longint;const i:TDynArray) of object;
  2184. TSetDynArrayProc=procedure(i:TDynArray) of object;
  2185. var
  2186. AMethod: TMethod;
  2187. begin
  2188. if PropInfo^.PropType^.Kind<>tkDynArray then
  2189. Exit;
  2190. case (PropInfo^.PropProcs shr 2) and 3 of
  2191. ptField:
  2192. CopyArray(PPointer(Pointer(Instance)+PtrUInt(PropInfo^.SetProc)), @Value, PropInfo^.PropType, 1);
  2193. ptStatic,
  2194. ptVirtual:
  2195. begin
  2196. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  2197. AMethod.Code:=PropInfo^.SetProc
  2198. else
  2199. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  2200. AMethod.Data:=Instance;
  2201. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2202. TSetDynArrayProcIndex(AMethod)(PropInfo^.Index,TDynArray(Value))
  2203. else
  2204. TSetDynArrayProc(AMethod)(TDynArray(Value));
  2205. end;
  2206. else
  2207. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  2208. end;
  2209. end;
  2210. { ---------------------------------------------------------------------
  2211. String properties
  2212. ---------------------------------------------------------------------}
  2213. Function GetStrProp(Instance: TObject; PropInfo: PPropInfo): AnsiString;
  2214. type
  2215. TGetShortStrProcIndex=function(index:longint):ShortString of object;
  2216. TGetShortStrProc=function():ShortString of object;
  2217. TGetAnsiStrProcIndex=function(index:longint):AnsiString of object;
  2218. TGetAnsiStrProc=function():AnsiString of object;
  2219. var
  2220. AMethod : TMethod;
  2221. begin
  2222. Result:='';
  2223. case Propinfo^.PropType^.Kind of
  2224. tkWString:
  2225. Result:=AnsiString(GetWideStrProp(Instance,PropInfo));
  2226. tkUString:
  2227. Result := AnsiString(GetUnicodeStrProp(Instance,PropInfo));
  2228. tkSString:
  2229. begin
  2230. case (PropInfo^.PropProcs) and 3 of
  2231. ptField:
  2232. Result := PShortString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  2233. ptStatic,
  2234. ptVirtual:
  2235. begin
  2236. if (PropInfo^.PropProcs and 3)=ptStatic then
  2237. AMethod.Code:=PropInfo^.GetProc
  2238. else
  2239. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  2240. AMethod.Data:=Instance;
  2241. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2242. Result:=TGetShortStrProcIndex(AMethod)(PropInfo^.Index)
  2243. else
  2244. Result:=TGetShortStrProc(AMethod)();
  2245. end;
  2246. else
  2247. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  2248. end;
  2249. end;
  2250. tkAString:
  2251. begin
  2252. case (PropInfo^.PropProcs) and 3 of
  2253. ptField:
  2254. Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  2255. ptStatic,
  2256. ptVirtual:
  2257. begin
  2258. if (PropInfo^.PropProcs and 3)=ptStatic then
  2259. AMethod.Code:=PropInfo^.GetProc
  2260. else
  2261. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  2262. AMethod.Data:=Instance;
  2263. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2264. Result:=TGetAnsiStrProcIndex(AMethod)(PropInfo^.Index)
  2265. else
  2266. Result:=TGetAnsiStrProc(AMethod)();
  2267. end;
  2268. else
  2269. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  2270. end;
  2271. end;
  2272. end;
  2273. end;
  2274. Procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo; const Value : AnsiString);
  2275. type
  2276. TSetShortStrProcIndex=procedure(index:longint;const s:ShortString) of object;
  2277. TSetShortStrProc=procedure(const s:ShortString) of object;
  2278. TSetAnsiStrProcIndex=procedure(index:longint;s:AnsiString) of object;
  2279. TSetAnsiStrProc=procedure(s:AnsiString) of object;
  2280. var
  2281. AMethod : TMethod;
  2282. begin
  2283. case Propinfo^.PropType^.Kind of
  2284. tkWString:
  2285. SetWideStrProp(Instance,PropInfo,WideString(Value));
  2286. tkUString:
  2287. SetUnicodeStrProp(Instance,PropInfo,UnicodeString(Value));
  2288. tkSString:
  2289. begin
  2290. case (PropInfo^.PropProcs shr 2) and 3 of
  2291. ptField:
  2292. PShortString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  2293. ptStatic,
  2294. ptVirtual:
  2295. begin
  2296. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  2297. AMethod.Code:=PropInfo^.SetProc
  2298. else
  2299. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  2300. AMethod.Data:=Instance;
  2301. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2302. TSetShortStrProcIndex(AMethod)(PropInfo^.Index,Value)
  2303. else
  2304. TSetShortStrProc(AMethod)(Value);
  2305. end;
  2306. else
  2307. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  2308. end;
  2309. end;
  2310. tkAString:
  2311. begin
  2312. case (PropInfo^.PropProcs shr 2) and 3 of
  2313. ptField:
  2314. PAnsiString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  2315. ptStatic,
  2316. ptVirtual:
  2317. begin
  2318. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  2319. AMethod.Code:=PropInfo^.SetProc
  2320. else
  2321. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  2322. AMethod.Data:=Instance;
  2323. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2324. TSetAnsiStrProcIndex(AMethod)(PropInfo^.Index,Value)
  2325. else
  2326. TSetAnsiStrProc(AMethod)(Value);
  2327. end;
  2328. else
  2329. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  2330. end;
  2331. end;
  2332. end;
  2333. end;
  2334. Function GetStrProp(Instance: TObject; const PropName: string): string;
  2335. begin
  2336. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  2337. end;
  2338. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  2339. begin
  2340. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  2341. end;
  2342. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  2343. begin
  2344. Result:=GetWideStrProp(Instance, FindPropInfo(Instance, PropName));
  2345. end;
  2346. procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  2347. begin
  2348. SetWideStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  2349. end;
  2350. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  2351. type
  2352. TGetWideStrProcIndex=function(index:longint):WideString of object;
  2353. TGetWideStrProc=function():WideString of object;
  2354. var
  2355. AMethod : TMethod;
  2356. begin
  2357. Result:='';
  2358. case Propinfo^.PropType^.Kind of
  2359. tkSString,tkAString:
  2360. Result:=WideString(GetStrProp(Instance,PropInfo));
  2361. tkUString :
  2362. Result := GetUnicodeStrProp(Instance,PropInfo);
  2363. tkWString:
  2364. begin
  2365. case (PropInfo^.PropProcs) and 3 of
  2366. ptField:
  2367. Result := PWideString(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  2368. ptStatic,
  2369. ptVirtual:
  2370. begin
  2371. if (PropInfo^.PropProcs and 3)=ptStatic then
  2372. AMethod.Code:=PropInfo^.GetProc
  2373. else
  2374. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  2375. AMethod.Data:=Instance;
  2376. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2377. Result:=TGetWideStrProcIndex(AMethod)(PropInfo^.Index)
  2378. else
  2379. Result:=TGetWideStrProc(AMethod)();
  2380. end;
  2381. else
  2382. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  2383. end;
  2384. end;
  2385. end;
  2386. end;
  2387. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  2388. type
  2389. TSetWideStrProcIndex=procedure(index:longint;s:WideString) of object;
  2390. TSetWideStrProc=procedure(s:WideString) of object;
  2391. var
  2392. AMethod : TMethod;
  2393. begin
  2394. case Propinfo^.PropType^.Kind of
  2395. tkSString,tkAString:
  2396. SetStrProp(Instance,PropInfo,AnsiString(Value));
  2397. tkUString:
  2398. SetUnicodeStrProp(Instance,PropInfo,Value);
  2399. tkWString:
  2400. begin
  2401. case (PropInfo^.PropProcs shr 2) and 3 of
  2402. ptField:
  2403. PWideString(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  2404. ptStatic,
  2405. ptVirtual:
  2406. begin
  2407. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  2408. AMethod.Code:=PropInfo^.SetProc
  2409. else
  2410. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  2411. AMethod.Data:=Instance;
  2412. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2413. TSetWideStrProcIndex(AMethod)(PropInfo^.Index,Value)
  2414. else
  2415. TSetWideStrProc(AMethod)(Value);
  2416. end;
  2417. else
  2418. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  2419. end;
  2420. end;
  2421. end;
  2422. end;
  2423. Function GetUnicodeStrProp(Instance: TObject; const PropName: string): UnicodeString;
  2424. begin
  2425. Result:=GetUnicodeStrProp(Instance, FindPropInfo(Instance, PropName));
  2426. end;
  2427. procedure SetUnicodeStrProp(Instance: TObject; const PropName: string; const Value: UnicodeString);
  2428. begin
  2429. SetUnicodeStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  2430. end;
  2431. Function GetUnicodeStrProp(Instance: TObject; PropInfo: PPropInfo): UnicodeString;
  2432. type
  2433. TGetUnicodeStrProcIndex=function(index:longint):UnicodeString of object;
  2434. TGetUnicodeStrProc=function():UnicodeString of object;
  2435. var
  2436. AMethod : TMethod;
  2437. begin
  2438. Result:='';
  2439. case Propinfo^.PropType^.Kind of
  2440. tkSString,tkAString:
  2441. Result:=UnicodeString(GetStrProp(Instance,PropInfo));
  2442. tkWString:
  2443. Result:=GetWideStrProp(Instance,PropInfo);
  2444. tkUString:
  2445. begin
  2446. case (PropInfo^.PropProcs) and 3 of
  2447. ptField:
  2448. Result := PUnicodeString(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  2449. ptStatic,
  2450. ptVirtual:
  2451. begin
  2452. if (PropInfo^.PropProcs and 3)=ptStatic then
  2453. AMethod.Code:=PropInfo^.GetProc
  2454. else
  2455. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  2456. AMethod.Data:=Instance;
  2457. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2458. Result:=TGetUnicodeStrProcIndex(AMethod)(PropInfo^.Index)
  2459. else
  2460. Result:=TGetUnicodeStrProc(AMethod)();
  2461. end;
  2462. else
  2463. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  2464. end;
  2465. end;
  2466. end;
  2467. end;
  2468. Procedure SetUnicodeStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: UnicodeString);
  2469. type
  2470. TSetUnicodeStrProcIndex=procedure(index:longint;s:UnicodeString) of object;
  2471. TSetUnicodeStrProc=procedure(s:UnicodeString) of object;
  2472. var
  2473. AMethod : TMethod;
  2474. begin
  2475. case Propinfo^.PropType^.Kind of
  2476. tkSString,tkAString:
  2477. SetStrProp(Instance,PropInfo,AnsiString(Value));
  2478. tkWString:
  2479. SetWideStrProp(Instance,PropInfo,Value);
  2480. tkUString:
  2481. begin
  2482. case (PropInfo^.PropProcs shr 2) and 3 of
  2483. ptField:
  2484. PUnicodeString(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  2485. ptStatic,
  2486. ptVirtual:
  2487. begin
  2488. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  2489. AMethod.Code:=PropInfo^.SetProc
  2490. else
  2491. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  2492. AMethod.Data:=Instance;
  2493. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2494. TSetUnicodeStrProcIndex(AMethod)(PropInfo^.Index,Value)
  2495. else
  2496. TSetUnicodeStrProc(AMethod)(Value);
  2497. end;
  2498. else
  2499. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  2500. end;
  2501. end;
  2502. end;
  2503. end;
  2504. function GetRawbyteStrProp(Instance: TObject; PropInfo: PPropInfo): RawByteString;
  2505. type
  2506. TGetRawByteStrProcIndex=function(index:longint): RawByteString of object;
  2507. TGetRawByteStrProc=function():RawByteString of object;
  2508. var
  2509. AMethod : TMethod;
  2510. begin
  2511. Result:='';
  2512. case Propinfo^.PropType^.Kind of
  2513. tkWString:
  2514. Result:=RawByteString(GetWideStrProp(Instance,PropInfo));
  2515. tkUString:
  2516. Result:=RawByteString(GetUnicodeStrProp(Instance,PropInfo));
  2517. tkSString:
  2518. Result:=RawByteString(GetStrProp(Instance,PropInfo));
  2519. tkAString:
  2520. begin
  2521. case (PropInfo^.PropProcs) and 3 of
  2522. ptField:
  2523. Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  2524. ptStatic,
  2525. ptVirtual:
  2526. begin
  2527. if (PropInfo^.PropProcs and 3)=ptStatic then
  2528. AMethod.Code:=PropInfo^.GetProc
  2529. else
  2530. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  2531. AMethod.Data:=Instance;
  2532. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2533. Result:=TGetRawByteStrProcIndex(AMethod)(PropInfo^.Index)
  2534. else
  2535. Result:=TGetRawByteStrProc(AMethod)();
  2536. end;
  2537. else
  2538. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  2539. end;
  2540. end;
  2541. end;
  2542. end;
  2543. function GetRawByteStrProp(Instance: TObject; const PropName: string): RawByteString;
  2544. begin
  2545. Result:=GetRawByteStrProp(Instance,FindPropInfo(Instance,PropName));
  2546. end;
  2547. procedure SetRawByteStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: RawByteString);
  2548. type
  2549. TSetRawByteStrProcIndex=procedure(index:longint;s:RawByteString) of object;
  2550. TSetRawByteStrProc=procedure(s:RawByteString) of object;
  2551. var
  2552. AMethod : TMethod;
  2553. begin
  2554. case Propinfo^.PropType^.Kind of
  2555. tkWString:
  2556. SetWideStrProp(Instance,PropInfo,WideString(Value));
  2557. tkUString:
  2558. SetUnicodeStrProp(Instance,PropInfo,UnicodeString(Value));
  2559. tkSString:
  2560. SetStrProp(Instance,PropInfo,Value); // Not 100% sure about this.
  2561. tkAString:
  2562. begin
  2563. case (PropInfo^.PropProcs shr 2) and 3 of
  2564. ptField:
  2565. PAnsiString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  2566. ptStatic,
  2567. ptVirtual:
  2568. begin
  2569. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  2570. AMethod.Code:=PropInfo^.SetProc
  2571. else
  2572. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  2573. AMethod.Data:=Instance;
  2574. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2575. TSetRawByteStrProcIndex(AMethod)(PropInfo^.Index,Value)
  2576. else
  2577. TSetRawByteStrProc(AMethod)(Value);
  2578. end;
  2579. else
  2580. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  2581. end;
  2582. end;
  2583. end;
  2584. end;
  2585. procedure SetRawByteStrProp(Instance: TObject; const PropName: string; const Value: RawByteString);
  2586. begin
  2587. SetRawByteStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  2588. end;
  2589. {$ifndef FPUNONE}
  2590. { ---------------------------------------------------------------------
  2591. Float properties
  2592. ---------------------------------------------------------------------}
  2593. function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
  2594. type
  2595. TGetExtendedProc = function:Extended of object;
  2596. TGetExtendedProcIndex = function(Index: integer): Extended of object;
  2597. TGetDoubleProc = function:Double of object;
  2598. TGetDoubleProcIndex = function(Index: integer): Double of object;
  2599. TGetSingleProc = function:Single of object;
  2600. TGetSingleProcIndex = function(Index: integer):Single of object;
  2601. TGetCurrencyProc = function : Currency of object;
  2602. TGetCurrencyProcIndex = function(Index: integer) : Currency of object;
  2603. var
  2604. AMethod : TMethod;
  2605. begin
  2606. Result:=0.0;
  2607. case PropInfo^.PropProcs and 3 of
  2608. ptField:
  2609. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  2610. ftSingle:
  2611. Result:=PSingle(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  2612. ftDouble:
  2613. Result:=PDouble(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  2614. ftExtended:
  2615. Result:=PExtended(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  2616. ftcomp:
  2617. Result:=PComp(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  2618. ftcurr:
  2619. Result:=PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  2620. end;
  2621. ptStatic,
  2622. ptVirtual:
  2623. begin
  2624. if (PropInfo^.PropProcs and 3)=ptStatic then
  2625. AMethod.Code:=PropInfo^.GetProc
  2626. else
  2627. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  2628. AMethod.Data:=Instance;
  2629. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  2630. ftSingle:
  2631. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  2632. Result:=TGetSingleProc(AMethod)()
  2633. else
  2634. Result:=TGetSingleProcIndex(AMethod)(PropInfo^.Index);
  2635. ftDouble:
  2636. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  2637. Result:=TGetDoubleProc(AMethod)()
  2638. else
  2639. Result:=TGetDoubleProcIndex(AMethod)(PropInfo^.Index);
  2640. ftExtended:
  2641. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  2642. Result:=TGetExtendedProc(AMethod)()
  2643. else
  2644. Result:=TGetExtendedProcIndex(AMethod)(PropInfo^.Index);
  2645. ftCurr:
  2646. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  2647. Result:=TGetCurrencyProc(AMethod)()
  2648. else
  2649. Result:=TGetCurrencyProcIndex(AMethod)(PropInfo^.Index);
  2650. end;
  2651. end;
  2652. else
  2653. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  2654. end;
  2655. end;
  2656. Procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo; Value : Extended);
  2657. type
  2658. TSetExtendedProc = procedure(const AValue: Extended) of object;
  2659. TSetExtendedProcIndex = procedure(Index: integer; AValue: Extended) of object;
  2660. TSetDoubleProc = procedure(const AValue: Double) of object;
  2661. TSetDoubleProcIndex = procedure(Index: integer; AValue: Double) of object;
  2662. TSetSingleProc = procedure(const AValue: Single) of object;
  2663. TSetSingleProcIndex = procedure(Index: integer; AValue: Single) of object;
  2664. TSetCurrencyProc = procedure(const AValue: Currency) of object;
  2665. TSetCurrencyProcIndex = procedure(Index: integer; AValue: Currency) of object;
  2666. Var
  2667. AMethod : TMethod;
  2668. begin
  2669. case (PropInfo^.PropProcs shr 2) and 3 of
  2670. ptfield:
  2671. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  2672. ftSingle:
  2673. PSingle(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  2674. ftDouble:
  2675. PDouble(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  2676. ftExtended:
  2677. PExtended(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  2678. {$ifdef FPC_COMP_IS_INT64}
  2679. ftComp:
  2680. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=trunc(Value);
  2681. {$else FPC_COMP_IS_INT64}
  2682. ftComp:
  2683. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Comp(Value);
  2684. {$endif FPC_COMP_IS_INT64}
  2685. ftCurr:
  2686. PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  2687. end;
  2688. ptStatic,
  2689. ptVirtual:
  2690. begin
  2691. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  2692. AMethod.Code:=PropInfo^.SetProc
  2693. else
  2694. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  2695. AMethod.Data:=Instance;
  2696. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  2697. ftSingle:
  2698. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  2699. TSetSingleProc(AMethod)(Value)
  2700. else
  2701. TSetSingleProcIndex(AMethod)(PropInfo^.Index,Value);
  2702. ftDouble:
  2703. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  2704. TSetDoubleProc(AMethod)(Value)
  2705. else
  2706. TSetDoubleProcIndex(AMethod)(PropInfo^.Index,Value);
  2707. ftExtended:
  2708. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  2709. TSetExtendedProc(AMethod)(Value)
  2710. else
  2711. TSetExtendedProcIndex(AMethod)(PropInfo^.Index,Value);
  2712. ftCurr:
  2713. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  2714. TSetCurrencyProc(AMethod)(Value)
  2715. else
  2716. TSetCurrencyProcIndex(AMethod)(PropInfo^.Index,Value);
  2717. end;
  2718. end;
  2719. else
  2720. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  2721. end;
  2722. end;
  2723. function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  2724. begin
  2725. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName))
  2726. end;
  2727. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  2728. begin
  2729. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  2730. end;
  2731. {$endif}
  2732. { ---------------------------------------------------------------------
  2733. Method properties
  2734. ---------------------------------------------------------------------}
  2735. Function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
  2736. type
  2737. TGetMethodProcIndex=function(Index: Longint): TMethod of object;
  2738. TGetMethodProc=function(): TMethod of object;
  2739. var
  2740. value: PMethod;
  2741. AMethod : TMethod;
  2742. begin
  2743. Result.Code:=nil;
  2744. Result.Data:=nil;
  2745. case (PropInfo^.PropProcs) and 3 of
  2746. ptField:
  2747. begin
  2748. Value:=PMethod(Pointer(Instance)+PtrUInt(PropInfo^.GetProc));
  2749. if Value<>nil then
  2750. Result:=Value^;
  2751. end;
  2752. ptStatic,
  2753. ptVirtual:
  2754. begin
  2755. if (PropInfo^.PropProcs and 3)=ptStatic then
  2756. AMethod.Code:=PropInfo^.GetProc
  2757. else
  2758. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  2759. AMethod.Data:=Instance;
  2760. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2761. Result:=TGetMethodProcIndex(AMethod)(PropInfo^.Index)
  2762. else
  2763. Result:=TGetMethodProc(AMethod)();
  2764. end;
  2765. else
  2766. raise EPropertyError.CreateFmt(SErrCannotReadProperty, [PropInfo^.Name]);
  2767. end;
  2768. end;
  2769. Procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo; const Value : TMethod);
  2770. type
  2771. TSetMethodProcIndex=procedure(index:longint;p:TMethod) of object;
  2772. TSetMethodProc=procedure(p:TMethod) of object;
  2773. var
  2774. AMethod : TMethod;
  2775. begin
  2776. case (PropInfo^.PropProcs shr 2) and 3 of
  2777. ptField:
  2778. PMethod(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^ := Value;
  2779. ptStatic,
  2780. ptVirtual:
  2781. begin
  2782. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  2783. AMethod.Code:=PropInfo^.SetProc
  2784. else
  2785. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  2786. AMethod.Data:=Instance;
  2787. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  2788. TSetMethodProcIndex(AMethod)(PropInfo^.Index,Value)
  2789. else
  2790. TSetMethodProc(AMethod)(Value);
  2791. end;
  2792. else
  2793. raise EPropertyError.CreateFmt(SErrCannotWriteToProperty, [PropInfo^.Name]);
  2794. end;
  2795. end;
  2796. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  2797. begin
  2798. Result:=GetMethodProp(Instance,FindPropInfo(Instance,PropName));
  2799. end;
  2800. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  2801. begin
  2802. SetMethodProp(Instance,FindPropInfo(Instance,PropName),Value);
  2803. end;
  2804. { ---------------------------------------------------------------------
  2805. Variant properties
  2806. ---------------------------------------------------------------------}
  2807. Procedure CheckVariantEvent(P : CodePointer);
  2808. begin
  2809. If (P=Nil) then
  2810. Raise Exception.Create(SErrNoVariantSupport);
  2811. end;
  2812. Function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
  2813. begin
  2814. CheckVariantEvent(CodePointer(OnGetVariantProp));
  2815. Result:=OnGetVariantProp(Instance,PropInfo);
  2816. end;
  2817. Procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo; const Value: Variant);
  2818. begin
  2819. CheckVariantEvent(CodePointer(OnSetVariantProp));
  2820. OnSetVariantProp(Instance,PropInfo,Value);
  2821. end;
  2822. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  2823. begin
  2824. Result:=GetVariantProp(Instance,FindPropInfo(Instance,PropName));
  2825. end;
  2826. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  2827. begin
  2828. SetVariantprop(instance,FindpropInfo(Instance,PropName),Value);
  2829. end;
  2830. { ---------------------------------------------------------------------
  2831. All properties through variant.
  2832. ---------------------------------------------------------------------}
  2833. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  2834. begin
  2835. Result := GetPropValue(Instance,FindPropInfo(Instance, PropName));
  2836. end;
  2837. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  2838. begin
  2839. Result := GetPropValue(Instance,FindPropInfo(Instance, PropName),PreferStrings);
  2840. end;
  2841. Function GetPropValue(Instance: TObject; PropInfo: PPropInfo): Variant;
  2842. begin
  2843. Result := GetPropValue(Instance, PropInfo, True);
  2844. end;
  2845. Function GetPropValue(Instance: TObject; PropInfo: PPropInfo; PreferStrings: Boolean): Variant;
  2846. begin
  2847. CheckVariantEvent(CodePointer(OnGetPropValue));
  2848. Result:=OnGetPropValue(Instance,PropInfo,PreferStrings);
  2849. end;
  2850. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  2851. begin
  2852. SetPropValue(Instance, FindPropInfo(Instance, PropName), Value);
  2853. end;
  2854. Procedure SetPropValue(Instance: TObject; PropInfo: PPropInfo; const Value: Variant);
  2855. begin
  2856. CheckVariantEvent(CodePointer(OnSetPropValue));
  2857. OnSetPropValue(Instance,PropInfo,Value);
  2858. end;
  2859. { ---------------------------------------------------------------------
  2860. Easy access methods that appeared in Delphi 5
  2861. ---------------------------------------------------------------------}
  2862. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  2863. begin
  2864. Result:=GetPropInfo(Instance,PropName)<>Nil;
  2865. end;
  2866. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  2867. begin
  2868. Result:=GetPropInfo(AClass,PropName)<>Nil;
  2869. end;
  2870. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  2871. begin
  2872. Result:=PropType(Instance,PropName)=TypeKind
  2873. end;
  2874. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  2875. begin
  2876. Result:=PropType(AClass,PropName)=TypeKind
  2877. end;
  2878. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  2879. begin
  2880. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind;
  2881. end;
  2882. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  2883. begin
  2884. Result:=FindPropInfo(AClass,PropName)^.PropType^.Kind;
  2885. end;
  2886. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  2887. begin
  2888. Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
  2889. end;
  2890. { TParameterLocation }
  2891. function TParameterLocation.GetReference: Boolean;
  2892. begin
  2893. Result := (LocType and $80) <> 0;
  2894. end;
  2895. function TParameterLocation.GetRegType: TRegisterType;
  2896. begin
  2897. Result := TRegisterType(LocType and $7F);
  2898. end;
  2899. function TParameterLocation.GetShiftVal: Int8;
  2900. begin
  2901. if GetReference then begin
  2902. if Offset < Low(Int8) then
  2903. Result := Low(Int8)
  2904. else if Offset > High(Int8) then
  2905. Result := High(Int8)
  2906. else
  2907. Result := Offset;
  2908. end else
  2909. Result := 0;
  2910. end;
  2911. { TParameterLocations }
  2912. function TParameterLocations.GetLocation(aIndex: Byte): PParameterLocation;
  2913. begin
  2914. if aIndex >= Count then
  2915. Result := Nil
  2916. else
  2917. Result := PParameterLocation(PByte(aligntoptr(PByte(@Count) + SizeOf(Count))) + SizeOf(TParameterLocation) * aIndex);
  2918. end;
  2919. function TParameterLocations.GetTail: Pointer;
  2920. begin
  2921. Result := PByte(aligntoptr(PByte(@Count) + SizeOf(Count))) + SizeOf(TParameterLocation) * Count;
  2922. end;
  2923. { TProcedureParam }
  2924. function TProcedureParam.GetParamType: PTypeInfo;
  2925. begin
  2926. Result := DerefTypeInfoPtr(ParamTypeRef);
  2927. end;
  2928. function TProcedureParam.GetFlags: Byte;
  2929. begin
  2930. Result := PByte(@ParamFlags)^;
  2931. end;
  2932. { TManagedField }
  2933. function TManagedField.GetTypeRef: PTypeInfo;
  2934. begin
  2935. Result := DerefTypeInfoPtr(TypeRefRef);
  2936. end;
  2937. { TArrayTypeData }
  2938. function TArrayTypeData.GetElType: PTypeInfo;
  2939. begin
  2940. Result := DerefTypeInfoPtr(ElTypeRef);
  2941. end;
  2942. function TArrayTypeData.GetDims(aIndex: Byte): PTypeInfo;
  2943. begin
  2944. Result := DerefTypeInfoPtr(DimsRef[aIndex]);
  2945. end;
  2946. { TProcedureSignature }
  2947. function TProcedureSignature.GetResultType: PTypeInfo;
  2948. begin
  2949. Result := DerefTypeInfoPtr(ResultTypeRef);
  2950. end;
  2951. function TProcedureSignature.GetParam(ParamIndex: Integer): PProcedureParam;
  2952. begin
  2953. if (ParamIndex<0)or(ParamIndex>=ParamCount) then
  2954. Exit(nil);
  2955. Result := PProcedureParam(PByte(@Flags) + SizeOf(Self));
  2956. while ParamIndex > 0 do
  2957. begin
  2958. Result := PProcedureParam(aligntoptr((PByte(@Result^.Name) + (Length(Result^.Name) + 1) * SizeOf(AnsiChar))));
  2959. dec(ParamIndex);
  2960. end;
  2961. end;
  2962. { TVmtMethodParam }
  2963. function TVmtMethodParam.GetTail: Pointer;
  2964. begin
  2965. Result := PByte(@ParaLocs) + SizeOf(ParaLocs);
  2966. end;
  2967. function TVmtMethodParam.GetNext: PVmtMethodParam;
  2968. begin
  2969. Result := PVmtMethodParam(aligntoptr(Tail));
  2970. end;
  2971. function TVmtMethodParam.GetName: ShortString;
  2972. begin
  2973. Result := NamePtr^;
  2974. end;
  2975. { TIntfMethodEntry }
  2976. function TIntfMethodEntry.GetParam(Index: Word): PVmtMethodParam;
  2977. begin
  2978. if Index >= ParamCount then
  2979. Result := Nil
  2980. else
  2981. Result := PVmtMethodParam(PByte(aligntoptr(PByte(@NamePtr) + SizeOf(NamePtr))) + Index * PtrUInt(aligntoptr(Pointer(SizeOf(TVmtMethodParam)))));
  2982. end;
  2983. function TIntfMethodEntry.GetResultLocs: PParameterLocations;
  2984. begin
  2985. if not Assigned(ResultType) then
  2986. Result := Nil
  2987. else
  2988. Result := PParameterLocations(PByte(aligntoptr(PByte(@NamePtr) + SizeOf(NamePtr))) + ParamCount * PtrUInt(aligntoptr(Pointer(SizeOf(TVmtMethodParam)))));
  2989. end;
  2990. function TIntfMethodEntry.GetTail: Pointer;
  2991. begin
  2992. Result := PByte(@NamePtr) + SizeOf(NamePtr);
  2993. if ParamCount > 0 then
  2994. Result := PByte(aligntoptr(Result)) + ParamCount * PtrUInt(aligntoptr(Pointer(SizeOf(TVmtMethodParam))));
  2995. if Assigned(ResultType) then
  2996. Result := PByte(aligntoptr(Result)) + SizeOf(PParameterLocations);
  2997. end;
  2998. function TIntfMethodEntry.GetNext: PIntfMethodEntry;
  2999. begin
  3000. Result := PIntfMethodEntry(aligntoptr(Tail));
  3001. end;
  3002. function TIntfMethodEntry.GetName: ShortString;
  3003. begin
  3004. Result := NamePtr^;
  3005. end;
  3006. { TIntfMethodTable }
  3007. function TIntfMethodTable.GetMethod(Index: Word): PIntfMethodEntry;
  3008. begin
  3009. if (RTTICount = $FFFF) or (Index >= RTTICount) then
  3010. Result := Nil
  3011. else
  3012. begin
  3013. Result := aligntoptr(PIntfMethodEntry(PByte(@RTTICount) + SizeOf(RTTICount)));
  3014. while Index > 0 do
  3015. begin
  3016. Result := Result^.Next;
  3017. Dec(Index);
  3018. end;
  3019. end;
  3020. end;
  3021. { TVmtMethodTable }
  3022. function TVmtMethodTable.GetEntry(Index: LongWord): PVmtMethodEntry;
  3023. begin
  3024. Result := PVmtMethodEntry(@Entries[0]) + Index;
  3025. end;
  3026. { TVmtFieldTable }
  3027. function TVmtFieldTable.GetField(aIndex: Word): PVmtFieldEntry;
  3028. var
  3029. c: Word;
  3030. begin
  3031. if aIndex >= Count then
  3032. Exit(Nil);
  3033. c := aIndex;
  3034. Result := @Fields;
  3035. while c > 0 do begin
  3036. Result := Result^.Next;
  3037. Dec(c);
  3038. end;
  3039. end;
  3040. { TVmtFieldEntry }
  3041. function TVmtFieldEntry.GetNext: PVmtFieldEntry;
  3042. begin
  3043. Result := aligntoptr(Tail);
  3044. end;
  3045. function TVmtFieldEntry.GetTail: Pointer;
  3046. begin
  3047. Result := PByte(@Name) + Length(Name) + SizeOf(Byte);
  3048. end;
  3049. { TInterfaceData }
  3050. function TInterfaceData.GetUnitName: ShortString;
  3051. begin
  3052. Result := UnitNameField;
  3053. end;
  3054. function TInterfaceData.GetPropertyTable: PPropData;
  3055. var
  3056. p: PByte;
  3057. begin
  3058. p := PByte(@UnitNameField[0]) + SizeOf(UnitNameField[0]) + Length(UnitNameField);
  3059. Result := AlignTypeData(p);
  3060. end;
  3061. function TInterfaceData.GetMethodTable: PIntfMethodTable;
  3062. begin
  3063. Result := aligntoptr(PropertyTable^.Tail);
  3064. end;
  3065. { TInterfaceRawData }
  3066. function TInterfaceRawData.GetUnitName: ShortString;
  3067. begin
  3068. Result := UnitNameField;
  3069. end;
  3070. function TInterfaceRawData.GetIIDStr: ShortString;
  3071. begin
  3072. Result := PShortString(AlignTypeData(PByte(@UnitNameField[0]) + SizeOf(UnitNameField[0]) + Length(UnitNameField)))^;
  3073. end;
  3074. function TInterfaceRawData.GetPropertyTable: PPropData;
  3075. var
  3076. p: PByte;
  3077. begin
  3078. p := AlignTypeData(PByte(@UnitNameField[0]) + SizeOf(UnitNameField[0]) + Length(UnitNameField));
  3079. p := p + SizeOf(p^) + p^;
  3080. Result := aligntoptr(p);
  3081. end;
  3082. function TInterfaceRawData.GetMethodTable: PIntfMethodTable;
  3083. begin
  3084. Result := aligntoptr(PropertyTable^.Tail);
  3085. end;
  3086. { TClassData }
  3087. function TClassData.GetUnitName: ShortString;
  3088. begin
  3089. Result := UnitNameField;
  3090. end;
  3091. function TClassData.GetPropertyTable: PPropData;
  3092. var
  3093. p: PByte;
  3094. begin
  3095. p := PByte(@UnitNameField[0]) + SizeOf(UnitNameField[0]) + Length(UnitNameField);
  3096. Result := AlignToPtr(p);
  3097. end;
  3098. { TTypeData }
  3099. function TTypeData.GetBaseType: PTypeInfo;
  3100. begin
  3101. Result := DerefTypeInfoPtr(BaseTypeRef);
  3102. end;
  3103. function TTypeData.GetCompType: PTypeInfo;
  3104. begin
  3105. Result := DerefTypeInfoPtr(CompTypeRef);
  3106. end;
  3107. function TTypeData.GetParentInfo: PTypeInfo;
  3108. begin
  3109. Result := DerefTypeInfoPtr(ParentInfoRef);
  3110. end;
  3111. {$ifndef VER3_0}
  3112. function TTypeData.GetRecInitData: PRecInitData;
  3113. begin
  3114. Result := PRecInitData(aligntoptr(PTypeData(RecInitInfo+2+PByte(RecInitInfo+1)^)));
  3115. end;
  3116. {$endif}
  3117. function TTypeData.GetHelperParent: PTypeInfo;
  3118. begin
  3119. Result := DerefTypeInfoPtr(HelperParentRef);
  3120. end;
  3121. function TTypeData.GetExtendedInfo: PTypeInfo;
  3122. begin
  3123. Result := DerefTypeInfoPtr(ExtendedInfoRef);
  3124. end;
  3125. function TTypeData.GetIntfParent: PTypeInfo;
  3126. begin
  3127. Result := DerefTypeInfoPtr(IntfParentRef);
  3128. end;
  3129. function TTypeData.GetRawIntfParent: PTypeInfo;
  3130. begin
  3131. Result := DerefTypeInfoPtr(RawIntfParentRef);
  3132. end;
  3133. function TTypeData.GetIIDStr: ShortString;
  3134. begin
  3135. Result := PShortString(AlignTypeData(Pointer(@RawIntfUnit) + Length(RawIntfUnit) + 1))^;
  3136. end;
  3137. function TTypeData.GetElType: PTypeInfo;
  3138. begin
  3139. Result := DerefTypeInfoPtr(elTypeRef);
  3140. end;
  3141. function TTypeData.GetElType2: PTypeInfo;
  3142. begin
  3143. Result := DerefTypeInfoPtr(elType2Ref);
  3144. end;
  3145. function TTypeData.GetInstanceType: PTypeInfo;
  3146. begin
  3147. Result := DerefTypeInfoPtr(InstanceTypeRef);
  3148. end;
  3149. function TTypeData.GetRefType: PTypeInfo;
  3150. begin
  3151. Result := DerefTypeInfoPtr(RefTypeRef);
  3152. end;
  3153. { TPropData }
  3154. function TPropData.GetProp(Index: Word): PPropInfo;
  3155. begin
  3156. if Index >= PropCount then
  3157. Result := Nil
  3158. else
  3159. begin
  3160. Result := PPropInfo(aligntoptr(PByte(@PropCount) + SizeOf(PropCount)));
  3161. while Index > 0 do
  3162. begin
  3163. Result := aligntoptr(Result^.Tail);
  3164. Dec(Index);
  3165. end;
  3166. end;
  3167. end;
  3168. function TPropData.GetTail: Pointer;
  3169. begin
  3170. if PropCount = 0 then
  3171. Result := PByte(@PropCount) + SizeOf(PropCount)
  3172. else
  3173. Result := Prop[PropCount - 1]^.Tail;
  3174. end;
  3175. { TPropInfo }
  3176. function TPropInfo.GetPropType: PTypeInfo;
  3177. begin
  3178. Result := DerefTypeInfoPtr(PropTypeRef);
  3179. end;
  3180. function TPropInfo.GetTail: Pointer;
  3181. begin
  3182. Result := PByte(@Name[0]) + SizeOf(Name[0]) + Length(Name);
  3183. end;
  3184. function TPropInfo.GetNext: PPropInfo;
  3185. begin
  3186. Result := PPropInfo(aligntoptr(Tail));
  3187. end;
  3188. type
  3189. TElementAlias = record
  3190. Ordinal : Integer;
  3191. Alias : string;
  3192. end;
  3193. TElementAliasArray = Array of TElementAlias;
  3194. PElementAliasArray = ^TElementAliasArray;
  3195. TEnumeratedAliases = record
  3196. TypeInfo: PTypeInfo;
  3197. Aliases: TElementAliasArray;
  3198. end;
  3199. TEnumeratedAliasesArray = Array of TEnumeratedAliases;
  3200. Var
  3201. EnumeratedAliases : TEnumeratedAliasesArray;
  3202. Function IndexOfEnumeratedAliases(aTypeInfo : PTypeInfo) : integer;
  3203. begin
  3204. Result:=High(EnumeratedAliases);
  3205. while (Result>=0) and (EnumeratedAliases[Result].TypeInfo<>aTypeInfo) do
  3206. Dec(Result);
  3207. end;
  3208. Function GetEnumeratedAliases(aTypeInfo : PTypeInfo) : PElementAliasArray;
  3209. Var
  3210. I : integer;
  3211. begin
  3212. I:=IndexOfEnumeratedAliases(aTypeInfo);
  3213. if I=-1 then
  3214. Result:=Nil
  3215. else
  3216. Result:=@EnumeratedAliases[i].Aliases
  3217. end;
  3218. Function AddEnumeratedAliases(aTypeInfo : PTypeInfo) : PElementAliasArray;
  3219. Var
  3220. L : Integer;
  3221. begin
  3222. L:=Length(EnumeratedAliases);
  3223. SetLength(EnumeratedAliases,L+1);
  3224. EnumeratedAliases[L].TypeInfo:=aTypeInfo;
  3225. Result:=@EnumeratedAliases[L].Aliases;
  3226. end;
  3227. procedure RemoveEnumElementAliases(aTypeInfo: PTypeInfo);
  3228. Var
  3229. I,L : integer;
  3230. A : TEnumeratedAliases;
  3231. begin
  3232. I:=IndexOfEnumeratedAliases(aTypeInfo);
  3233. if I=-1 then
  3234. exit;
  3235. A:=EnumeratedAliases[i];
  3236. A.Aliases:=Nil;
  3237. A.TypeInfo:=Nil;
  3238. L:=High(EnumeratedAliases);
  3239. EnumeratedAliases[i]:=EnumeratedAliases[L];
  3240. EnumeratedAliases[L]:=A;
  3241. SetLength(EnumeratedAliases,L);
  3242. end;
  3243. Resourcestring
  3244. SErrNotAnEnumerated = 'Type information points to non-enumerated type';
  3245. SErrInvalidEnumeratedCount = 'Invalid number of enumerated values';
  3246. SErrDuplicateEnumerated = 'Duplicate alias for enumerated value';
  3247. procedure AddEnumElementAliases(aTypeInfo: PTypeInfo; const aNames: array of string; aStartValue: Integer = 0);
  3248. var
  3249. Aliases: PElementAliasArray;
  3250. A : TElementAliasArray;
  3251. L, I, J : Integer;
  3252. N : String;
  3253. PT : PTypeData;
  3254. begin
  3255. if (aTypeInfo^.Kind<>tkEnumeration) then
  3256. raise EArgumentException.Create(SErrNotAnEnumerated);
  3257. PT:=GetTypeData(aTypeInfo);
  3258. if (High(aNames)=-1) or ((aStartValue+High(aNames))> PT^.MaxValue) then
  3259. raise EArgumentException.Create(SErrInvalidEnumeratedCount);
  3260. Aliases:=GetEnumeratedAliases(aTypeInfo);
  3261. if (Aliases=Nil) then
  3262. Aliases:=AddEnumeratedAliases(aTypeInfo);
  3263. A:=Aliases^;
  3264. I:=0;
  3265. L:=Length(a);
  3266. SetLength(a,L+High(aNames)+1);
  3267. try
  3268. for N in aNames do
  3269. begin
  3270. for J:=0 to (L+I)-1 do
  3271. if SameText(N,A[J].Alias) then
  3272. raise EArgumentException.Create(SErrDuplicateEnumerated);
  3273. with A[L+I] do
  3274. begin
  3275. Ordinal:=aStartValue+I;
  3276. alias:=N;
  3277. end;
  3278. Inc(I);
  3279. end;
  3280. finally
  3281. // In case of exception, we need to correct the length.
  3282. if Length(A)<>I+L then
  3283. SetLength(A,I+L);
  3284. Aliases^:=A;
  3285. end;
  3286. end;
  3287. function GetEnumeratedAliasValue(aTypeInfo: PTypeInfo; const aName: string): Integer;
  3288. var
  3289. I : Integer;
  3290. Aliases: PElementAliasArray;
  3291. begin
  3292. Result:=-1;
  3293. Aliases:=GetEnumeratedAliases(aTypeInfo);
  3294. if (Aliases=Nil) then
  3295. Exit;
  3296. I:=High(Aliases^);
  3297. While (Result=-1) and (I>=0) do
  3298. begin
  3299. if SameText(Aliases^[I].Alias, aName) then
  3300. Result:=Aliases^[I].Ordinal;
  3301. Dec(I);
  3302. end;
  3303. end;
  3304. {$IFDEF HAVE_INVOKEHELPER}
  3305. procedure CallInvokeHelper(Instance: Pointer; aMethod : PIntfMethodEntry; aArgs : PPointer);
  3306. begin
  3307. if (aMethod=Nil) then
  3308. Raise EArgumentNilException.Create('Cannot call invoke helper on nil method info');
  3309. if (aMethod^.InvokeHelper=Nil) then
  3310. Raise EArgumentException.CreateFmt('Method %s has no invoke helper.',[aMethod^.Name]);
  3311. aMethod^.InvokeHelper(Instance,aArgs);
  3312. end;
  3313. procedure CallInvokeHelper(aTypeInfo : PTypeInfo; Instance: Pointer; const aMethod : String; aArgs : PPointer);
  3314. Var
  3315. Data : PInterfaceData;
  3316. DataR : PInterfaceRawData;
  3317. MethodTable : PIntfMethodTable;
  3318. MethodEntry : PIntfMethodEntry;
  3319. I : Integer;
  3320. begin
  3321. If Instance=Nil then
  3322. Raise EArgumentNilException.Create('Cannot call invoke helper on nil instance');
  3323. if not (aTypeInfo^.Kind in [tkInterface,tkInterfaceRaw]) then
  3324. Raise EArgumentException.Create('Cannot call invoke helper non non-interfaces');
  3325. // Get method table
  3326. if (aTypeInfo^.Kind=tkInterface) then
  3327. begin
  3328. Data:=PInterfaceData(GetTypeData(aTypeInfo));
  3329. MethodTable:=Data^.MethodTable;
  3330. end
  3331. else
  3332. begin
  3333. DataR:=PInterfaceRawData(GetTypeData(aTypeInfo));
  3334. MethodTable:=DataR^.MethodTable;
  3335. end;
  3336. // Search method in method table
  3337. MethodEntry:=nil;
  3338. I:=MethodTable^.Count-1;
  3339. While (MethodEntry=Nil) and (I>=0) do
  3340. begin
  3341. MethodEntry:=MethodTable^.Method[i];
  3342. if not SameText(MethodEntry^.Name,aMethod) then
  3343. MethodEntry:=Nil;
  3344. Dec(I);
  3345. end;
  3346. if MethodEntry=Nil then
  3347. Raise EArgumentException.CreateFmt('Interface %s has no method %s.',[aTypeInfo^.Name,aMethod]);
  3348. CallInvokeHelper(Instance,MethodEntry,aArgs);
  3349. end;
  3350. {$ENDIF HAVE_INVOKEHELPER}
  3351. end.