rtti.pp 217 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (C) 2013 Joost van der Sluis [email protected]
  4. member of the Free Pascal development team.
  5. Extended RTTI compatibility unit
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. }
  12. {$IFNDEF FPC_DOTTEDUNITS}
  13. unit Rtti;
  14. {$ENDIF}
  15. {$mode objfpc}{$H+}
  16. {$modeswitch advancedrecords}
  17. {$goto on}
  18. {$Assertions on}
  19. { Note: since the Lazarus IDE is not yet capable of correctly handling generic
  20. functions it is best to define a InLazIDE define inside the IDE that disables
  21. the generic code for CodeTools. To do this do this:
  22. - go to Tools -> Codetools Defines Editor
  23. - go to Edit -> Insert Node Below -> Define Recurse
  24. - enter the following values:
  25. Name: InLazIDE
  26. Description: Define InLazIDE everywhere
  27. Variable: InLazIDE
  28. Value from text: 1
  29. }
  30. {$ifdef InLazIDE}
  31. {$define NoGenericMethods}
  32. {$endif}
  33. {$WARN 4055 off : Conversion between ordinals and pointers is not portable}
  34. interface
  35. {$IFDEF FPC_DOTTEDUNITS}
  36. uses
  37. System.Types,
  38. System.Classes,
  39. System.SysUtils,
  40. System.TypInfo;
  41. {$ELSE FPC_DOTTEDUNITS}
  42. uses
  43. Types,
  44. Classes,
  45. SysUtils,
  46. typinfo;
  47. {$ENDIF FPC_DOTTEDUNITS}
  48. Const
  49. {$IFDEF FPC_DOTTEDUNITS}
  50. DefaultUsePublishedOnly = False;
  51. {$ELSE}
  52. DefaultUsePublishedOnly = True;
  53. {$ENDIF}
  54. Var
  55. GlobalUsePublishedOnly : Boolean = DefaultUsePublishedOnly;
  56. type
  57. TRttiObject = class;
  58. TRttiType = class;
  59. TRttiMethod = class;
  60. TRttiIndexedProperty = class;
  61. TRttiField = Class;
  62. TRttiProperty = class;
  63. TRttiInstanceType = class;
  64. TRttiRecordType = class;
  65. TCustomAttributeClass = class of TCustomAttribute;
  66. TRttiClass = class of TRttiObject;
  67. TCustomAttributeArray = specialize TArray<TCustomAttribute>;
  68. TFunctionCallCallback = class
  69. protected
  70. function GetCodeAddress: CodePointer; virtual; abstract;
  71. public
  72. property CodeAddress: CodePointer read GetCodeAddress;
  73. end;
  74. TFunctionCallFlag = (
  75. fcfStatic
  76. );
  77. TFunctionCallFlags = set of TFunctionCallFlag;
  78. TFunctionCallParameterInfo = record
  79. ParamType: PTypeInfo;
  80. ParamFlags: TParamFlags;
  81. ParaLocs: PParameterLocations;
  82. end;
  83. IValueData = interface
  84. ['{1338B2F3-2C21-4798-A641-CA2BC5BF2396}']
  85. procedure ExtractRawData(ABuffer: pointer);
  86. procedure ExtractRawDataNoCopy(ABuffer: pointer);
  87. function GetDataSize: SizeInt;
  88. function GetReferenceToRawData: pointer;
  89. end;
  90. TValueData = record
  91. FTypeInfo: PTypeInfo;
  92. FValueData: IValueData;
  93. case integer of
  94. 0: (FAsUByte: Byte);
  95. 1: (FAsUWord: Word);
  96. 2: (FAsULong: LongWord);
  97. 3: (FAsObject: Pointer);
  98. 4: (FAsClass: TClass);
  99. 5: (FAsSByte: Shortint);
  100. 6: (FAsSWord: Smallint);
  101. 7: (FAsSLong: LongInt);
  102. 8: (FAsSingle: Single);
  103. 9: (FAsDouble: Double);
  104. 10: (FAsExtended: Extended);
  105. 11: (FAsComp: Comp);
  106. 12: (FAsCurr: Currency);
  107. 13: (FAsUInt64: QWord);
  108. 14: (FAsSInt64: Int64);
  109. 15: (FAsMethod: TMethod);
  110. 16: (FAsPointer: Pointer);
  111. { FPC addition for open arrays }
  112. 17: (FArrLength: SizeInt; FElSize: SizeInt);
  113. end;
  114. { TValue }
  115. TValue = record
  116. private
  117. FData: TValueData;
  118. function GetDataSize: SizeInt;
  119. function GetTypeDataProp: PTypeData; inline;
  120. function GetTypeInfo: PTypeInfo; inline;
  121. function GetTypeKind: TTypeKind; // inline;
  122. function GetIsEmpty: boolean; inline;
  123. procedure Init; inline;
  124. // typecast
  125. procedure CastAssign(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  126. procedure CastToVariant(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  127. // from integer
  128. procedure CastIntegerToFloat(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  129. procedure CastIntegerToInteger(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  130. procedure CastIntegerToInt64(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  131. procedure CastIntegerToQWord(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  132. procedure CastFromInteger(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  133. // from Ansichar
  134. procedure CastCharToString(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  135. procedure CastFromAnsiChar(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  136. // From WideChar
  137. procedure CastWCharToString(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  138. procedure CastFromWideChar(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  139. // From Enumerated
  140. procedure CastEnumToEnum(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  141. procedure CastFromEnum(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  142. // From float
  143. procedure CastFloatToFloat(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  144. procedure CastFloatToInteger(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  145. procedure CastFromFloat(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  146. // From string
  147. procedure CastStringToString(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  148. procedure CastFromString(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  149. // From class
  150. procedure CastClassRefToClassRef(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  151. procedure CastClassToClass(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  152. procedure CastClassToInterface(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  153. procedure CastFromClass(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  154. // From Int64
  155. procedure CastInt64ToFloat(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  156. procedure CastInt64ToQWord(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  157. procedure CastInt64ToInteger(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  158. procedure CastFromInt64(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  159. // From QWord
  160. procedure CastQWordToFloat(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  161. procedure CastQWordToInteger(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  162. procedure CastQWordToInt64(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  163. procedure CastFromQWord(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  164. // From Interface
  165. procedure CastInterfaceToInterface(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  166. procedure CastFromInterface(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  167. // From Pointer
  168. procedure CastFromPointer(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  169. // From set
  170. procedure CastSetToSet(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  171. procedure CastFromSet(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  172. // From variant
  173. procedure CastVariantToVariant(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  174. procedure CastFromVariant(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  175. procedure DoCastFromVariant(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  176. // Cast entry
  177. procedure CastFromType(out aRes: Boolean; out ADest: TValue; aDestType: PTypeInfo);
  178. public
  179. class function Empty: TValue; static;
  180. class procedure Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue); static;
  181. class procedure Make(AValue: NativeInt; ATypeInfo: PTypeInfo; out Result: TValue); static; inline;
  182. { Note: a TValue based on an open array is only valid until the routine having the open array parameter is left! }
  183. class procedure MakeOpenArray(AArray: Pointer; ALength: SizeInt; ATypeInfo: PTypeInfo; out Result: TValue); static;
  184. {$ifndef NoGenericMethods}
  185. generic class procedure Make<T>(const AValue: T; out Result: TValue); static; inline;
  186. generic class function From<T>(constref aValue: T): TValue; static; inline;
  187. { Note: a TValue based on an open array is only valid until the routine having the open array parameter is left! }
  188. generic class function FromOpenArray<T>(constref aValue: array of T): TValue; static; inline;
  189. {$endif}
  190. class function FromOrdinal(aTypeInfo: PTypeInfo; aValue: Int64): TValue; static; {inline;}
  191. class function FromArray(aArrayTypeInfo: PTypeInfo; const aValues: array of TValue): TValue; static;
  192. class function FromVarRec(const aValue: TVarRec): TValue; static;
  193. class function FromVariant(const aValue : Variant) : TValue; static;
  194. function IsArray: boolean; inline;
  195. function IsOpenArray: Boolean; inline;
  196. // Maybe we need to check these now that Cast<> is implemented.
  197. // OTOH they will probablu be faster.
  198. function AsString: string; inline;
  199. function AsUnicodeString: UnicodeString;
  200. function AsAnsiString: AnsiString;
  201. function AsExtended: Extended;
  202. function IsClass: boolean; inline;
  203. function AsClass: TClass;
  204. function IsObject: boolean; inline;
  205. function AsObject: TObject;
  206. function IsOrdinal: boolean; inline;
  207. function AsOrdinal: Int64;
  208. function AsBoolean: boolean;
  209. function AsCurrency: Currency;
  210. function AsSingle : Single;
  211. function AsDateTime : TDateTime;
  212. function IsDateTime: boolean; inline;
  213. function AsDouble : Double;
  214. function AsInteger: Integer;
  215. function AsError: HRESULT;
  216. function AsChar: AnsiChar; inline;
  217. function AsAnsiChar: AnsiChar;
  218. function AsWideChar: WideChar;
  219. function AsInt64: Int64;
  220. function AsUInt64: QWord;
  221. function AsInterface: IInterface;
  222. function AsPointer : Pointer;
  223. function AsVariant : Variant;
  224. function ToString: String;
  225. function GetArrayLength: SizeInt;
  226. function GetArrayElement(AIndex: SizeInt): TValue;
  227. procedure SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
  228. function IsType(aTypeInfo: PTypeInfo): boolean; inline;
  229. function IsInstanceOf(aClass : TClass): boolean; inline;
  230. function TryCast(aTypeInfo: PTypeInfo; out aResult: TValue; const aEmptyAsAnyType: Boolean = True): Boolean;
  231. function Cast(aTypeInfo: PTypeInfo; const aEmptyAsAnyType: Boolean = True): TValue; overload;
  232. {$ifndef NoGenericMethods}
  233. generic function Cast<T>(const aEmptyAsAnyType: Boolean = True): TValue; overload;
  234. generic function IsType<T>: Boolean; inline;
  235. generic function AsType<T>(const aEmptyAsAnyType: Boolean = True): T;
  236. generic function TryAsType<T>(out aResult: T; const aEmptyAsAnyType: Boolean = True): Boolean; inline;
  237. {$endif}
  238. function TryAsOrdinal(out AResult: int64): boolean;
  239. function GetReferenceToRawData: Pointer;
  240. procedure ExtractRawData(ABuffer: Pointer);
  241. procedure ExtractRawDataNoCopy(ABuffer: Pointer);
  242. class operator := (const AValue: ShortString): TValue; inline;
  243. class operator := (const AValue: AnsiString): TValue; inline;
  244. class operator := (const AValue: UnicodeString): TValue; inline;
  245. class operator := (const AValue: WideString): TValue; inline;
  246. class operator := (AValue: LongInt): TValue; inline;
  247. class operator := (AValue: SmallInt): TValue; inline;
  248. class operator := (AValue: ShortInt): TValue; inline;
  249. class operator := (AValue: Byte): TValue; inline;
  250. class operator := (AValue: Word): TValue; inline;
  251. class operator := (AValue: Cardinal): TValue; inline;
  252. class operator := (AValue: Single): TValue; inline;
  253. class operator := (AValue: Double): TValue; inline;
  254. {$ifdef FPC_HAS_TYPE_EXTENDED}
  255. class operator := (AValue: Extended): TValue; inline;
  256. {$endif}
  257. class operator := (AValue: Currency): TValue; inline;
  258. class operator := (AValue: Comp): TValue; inline;
  259. class operator := (AValue: Int64): TValue; inline;
  260. class operator := (AValue: QWord): TValue; inline;
  261. class operator := (AValue: TObject): TValue; inline;
  262. class operator := (AValue: TClass): TValue; inline;
  263. class operator := (AValue: Boolean): TValue; inline;
  264. class operator := (AValue: IUnknown): TValue; inline;
  265. class operator := (AValue: TVarRec): TValue; inline;
  266. property DataSize: SizeInt read GetDataSize;
  267. property Kind: TTypeKind read GetTypeKind;
  268. property TypeData: PTypeData read GetTypeDataProp;
  269. property TypeInfo: PTypeInfo read GetTypeInfo;
  270. property IsEmpty: boolean read GetIsEmpty;
  271. end;
  272. PValue = ^TValue;
  273. TValueArray = specialize TArray<TValue>;
  274. { TRttiContext }
  275. TRttiContext = record
  276. strict private
  277. class var FKeptContexts: array[Boolean] of IUnknown;
  278. Public
  279. UsePublishedOnly : Boolean;
  280. private
  281. FContextToken: IInterface;
  282. function GetByHandle(AHandle: Pointer): TRttiObject;
  283. procedure AddObject(AObject: TRttiObject);
  284. public
  285. class function Create: TRttiContext; static;
  286. class function Create(aUsePublishedOnly : Boolean): TRttiContext; static;
  287. class procedure DropContext; static;
  288. class procedure KeepContext; static;
  289. procedure Free;
  290. function GetType(ATypeInfo: PTypeInfo): TRttiType;
  291. function GetType(AClass: TClass): TRttiType;
  292. //function GetTypes: specialize TArray<TRttiType>;
  293. end;
  294. { TRttiObject }
  295. TRttiObject = class abstract
  296. Private
  297. FUsePublishedOnly : Boolean;
  298. protected
  299. function GetHandle: Pointer; virtual; abstract;
  300. public
  301. function HasAttribute(aClass: TCustomAttributeClass): Boolean;
  302. function GetAttribute(aClass: TCustomAttributeClass): TCustomAttribute;
  303. generic function GetAttribute<T>: T;
  304. generic function HasAttribute<T>: Boolean;
  305. function GetAttributes: TCustomAttributeArray; virtual; abstract;
  306. property Handle: Pointer read GetHandle;
  307. end;
  308. { TRttiNamedObject }
  309. TRttiNamedObject = class(TRttiObject)
  310. protected
  311. function GetName: string; virtual;
  312. public
  313. function HasName(const aName: string): Boolean;
  314. property Name: string read GetName;
  315. end;
  316. { TRttiType }
  317. TRttiFieldArray = specialize TArray<TRttiField>;
  318. TRttiPropertyArray = specialize TArray<TRttiProperty>;
  319. TRttiMethodArray = specialize TArray<TRttiMethod>;
  320. TRttiIndexedPropertyArray = specialize TArray<TRttiIndexedProperty>;
  321. TRttiType = class(TRttiNamedObject)
  322. private
  323. FTypeInfo: PTypeInfo;
  324. FAttributesResolved: boolean;
  325. FAttributes: TCustomAttributeArray;
  326. FMethods: TRttiMethodArray;
  327. FFields : TRttiFieldArray;
  328. FProperties : TRttiPropertyArray;
  329. FIndexedProperties : TRttiIndexedPropertyArray;
  330. function GetAsInstance: TRttiInstanceType;
  331. protected
  332. FTypeData: PTypeData;
  333. function GetName: string; override;
  334. function GetHandle: Pointer; override;
  335. function GetIsInstance: boolean; virtual;
  336. function GetIsManaged: boolean; virtual;
  337. function GetIsOrdinal: boolean; virtual;
  338. function GetIsRecord: boolean; virtual;
  339. function GetIsSet: boolean; virtual;
  340. function GetTypeKind: TTypeKind; virtual;
  341. function GetTypeSize: integer; virtual;
  342. function GetBaseType: TRttiType; virtual;
  343. public
  344. constructor Create(ATypeInfo : PTypeInfo);
  345. constructor Create(ATypeInfo : PTypeInfo; aUsePublishedOnly : Boolean);
  346. destructor Destroy; override;
  347. function GetAttributes: TCustomAttributeArray; override;
  348. function GetFields: TRttiFieldArray; virtual;
  349. function GetField(const aName: String): TRttiField; virtual;
  350. function GetDeclaredMethods: TRttiMethodArray; virtual;
  351. function GetDeclaredFields: TRttiFieldArray; virtual;
  352. function GetDeclaredProperties: TRttiPropertyArray; virtual;
  353. function GetDeclaredIndexedProperties: TRttiIndexedPropertyArray; virtual;
  354. function GetProperty(const AName: string): TRttiProperty; virtual;
  355. function GetProperties: TRttiPropertyArray; virtual;
  356. function GetIndexedProperty(const AName: string): TRttiIndexedProperty; virtual;
  357. function GetIndexedProperties: TRttiIndexedPropertyArray; virtual;
  358. function GetMethods: TRttiMethodArray; virtual; overload;
  359. function GetMethods(const aName: string): TRttiMethodArray; overload; virtual;
  360. function GetMethod(const aName: String): TRttiMethod; virtual;
  361. property IsInstance: boolean read GetIsInstance;
  362. property IsManaged: boolean read GetIsManaged;
  363. property IsOrdinal: boolean read GetIsOrdinal;
  364. property IsRecord: boolean read GetIsRecord;
  365. property IsSet: boolean read GetIsSet;
  366. property BaseType: TRttiType read GetBaseType;
  367. property Handle: PTypeInfo read FTypeInfo;
  368. property AsInstance: TRttiInstanceType read GetAsInstance;
  369. property TypeKind: TTypeKind read GetTypeKind;
  370. property TypeSize: integer read GetTypeSize;
  371. end;
  372. { TRttiFloatType }
  373. TRttiFloatType = class(TRttiType)
  374. private
  375. function GetFloatType: TFloatType; inline;
  376. protected
  377. function GetTypeSize: integer; override;
  378. public
  379. property FloatType: TFloatType read GetFloatType;
  380. end;
  381. TRttiOrdinalType = class(TRttiType)
  382. private
  383. function GetMaxValue: LongInt; inline;
  384. function GetMinValue: LongInt; inline;
  385. function GetOrdType: TOrdType; inline;
  386. protected
  387. function GetTypeSize: Integer; override;
  388. public
  389. property OrdType: TOrdType read GetOrdType;
  390. property MinValue: LongInt read GetMinValue;
  391. property MaxValue: LongInt read GetMaxValue;
  392. end;
  393. { TRttiEnumerationType }
  394. TRttiEnumerationType = class(TRttiOrdinalType)
  395. private
  396. function GetUnderlyingType: TRttiType;
  397. public
  398. function GetNames: TStringDynArray;
  399. generic class function GetName<T{: enum}>(AValue: T): string; reintroduce; static;
  400. generic class function GetValue<T{: enum}>(const AName: string): T; static;
  401. property UnderlyingType: TRttiType read GetUnderlyingType;
  402. end;
  403. TRttiInt64Type = class(TRttiType)
  404. private
  405. function GetMaxValue: Int64; inline;
  406. function GetMinValue: Int64; inline;
  407. function GetUnsigned: Boolean; inline;
  408. protected
  409. function GetTypeSize: integer; override;
  410. public
  411. property MinValue: Int64 read GetMinValue;
  412. property MaxValue: Int64 read GetMaxValue;
  413. property Unsigned: Boolean read GetUnsigned;
  414. end;
  415. TRttiStringKind = (skShortString, skAnsiString, skWideString, skUnicodeString);
  416. { TRttiStringType }
  417. TRttiStringType = class(TRttiType)
  418. private
  419. function GetStringKind: TRttiStringKind;
  420. public
  421. property StringKind: TRttiStringKind read GetStringKind;
  422. end;
  423. TRttiAnsiStringType = class(TRttiStringType)
  424. private
  425. function GetCodePage: Word;
  426. public
  427. property CodePage: Word read GetCodePage;
  428. end;
  429. TRttiPointerType = class(TRttiType)
  430. private
  431. function GetReferredType: TRttiType;
  432. public
  433. property ReferredType: TRttiType read GetReferredType;
  434. end;
  435. TRttiArrayType = class(TRttiType)
  436. private
  437. function GetDimensionCount: SizeUInt; inline;
  438. function GetDimension(aIndex: SizeInt): TRttiType; inline;
  439. function GetElementType: TRttiType; inline;
  440. function GetTotalElementCount: SizeInt; inline;
  441. public
  442. property DimensionCount: SizeUInt read GetDimensionCount;
  443. property Dimensions[Index: SizeInt]: TRttiType read GetDimension;
  444. property ElementType: TRttiType read GetElementType;
  445. property TotalElementCount: SizeInt read GetTotalElementCount;
  446. end;
  447. TRttiDynamicArrayType = class(TRttiType)
  448. private
  449. function GetDeclaringUnitName: String; inline;
  450. function GetElementSize: SizeUInt; inline;
  451. function GetElementType: TRttiType; inline;
  452. function GetOleAutoVarType: TVarType; inline;
  453. public
  454. property DeclaringUnitName: String read GetDeclaringUnitName;
  455. property ElementSize: SizeUInt read GetElementSize;
  456. property ElementType: TRttiType read GetElementType;
  457. property OleAutoVarType: TVarType read GetOleAutoVarType;
  458. end;
  459. { TRttiMember }
  460. TMemberVisibility=(mvPrivate, mvProtected, mvPublic, mvPublished);
  461. TRttiMember = class(TRttiNamedObject)
  462. private
  463. FParent: TRttiType;
  464. FVisibility : TMemberVisibility;
  465. FStrictVisibility : Boolean;
  466. function GetVisibility: TMemberVisibility; virtual;
  467. function GetStrictVisibility: Boolean; virtual;
  468. public
  469. constructor Create(AParent: TRttiType);
  470. property Visibility: TMemberVisibility read GetVisibility;
  471. Property StrictVisibility: Boolean Read GetStrictVisibility;
  472. property Parent: TRttiType read FParent;
  473. end;
  474. TRttiDataMember = class abstract(TRttiMember)
  475. private
  476. function GetDataType: TRttiType; virtual; abstract;
  477. function GetIsReadable: Boolean; virtual; abstract;
  478. function GetIsWritable: Boolean; virtual; abstract;
  479. public
  480. function GetValue(Instance: Pointer): TValue; virtual; abstract;
  481. procedure SetValue(Instance: Pointer; const AValue: TValue); virtual; abstract;
  482. property DataType: TRttiType read GetDataType;
  483. property IsReadable: Boolean read GetIsReadable;
  484. property IsWritable: Boolean read GetIsWritable;
  485. end;
  486. { TRttiProperty }
  487. TRttiProperty = class(TRttiDataMember)
  488. private
  489. FPropInfo: PPropInfo;
  490. FAttributesResolved: boolean;
  491. FAttributes: TCustomAttributeArray;
  492. function GetPropertyType: TRttiType;
  493. function GetIsWritable: boolean; override;
  494. function GetIsReadable: boolean; override;
  495. function GetDataType: TRttiType; override;
  496. protected
  497. function GetName: string; override;
  498. function GetHandle: Pointer; override;
  499. public
  500. constructor Create(AParent: TRttiType; APropInfo: PPropInfo);
  501. destructor Destroy; override;
  502. function GetAttributes: TCustomAttributeArray; override;
  503. function GetValue(Instance: pointer): TValue; override;
  504. procedure SetValue(Instance: pointer; const AValue: TValue); override;
  505. function ToString: String; override;
  506. property PropertyType: TRttiType read GetPropertyType;
  507. property IsReadable: boolean read GetIsReadable;
  508. property IsWritable: boolean read GetIsWritable;
  509. end;
  510. { TRttiField }
  511. TRttiField = class(TRttiDataMember)
  512. private
  513. FFieldType: TRttiType;
  514. FOffset: Integer;
  515. FName : String;
  516. FHandle : PExtendedFieldEntry;
  517. FAttributes: TCustomAttributeArray;
  518. FAttributesResolved : Boolean;
  519. function GetName: string; override;
  520. function GetDataType: TRttiType; override;
  521. function GetIsReadable: Boolean; override;
  522. function GetIsWritable: Boolean; override;
  523. function GetHandle: Pointer; override;
  524. Function GetAttributes: TCustomAttributeArray; override;
  525. procedure ResolveAttributes;
  526. // constructor Create(AParent: TRttiObject; var P: PByte); override;
  527. public
  528. destructor destroy; override;
  529. function GetValue(aInstance: Pointer): TValue; override;
  530. procedure SetValue(aInstance: Pointer; const aValue: TValue); override;
  531. function ToString: string; override;
  532. property FieldType: TRttiType read FFieldType;
  533. property Offset: Integer read FOffset;
  534. end;
  535. (*
  536. TRttiManagedField = class(TRttiObject)
  537. private
  538. function GetFieldOffset: Integer;
  539. function GetDataType: TRttiType;
  540. // constructor Create(AParent: TRttiObject; var P: PByte); override;
  541. public
  542. property FieldType: TRttiType read GetDataType;
  543. property FieldOffset: Integer read GetFieldOffset;
  544. end;
  545. *)
  546. TRttiParameter = class(TRttiNamedObject)
  547. private
  548. FString: String;
  549. protected
  550. function GetParamType: TRttiType; virtual; abstract;
  551. function GetFlags: TParamFlags; virtual; abstract;
  552. public
  553. property ParamType: TRttiType read GetParamType;
  554. property Flags: TParamFlags read GetFlags;
  555. function ToString: String; override;
  556. end;
  557. TRttiParameterArray = specialize TArray<TRttiParameter>;
  558. TMethodImplementationCallbackMethod = procedure(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue) of object;
  559. TMethodImplementationCallbackProc = procedure(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue);
  560. TFunctionCallParameterInfoArray = specialize TArray<TFunctionCallParameterInfo>;
  561. TPointerArray = specialize TArray<Pointer>;
  562. TMethodImplementation = class
  563. private
  564. fLowLevelCallback: TFunctionCallCallback;
  565. fCallbackProc: TMethodImplementationCallbackProc;
  566. fCallbackMethod: TMethodImplementationCallbackMethod;
  567. fArgs: specialize TArray<TFunctionCallParameterInfo>;
  568. fArgLen: SizeInt;
  569. fRefArgs: specialize TArray<SizeInt>;
  570. fFlags: TFunctionCallFlags;
  571. fResult: PTypeInfo;
  572. fCC: TCallConv;
  573. procedure InitArgs;
  574. procedure HandleCallback(const aArgs: TPointerArray; aResult: Pointer; aContext: Pointer);
  575. constructor Create(aCC: TCallConv; aArgs: TFunctionCallParameterInfoArray; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod);
  576. constructor Create(aCC: TCallConv; aArgs: TFunctionCallParameterInfoArray; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackProc);
  577. Protected
  578. function GetCodeAddress: CodePointer; inline;
  579. public
  580. constructor Create;
  581. destructor Destroy; override;
  582. property CodeAddress: CodePointer read GetCodeAddress;
  583. end;
  584. TRttiInvokableType = class(TRttiType)
  585. protected
  586. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; virtual; abstract;
  587. function GetCallingConvention: TCallConv; virtual; abstract;
  588. function GetReturnType: TRttiType; virtual; abstract;
  589. function GetFlags: TFunctionCallFlags; virtual; abstract;
  590. public type
  591. TCallbackMethod = procedure(aInvokable: TRttiInvokableType; const aArgs: TValueArray; out aResult: TValue) of object;
  592. TCallbackProc = procedure(aInvokable: TRttiInvokableType; const aArgs: TValueArray; out aResult: TValue);
  593. public
  594. function GetParameters: TRttiParameterArray; inline;
  595. property CallingConvention: TCallConv read GetCallingConvention;
  596. property ReturnType: TRttiType read GetReturnType;
  597. function Invoke(const aProcOrMeth: TValue; const aArgs: array of TValue): TValue; virtual; abstract;
  598. { Note: once "reference to" is supported these will be replaced by a single method }
  599. function CreateImplementation(aCallback: TCallbackMethod): TMethodImplementation;
  600. function CreateImplementation(aCallback: TCallbackProc): TMethodImplementation;
  601. function ToString : string; override;
  602. end;
  603. TRttiMethodType = class(TRttiInvokableType)
  604. private
  605. FCallConv: TCallConv;
  606. FReturnType: TRttiType;
  607. FParams, FParamsAll: TRttiParameterArray;
  608. protected
  609. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; override;
  610. function GetCallingConvention: TCallConv; override;
  611. function GetReturnType: TRttiType; override;
  612. function GetFlags: TFunctionCallFlags; override;
  613. public
  614. function Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue; override;
  615. function ToString: string; override;
  616. end;
  617. TRttiProcedureType = class(TRttiInvokableType)
  618. private
  619. FParams, FParamsAll: TRttiParameterArray;
  620. protected
  621. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; override;
  622. function GetCallingConvention: TCallConv; override;
  623. function GetReturnType: TRttiType; override;
  624. function GetFlags: TFunctionCallFlags; override;
  625. public
  626. function Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue; override;
  627. end;
  628. TDispatchKind = (
  629. dkStatic,
  630. dkVtable,
  631. dkDynamic,
  632. dkMessage,
  633. dkInterface,
  634. { the following are FPC-only and will be moved should Delphi add more }
  635. dkMessageString
  636. );
  637. TRttiMethod = class(TRttiMember)
  638. private
  639. FString: String;
  640. function GetFlags: TFunctionCallFlags;
  641. protected
  642. function GetCallingConvention: TCallConv; virtual; abstract;
  643. function GetCodeAddress: CodePointer; virtual; abstract;
  644. function GetDispatchKind: TDispatchKind; virtual; abstract;
  645. function GetHasExtendedInfo: Boolean; virtual;
  646. function GetIsClassMethod: Boolean; virtual; abstract;
  647. function GetIsConstructor: Boolean; virtual; abstract;
  648. function GetIsDestructor: Boolean; virtual; abstract;
  649. function GetIsStatic: Boolean; virtual; abstract;
  650. function GetMethodKind: TMethodKind; virtual; abstract;
  651. function GetReturnType: TRttiType; virtual; abstract;
  652. function GetVirtualIndex: SmallInt; virtual; abstract;
  653. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; virtual; abstract;
  654. public
  655. property CallingConvention: TCallConv read GetCallingConvention;
  656. property CodeAddress: CodePointer read GetCodeAddress;
  657. property DispatchKind: TDispatchKind read GetDispatchKind;
  658. property HasExtendedInfo: Boolean read GetHasExtendedInfo;
  659. property IsClassMethod: Boolean read GetIsClassMethod;
  660. property IsConstructor: Boolean read GetIsConstructor;
  661. property IsDestructor: Boolean read GetIsDestructor;
  662. property IsStatic: Boolean read GetIsStatic;
  663. property MethodKind: TMethodKind read GetMethodKind;
  664. property ReturnType: TRttiType read GetReturnType;
  665. property VirtualIndex: SmallInt read GetVirtualIndex;
  666. function ToString: String; override;
  667. function GetParameters: TRttiParameterArray;
  668. function Invoke(aInstance: TObject; const aArgs: array of TValue): TValue;
  669. function Invoke(aInstance: TClass; const aArgs: array of TValue): TValue;
  670. function Invoke(aInstance: TValue; const aArgs: array of TValue): TValue;
  671. { Note: once "reference to" is supported these will be replaced by a single method }
  672. function CreateImplementation(aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod): TMethodImplementation;
  673. function CreateImplementation(aUserData: Pointer; aCallback: TMethodImplementationCallbackProc): TMethodImplementation;
  674. end;
  675. TRttiIndexedProperty = class(TRttiMember)
  676. private
  677. FPropInfo: PPropInfo;
  678. FAttributesResolved: boolean;
  679. FAttributes: TCustomAttributeArray;
  680. FReadMethod: TRttiMethod;
  681. FWriteMethod: TRttiMethod;
  682. procedure GetAccessors;
  683. //function GetIsDefault: Boolean; virtual;
  684. function GetPropertyType: TRttiType; virtual;
  685. function GetIsReadable: Boolean; virtual;
  686. function GetIsWritable: Boolean; virtual;
  687. function GetReadMethod: TRttiMethod; virtual;
  688. function GetWriteMethod: TRttiMethod; virtual;
  689. function GetReadProc: CodePointer; virtual;
  690. function GetWriteProc: CodePointer; virtual;
  691. protected
  692. function GetName: string; override;
  693. function GetHandle: Pointer; override;
  694. public
  695. constructor Create(AParent: TRttiType; APropInfo: PPropInfo);
  696. destructor Destroy; override;
  697. function GetAttributes: TCustomAttributeArray; override;
  698. function GetValue(aInstance: Pointer; const aArgs: array of TValue): TValue;
  699. procedure SetValue(aInstance: Pointer; const aArgs: array of TValue;
  700. const aValue: TValue);
  701. function ToString: String; override;
  702. property Handle: Pointer read GetHandle;
  703. property IsReadable: Boolean read GetIsReadable;
  704. property IsWritable: Boolean read GetIsWritable;
  705. property PropertyType: TRttiType read GetPropertyType;
  706. property ReadMethod: TRttiMethod read GetReadMethod;
  707. property WriteMethod: TRttiMethod read GetWriteMethod;
  708. property ReadProc: CodePointer read GetReadProc;
  709. property WriteProc: CodePointer read GetWriteProc;
  710. end;
  711. TRttiStructuredType = class(TRttiType)
  712. end;
  713. TInterfaceType = (
  714. itRefCounted, { aka COM interface }
  715. itRaw { aka CORBA interface }
  716. );
  717. TRttiInterfaceType = class(TRttiType)
  718. private
  719. fDeclaredMethods: TRttiMethodArray;
  720. protected
  721. function IntfMethodCount: Word;
  722. function MethodTable: PIntfMethodTable; virtual; abstract;
  723. function GetBaseType: TRttiType; override;
  724. function GetIntfBaseType: TRttiInterfaceType; virtual; abstract;
  725. function GetDeclaringUnitName: String; virtual; abstract;
  726. function GetGUID: TGUID; virtual; abstract;
  727. function GetGUIDStr: String; virtual;
  728. function GetIntfFlags: TIntfFlags; virtual; abstract;
  729. function GetIntfType: TInterfaceType; virtual; abstract;
  730. public
  731. property BaseType: TRttiInterfaceType read GetIntfBaseType;
  732. property DeclaringUnitName: String read GetDeclaringUnitName;
  733. property GUID: TGUID read GetGUID;
  734. property GUIDStr: String read GetGUIDStr;
  735. property IntfFlags: TIntfFlags read GetIntfFlags;
  736. property IntfType: TInterfaceType read GetIntfType;
  737. function GetDeclaredMethods: TRttiMethodArray; override;
  738. end;
  739. { TRttiInstanceType }
  740. TRttiInstanceType = class(TRttiStructuredType)
  741. private
  742. FFieldsResolved: Boolean;
  743. FMethodsResolved : Boolean;
  744. FPropertiesResolved: Boolean;
  745. FIndexedPropertiesResolved: Boolean;
  746. FDeclaredFields: TRttiFieldArray;
  747. FDeclaredMethods : TRttiMethodArray;
  748. FDeclaredProperties : TRttiPropertyArray;
  749. FDeclaredIndexedProperties : TRttiIndexedPropertyArray;
  750. function GetDeclaringUnitName: string;
  751. function GetMetaClassType: TClass;
  752. procedure ResolveClassicDeclaredProperties;
  753. procedure ResolveExtendedDeclaredProperties;
  754. procedure ResolveDeclaredIndexedProperties;
  755. procedure ResolveDeclaredFields;
  756. procedure ResolveDeclaredMethods;
  757. protected
  758. function GetIsInstance: boolean; override;
  759. function GetTypeSize: integer; override;
  760. function GetBaseType: TRttiType; override;
  761. public
  762. function GetDeclaredFields: TRttiFieldArray; override;
  763. function GetDeclaredMethods: TRttiMethodArray; override;
  764. function GetDeclaredProperties: TRttiPropertyArray; override;
  765. function GetDeclaredIndexedProperties: TRttiIndexedPropertyArray; override;
  766. property MetaClassType: TClass read GetMetaClassType;
  767. property DeclaringUnitName: string read GetDeclaringUnitName;
  768. end;
  769. { TRttiRecordType }
  770. TRttiRecordType = class(TRttiStructuredType)
  771. private
  772. FMethOfs: PByte;
  773. // function GetManagedFields: TRttiManagedFieldArray;
  774. FFieldsResolved: Boolean;
  775. FMethodsResolved : Boolean;
  776. FPropertiesResolved: Boolean;
  777. FIndexedPropertiesResolved: Boolean;
  778. FDeclaredFields: TRttiFieldArray;
  779. FDeclaredMethods : TRttiMethodArray;
  780. FDeclaredProperties: TRttiPropertyArray;
  781. FDeclaredIndexedProperties: TRttiIndexedPropertyArray;
  782. protected
  783. procedure ResolveFields;
  784. procedure ResolveMethods;
  785. procedure ResolveProperties;
  786. procedure ResolveIndexedProperties;
  787. function GetTypeSize: Integer; override;
  788. public
  789. function GetMethods: TRttiMethodArray; override;
  790. function GetProperties: TRttiPropertyArray; override;
  791. function GetDeclaredFields: TRttiFieldArray; override;
  792. function GetDeclaredMethods: TRttiMethodArray; override;
  793. function GetDeclaredProperties: TRttiPropertyArray; override;
  794. function GetDeclaredIndexedProperties: TRttiIndexedPropertyArray; override;
  795. function GetAttributes: TCustomAttributeArray;
  796. // property ManagedFields: TRttiManagedFieldArray read GetManagedFields;
  797. end;
  798. TVirtualInterfaceInvokeEvent = procedure(aMethod: TRttiMethod; const aArgs: TValueArray; out aResult: TValue) of object;
  799. TVirtualInterface = class(TInterfacedObject, IInterface)
  800. private
  801. fGUID: TGUID;
  802. fOnInvoke: TVirtualInterfaceInvokeEvent;
  803. fContext: TRttiContext;
  804. fThunks: array[0..2] of CodePointer;
  805. fImpls: array of TMethodImplementation;
  806. fVmt: PCodePointer;
  807. protected
  808. function QueryInterface(constref aIID: TGuid; out aObj): LongInt;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; reintroduce; virtual;
  809. function _AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; reintroduce; virtual;
  810. function _Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; reintroduce; virtual;
  811. procedure HandleUserCallback(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue);
  812. public
  813. constructor Create(aPIID: PTypeInfo);
  814. constructor Create(aPIID: PTypeInfo; aInvokeEvent: TVirtualInterfaceInvokeEvent);
  815. destructor Destroy; override;
  816. property OnInvoke: TVirtualInterfaceInvokeEvent read fOnInvoke write fOnInvoke;
  817. end;
  818. ERtti = class(Exception);
  819. EInsufficientRtti = class(ERtti);
  820. EInvocationError = class(ERtti);
  821. ENonPublicType = class(ERtti);
  822. TFunctionCallParameter = record
  823. ValueRef: Pointer;
  824. ValueSize: SizeInt;
  825. Info: TFunctionCallParameterInfo;
  826. end;
  827. TFunctionCallParameterArray = specialize TArray<TFunctionCallParameter>;
  828. TFunctionCallProc = procedure(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
  829. TFunctionCallMethod = procedure(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer) of object;
  830. TFunctionCallManager = record
  831. Invoke: procedure(CodeAddress: CodePointer; const Args: TFunctionCallParameterArray; CallingConvention: TCallConv;
  832. ResultType: PTypeInfo; ResultValue: Pointer; Flags: TFunctionCallFlags);
  833. CreateCallbackProc: function(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  834. CreateCallbackMethod: function(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  835. end;
  836. TFunctionCallManagerArray = array[TCallConv] of TFunctionCallManager;
  837. TCallConvSet = set of TCallConv;
  838. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager; out aOldFuncCallMgr: TFunctionCallManager);
  839. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager);
  840. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  841. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager);
  842. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  843. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray);
  844. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  845. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray);
  846. procedure GetFunctionCallManager(aCallConv: TCallConv; out aFuncCallMgr: TFunctionCallManager);
  847. procedure GetFunctionCallManagers(aCallConvs: TCallConvSet; out aFuncCallMgrs: TFunctionCallManagerArray);
  848. procedure GetFunctionCallManagers(out aFuncCallMgrs: TFunctionCallManagerArray);
  849. function Invoke(aCodeAddress: CodePointer; const aArgs: TValueArray; aCallConv: TCallConv;
  850. aResultType: PTypeInfo; aIsStatic: Boolean; aIsConstructor: Boolean): TValue;
  851. function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  852. function CreateCallbackMethod(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  853. function IsManaged(TypeInfo: PTypeInfo): boolean;
  854. function IsBoolType(ATypeInfo: PTypeInfo): Boolean;
  855. function ArrayOfConstToTValueArray(const aValues: array of const): TValueArray;
  856. {$ifndef InLazIDE}
  857. generic function OpenArrayToDynArrayValue<T>(constref aArray: array of T): TValue;
  858. {$endif}
  859. { these resource strings are needed by units implementing function call managers }
  860. resourcestring
  861. SErrInvokeNotImplemented = 'Invoke functionality is not implemented';
  862. SErrInvokeResultTypeNoValue = 'Function has a result type, but no result pointer provided';
  863. SErrInvokeFailed = 'Invoke call failed';
  864. SErrMethodImplCreateFailed = 'Failed to create method implementation';
  865. SErrCallbackNotImplemented = 'Callback functionality is not implemented';
  866. SErrCallConvNotSupported = 'Calling convention not supported: %s';
  867. SErrTypeKindNotSupported = 'Type kind is not supported: %s';
  868. SErrCallbackHandlerNil = 'Callback handler is Nil';
  869. SErrMissingSelfParam = 'Missing self parameter';
  870. SErrNotEnumeratedType = '%s is not an enumerated type.';
  871. SErrNoFieldRtti = 'No field type info available';
  872. SErrNotImplementedRtti = 'This functionality is not implemented in RTTI';
  873. implementation
  874. uses
  875. {$IFDEF FPC_DOTTEDUNITS}
  876. System.Variants,
  877. {$ifdef windows}
  878. WinApi.Windows,
  879. {$endif}
  880. {$ifdef unix}
  881. UnixApi.Base,
  882. {$endif}
  883. System.SysConst,
  884. System.FGL;
  885. {$ELSE FPC_DOTTEDUNITS}
  886. Variants,
  887. {$ifdef windows}
  888. Windows,
  889. {$endif}
  890. {$ifdef unix}
  891. BaseUnix,
  892. {$endif}
  893. sysconst,
  894. fgl;
  895. {$ENDIF FPC_DOTTEDUNITS}
  896. Const
  897. MemberVisibilities: array[TVisibilityClass] of TMemberVisibility
  898. = (mvPrivate, mvProtected, mvPublic, mvPublished);
  899. function AlignToPtr(aPtr: Pointer): Pointer; inline;
  900. begin
  901. {$ifdef CPUM68K}
  902. Result := AlignTypeData(aPtr);
  903. {$else}
  904. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  905. Result := Align(aPtr, SizeOf(Pointer));
  906. {$else}
  907. Result := aPtr;
  908. {$endif}
  909. {$endif}
  910. end;
  911. Function IsDateTimeType(aData : PTypeInfo) : Boolean; inline;
  912. begin
  913. Result:=(aData=TypeInfo(TDateTime))
  914. or (aData=TypeInfo(TDate))
  915. or (aData=TypeInfo(TTime));
  916. end;
  917. Function TypeInfoToVarType(aTypeInfo : PTypeInfo; out aType : TVarType) : Boolean;
  918. begin
  919. aType:=varEmpty;
  920. case aTypeInfo^.Kind of
  921. tkChar,
  922. tkWideChar,
  923. tkString,
  924. tkLString:
  925. aType:=varString;
  926. tkUString:
  927. aType:=varUString;
  928. tkWString:
  929. aType:=varOleStr;
  930. tkVariant:
  931. aType:=varVariant;
  932. tkInteger:
  933. case GetTypeData(aTypeInfo)^.OrdType of
  934. otSByte: aType:=varShortInt;
  935. otSWord: aType:=varSmallint;
  936. otSLong: aType:=varInteger;
  937. otUByte: aType:=varByte;
  938. otUWord: aType:=varWord;
  939. otULong: aType:=varLongWord;
  940. otUQWord: aType:=varQWord;
  941. otSQWord: aType:=varInt64;
  942. end;
  943. tkEnumeration:
  944. if IsBoolType(aTypeInfo) then
  945. aType:=varBoolean;
  946. tkFloat:
  947. if IsDateTimeType(aTypeInfo) then
  948. aType:=varDate
  949. else
  950. case GetTypeData(aTypeInfo)^.FloatType of
  951. ftSingle: aType:=varSingle;
  952. ftDouble: aType:=varDouble;
  953. ftExtended: aType:=varDouble;
  954. ftComp: aType:=varInt64;
  955. ftCurr: aType:=varCurrency;
  956. end;
  957. tkInterface:
  958. if aTypeInfo=System.TypeInfo(IDispatch) then
  959. aType:=varDispatch
  960. else
  961. aType:=varUnknown;
  962. tkInt64:
  963. aType:=varInt64;
  964. tkQWord:
  965. aType:=varUInt64
  966. else
  967. aType:=varEmpty;
  968. end;
  969. Result:=(aType<>varEmpty);
  970. end;
  971. function VarTypeToTypeInfo(aVarType : TVarType; out DataType: PTypeInfo) : Boolean;
  972. begin
  973. Result:=True;
  974. DataType:=Nil;
  975. case aVarType of
  976. varEmpty,
  977. varNull:
  978. ;
  979. varUnknown:
  980. DataType:=System.TypeInfo(IInterface);
  981. varShortInt:
  982. DataType:=System.TypeInfo(ShortInt);
  983. varSmallint:
  984. DataType:=System.TypeInfo(SmallInt);
  985. varInteger:
  986. DataType:=System.TypeInfo(Integer);
  987. varSingle:
  988. DataType:=System.TypeInfo(Single);
  989. varCurrency:
  990. DataType:=System.TypeInfo(Currency);
  991. varDate:
  992. DataType:=System.TypeInfo(TDateTime);
  993. varOleStr:
  994. DataType:=System.TypeInfo(WideString);
  995. varUString:
  996. DataType:=System.TypeInfo(UnicodeString);
  997. varDispatch:
  998. DataType:=System.TypeInfo(IDispatch);
  999. varError:
  1000. DataType:=System.TypeInfo(HRESULT);
  1001. varByte:
  1002. DataType:=System.TypeInfo(Byte);
  1003. varWord:
  1004. DataType:=System.TypeInfo(Word);
  1005. varInt64:
  1006. DataType:=System.TypeInfo(Int64);
  1007. varUInt64:
  1008. DataType:=System.TypeInfo(UInt64);
  1009. varBoolean:
  1010. DataType:=System.TypeInfo(Boolean);
  1011. varDouble:
  1012. DataType:=System.TypeInfo(Double);
  1013. varString:
  1014. DataType:=System.TypeInfo(RawByteString);
  1015. else
  1016. Result:=False;
  1017. end;
  1018. end;
  1019. Function FloatTypeToTypeInfo(FT : TFloatType) : PTypeInfo;
  1020. begin
  1021. Case FT of
  1022. ftSingle: Result:=System.TypeInfo(Single);
  1023. ftDouble: Result:=System.TypeInfo(Double);
  1024. ftExtended: Result:=System.TypeInfo(Extended);
  1025. ftComp: Result:=System.TypeInfo(Comp);
  1026. ftCurr: Result:=System.TypeInfo(Currency);
  1027. end;
  1028. end;
  1029. type
  1030. { TRttiPool }
  1031. TRttiPool = class
  1032. private type
  1033. TRttiObjectMap = specialize TFPGMap<Pointer, TRttiObject>;
  1034. private
  1035. FObjectMap: TRttiObjectMap;
  1036. FTypesList: specialize TArray<TRttiType>;
  1037. FTypeCount: LongInt;
  1038. FLock: TRTLCriticalSection;
  1039. public
  1040. function GetTypes: specialize TArray<TRttiType>;
  1041. function GetType(ATypeInfo: PTypeInfo): TRttiType;
  1042. function GetType(ATypeInfo: PTypeInfo; UsePublishedOnly : Boolean): TRttiType;
  1043. function GetByHandle(aHandle: Pointer): TRttiObject;
  1044. procedure AddObject(aObject: TRttiObject);
  1045. constructor Create;
  1046. destructor Destroy; override;
  1047. end;
  1048. IPooltoken = interface
  1049. ['{3CDB3CE9-AB55-CBAA-7B9D-2F3BB1CF5AF8}']
  1050. function RttiPool: TRttiPool;
  1051. end;
  1052. { TPoolToken }
  1053. TPoolToken = class(TInterfacedObject, IPooltoken)
  1054. FUsePublishedOnly : Boolean;
  1055. public
  1056. constructor Create(aUsePublishedOnly : Boolean);
  1057. destructor Destroy; override;
  1058. function RttiPool: TRttiPool;
  1059. end;
  1060. { TValueDataIntImpl }
  1061. TValueDataIntImpl = class(TInterfacedObject, IValueData)
  1062. private
  1063. FBuffer: Pointer;
  1064. FDataSize: SizeInt;
  1065. FTypeInfo: PTypeInfo;
  1066. FIsCopy: Boolean;
  1067. FUseAddRef: Boolean;
  1068. public
  1069. constructor CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  1070. constructor CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  1071. destructor Destroy; override;
  1072. procedure ExtractRawData(ABuffer: pointer);
  1073. procedure ExtractRawDataNoCopy(ABuffer: pointer);
  1074. function GetDataSize: SizeInt;
  1075. function GetReferenceToRawData: pointer;
  1076. end;
  1077. TRttiRefCountedInterfaceType = class(TRttiInterfaceType)
  1078. private
  1079. function IntfData: PInterfaceData; inline;
  1080. protected
  1081. function MethodTable: PIntfMethodTable; override;
  1082. function GetIntfBaseType: TRttiInterfaceType; override;
  1083. function GetDeclaringUnitName: String; override;
  1084. function GetGUID: TGUID; override;
  1085. function GetIntfFlags: TIntfFlags; override;
  1086. function GetIntfType: TInterfaceType; override;
  1087. end;
  1088. TRttiRawInterfaceType = class(TRttiInterfaceType)
  1089. private
  1090. function IntfData: PInterfaceRawData; inline;
  1091. protected
  1092. function MethodTable: PIntfMethodTable; override;
  1093. function GetIntfBaseType: TRttiInterfaceType; override;
  1094. function GetDeclaringUnitName: String; override;
  1095. function GetGUID: TGUID; override;
  1096. function GetGUIDStr: String; override;
  1097. function GetIntfFlags: TIntfFlags; override;
  1098. function GetIntfType: TInterfaceType; override;
  1099. end;
  1100. { TRttiVmtMethodParameter }
  1101. TRttiVmtMethodParameter = class(TRttiParameter)
  1102. private
  1103. FVmtMethodParam: PVmtMethodParam;
  1104. protected
  1105. function GetHandle: Pointer; override;
  1106. function GetName: String; override;
  1107. function GetFlags: TParamFlags; override;
  1108. function GetParamType: TRttiType; override;
  1109. public
  1110. constructor Create(AVmtMethodParam: PVmtMethodParam);
  1111. function GetAttributes: TCustomAttributeArray; override;
  1112. end;
  1113. { TRttiMethodTypeParameter }
  1114. TRttiMethodTypeParameter = class(TRttiParameter)
  1115. private
  1116. fHandle: Pointer;
  1117. fName: String;
  1118. fFlags: TParamFlags;
  1119. fType: PTypeInfo;
  1120. protected
  1121. function GetHandle: Pointer; override;
  1122. function GetName: String; override;
  1123. function GetFlags: TParamFlags; override;
  1124. function GetParamType: TRttiType; override;
  1125. public
  1126. constructor Create(aHandle: Pointer; const aName: String; aFlags: TParamFlags; aType: PTypeInfo);
  1127. function GetAttributes: TCustomAttributeArray; override;
  1128. end;
  1129. { TRttiIntfMethod }
  1130. TRttiIntfMethod = class(TRttiMethod)
  1131. private
  1132. FIntfMethodEntry: PIntfMethodEntry;
  1133. FIndex: SmallInt;
  1134. FParams, FParamsAll: TRttiParameterArray;
  1135. FAttributesResolved: boolean;
  1136. FAttributes: TCustomAttributeArray;
  1137. protected
  1138. function GetHandle: Pointer; override;
  1139. function GetName: String; override;
  1140. function GetCallingConvention: TCallConv; override;
  1141. function GetCodeAddress: CodePointer; override;
  1142. function GetDispatchKind: TDispatchKind; override;
  1143. function GetHasExtendedInfo: Boolean; override;
  1144. function GetIsClassMethod: Boolean; override;
  1145. function GetIsConstructor: Boolean; override;
  1146. function GetIsDestructor: Boolean; override;
  1147. function GetIsStatic: Boolean; override;
  1148. function GetMethodKind: TMethodKind; override;
  1149. function GetReturnType: TRttiType; override;
  1150. function GetVirtualIndex: SmallInt; override;
  1151. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; override;
  1152. public
  1153. constructor Create(AParent: TRttiType; AIntfMethodEntry: PIntfMethodEntry; AIndex: SmallInt);
  1154. function GetAttributes: TCustomAttributeArray; override;
  1155. end;
  1156. { TRttiInstanceMethod }
  1157. TRttiInstanceMethod = class(TRttiMethod)
  1158. Type
  1159. TStaticMethod = (smCalc, smFalse, smTrue);
  1160. private
  1161. FHandle: PVmtMethodExEntry;
  1162. // False: without hidden, true: with hidden
  1163. FParams : Array [Boolean] of TRttiParameterArray;
  1164. FAttributesResolved: boolean;
  1165. FAttributes: TCustomAttributeArray;
  1166. FStaticCalculated : TStaticMethod;
  1167. procedure ResolveParams;
  1168. procedure ResolveAttributes;
  1169. protected
  1170. function GetHandle: Pointer; override;
  1171. function GetName: String; override;
  1172. function GetCallingConvention: TCallConv; override;
  1173. function GetCodeAddress: CodePointer; override;
  1174. function GetDispatchKind: TDispatchKind; override;
  1175. function GetHasExtendedInfo: Boolean; override;
  1176. function GetIsClassMethod: Boolean; override;
  1177. function GetIsConstructor: Boolean; override;
  1178. function GetIsDestructor: Boolean; override;
  1179. function GetIsStatic: Boolean; override;
  1180. function GetMethodKind: TMethodKind; override;
  1181. function GetReturnType: TRttiType; override;
  1182. function GetVirtualIndex: SmallInt; override;
  1183. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; override;
  1184. public
  1185. constructor Create(AParent: TRttiType; aHandle: PVmtMethodExEntry);
  1186. function GetAttributes: TCustomAttributeArray; override;
  1187. end;
  1188. { TRttiRecordMethod }
  1189. TRttiRecordMethod = class(TRttiMethod)
  1190. private
  1191. FHandle : PRecMethodExEntry;
  1192. // False: without hidden, true: with hidden
  1193. FParams : Array [Boolean] of TRttiParameterArray;
  1194. procedure ResolveParams;
  1195. Protected
  1196. function GetName: string; override;
  1197. Function GetIsConstructor: Boolean; override;
  1198. Function GetIsDestructor: Boolean; override;
  1199. function GetCallingConvention: TCallConv; override;
  1200. function GetReturnType: TRttiType; override;
  1201. function GetDispatchKind: TDispatchKind; override;
  1202. function GetMethodKind: TMethodKind; override;
  1203. function GetHasExtendedInfo: Boolean; override;
  1204. function GetCodeAddress: CodePointer; override;
  1205. function GetIsClassMethod: Boolean; override;
  1206. function GetIsStatic: Boolean; override;
  1207. function GetVisibility: TMemberVisibility; override;
  1208. function GetHandle : Pointer; override;
  1209. function GetVirtualIndex: SmallInt; override;
  1210. public
  1211. constructor Create(AParent: TRttiType; aHandle: PRecMethodExEntry);
  1212. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; override;
  1213. Function GetAttributes: TCustomAttributeArray; override;
  1214. end;
  1215. resourcestring
  1216. SErrUnableToGetValueForType = 'Unable to get value for type %s';
  1217. SErrUnableToSetValueForType = 'Unable to set value for type %s';
  1218. SErrDimensionOutOfRange = 'Dimension index %d is out of range [0, %d[';
  1219. SErrLengthOfArrayMismatch = 'Length of static array does not match: Got %d, but expected %d';
  1220. SErrInvalidTypecast = 'Invalid class typecast';
  1221. SErrRttiObjectNoHandle = 'RTTI object instance has no valid handle property';
  1222. SErrRttiObjectAlreadyRegistered = 'A RTTI object with handle 0x%x is already registered';
  1223. SErrInvokeInsufficientRtti = 'Insufficient RTTI to invoke function';
  1224. SErrInvokeStaticNoSelf = 'Static function must not be called with in an instance: %s';
  1225. SErrInvokeNotStaticNeedsSelf = 'Non static function must be called with an instance: %s';
  1226. SErrInvokeClassMethodClassSelf = 'Class method needs to be called with a class type: %s';
  1227. SErrInvokeArrayArgExpected = 'Array argument expected for parameter %s of method %s';
  1228. SErrInvokeArgInvalidType = 'Invalid type of argument for parameter %s of method %s';
  1229. SErrInvokeArgCount = 'Invalid argument count for method %s; expected %d, but got %d';
  1230. SErrInvokeNoCodeAddr = 'Failed to determine code address for method: %s';
  1231. SErrInvokeRttiDataError = 'The RTTI data is inconsistent for method: %s';
  1232. SErrInvokeCallableNotProc = 'The callable value is not a procedure variable for: %s';
  1233. SErrInvokeCallableNotMethod = 'The callable value is not a method variable for: %s';
  1234. SErrMethodImplNoCallback = 'No callback specified for method implementation';
  1235. // SErrMethodImplInsufficientRtti = 'Insufficient RTTI to create method implementation';
  1236. SErrMethodImplCreateNoArg = 'TMethodImplementation can not be created this way';
  1237. SErrVirtIntfTypeNil = 'No type information provided for TVirtualInterface';
  1238. SErrVirtIntfTypeMustBeIntf = 'Type ''%s'' is not an interface type';
  1239. SErrVirtIntfTypeNotFound = 'Type ''%s'' is not valid';
  1240. SErrVirtIntfNotAllMethodsRTTI = 'Not all methods of ''%s'' or its parents have the required RTTI';
  1241. // SErrVirtIntfRetrieveIInterface = 'Failed to retrieve IInterface information';
  1242. SErrVirtIntfCreateThunk = 'Failed to create thunks for ''%0:s''';
  1243. // SErrVirtIntfCreateImpl = 'Failed to create implementation for method ''%1:s'' of ''%0:s''';
  1244. SErrVirtIntfInvalidVirtIdx = 'Virtual index %2:d for method ''%1:s'' of ''%0:s'' is invalid';
  1245. SErrVirtIntfMethodNil = 'Method %1:d of ''%0:s'' is Nil';
  1246. SErrVirtIntfCreateVmt = 'Failed to create VMT for ''%s''';
  1247. // SErrVirtIntfIInterface = 'Failed to prepare IInterface method callbacks';
  1248. SErrCannotWriteToIndexedProperty = 'Cannot write to indexed property "%s"';
  1249. SErrCannotReadIndexedProperty = 'Cannot read indexed property "%s"';
  1250. var
  1251. // Boolean = UsePublishedOnly
  1252. PoolRefCount : Array [Boolean] of integer;
  1253. GRttiPool : Array [Boolean] of TRttiPool;
  1254. FuncCallMgr: TFunctionCallManagerArray;
  1255. function AllocateMemory(aSize: PtrUInt): Pointer;
  1256. begin
  1257. {$IF DEFINED(WINDOWS)}
  1258. Result := VirtualAlloc(Nil, aSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
  1259. {$ELSEIF DEFINED(UNIX)}
  1260. Result := fpmmap(Nil, aSize, PROT_READ or PROT_WRITE, MAP_PRIVATE or MAP_ANONYMOUS, 0, 0);
  1261. {$ELSE}
  1262. Result := Nil;
  1263. {$ENDIF}
  1264. end;
  1265. function ProtectMemory(aPtr: Pointer; aSize: PtrUInt; aExecutable: Boolean): Boolean;
  1266. {$IF DEFINED(WINDOWS)}
  1267. var
  1268. oldprot: DWORD;
  1269. {$ENDIF}
  1270. begin
  1271. {$IF DEFINED(WINDOWS)}
  1272. if aExecutable then
  1273. Result := VirtualProtect(aPtr, aSize, PAGE_EXECUTE_READ, oldprot)
  1274. else
  1275. Result := VirtualProtect(aPtr, aSize, PAGE_READWRITE, oldprot);
  1276. {$ELSEIF DEFINED(UNIX)}
  1277. if aExecutable then
  1278. Result := Fpmprotect(aPtr, aSize, PROT_EXEC or PROT_READ) = 0
  1279. else
  1280. Result := Fpmprotect(aPtr, aSize, PROT_READ or PROT_WRITE) = 0;
  1281. {$ELSE}
  1282. Result := False;
  1283. {$ENDIF}
  1284. end;
  1285. procedure FreeMemory(aPtr: Pointer; aSize: PtrUInt);
  1286. begin
  1287. {$IF DEFINED(WINDOWS)}
  1288. VirtualFree(aPtr, 0, MEM_RELEASE);
  1289. {$ELSEIF DEFINED(UNIX)}
  1290. fpmunmap(aPtr, aSize);
  1291. {$ELSE}
  1292. { nothing }
  1293. {$ENDIF}
  1294. end;
  1295. label
  1296. RawThunkEnd;
  1297. {$if defined(cpui386)}
  1298. const
  1299. RawThunkPlaceholderBytesToPop = $12341234;
  1300. RawThunkPlaceholderProc = $87658765;
  1301. RawThunkPlaceholderContext = $43214321;
  1302. type
  1303. TRawThunkBytesToPop = UInt32;
  1304. TRawThunkProc = PtrUInt;
  1305. TRawThunkContext = PtrUInt;
  1306. { works for both cdecl and stdcall }
  1307. procedure RawThunk; assembler; nostackframe;
  1308. asm
  1309. { the stack layout is
  1310. $ReturnAddr <- ESP
  1311. ArgN
  1312. ArgN - 1
  1313. ...
  1314. Arg1
  1315. Arg0
  1316. aBytesToPop is the size of the stack to the Self argument }
  1317. movl RawThunkPlaceholderBytesToPop, %eax
  1318. movl %esp, %ecx
  1319. lea (%ecx,%eax), %eax
  1320. movl RawThunkPlaceholderContext, (%eax)
  1321. movl RawThunkPlaceholderProc, %eax
  1322. jmp %eax
  1323. RawThunkEnd:
  1324. end;
  1325. {$elseif defined(cpux86_64)}
  1326. const
  1327. RawThunkPlaceholderProc = PtrUInt($8765876587658765);
  1328. RawThunkPlaceholderContext = PtrUInt($4321432143214321);
  1329. type
  1330. TRawThunkProc = PtrUInt;
  1331. TRawThunkContext = PtrUInt;
  1332. {$ifdef win64}
  1333. procedure RawThunk; assembler; nostackframe;
  1334. asm
  1335. { Self is always in register RCX }
  1336. movq RawThunkPlaceholderContext, %rcx
  1337. movq RawThunkPlaceholderProc, %rax
  1338. jmp %rax
  1339. RawThunkEnd:
  1340. end;
  1341. {$else}
  1342. procedure RawThunk; assembler; nostackframe;
  1343. asm
  1344. { Self is always in register RDI }
  1345. movq RawThunkPlaceholderContext, %rdi
  1346. movq RawThunkPlaceholderProc, %rax
  1347. jmp %rax
  1348. RawThunkEnd:
  1349. end;
  1350. {$endif}
  1351. {$elseif defined(cpuarm)}
  1352. const
  1353. RawThunkPlaceholderProc = $87658765;
  1354. RawThunkPlaceholderContext = $43214321;
  1355. type
  1356. TRawThunkProc = PtrUInt;
  1357. TRawThunkContext = PtrUInt;
  1358. procedure RawThunk; assembler; nostackframe;
  1359. asm
  1360. (* To be compatible with Thumb we first load the function pointer into R0,
  1361. then move that to R12 which is volatile and then we load the new Self into
  1362. R0 *)
  1363. ldr r0, .LProc
  1364. mov r12, r0
  1365. ldr r0, .LContext
  1366. {$ifdef CPUARM_HAS_BX}
  1367. bx r12
  1368. {$else}
  1369. mov pc, r12
  1370. {$endif}
  1371. .LProc:
  1372. .long RawThunkPlaceholderProc
  1373. .LContext:
  1374. .long RawThunkPlaceholderContext
  1375. RawThunkEnd:
  1376. end;
  1377. {$elseif defined(cpuaarch64)}
  1378. const
  1379. RawThunkPlaceholderProc = $8765876587658765;
  1380. RawThunkPlaceholderContext = $4321432143214321;
  1381. type
  1382. TRawThunkProc = PtrUInt;
  1383. TRawThunkContext = PtrUInt;
  1384. procedure RawThunk; assembler; nostackframe;
  1385. asm
  1386. ldr x16, .LProc
  1387. ldr x0, .LContext
  1388. br x16
  1389. .LProc:
  1390. .quad RawThunkPlaceholderProc
  1391. .LContext:
  1392. .quad RawThunkPlaceholderContext
  1393. RawThunkEnd:
  1394. end;
  1395. {$elseif defined(cpum68k)}
  1396. const
  1397. RawThunkPlaceholderProc = $87658765;
  1398. RawThunkPlaceholderContext = $43214321;
  1399. type
  1400. TRawThunkProc = PtrUInt;
  1401. TRawThunkContext = PtrUInt;
  1402. procedure RawThunk; assembler; nostackframe;
  1403. asm
  1404. lea 4(sp), a0
  1405. move.l #RawThunkPlaceholderContext, (a0)
  1406. move.l #RawThunkPlaceholderProc, a0
  1407. jmp (a0)
  1408. RawThunkEnd:
  1409. end;
  1410. {$elseif defined(cpuriscv64)}
  1411. const
  1412. RawThunkPlaceholderProc = $8765876587658765;
  1413. RawThunkPlaceholderContext = $4321432143214321;
  1414. type
  1415. TRawThunkProc = PtrUInt;
  1416. TRawThunkContext = PtrUInt;
  1417. procedure RawThunk; assembler; nostackframe;
  1418. asm
  1419. ld x5, .LProc
  1420. ld x10, .LContext
  1421. jalr x0, x5, 0
  1422. .LProc:
  1423. .quad RawThunkPlaceholderProc
  1424. .LContext:
  1425. .quad RawThunkPlaceholderContext
  1426. RawThunkEnd:
  1427. end;
  1428. {$elseif defined(cpuriscv32)}
  1429. const
  1430. RawThunkPlaceholderProc = $87658765;
  1431. RawThunkPlaceholderContext = $43214321;
  1432. type
  1433. TRawThunkProc = PtrUInt;
  1434. TRawThunkContext = PtrUInt;
  1435. procedure RawThunk; assembler; nostackframe;
  1436. asm
  1437. lw x5, .LProc
  1438. lw x10, .LContext
  1439. jalr x0, x5, 0
  1440. .LProc:
  1441. .long RawThunkPlaceholderProc
  1442. .LContext:
  1443. .long RawThunkPlaceholderContext
  1444. RawThunkEnd:
  1445. end;
  1446. {$elseif defined(cpuloongarch64)}
  1447. const
  1448. RawThunkPlaceholderProc = $8765876587658765;
  1449. RawThunkPlaceholderContext = $4321432143214321;
  1450. type
  1451. TRawThunkProc = PtrUInt;
  1452. TRawThunkContext = PtrUInt;
  1453. procedure RawThunk; assembler; nostackframe;
  1454. asm
  1455. move $t0, $ra
  1456. bl .Lreal
  1457. .quad RawThunkPlaceholderProc
  1458. .quad RawThunkPlaceholderContext
  1459. .Lreal:
  1460. ld.d $a0, $ra, 8
  1461. ld.d $t1, $ra, 0
  1462. move $ra, $t0
  1463. jr $t1
  1464. RawThunkEnd:
  1465. end;
  1466. {$endif}
  1467. {$if declared(RawThunk)}
  1468. const
  1469. RawThunkEndPtr: Pointer = @RawThunkEnd;
  1470. type
  1471. {$if declared(TRawThunkBytesToPop)}
  1472. PRawThunkBytesToPop = ^TRawThunkBytesToPop;
  1473. {$endif}
  1474. PRawThunkContext = ^TRawThunkContext;
  1475. PRawThunkProc = ^TRawThunkProc;
  1476. {$endif}
  1477. { Delphi has these as part of TRawVirtualClass.TVTable; until we have that we
  1478. simply leave that here in the implementation }
  1479. function AllocateRawThunk(aProc: CodePointer; aContext: Pointer; aBytesToPop: SizeInt): CodePointer;
  1480. {$if declared(RawThunk)}
  1481. var
  1482. size, i: SizeInt;
  1483. {$if declared(TRawThunkBytesToPop)}
  1484. btp: PRawThunkBytesToPop;
  1485. btpdone: Boolean;
  1486. {$endif}
  1487. context: PRawThunkContext;
  1488. contextdone: Boolean;
  1489. proc: PRawThunkProc;
  1490. procdone: Boolean;
  1491. {$endif}
  1492. begin
  1493. {$if not declared(RawThunk)}
  1494. { platform dose not have thunk support... :/ }
  1495. Result := Nil;
  1496. {$else}
  1497. Size := PtrUInt(RawThunkEndPtr) - PtrUInt(@RawThunk) + 1;
  1498. Result := AllocateMemory(size);
  1499. Move(Pointer(@RawThunk)^, Result^, size);
  1500. {$if declared(TRawThunkBytesToPop)}
  1501. btpdone := False;
  1502. {$endif}
  1503. contextdone := False;
  1504. procdone := False;
  1505. for i := 0 to Size - 1 do begin
  1506. {$if declared(TRawThunkBytesToPop)}
  1507. if not btpdone and (i <= Size - SizeOf(TRawThunkBytesToPop)) then begin
  1508. btp := PRawThunkBytesToPop(PByte(Result) + i);
  1509. if btp^ = TRawThunkBytesToPop(RawThunkPlaceholderBytesToPop) then begin
  1510. btp^ := TRawThunkBytesToPop(aBytesToPop);
  1511. btpdone := True;
  1512. end;
  1513. end;
  1514. {$endif}
  1515. if not contextdone and (i <= Size - SizeOf(TRawThunkContext)) then begin
  1516. context := PRawThunkContext(PByte(Result) + i);
  1517. if context^ = TRawThunkContext(RawThunkPlaceholderContext) then begin
  1518. context^ := TRawThunkContext(aContext);
  1519. contextdone := True;
  1520. end;
  1521. end;
  1522. if not procdone and (i <= Size - SizeOf(TRawThunkProc)) then begin
  1523. proc := PRawThunkProc(PByte(Result) + i);
  1524. if proc^ = TRawThunkProc(RawThunkPlaceholderProc) then begin
  1525. proc^ := TRawThunkProc(aProc);
  1526. procdone := True;
  1527. end;
  1528. end;
  1529. end;
  1530. if not contextdone or not procdone
  1531. {$if declared(TRawThunkBytesToPop)}
  1532. or not btpdone
  1533. {$endif}
  1534. then begin
  1535. FreeMemory(Result, Size);
  1536. Result := Nil;
  1537. end else
  1538. ProtectMemory(Result, Size, True);
  1539. {$endif}
  1540. end;
  1541. procedure FreeRawThunk(aThunk: CodePointer);
  1542. begin
  1543. {$if declared(RawThunk)}
  1544. FreeMemory(aThunk, PtrUInt(RawThunkEndPtr) - PtrUInt(@RawThunk));
  1545. {$endif}
  1546. end;
  1547. function CCToStr(aCC: TCallConv): String; inline;
  1548. begin
  1549. WriteStr(Result, aCC);
  1550. end;
  1551. procedure NoInvoke(aCodeAddress: CodePointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv;
  1552. aResultType: PTypeInfo; aResultValue: Pointer; aFlags: TFunctionCallFlags);
  1553. begin
  1554. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  1555. end;
  1556. function NoCreateCallbackProc(aFunc: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  1557. begin
  1558. Result := Nil;
  1559. raise ENotImplemented.Create(SErrCallbackNotImplemented);
  1560. end;
  1561. function NoCreateCallbackMethod(aFunc: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  1562. begin
  1563. Result := Nil;
  1564. raise ENotImplemented.Create(SErrCallbackNotImplemented);
  1565. end;
  1566. const
  1567. NoFunctionCallManager: TFunctionCallManager = (
  1568. Invoke: @NoInvoke;
  1569. CreateCallbackProc: @NoCreateCallbackProc;
  1570. CreateCallbackMethod: @NoCreateCallbackMethod;
  1571. );
  1572. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager;
  1573. out aOldFuncCallMgr: TFunctionCallManager);
  1574. begin
  1575. aOldFuncCallMgr := FuncCallMgr[aCallConv];
  1576. FuncCallMgr[aCallConv] := aFuncCallMgr;
  1577. end;
  1578. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager);
  1579. var
  1580. dummy: TFunctionCallManager;
  1581. begin
  1582. SetFunctionCallManager(aCallConv, aFuncCallMgr, dummy);
  1583. end;
  1584. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager;
  1585. out aOldFuncCallMgrs: TFunctionCallManagerArray);
  1586. var
  1587. cc: TCallConv;
  1588. begin
  1589. for cc := Low(TCallConv) to High(TCallConv) do
  1590. if cc in aCallConvs then begin
  1591. aOldFuncCallMgrs[cc] := FuncCallMgr[cc];
  1592. FuncCallMgr[cc] := aFuncCallMgr;
  1593. end else
  1594. aOldFuncCallMgrs[cc] := Default(TFunctionCallManager);
  1595. end;
  1596. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager);
  1597. var
  1598. dummy: TFunctionCallManagerArray;
  1599. begin
  1600. SetFunctionCallManager(aCallConvs, aFuncCallMgr, dummy);
  1601. end;
  1602. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  1603. var
  1604. cc: TCallConv;
  1605. begin
  1606. for cc := Low(TCallConv) to High(TCallConv) do
  1607. if cc in aCallConvs then begin
  1608. aOldFuncCallMgrs[cc] := FuncCallMgr[cc];
  1609. FuncCallMgr[cc] := aFuncCallMgrs[cc];
  1610. end else
  1611. aOldFuncCallMgrs[cc] := Default(TFunctionCallManager);
  1612. end;
  1613. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray);
  1614. var
  1615. dummy: TFunctionCallManagerArray;
  1616. begin
  1617. SetFunctionCallManagers(aCallConvs, aFuncCallMgrs, dummy);
  1618. end;
  1619. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  1620. begin
  1621. aOldFuncCallMgrs := FuncCallMgr;
  1622. FuncCallMgr := aFuncCallMgrs;
  1623. end;
  1624. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray);
  1625. var
  1626. dummy: TFunctionCallManagerArray;
  1627. begin
  1628. SetFunctionCallManagers(aFuncCallMgrs, dummy);
  1629. end;
  1630. procedure GetFunctionCallManager(aCallConv: TCallConv; out aFuncCallMgr: TFunctionCallManager);
  1631. begin
  1632. aFuncCallMgr := FuncCallMgr[aCallConv];
  1633. end;
  1634. procedure GetFunctionCallManagers(aCallConvs: TCallConvSet; out aFuncCallMgrs: TFunctionCallManagerArray);
  1635. var
  1636. cc: TCallConv;
  1637. begin
  1638. for cc := Low(TCallConv) to High(TCallConv) do
  1639. if cc in aCallConvs then
  1640. aFuncCallMgrs[cc] := FuncCallMgr[cc]
  1641. else
  1642. aFuncCallMgrs[cc] := Default(TFunctionCallManager);
  1643. end;
  1644. procedure GetFunctionCallManagers(out aFuncCallMgrs: TFunctionCallManagerArray);
  1645. begin
  1646. aFuncCallMgrs := FuncCallMgr;
  1647. end;
  1648. procedure InitDefaultFunctionCallManager;
  1649. var
  1650. cc: TCallConv;
  1651. begin
  1652. for cc := Low(TCallConv) to High(TCallConv) do
  1653. FuncCallMgr[cc] := NoFunctionCallManager;
  1654. end;
  1655. { TRttiInstanceMethod }
  1656. function TRttiInstanceMethod.GetHandle: Pointer;
  1657. begin
  1658. Result:=FHandle;
  1659. end;
  1660. function TRttiInstanceMethod.GetName: String;
  1661. begin
  1662. Result:=FHandle^.Name;
  1663. end;
  1664. function TRttiInstanceMethod.GetCallingConvention: TCallConv;
  1665. begin
  1666. Result:=FHandle^.CC;
  1667. end;
  1668. function TRttiInstanceMethod.GetCodeAddress: CodePointer;
  1669. begin
  1670. Result:=FHandle^.CodeAddress;
  1671. end;
  1672. function TRttiInstanceMethod.GetDispatchKind: TDispatchKind;
  1673. begin
  1674. if FHandle^.VmtIndex<>-1 then
  1675. Result:=dkStatic
  1676. else
  1677. Result:=dkVtable;
  1678. end;
  1679. function TRttiInstanceMethod.GetHasExtendedInfo: Boolean;
  1680. begin
  1681. Result:=True;
  1682. end;
  1683. function TRttiInstanceMethod.GetIsClassMethod: Boolean;
  1684. begin
  1685. Result:=MethodKind in [mkClassConstructor, mkClassDestructor, mkClassProcedure,mkClassFunction];
  1686. end;
  1687. function TRttiInstanceMethod.GetIsConstructor: Boolean;
  1688. begin
  1689. Result:=MethodKind in [mkClassConstructor, mkConstructor];
  1690. end;
  1691. function TRttiInstanceMethod.GetIsDestructor: Boolean;
  1692. begin
  1693. Result:=MethodKind in [mkClassDestructor, mkDestructor];
  1694. end;
  1695. function TRttiInstanceMethod.GetIsStatic: Boolean;
  1696. var
  1697. I : integer;
  1698. begin
  1699. if FStaticCalculated=smCalc then
  1700. begin
  1701. FStaticCalculated:=smTrue;
  1702. I:=0;
  1703. While (FStaticCalculated=smTrue) and (I<FHandle^.ParamCount) do
  1704. begin
  1705. if ((FHandle^.Param[i]^.Flags * [pfSelf,pfVmt])<>[]) then
  1706. FStaticCalculated:=smFalse;
  1707. Inc(I);
  1708. end;
  1709. end;
  1710. Result:=(FStaticCalculated=smTrue);
  1711. end;
  1712. function TRttiInstanceMethod.GetMethodKind: TMethodKind;
  1713. begin
  1714. Result:=FHandle^.Kind;
  1715. end;
  1716. function TRttiInstanceMethod.GetReturnType: TRttiType;
  1717. var
  1718. context: TRttiContext;
  1719. begin
  1720. if not Assigned(FHandle^.ResultType) then
  1721. Exit(Nil);
  1722. context := TRttiContext.Create(FUsePublishedOnly);
  1723. try
  1724. Result := context.GetType(FHandle^.ResultType^);
  1725. finally
  1726. context.Free;
  1727. end;
  1728. end;
  1729. function TRttiInstanceMethod.GetVirtualIndex: SmallInt;
  1730. begin
  1731. Result:=FHandle^.VmtIndex;
  1732. end;
  1733. procedure TRttiInstanceMethod.ResolveParams;
  1734. var
  1735. param: PVmtMethodParam;
  1736. total, visible: SizeInt;
  1737. context: TRttiContext;
  1738. obj: TRttiObject;
  1739. prtti : TRttiVmtMethodParameter;
  1740. begin
  1741. total := 0;
  1742. visible := 0;
  1743. SetLength(FParams[False],FHandle^.ParamCount);
  1744. SetLength(FParams[True],FHandle^.ParamCount);
  1745. context := TRttiContext.Create(FUsePublishedOnly);
  1746. try
  1747. param := FHandle^.Param[0];
  1748. while total < FHandle^.ParamCount do
  1749. begin
  1750. obj := context.GetByHandle(param);
  1751. if Assigned(obj) then
  1752. prtti := obj as TRttiVmtMethodParameter
  1753. else
  1754. begin
  1755. prtti := TRttiVmtMethodParameter.Create(param);
  1756. context.AddObject(prtti);
  1757. end;
  1758. FParams[True][total]:=prtti;
  1759. if not (pfHidden in param^.Flags) then
  1760. begin
  1761. FParams[False][visible] := prtti;
  1762. Inc(visible);
  1763. end;
  1764. param := param^.Next;
  1765. Inc(total);
  1766. end;
  1767. if visible <> total then
  1768. SetLength(FParams[False], visible);
  1769. finally
  1770. context.Free;
  1771. end;
  1772. end;
  1773. procedure TRttiInstanceMethod.ResolveAttributes;
  1774. var
  1775. tbl : PAttributeTable;
  1776. i : Integer;
  1777. begin
  1778. FAttributesResolved:=True;
  1779. tbl:=FHandle^.AttributeTable;
  1780. if not (assigned(Tbl) and (Tbl^.AttributeCount>0)) then
  1781. exit;
  1782. SetLength(FAttributes,Tbl^.AttributeCount);
  1783. For I:=0 to Length(FAttributes)-1 do
  1784. FAttributes[I]:={$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}TypInfo.GetAttribute(Tbl,I);
  1785. end;
  1786. function TRttiInstanceMethod.GetParameters(aWithHidden: Boolean): TRttiParameterArray;
  1787. begin
  1788. if (Length(FParams[aWithHidden]) > 0) then
  1789. Exit(FParams[aWithHidden]);
  1790. if FHandle^.ParamCount = 0 then
  1791. Exit(Nil);
  1792. ResolveParams;
  1793. Result := FParams[aWithHidden];
  1794. end;
  1795. constructor TRttiInstanceMethod.Create(AParent: TRttiType; aHandle: PVmtMethodExEntry);
  1796. begin
  1797. Inherited Create(aParent);
  1798. FHandle:=aHandle;
  1799. end;
  1800. function TRttiInstanceMethod.GetAttributes: TCustomAttributeArray;
  1801. begin
  1802. if not FAttributesResolved then
  1803. ResolveAttributes;
  1804. Result:=FAttributes;
  1805. end;
  1806. { TRttiPool }
  1807. function TRttiPool.GetTypes: specialize TArray<TRttiType>;
  1808. begin
  1809. if not Assigned(FTypesList) then
  1810. Exit(Nil);
  1811. {$ifdef FPC_HAS_FEATURE_THREADING}
  1812. EnterCriticalsection(FLock);
  1813. try
  1814. {$endif}
  1815. Result := Copy(FTypesList, 0, FTypeCount);
  1816. {$ifdef FPC_HAS_FEATURE_THREADING}
  1817. finally
  1818. LeaveCriticalsection(FLock);
  1819. end;
  1820. {$endif}
  1821. end;
  1822. function TRttiPool.GetType(ATypeInfo: PTypeInfo): TRttiType;
  1823. begin
  1824. Result:=GetType(aTypeInfo,GlobalUsePublishedOnly);
  1825. end;
  1826. function TRttiPool.GetType(ATypeInfo: PTypeInfo; UsePublishedOnly : Boolean): TRttiType;
  1827. var
  1828. obj: TRttiObject;
  1829. begin
  1830. if not Assigned(ATypeInfo) then
  1831. Exit(Nil);
  1832. {$ifdef FPC_HAS_FEATURE_THREADING}
  1833. EnterCriticalsection(FLock);
  1834. try
  1835. {$endif}
  1836. Result := Nil;
  1837. obj := GetByHandle(ATypeInfo);
  1838. if Assigned(obj) then
  1839. Result := obj as TRttiType;
  1840. if not Assigned(Result) then
  1841. begin
  1842. if FTypeCount = Length(FTypesList) then
  1843. begin
  1844. SetLength(FTypesList, FTypeCount * 2);
  1845. end;
  1846. case ATypeInfo^.Kind of
  1847. tkClass : Result := TRttiInstanceType.Create(ATypeInfo,UsePublishedOnly);
  1848. tkInterface: Result := TRttiRefCountedInterfaceType.Create(ATypeInfo,UsePublishedOnly);
  1849. tkInterfaceRaw: Result := TRttiRawInterfaceType.Create(ATypeInfo,UsePublishedOnly);
  1850. tkArray: Result := TRttiArrayType.Create(ATypeInfo);
  1851. tkDynArray: Result := TRttiDynamicArrayType.Create(ATypeInfo);
  1852. tkInt64,
  1853. tkQWord: Result := TRttiInt64Type.Create(ATypeInfo);
  1854. tkInteger,
  1855. tkChar,
  1856. tkWChar: Result := TRttiOrdinalType.Create(ATypeInfo);
  1857. tkEnumeration : Result := TRttiEnumerationType.Create(ATypeInfo);
  1858. tkSString,
  1859. tkLString,
  1860. tkAString,
  1861. tkUString,
  1862. tkWString : Result := TRttiStringType.Create(ATypeInfo);
  1863. tkFloat : Result := TRttiFloatType.Create(ATypeInfo);
  1864. tkPointer : Result := TRttiPointerType.Create(ATypeInfo);
  1865. tkProcVar : Result := TRttiProcedureType.Create(ATypeInfo);
  1866. tkMethod : Result := TRttiMethodType.Create(ATypeInfo);
  1867. tkRecord : Result:=TRttiRecordType.Create(aTypeInfo,UsePublishedOnly);
  1868. else
  1869. Result := TRttiType.Create(ATypeInfo);
  1870. end;
  1871. FTypesList[FTypeCount] := Result;
  1872. FObjectMap.Add(ATypeInfo, Result);
  1873. Inc(FTypeCount);
  1874. end;
  1875. {$ifdef FPC_HAS_FEATURE_THREADING}
  1876. finally
  1877. LeaveCriticalsection(FLock);
  1878. end;
  1879. {$endif}
  1880. end;
  1881. function TRttiPool.GetByHandle(aHandle: Pointer): TRttiObject;
  1882. var
  1883. idx: LongInt;
  1884. begin
  1885. if not Assigned(aHandle) then
  1886. Exit(Nil);
  1887. {$ifdef FPC_HAS_FEATURE_THREADING}
  1888. EnterCriticalsection(FLock);
  1889. try
  1890. {$endif}
  1891. idx := FObjectMap.IndexOf(aHandle);
  1892. if idx < 0 then
  1893. Result := Nil
  1894. else
  1895. Result := FObjectMap.Data[idx];
  1896. {$ifdef FPC_HAS_FEATURE_THREADING}
  1897. finally
  1898. LeaveCriticalsection(FLock);
  1899. end;
  1900. {$endif}
  1901. end;
  1902. procedure TRttiPool.AddObject(aObject: TRttiObject);
  1903. var
  1904. idx: LongInt;
  1905. begin
  1906. if not Assigned(aObject) then
  1907. Exit;
  1908. if not Assigned(aObject.Handle) then
  1909. raise EArgumentException.Create(SErrRttiObjectNoHandle);
  1910. {$ifdef FPC_HAS_FEATURE_THREADING}
  1911. EnterCriticalsection(FLock);
  1912. try
  1913. {$endif}
  1914. idx := FObjectMap.IndexOf(aObject.Handle);
  1915. if idx < 0 then
  1916. FObjectMap.Add(aObject.Handle, aObject)
  1917. else if FObjectMap.Data[idx] <> aObject then
  1918. raise EInvalidOpException.CreateFmt(SErrRttiObjectAlreadyRegistered, [aObject.Handle]);
  1919. {$ifdef FPC_HAS_FEATURE_THREADING}
  1920. finally
  1921. LeaveCriticalsection(FLock);
  1922. end;
  1923. {$endif}
  1924. end;
  1925. constructor TRttiPool.Create;
  1926. begin
  1927. {$ifdef FPC_HAS_FEATURE_THREADING}
  1928. InitCriticalSection(FLock);
  1929. {$endif}
  1930. SetLength(FTypesList, 32);
  1931. FObjectMap := TRttiObjectMap.Create;
  1932. end;
  1933. destructor TRttiPool.Destroy;
  1934. var
  1935. i: LongInt;
  1936. begin
  1937. for i := 0 to FObjectMap.Count - 1 do
  1938. FObjectMap.Data[i].Free;
  1939. FObjectMap.Free;
  1940. {$ifdef FPC_HAS_FEATURE_THREADING}
  1941. DoneCriticalsection(FLock);
  1942. {$endif}
  1943. inherited Destroy;
  1944. end;
  1945. { TPoolToken }
  1946. constructor TPoolToken.Create(aUsePublishedOnly : Boolean);
  1947. begin
  1948. inherited Create;
  1949. FUsePublishedOnly:=aUsePublishedOnly;
  1950. if InterlockedIncrement(PoolRefCount[FUsePublishedOnly])=1 then
  1951. GRttiPool[FUsePublishedOnly] := TRttiPool.Create
  1952. end;
  1953. destructor TPoolToken.Destroy;
  1954. begin
  1955. if InterlockedDecrement(PoolRefCount[FUsePublishedOnly])=0 then
  1956. GRttiPool[FUsePublishedOnly].Free;
  1957. inherited;
  1958. end;
  1959. function TPoolToken.RttiPool: TRttiPool;
  1960. begin
  1961. result := GRttiPool[FUsePublishedOnly];
  1962. end;
  1963. { TValueDataIntImpl }
  1964. procedure IntFinalize(APointer, ATypeInfo: Pointer);
  1965. external name 'FPC_FINALIZE';
  1966. procedure IntInitialize(APointer, ATypeInfo: Pointer);
  1967. external name 'FPC_INITIALIZE';
  1968. procedure IntAddRef(APointer, ATypeInfo: Pointer);
  1969. external name 'FPC_ADDREF';
  1970. function IntCopy(ASource, ADest, ATypeInfo: Pointer): SizeInt;
  1971. external name 'FPC_COPY';
  1972. constructor TValueDataIntImpl.CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  1973. begin
  1974. FTypeInfo := ATypeInfo;
  1975. FDataSize:=ALen;
  1976. if ALen>0 then
  1977. begin
  1978. Getmem(FBuffer,FDataSize);
  1979. if Assigned(ACopyFromBuffer) then
  1980. system.move(ACopyFromBuffer^,FBuffer^,FDataSize)
  1981. else
  1982. FillChar(FBuffer^, FDataSize, 0);
  1983. end;
  1984. FIsCopy := True;
  1985. FUseAddRef := AAddRef;
  1986. if AAddRef and (ALen > 0) then begin
  1987. if Assigned(ACopyFromBuffer) then
  1988. IntAddRef(FBuffer, FTypeInfo)
  1989. else
  1990. IntInitialize(FBuffer, FTypeInfo);
  1991. end;
  1992. end;
  1993. constructor TValueDataIntImpl.CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  1994. begin
  1995. FTypeInfo := ATypeInfo;
  1996. FDataSize := SizeOf(Pointer);
  1997. if Assigned(AData) then
  1998. FBuffer := PPointer(AData)^
  1999. else
  2000. FBuffer := Nil;
  2001. FIsCopy := False;
  2002. FUseAddRef := AAddRef;
  2003. if AAddRef and Assigned(AData) then
  2004. IntAddRef(@FBuffer, FTypeInfo);
  2005. end;
  2006. destructor TValueDataIntImpl.Destroy;
  2007. begin
  2008. if Assigned(FBuffer) then begin
  2009. if FUseAddRef then
  2010. if FIsCopy then
  2011. IntFinalize(FBuffer, FTypeInfo)
  2012. else
  2013. IntFinalize(@FBuffer, FTypeInfo);
  2014. if FIsCopy then
  2015. Freemem(FBuffer);
  2016. end;
  2017. inherited Destroy;
  2018. end;
  2019. procedure TValueDataIntImpl.ExtractRawData(ABuffer: pointer);
  2020. begin
  2021. if FDataSize = 0 then
  2022. Exit;
  2023. if FIsCopy then
  2024. System.Move(FBuffer^, ABuffer^, FDataSize)
  2025. else
  2026. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  2027. if FUseAddRef then
  2028. IntAddRef(ABuffer, FTypeInfo);
  2029. end;
  2030. procedure TValueDataIntImpl.ExtractRawDataNoCopy(ABuffer: pointer);
  2031. begin
  2032. if FDataSize = 0 then
  2033. Exit;
  2034. if FIsCopy then
  2035. system.move(FBuffer^, ABuffer^, FDataSize)
  2036. else
  2037. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  2038. end;
  2039. function TValueDataIntImpl.GetDataSize: SizeInt;
  2040. begin
  2041. result := FDataSize;
  2042. end;
  2043. function TValueDataIntImpl.GetReferenceToRawData: pointer;
  2044. begin
  2045. if FIsCopy then
  2046. result := FBuffer
  2047. else
  2048. result := @FBuffer;
  2049. end;
  2050. { TValue }
  2051. function TValue.GetTypeDataProp: PTypeData;
  2052. begin
  2053. result := GetTypeData(FData.FTypeInfo);
  2054. end;
  2055. function TValue.GetTypeInfo: PTypeInfo;
  2056. begin
  2057. result := FData.FTypeInfo;
  2058. end;
  2059. function TValue.GetTypeKind: TTypeKind;
  2060. begin
  2061. if not Assigned(FData.FTypeInfo) then
  2062. Result := tkUnknown
  2063. else
  2064. result := FData.FTypeInfo^.Kind;
  2065. end;
  2066. function TValue.IsObject: boolean;
  2067. begin
  2068. result := (Kind = tkClass) or ((Kind = tkUnknown) and not Assigned(FData.FAsObject));
  2069. end;
  2070. function TValue.IsClass: boolean;
  2071. begin
  2072. result := (Kind = tkClassRef) or ((Kind in [tkClass,tkUnknown]) and not Assigned(FData.FAsObject));
  2073. end;
  2074. function TValue.IsOrdinal: boolean;
  2075. begin
  2076. result := (Kind in [tkInteger, tkInt64, tkQWord, tkBool, tkEnumeration, tkChar, tkWChar, tkUChar]) or
  2077. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown]) and not Assigned(FData.FAsPointer));
  2078. end;
  2079. function TValue.IsDateTime: boolean;
  2080. begin
  2081. Result:=IsDateTimeType(TypeInfo);
  2082. end;
  2083. function TValue.IsInstanceOf(aClass : TClass): boolean;
  2084. var
  2085. Obj : TObject;
  2086. begin
  2087. Result:=IsObject;
  2088. if not Result then
  2089. exit;
  2090. Obj:=AsObject;
  2091. Result:=Assigned(Obj) and Obj.InheritsFrom(aClass);
  2092. end;
  2093. {$ifndef NoGenericMethods}
  2094. generic function TValue.IsType<T>:Boolean;
  2095. begin
  2096. Result := IsType(PTypeInfo(System.TypeInfo(T)));
  2097. end;
  2098. generic class procedure TValue.Make<T>(const AValue: T; out Result: TValue);
  2099. begin
  2100. TValue.Make(@AValue, PTypeInfo(System.TypeInfo(T)), Result);
  2101. end;
  2102. generic class function TValue.From<T>(constref aValue: T): TValue;
  2103. begin
  2104. TValue.Make(@aValue, PTypeInfo(System.TypeInfo(T)), Result);
  2105. end;
  2106. generic class function TValue.FromOpenArray<T>(constref aValue: array of T): TValue;
  2107. var
  2108. arrdata: Pointer;
  2109. begin
  2110. if Length(aValue) > 0 then
  2111. arrdata := @aValue[0]
  2112. else
  2113. arrdata := Nil;
  2114. TValue.MakeOpenArray(arrdata, Length(aValue), PTypeInfo(System.TypeInfo(aValue)), Result);
  2115. end;
  2116. {$endif}
  2117. function TValue.IsType(ATypeInfo: PTypeInfo): boolean;
  2118. begin
  2119. result := ATypeInfo = TypeInfo;
  2120. end;
  2121. class procedure TValue.Make(AValue: NativeInt; ATypeInfo: PTypeInfo; out Result: TValue);
  2122. begin
  2123. TValue.Make(@AValue, ATypeInfo, Result);
  2124. end;
  2125. class operator TValue.:=(const AValue: ShortString): TValue;
  2126. begin
  2127. Make(@AValue, System.TypeInfo(AValue), Result);
  2128. end;
  2129. class operator TValue.:=(const AValue: AnsiString): TValue;
  2130. begin
  2131. Make(@AValue, System.TypeInfo(AValue), Result);
  2132. end;
  2133. class operator TValue.:=(const AValue: UnicodeString): TValue;
  2134. begin
  2135. Make(@AValue, System.TypeInfo(AValue), Result);
  2136. end;
  2137. class operator TValue.:=(const AValue: WideString): TValue;
  2138. begin
  2139. Make(@AValue, System.TypeInfo(AValue), Result);
  2140. end;
  2141. class operator TValue.:= (AValue: SmallInt): TValue;
  2142. begin
  2143. Make(@AValue, System.TypeInfo(AValue), Result);
  2144. end;
  2145. class operator TValue.:= (AValue: ShortInt): TValue;
  2146. begin
  2147. Make(@AValue, System.TypeInfo(AValue), Result);
  2148. end;
  2149. class operator TValue.:= (AValue: Byte): TValue; inline;
  2150. begin
  2151. Make(@AValue, System.TypeInfo(AValue), Result);
  2152. end;
  2153. class operator TValue.:= (AValue: Word): TValue; inline;
  2154. begin
  2155. Make(@AValue, System.TypeInfo(AValue), Result);
  2156. end;
  2157. class operator TValue.:= (AValue: Cardinal): TValue; inline;
  2158. begin
  2159. Make(@AValue, System.TypeInfo(AValue), Result);
  2160. end;
  2161. class operator TValue.:=(AValue: LongInt): TValue;
  2162. begin
  2163. Make(@AValue, System.TypeInfo(AValue), Result);
  2164. end;
  2165. class operator TValue.:=(AValue: Single): TValue;
  2166. begin
  2167. Make(@AValue, System.TypeInfo(AValue), Result);
  2168. end;
  2169. class operator TValue.:=(AValue: Double): TValue;
  2170. begin
  2171. Make(@AValue, System.TypeInfo(AValue), Result);
  2172. end;
  2173. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2174. class operator TValue.:=(AValue: Extended): TValue;
  2175. begin
  2176. Make(@AValue, System.TypeInfo(AValue), Result);
  2177. end;
  2178. {$endif}
  2179. class operator TValue.:=(AValue: Currency): TValue;
  2180. begin
  2181. Make(@AValue, System.TypeInfo(AValue), Result);
  2182. end;
  2183. class operator TValue.:=(AValue: Comp): TValue;
  2184. begin
  2185. Make(@AValue, System.TypeInfo(AValue), Result);
  2186. end;
  2187. class operator TValue.:=(AValue: Int64): TValue;
  2188. begin
  2189. Make(@AValue, System.TypeInfo(AValue), Result);
  2190. end;
  2191. class operator TValue.:=(AValue: QWord): TValue;
  2192. begin
  2193. Make(@AValue, System.TypeInfo(AValue), Result);
  2194. end;
  2195. class operator TValue.:=(AValue: TObject): TValue;
  2196. begin
  2197. Make(@AValue, PTypeInfo(AValue.ClassInfo), Result);
  2198. end;
  2199. class operator TValue.:=(AValue: TClass): TValue;
  2200. begin
  2201. Make(@AValue, System.TypeInfo(AValue), Result);
  2202. end;
  2203. class operator TValue.:=(AValue: Boolean): TValue;
  2204. begin
  2205. Make(@AValue, System.TypeInfo(AValue), Result);
  2206. end;
  2207. class operator TValue.:=(AValue: IUnknown): TValue;
  2208. begin
  2209. Make(@AValue, System.TypeInfo(AValue), Result);
  2210. end;
  2211. class operator TValue.:= (AValue: TVarRec): TValue;
  2212. begin
  2213. Result:=TValue.FromVarRec(aValue);
  2214. end;
  2215. function TValue.AsString: string;
  2216. begin
  2217. if System.GetTypeKind(String) = tkUString then
  2218. Result := String(AsUnicodeString)
  2219. else
  2220. Result := String(AsAnsiString);
  2221. end;
  2222. procedure TValue.Init;
  2223. begin
  2224. { resets the whole variant part; FValueData is already Nil }
  2225. {$if SizeOf(TMethod) > SizeOf(QWord)}
  2226. FData.FAsMethod.Code := Nil;
  2227. FData.FAsMethod.Data := Nil;
  2228. {$else}
  2229. FData.FAsUInt64 := 0;
  2230. {$endif}
  2231. end;
  2232. class function TValue.Empty: TValue;
  2233. begin
  2234. Result.Init;
  2235. result.FData.FTypeInfo := nil;
  2236. end;
  2237. function TValue.GetDataSize: SizeInt;
  2238. begin
  2239. if Assigned(FData.FValueData) and (Kind <> tkSString) then
  2240. Result := FData.FValueData.GetDataSize
  2241. else begin
  2242. Result := 0;
  2243. case Kind of
  2244. tkEnumeration,
  2245. tkBool,
  2246. tkInt64,
  2247. tkQWord,
  2248. tkInteger:
  2249. case TypeData^.OrdType of
  2250. otSByte,
  2251. otUByte:
  2252. Result := SizeOf(Byte);
  2253. otSWord,
  2254. otUWord:
  2255. Result := SizeOf(Word);
  2256. otSLong,
  2257. otULong:
  2258. Result := SizeOf(LongWord);
  2259. otSQWord,
  2260. otUQWord:
  2261. Result := SizeOf(QWord);
  2262. end;
  2263. tkChar:
  2264. Result := SizeOf(AnsiChar);
  2265. tkFloat:
  2266. case TypeData^.FloatType of
  2267. ftSingle:
  2268. Result := SizeOf(Single);
  2269. ftDouble:
  2270. Result := SizeOf(Double);
  2271. ftExtended:
  2272. Result := SizeOf(Extended);
  2273. ftComp:
  2274. Result := SizeOf(Comp);
  2275. ftCurr:
  2276. Result := SizeOf(Currency);
  2277. end;
  2278. tkSet:
  2279. Result := TypeData^.SetSize;
  2280. tkMethod:
  2281. Result := SizeOf(TMethod);
  2282. tkSString:
  2283. { ShortString can hold max. 254 characters as [0] is Length and [255] is #0 }
  2284. Result := SizeOf(ShortString) - 2;
  2285. tkVariant:
  2286. Result := SizeOf(Variant);
  2287. tkProcVar:
  2288. Result := SizeOf(CodePointer);
  2289. tkWChar:
  2290. Result := SizeOf(WideChar);
  2291. tkUChar:
  2292. Result := SizeOf(UnicodeChar);
  2293. tkFile:
  2294. { ToDo }
  2295. Result := SizeOf(TTextRec);
  2296. tkAString,
  2297. tkWString,
  2298. tkUString,
  2299. tkInterface,
  2300. tkDynArray,
  2301. tkClass,
  2302. tkHelper,
  2303. tkClassRef,
  2304. tkInterfaceRaw,
  2305. tkPointer:
  2306. Result := SizeOf(Pointer);
  2307. tkObject,
  2308. tkRecord:
  2309. Result := TypeData^.RecSize;
  2310. tkArray:
  2311. Result := TypeData^.ArrayData.Size;
  2312. tkUnknown,
  2313. tkLString:
  2314. Assert(False);
  2315. end;
  2316. end;
  2317. end;
  2318. Procedure TValue.CastAssign(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2319. begin
  2320. aRes:=True;
  2321. aDest:=Self;
  2322. end;
  2323. Procedure TValue.CastIntegerToInteger(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2324. var
  2325. Tmp : Integer;
  2326. begin
  2327. with FData do
  2328. case GetTypeData(FTypeInfo)^.OrdType of
  2329. otSByte: Tmp:=FAsSByte;
  2330. otSWord: Tmp:=FAsSWord;
  2331. otSLong: Tmp:=FAsSLong;
  2332. else
  2333. Tmp:=Integer(FAsULong);
  2334. end;
  2335. TValue.Make(@Tmp,aDestType,aDest);
  2336. aRes:=True;
  2337. end;
  2338. Procedure TValue.CastIntegerToFloat(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2339. var
  2340. Tmp : Int64;
  2341. Ti : PtypeInfo;
  2342. DestFloatType: TFloatType;
  2343. S: Single;
  2344. D: Double;
  2345. E: Extended;
  2346. Co: Comp;
  2347. Cu: Currency;
  2348. begin
  2349. Tmp:=AsInt64;
  2350. DestFloatType := GetTypeData(aDestType)^.FloatType;
  2351. Ti:=FloatTypeToTypeInfo(DestFloatType);
  2352. case DestFloatType of
  2353. ftSingle: begin S := Tmp; TValue.Make(@S, Ti,aDest); end;
  2354. ftDouble: begin D := Tmp; TValue.Make(@D, Ti,aDest); end;
  2355. ftExtended: begin E := Tmp; TValue.Make(@E, Ti,aDest); end;
  2356. ftComp: begin Co := Tmp; TValue.Make(@Co,Ti,aDest); end;
  2357. ftCurr: begin Cu := Tmp; TValue.Make(@Cu,Ti,aDest); end;
  2358. else
  2359. aRes := False;
  2360. Exit;
  2361. end;
  2362. aRes:=True;
  2363. end;
  2364. Procedure TValue.CastIntegerToInt64(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2365. var
  2366. Tmp: Int64;
  2367. begin
  2368. Tmp:=AsInt64;
  2369. TValue.Make(@Tmp,aDestType,aDest);
  2370. aRes:=True;
  2371. end;
  2372. Procedure TValue.CastIntegerToQWord(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2373. var
  2374. Tmp: QWord;
  2375. begin
  2376. Tmp:=QWord(AsInt64);
  2377. TValue.Make(@Tmp, aDestType, aDest);
  2378. aRes:=True;
  2379. end;
  2380. Procedure TValue.CastCharToString(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2381. var
  2382. Tmp: AnsiChar;
  2383. S : RawByteString;
  2384. begin
  2385. Tmp:=AsAnsiChar;
  2386. aRes:=True;
  2387. case aDestType^.Kind of
  2388. tkChar:
  2389. TValue.Make(NativeInt(Tmp), aDestType, aDest);
  2390. tkString:
  2391. TValue.Make(@Tmp,System.TypeInfo(ShortString),aDest);
  2392. tkWString:
  2393. TValue.Make(@Tmp,System.TypeInfo(WideString),aDest);
  2394. tkUString:
  2395. TValue.Make(@Tmp,System.TypeInfo(UnicodeString),aDest);
  2396. tkLString:
  2397. begin
  2398. SetString(S, PAnsiChar(@Tmp), 1);
  2399. SetCodePage(S,GetTypeData(aDestType)^.CodePage);
  2400. TValue.Make(@S, aDestType, aDest);
  2401. end;
  2402. else
  2403. aRes:=False;
  2404. end;
  2405. end;
  2406. Procedure TValue.CastWCharToString(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2407. var
  2408. Tmp: WideChar;
  2409. RS: RawByteString;
  2410. SS : ShortString;
  2411. WS : WideString;
  2412. US : WideString;
  2413. begin
  2414. Tmp:=AsWideChar;
  2415. aRes:=True;
  2416. case aDestType^.Kind of
  2417. tkWChar: TValue.Make(NativeInt(Tmp), aDestType, aDest);
  2418. tkString:
  2419. begin
  2420. SS:=Tmp;
  2421. TValue.Make(@SS,System.TypeInfo(ShortString),aDest);
  2422. end;
  2423. tkWString:
  2424. begin
  2425. WS:=Tmp;
  2426. TValue.Make(@WS,System.TypeInfo(WideString),aDest);
  2427. end;
  2428. tkUString:
  2429. begin
  2430. US:=Tmp;
  2431. TValue.Make(@US,System.TypeInfo(UnicodeString),aDest);
  2432. end;
  2433. tkLString:
  2434. begin
  2435. SetString(RS,PAnsiChar(@Tmp),1);
  2436. SetCodePage(RS,GetTypeData(aDestType)^.CodePage);
  2437. TValue.Make(@RS,aDestType,aDest);
  2438. end;
  2439. else
  2440. aRes:=False;
  2441. end;
  2442. end;
  2443. Procedure TValue.CastEnumToEnum(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2444. Function GetEnumBaseType(aType : PTypeInfo) : PTypeInfo;
  2445. begin
  2446. if aType^.Kind=tkEnumeration then
  2447. Result:=GetTypeData(aType)^.BaseType
  2448. else
  2449. Result:=Nil;
  2450. end;
  2451. var
  2452. N : NativeInt;
  2453. BoolType : PTypeInfo;
  2454. begin
  2455. N:=AsOrdinal;
  2456. if IsBoolType(FData.FTypeInfo) and IsBoolType(aDestType) then
  2457. begin
  2458. aRes:=True;
  2459. BoolType:=GetEnumBaseType(aDestType);
  2460. if (N<>0) then
  2461. if (BoolType=System.TypeInfo(Boolean)) then
  2462. N:=Ord(True)
  2463. else
  2464. N:=-1;
  2465. TValue.Make(NativeInt(N),aDestType,aDest)
  2466. end
  2467. else
  2468. begin
  2469. aRes:=GetEnumBaseType(FData.FTypeInfo)=GetEnumBaseType(aDestType);
  2470. if aRes then
  2471. TValue.Make(NativeInt(N), aDestType, aDest);
  2472. end;
  2473. end;
  2474. Procedure TValue.CastFloatToFloat(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2475. var
  2476. Ti : PTypeInfo;
  2477. S : Single;
  2478. D : Double;
  2479. E : Extended;
  2480. Cu : Currency;
  2481. DestFloatType: TFloatType;
  2482. begin
  2483. if TypeData^.FloatType = ftComp then
  2484. begin
  2485. aRes := False;
  2486. Exit;
  2487. end;
  2488. // Destination float type
  2489. DestFloatType := GetTypeData(aDestType)^.FloatType;
  2490. if DestFloatType = ftComp then
  2491. begin
  2492. aRes := False;
  2493. Exit;
  2494. end;
  2495. ti:=FloatTypeToTypeInfo(DestFloatType);
  2496. case TypeData^.FloatType of
  2497. ftSingle:
  2498. begin
  2499. S:=AsSingle;
  2500. case DestFloatType of
  2501. ftSingle: begin TValue.Make(@S, Ti,aDest); end;
  2502. ftDouble: begin D := S; TValue.Make(@D, Ti,aDest); end;
  2503. ftExtended: begin E := S; TValue.Make(@E, Ti,aDest); end;
  2504. ftCurr: begin Cu := S; TValue.Make(@Cu,Ti,aDest); end;
  2505. end;
  2506. end;
  2507. ftDouble:
  2508. begin
  2509. D:=AsDouble;
  2510. case DestFloatType of
  2511. ftSingle: begin S := D; TValue.Make(@S, Ti,aDest); end;
  2512. ftDouble: begin TValue.Make(@D, Ti,aDest); end;
  2513. ftExtended: begin E := D; TValue.Make(@E, Ti,aDest); end;
  2514. ftCurr: begin Cu := D; TValue.Make(@Cu,Ti,aDest); end;
  2515. end;
  2516. end;
  2517. ftExtended:
  2518. begin
  2519. E:=AsExtended;
  2520. case DestFloatType of
  2521. ftSingle: begin S := E; TValue.Make(@S, Ti,aDest); end;
  2522. ftDouble: begin D := E; TValue.Make(@D, Ti,aDest); end;
  2523. ftExtended: begin TValue.Make(@E, Ti,aDest); end;
  2524. ftCurr: begin Cu := E; TValue.Make(@Cu,Ti,aDest); end;
  2525. end;
  2526. end;
  2527. ftCurr:
  2528. begin
  2529. Cu:=AsCurrency;
  2530. case DestFloatType of
  2531. ftSingle: begin S := Cu; TValue.Make(@S, Ti,aDest); end;
  2532. ftDouble: begin D := Cu; TValue.Make(@D, Ti,aDest); end;
  2533. ftExtended: begin E := Cu; TValue.Make(@E, Ti,aDest); end;
  2534. ftCurr: begin TValue.Make(@Cu,Ti,aDest); end;
  2535. end;
  2536. end;
  2537. end;
  2538. aRes:=True;
  2539. // This is for TDateTime, TDate, TTime
  2540. aDest.FData.FTypeInfo:=aDestType;
  2541. end;
  2542. Procedure TValue.CastStringToString(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2543. var
  2544. US : UnicodeString;
  2545. RS : RawByteString;
  2546. WS : WideString;
  2547. SS : ShortString;
  2548. begin
  2549. aRes:=False;
  2550. US:=AsUnicodeString;
  2551. case aDestType^.Kind of
  2552. tkUString:
  2553. TValue.Make(@US,aDestType,aDest);
  2554. tkWString:
  2555. begin
  2556. WS:=US;
  2557. TValue.Make(@WS,aDestType,aDest);
  2558. end;
  2559. tkString:
  2560. begin
  2561. RS:=AnsiString(US);
  2562. if Length(RS)>GetTypeData(aDestType)^.MaxLength then
  2563. Exit;
  2564. SS:=RS;
  2565. TValue.Make(@SS,aDestType,aDest);
  2566. end;
  2567. tkChar:
  2568. begin
  2569. RS:=AnsiString(US);
  2570. if Length(RS)<>1 then
  2571. Exit;
  2572. TValue.Make(PAnsiChar(RS),aDestType,aDest);
  2573. end;
  2574. tkLString:
  2575. begin
  2576. SetString(RS,PAnsiChar(US),Length(US));
  2577. TValue.Make(@RS, aDestType, aDest);
  2578. end;
  2579. tkWChar:
  2580. begin
  2581. if Length(US)<>1 then
  2582. Exit;
  2583. TValue.Make(PWideChar(US),aDestType,aDest);
  2584. end;
  2585. else
  2586. // silence compiler warning
  2587. end;
  2588. aRes:=True;
  2589. end;
  2590. Procedure TValue.CastClassToClass(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2591. var
  2592. Tmp : TObject;
  2593. aClass : TClass;
  2594. begin
  2595. Tmp:=AsObject;
  2596. aClass:=GetTypeData(aDestType)^.ClassType;
  2597. aRes:=Tmp.InheritsFrom(aClass);
  2598. if aRes then
  2599. TValue.Make(IntPtr(Tmp),aDestType,aDest);
  2600. end;
  2601. Procedure TValue.CastClassRefToClassRef(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2602. var
  2603. Cfrom,Cto: TClass;
  2604. begin
  2605. ExtractRawData(@CFrom);
  2606. Cto:=GetTypeData(GetTypeData(aDestType)^.InstanceType)^.ClassType;
  2607. aRes:=(cFrom=nil) or (Cfrom.InheritsFrom(cTo));
  2608. if aRes then
  2609. TValue.Make(PtrInt(cFrom),aDestType,aDest);
  2610. end;
  2611. Procedure TValue.CastClassToInterface(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2612. var
  2613. aGUID : TGUID;
  2614. P : Pointer;
  2615. begin
  2616. aRes:=False;
  2617. aGUID:=GetTypeData(aDestType)^.Guid;
  2618. if IsEqualGUID(GUID_NULL,aGUID) then
  2619. Exit;
  2620. aRes:=TObject(AsObject).GetInterface(aGUID,P);
  2621. if aRes then
  2622. begin
  2623. TValue.Make(@P,aDestType,aDest);
  2624. IUnknown(P)._Release;
  2625. end;
  2626. end;
  2627. Procedure TValue.CastInterfaceToInterface(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2628. var
  2629. Parent: PTypeData;
  2630. Tmp : Pointer;
  2631. begin
  2632. aRes:=(aDestType=TypeInfo) or (aDestType=System.TypeInfo(IInterface));
  2633. if not aRes then
  2634. begin
  2635. Parent:=GetTypeData(TypeInfo);
  2636. while (not aRes) and Assigned(Parent) and Assigned(Parent^.IntfParent) do
  2637. begin
  2638. aRes:=(Parent^.IntfParent=aDestType);
  2639. if not aRes then
  2640. Parent:=GetTypeData(Parent^.IntfParent);
  2641. end;
  2642. end;
  2643. if not aRes then
  2644. exit;
  2645. ExtractRawDataNoCopy(@Tmp);
  2646. TValue.Make(@Tmp,aDestType,aDest);
  2647. end;
  2648. Procedure TValue.CastQWordToInteger(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2649. var
  2650. Tmp : QWord;
  2651. N : NativeInt;
  2652. begin
  2653. aRes:=True;
  2654. Tmp:=FData.FAsUInt64;
  2655. case GetTypeData(aDestType)^.OrdType of
  2656. otSByte: N:=NativeInt(Int8(Tmp));
  2657. otSWord: N:=NativeInt(Int16(Tmp));
  2658. otSLong: N:=NativeInt(Int32(Tmp));
  2659. otUByte: N:=NativeInt(UInt8(Tmp));
  2660. otUWord: N:=NativeInt(UInt16(Tmp));
  2661. otULong: N:=NativeInt(UInt32(Tmp));
  2662. else
  2663. aRes:=False;
  2664. end;
  2665. if aRes then
  2666. TValue.Make(N, aDestType, aDest);
  2667. end;
  2668. Procedure TValue.CastInt64ToInteger(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2669. var
  2670. Tmp: Int64;
  2671. N : NativeInt;
  2672. begin
  2673. Tmp:=FData.FAsSInt64;
  2674. aRes:=True;
  2675. case GetTypeData(aDestType)^.OrdType of
  2676. otSByte: N:=NativeInt(Int8(Tmp));
  2677. otSWord: N:=NativeInt(Int16(Tmp));
  2678. otSLong: N:=NativeInt(Int32(Tmp));
  2679. otUByte: N:=NativeInt(UInt8(Tmp));
  2680. otUWord: N:=NativeInt(UInt16(Tmp));
  2681. otULong: N:=NativeInt(UInt32(Tmp));
  2682. else
  2683. aRes:=False;
  2684. end;
  2685. if aRes then
  2686. TValue.Make(N, aDestType, aDest);
  2687. end;
  2688. Procedure TValue.CastQWordToInt64(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2689. var
  2690. Tmp : QWord;
  2691. begin
  2692. Tmp:=FData.FAsUInt64;
  2693. TValue.Make(@Tmp,System.TypeInfo(Int64),aDest);
  2694. aRes:=True;
  2695. end;
  2696. Procedure TValue.CastInt64ToQWord(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2697. var
  2698. Tmp : Int64;
  2699. begin
  2700. Tmp:=FData.FAsSInt64;
  2701. TValue.Make(@Tmp,System.TypeInfo(QWord),aDest);
  2702. aRes:=True;
  2703. end;
  2704. Procedure TValue.CastQWordToFloat(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2705. var
  2706. Tmp : QWord;
  2707. Ti : PTypeInfo;
  2708. begin
  2709. Tmp:=FData.FAsUInt64;
  2710. Ti:=FloatTypeToTypeInfo(GetTypeData(aDestType)^.FloatType);
  2711. TValue.Make(@Tmp,Ti,aDest);
  2712. aRes:=True;
  2713. end;
  2714. Procedure TValue.CastInt64ToFloat(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2715. var
  2716. Tmp : Int64;
  2717. Ti : PTypeInfo;
  2718. begin
  2719. Tmp:=AsInt64;
  2720. Ti:=FloatTypeToTypeInfo(GetTypeData(aDestType)^.FloatType);
  2721. TValue.Make(@Tmp,Ti,aDest);
  2722. aRes:=True;
  2723. end;
  2724. Procedure TValue.CastFloatToInteger(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2725. var
  2726. Tmp: Int64;
  2727. DTD : PTypeData;
  2728. begin
  2729. aRes:=TypeData^.FloatType=ftComp;
  2730. if not aRes then
  2731. Exit;
  2732. Tmp:=FData.FAsSInt64;
  2733. DTD:=GetTypeData(aDestType);
  2734. Case aDestType^.Kind of
  2735. tkInteger:
  2736. begin
  2737. with DTD^ do
  2738. if MinValue<=MaxValue then
  2739. aRes:=(Tmp>=MinValue) and (Tmp<=MaxValue)
  2740. else
  2741. aRes:=(Tmp>=Cardinal(MinValue)) and (Tmp<=Cardinal(MaxValue))
  2742. end;
  2743. tkInt64:
  2744. With DTD^ do
  2745. aRes:=(Tmp>=MinInt64Value) and (Tmp<=MaxInt64Value);
  2746. tkQWord:
  2747. With DTD^ do
  2748. aRes:=(Tmp>=0) and (QWord(Tmp)>=Qword(MinInt64Value)) and (QWord(Tmp)<=UInt64(MaxInt64Value));
  2749. else
  2750. aRes:=False;
  2751. end;
  2752. if aRes then
  2753. TValue.Make(@Tmp, aDestType, aDest);
  2754. end;
  2755. Procedure TValue.CastFromVariant(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2756. var
  2757. Tmp : Variant;
  2758. tmpBool: Boolean;
  2759. tmpExtended: Extended;
  2760. tmpShortString: ShortString;
  2761. VarType: TVarType;
  2762. DataPtr: Pointer;
  2763. DataType: PTypeInfo;
  2764. begin
  2765. aRes:=False;
  2766. Tmp:=AsVariant;
  2767. if VarIsNull(Tmp) and NullStrictConvert then
  2768. Exit;
  2769. if not TypeInfoToVarType(aDestType,VarType) then
  2770. exit;
  2771. try
  2772. Tmp:=VarAsType(Tmp,VarType);
  2773. except
  2774. Exit;
  2775. end;
  2776. DataType:=nil;
  2777. DataPtr:=@TVarData(Tmp).VBoolean;
  2778. if not VarTypeToTypeInfo(TVarData(Tmp).VType,DataType) then
  2779. Exit;
  2780. if DataType=Nil then
  2781. begin
  2782. aDest:=TValue.Empty;
  2783. aRes:=True;
  2784. Exit;
  2785. end;
  2786. // Some special cases
  2787. if (DataType=System.TypeInfo(Boolean)) then
  2788. begin
  2789. tmpBool:=TVarData(Tmp).VBoolean=True;
  2790. DataPtr:=@tmpBool;
  2791. end
  2792. else if (DataType=System.TypeInfo(Double)) then
  2793. begin
  2794. if GetTypeData(aDestType)^.FloatType=ftExtended then
  2795. begin
  2796. tmpExtended:=Extended(TVarData(Tmp).VDouble);
  2797. DataPtr:=@tmpExtended;
  2798. DataType:=System.TypeInfo(Extended);
  2799. end
  2800. end
  2801. else if (DataType=System.TypeInfo(ShortString)) then
  2802. begin
  2803. tmpShortString:=RawByteString(TVarData(tmp).VString);
  2804. DataPtr:=@tmpShortString;
  2805. end;
  2806. TValue.Make(DataPtr,DataType,aDest);
  2807. aRes:=True;
  2808. end;
  2809. Procedure TValue.CastToVariant(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2810. var
  2811. Tmp: Variant;
  2812. begin
  2813. aRes:=False;
  2814. case Self.Kind of
  2815. tkChar:
  2816. Tmp:=Specialize AsType<AnsiChar>;
  2817. tkString,
  2818. tkLString,
  2819. tkWString,
  2820. tkUString:
  2821. Tmp:=AsString;
  2822. tkWChar:
  2823. Tmp:=WideChar(FData.FAsUWord);
  2824. tkClass:
  2825. Tmp:=PtrInt(AsObject);
  2826. tkInterface:
  2827. Tmp:=AsInterface;
  2828. tkInteger:
  2829. begin
  2830. case TypeData^.OrdType of
  2831. otSByte: Tmp:=FData.FAsSByte;
  2832. otUByte: Tmp:=FData.FAsUByte;
  2833. otSWord: Tmp:=FData.FAsSWord;
  2834. otUWord: Tmp:=FData.FAsUWord;
  2835. otSLong: Tmp:=FData.FAsSLong;
  2836. otULong: Tmp:=FData.FAsULong;
  2837. otSQWord: Tmp:=FData.FAsSInt64;
  2838. otUQWord: Tmp:=FData.FAsUInt64;
  2839. end;
  2840. end;
  2841. tkFloat:
  2842. if IsDateTime then
  2843. Tmp:=TDateTime(FData.FAsDouble)
  2844. else
  2845. case TypeData^.FloatType of
  2846. ftSingle,
  2847. ftDouble,
  2848. ftExtended:
  2849. Tmp:=AsExtended;
  2850. ftComp:
  2851. Tmp:=FData.FAsComp;
  2852. ftCurr:
  2853. Tmp:=FData.FAsCurr;
  2854. end;
  2855. tkInt64:
  2856. Tmp:=AsInt64;
  2857. tkQWord:
  2858. Tmp:=AsUInt64;
  2859. tkEnumeration:
  2860. if IsType(System.TypeInfo(Boolean)) then
  2861. Tmp:=AsBoolean
  2862. else
  2863. Tmp:=AsOrdinal;
  2864. else
  2865. Exit;
  2866. end;
  2867. if aDestType=System.TypeInfo(OleVariant) then
  2868. TValue.Make(@Tmp,System.TypeInfo(OleVariant),aDest)
  2869. else
  2870. TValue.Make(@Tmp,System.TypeInfo(Variant),aDest);
  2871. aRes:=True;
  2872. end;
  2873. Procedure TValue.CastVariantToVariant(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2874. var
  2875. Tmp : Variant;
  2876. begin
  2877. if (TypeInfo=aDestType) then
  2878. aDest:=Self
  2879. else
  2880. begin
  2881. Tmp:=AsVariant;
  2882. if (aDestType=System.TypeInfo(OleVariant)) then
  2883. TValue.Make(@Tmp,System.TypeInfo(OleVariant),aDest)
  2884. else
  2885. TValue.Make(@Tmp,System.TypeInfo(Variant),aDest);
  2886. end;
  2887. aRes:=True;
  2888. end;
  2889. Procedure TValue.CastSetToSet(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2890. var
  2891. sMax, dMax, sMin, dMin : Integer;
  2892. TD : PTypeData;
  2893. begin
  2894. aRes:=False;
  2895. TD:=TypeData;
  2896. TD:=GetTypeData(TD^.CompType);
  2897. sMin:=TD^.MinValue;
  2898. sMax:=TD^.MaxValue;
  2899. TD:=GetTypeData(aDestType);
  2900. TD:=GetTypeData(TD^.CompType);
  2901. dMin:=TD^.MinValue;
  2902. dMax:=TD^.MaxValue;
  2903. aRes:=(sMin=dMin) and (sMax=dMax);
  2904. if aRes then
  2905. begin
  2906. TValue.Make(GetReferenceToRawData, aDestType, aDest);
  2907. aRes:=true;
  2908. end
  2909. end;
  2910. Procedure TValue.CastFromInteger(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2911. begin
  2912. Case aDestType^.Kind of
  2913. tkChar: CastIntegerToInteger(aRes,aDest,aDestType);
  2914. tkVariant : CastToVariant(aRes,aDest,aDestType);
  2915. tkInt64 : CastIntegerToInt64(aRes,aDest,aDestType);
  2916. tkQWord : CastIntegerToQWord(aRes,aDest,aDestType);
  2917. tkFloat : CastIntegerToFloat(aRes,aDest,aDestType);
  2918. else
  2919. aRes:=False
  2920. end;
  2921. end;
  2922. Procedure TValue.CastFromAnsiChar(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2923. begin
  2924. case aDestType^.Kind of
  2925. tkString,
  2926. tkWChar,
  2927. tkLString,
  2928. tkWString,
  2929. tkUString : CastCharToString(aRes,aDest,aDestType);
  2930. tkVariant : CastToVariant(aRes,aDest,aDestType);
  2931. else
  2932. aRes:=False
  2933. end;
  2934. end;
  2935. Procedure TValue.CastFromWideChar(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2936. begin
  2937. case aDestType^.Kind of
  2938. tkString,
  2939. tkWChar,
  2940. tkLString,
  2941. tkWString,
  2942. tkUString : CastWCharToString(aRes,aDest,aDestType);
  2943. tkVariant : CastToVariant(aRes,aDest,aDestType);
  2944. else
  2945. aRes:=False;
  2946. end;
  2947. end;
  2948. Procedure TValue.CastFromEnum(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2949. begin
  2950. case aDestType^.Kind of
  2951. tkEnumeration : CastEnumToEnum(aRes,aDest,aDestType);
  2952. tkVariant : CastToVariant(aRes,aDest,aDestType);
  2953. else
  2954. aRes:=false;
  2955. end;
  2956. end;
  2957. Procedure TValue.CastFromFloat(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2958. begin
  2959. case aDestType^.Kind of
  2960. tkInt64,
  2961. tkQWord,
  2962. tkInteger : CastFloatToInteger(aRes,aDest,aDestType);
  2963. tkFloat : CastFloatToFloat(aRes,aDest,aDestType);
  2964. tkVariant : CastToVariant(aRes,aDest,aDestType);
  2965. else
  2966. aRes:=False;
  2967. end;
  2968. end;
  2969. Procedure TValue.CastFromString(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2970. begin
  2971. Case aDestType^.Kind of
  2972. tkString,
  2973. tkWChar,
  2974. tkLString,
  2975. tkAString,
  2976. tkWString,
  2977. tkUString,
  2978. tkChar : CastStringToString(aRes,aDest,aDestType);
  2979. tkVariant : CastToVariant(aRes,aDest,aDestType);
  2980. else
  2981. aRes:=False;
  2982. end
  2983. end;
  2984. Procedure TValue.CastFromSet(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2985. begin
  2986. Case aDestType^.Kind of
  2987. tkSet : CastSetToSet(aRes,aDest,aDestType);
  2988. tkVariant : CastToVariant(aRes,aDest,aDestType);
  2989. else
  2990. aRes:=False;
  2991. end;
  2992. end;
  2993. Procedure TValue.CastFromClass(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  2994. begin
  2995. Case aDestType^.Kind of
  2996. tkClass : CastClassToClass(aRes,aDest,aDestType);
  2997. tkInterfaceRaw,
  2998. tkInterface : CastClassToInterface(aRes,aDest,aDestType);
  2999. tkVariant : CastToVariant(aRes,aDest,aDestType);
  3000. else
  3001. aRes:=False;
  3002. end;
  3003. end;
  3004. Procedure TValue.CastFromInterface(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  3005. begin
  3006. Case aDestType^.Kind of
  3007. tkInterfaceRaw,
  3008. tkInterface : CastInterfaceToInterface(aRes,aDest,aDestType);
  3009. tkVariant : CastToVariant(aRes,aDest,aDestType);
  3010. else
  3011. aRes:=False;
  3012. end;
  3013. end;
  3014. Procedure TValue.DoCastFromVariant(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  3015. begin
  3016. Case aDestType^.Kind of
  3017. tkInteger,
  3018. tkChar,
  3019. tkEnumeration,
  3020. tkFloat,
  3021. tkString,
  3022. tkWChar,
  3023. tkLString,
  3024. tkWString,
  3025. tkInt64,
  3026. tkQWord,
  3027. tkUnicodeString : CastFromVariant(aRes,aDest,aDestType);
  3028. tkVariant : CastVariantToVariant(aRes,aDest,aDestType);
  3029. else
  3030. aRes:=False;
  3031. end;
  3032. end;
  3033. Procedure TValue.CastFromPointer(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  3034. begin
  3035. Case aDestType^.Kind of
  3036. tkPointer, tkProcedure: CastAssign(aRes,aDest,aDestType);
  3037. else
  3038. aRes:=False;
  3039. end;
  3040. end;
  3041. Procedure TValue.CastFromInt64(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  3042. begin
  3043. Case aDestType^.Kind of
  3044. tkInteger: CastInt64ToInteger(aRes,aDest,aDestType);
  3045. tkVariant : CastToVariant(aRes,aDest,aDestType);
  3046. tkInt64 : CastAssign(aRes,aDest,aDestType);
  3047. tkQWord : CastInt64ToQWord(aRes,aDest,aDestType);
  3048. tkFloat : CastInt64ToFloat(aRes,aDest,aDestType);
  3049. else
  3050. aRes:=False;
  3051. end;
  3052. end;
  3053. Procedure TValue.CastFromQWord(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  3054. begin
  3055. Case aDestType^.Kind of
  3056. tkInteger: CastQWordToInteger(aRes,aDest,aDestType);
  3057. tkVariant : CastToVariant(aRes,aDest,aDestType);
  3058. tkInt64 : CastQWordToInt64(aRes,aDest,aDestType);
  3059. tkQWord : CastAssign(aRes,aDest,aDestType);
  3060. tkFloat : CastQWordToFloat(aRes,aDest,aDestType);
  3061. else
  3062. aRes:=False;
  3063. end;
  3064. end;
  3065. Procedure TValue.CastFromType(out aRes : Boolean; out ADest: TValue; aDestType: PTypeInfo);
  3066. begin
  3067. Case Kind of
  3068. tkInteger : CastFromInteger(aRes,aDest,aDestType);
  3069. tkChar : CastFromAnsiChar(aRes,aDest,aDestType);
  3070. tkEnumeration : CastFromEnum(aRes,aDest,aDestType);
  3071. tkFloat : CastFromFloat(aRes,aDest,aDestType);
  3072. tkLString,
  3073. tkAString,
  3074. tkWString,
  3075. tkUstring,
  3076. tkSString : CastFromString(aRes,aDest,aDestType);
  3077. tkSet : CastFromSet(aRes,aDest,aDestType);
  3078. tkWChar : CastFromWideChar(aRes,aDest,aDestType);
  3079. tkInterfaceRaw,
  3080. tkInterface : CastFromInterface(aRes,aDest,aDestType);
  3081. tkVariant : DoCastFromVariant(aRes,aDest,aDestType);
  3082. tkInt64 : CastFromInt64(aRes,aDest,aDestType);
  3083. tkQWord : CastFromQWord(aRes,aDest,aDestType);
  3084. tkClass : CastFromClass(aRes,aDest,aDestType);
  3085. tkClassRef : begin
  3086. aRes:=(aDestType^.kind=tkClassRef);
  3087. if aRes then
  3088. CastClassRefToClassRef(aRes,aDest,aDestType);
  3089. end;
  3090. tkProcedure,
  3091. tkPointer : CastFromPointer(aRes,aDest,aDestType);
  3092. else
  3093. aRes:=False;
  3094. end;
  3095. end;
  3096. class procedure TValue.Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue);
  3097. type
  3098. PMethod = ^TMethod;
  3099. var
  3100. td: PTypeData;
  3101. begin
  3102. result.Init;
  3103. result.FData.FTypeInfo:=ATypeInfo;
  3104. if not Assigned(ATypeInfo) then
  3105. Exit;
  3106. { first handle those types that need a TValueData implementation }
  3107. case ATypeInfo^.Kind of
  3108. tkSString : begin
  3109. td := GetTypeData(ATypeInfo);
  3110. result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, td^.MaxLength + 1, ATypeInfo, True);
  3111. end;
  3112. tkWString,
  3113. tkUString,
  3114. tkAString : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  3115. tkDynArray : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  3116. tkArray : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.ArrayData.Size, ATypeInfo, False);
  3117. tkObject,
  3118. tkRecord : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.RecSize, ATypeInfo, False);
  3119. tkVariant : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, SizeOf(Variant), ATypeInfo, False);
  3120. tkInterface: result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  3121. else
  3122. // Silence compiler warning
  3123. end;
  3124. if not Assigned(ABuffer) then
  3125. Exit;
  3126. { now handle those that are happy with the variant part of FData }
  3127. case ATypeInfo^.Kind of
  3128. tkSString,
  3129. tkWString,
  3130. tkUString,
  3131. tkAString,
  3132. tkDynArray,
  3133. tkArray,
  3134. tkObject,
  3135. tkRecord,
  3136. tkVariant,
  3137. tkInterface:
  3138. { ignore }
  3139. ;
  3140. tkClass : result.FData.FAsObject := PPointer(ABuffer)^;
  3141. tkClassRef : result.FData.FAsClass := PClass(ABuffer)^;
  3142. tkInterfaceRaw : result.FData.FAsPointer := PPointer(ABuffer)^;
  3143. tkInt64 : result.FData.FAsSInt64 := PInt64(ABuffer)^;
  3144. tkQWord : result.FData.FAsUInt64 := PQWord(ABuffer)^;
  3145. tkProcVar : result.FData.FAsMethod.Code := PCodePointer(ABuffer)^;
  3146. tkMethod : result.FData.FAsMethod := PMethod(ABuffer)^;
  3147. tkPointer : result.FData.FAsPointer := PPointer(ABuffer)^;
  3148. tkSet : begin
  3149. td := GetTypeData(ATypeInfo);
  3150. case td^.OrdType of
  3151. otUByte: begin
  3152. { this can either really be 1 Byte or a set > 32-bit, so
  3153. check the underlying type }
  3154. if not (td^.CompType^.Kind in [tkInteger,tkEnumeration]) then
  3155. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  3156. case td^.SetSize of
  3157. 0, 1:
  3158. Result.FData.FAsUByte := PByte(ABuffer)^;
  3159. { these two cases shouldn't happen, but better safe than sorry... }
  3160. 2:
  3161. Result.FData.FAsUWord := PWord(ABuffer)^;
  3162. 3, 4:
  3163. Result.FData.FAsULong := PLongWord(ABuffer)^;
  3164. { maybe we should also allow storage as otUQWord? }
  3165. 5..8:
  3166. Result.FData.FAsUInt64 := PQWord(ABuffer)^;
  3167. else
  3168. Result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, td^.SetSize, ATypeInfo, False);
  3169. end;
  3170. end;
  3171. otUWord:
  3172. Result.FData.FAsUWord := PWord(ABuffer)^;
  3173. otULong:
  3174. Result.FData.FAsULong := PLongWord(ABuffer)^;
  3175. else
  3176. { ehm... Panic? }
  3177. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  3178. end;
  3179. end;
  3180. tkChar,
  3181. tkWChar,
  3182. tkUChar,
  3183. tkEnumeration,
  3184. tkInteger : begin
  3185. case GetTypeData(ATypeInfo)^.OrdType of
  3186. otSByte: result.FData.FAsSByte := PShortInt(ABuffer)^;
  3187. otUByte: result.FData.FAsUByte := PByte(ABuffer)^;
  3188. otSWord: result.FData.FAsSWord := PSmallInt(ABuffer)^;
  3189. otUWord: result.FData.FAsUWord := PWord(ABuffer)^;
  3190. otSLong: result.FData.FAsSLong := PLongInt(ABuffer)^;
  3191. otULong: result.FData.FAsULong := PLongWord(ABuffer)^;
  3192. else
  3193. // Silence compiler warning
  3194. end;
  3195. end;
  3196. tkBool : begin
  3197. case GetTypeData(ATypeInfo)^.OrdType of
  3198. otUByte: result.FData.FAsUByte := Byte(System.PBoolean(ABuffer)^);
  3199. otUWord: result.FData.FAsUWord := Word(PBoolean16(ABuffer)^);
  3200. otULong: result.FData.FAsULong := DWord(PBoolean32(ABuffer)^);
  3201. otUQWord: result.FData.FAsUInt64 := QWord(PBoolean64(ABuffer)^);
  3202. otSByte: result.FData.FAsSByte := ShortInt(PByteBool(ABuffer)^);
  3203. otSWord: result.FData.FAsSWord := SmallInt(PWordBool(ABuffer)^);
  3204. otSLong: result.FData.FAsSLong := LongInt(PLongBool(ABuffer)^);
  3205. otSQWord: result.FData.FAsSInt64 := Int64(PQWordBool(ABuffer)^);
  3206. end;
  3207. end;
  3208. tkFloat : begin
  3209. case GetTypeData(ATypeInfo)^.FloatType of
  3210. ftCurr : result.FData.FAsCurr := PCurrency(ABuffer)^;
  3211. ftSingle : result.FData.FAsSingle := PSingle(ABuffer)^;
  3212. ftDouble : result.FData.FAsDouble := PDouble(ABuffer)^;
  3213. ftExtended: result.FData.FAsExtended := PExtended(ABuffer)^;
  3214. ftComp : result.FData.FAsComp := PComp(ABuffer)^;
  3215. end;
  3216. end;
  3217. else
  3218. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  3219. end;
  3220. end;
  3221. class procedure TValue.MakeOpenArray(AArray: Pointer; ALength: SizeInt; ATypeInfo: PTypeInfo; out Result: TValue);
  3222. var
  3223. el: TValue;
  3224. begin
  3225. Result.FData.FTypeInfo := ATypeInfo;
  3226. { resets the whole variant part; FValueData is already Nil }
  3227. {$if SizeOf(TMethod) > SizeOf(QWord)}
  3228. Result.FData.FAsMethod.Code := Nil;
  3229. Result.FData.FAsMethod.Data := Nil;
  3230. {$else}
  3231. Result.FData.FAsUInt64 := 0;
  3232. {$endif}
  3233. if not Assigned(ATypeInfo) then
  3234. Exit;
  3235. if ATypeInfo^.Kind <> tkArray then
  3236. Exit;
  3237. if not Assigned(AArray) then
  3238. Exit;
  3239. if ALength < 0 then
  3240. Exit;
  3241. Result.FData.FValueData := TValueDataIntImpl.CreateRef(@AArray, ATypeInfo, False);
  3242. Result.FData.FArrLength := ALength;
  3243. Make(Nil, Result.TypeData^.ArrayData.ElType, el);
  3244. Result.FData.FElSize := el.DataSize;
  3245. end;
  3246. class function TValue.FromOrdinal(aTypeInfo: PTypeInfo; aValue: Int64): TValue;
  3247. {$ifdef ENDIAN_BIG}
  3248. var
  3249. p: PByte;
  3250. td: PTypeData;
  3251. {$endif}
  3252. begin
  3253. if not Assigned(aTypeInfo) or
  3254. not (aTypeInfo^.Kind in [tkInteger, tkInt64, tkQWord, tkEnumeration, tkBool, tkChar, tkWChar, tkUChar]) then
  3255. raise EInvalidCast.Create(SErrInvalidTypecast);
  3256. {$ifdef ENDIAN_BIG}
  3257. td := GetTypeData(aTypeInfo);
  3258. p := @aValue;
  3259. case td^.OrdType of
  3260. otSByte,
  3261. otUByte:
  3262. p := p + 7;
  3263. otSWord,
  3264. otUWord:
  3265. p := p + 6;
  3266. otSLong,
  3267. otULong:
  3268. p := p + 4;
  3269. otSQWord,
  3270. otUQWord: ;
  3271. end;
  3272. TValue.Make(p, aTypeInfo, Result);
  3273. {$else}
  3274. TValue.Make(@aValue, aTypeInfo, Result);
  3275. {$endif}
  3276. end;
  3277. class function TValue.FromArray(aArrayTypeInfo: PTypeInfo; const aValues: array of TValue): TValue; static;
  3278. var
  3279. i, sz: SizeInt;
  3280. data: TValueDataIntImpl;
  3281. begin
  3282. Result.Init;
  3283. Result.FData.FTypeInfo := aArrayTypeInfo;
  3284. if not Assigned(aArrayTypeInfo) then
  3285. Exit;
  3286. if aArrayTypeInfo^.Kind = tkDynArray then begin
  3287. data := TValueDataIntImpl.CreateRef(Nil, aArrayTypeInfo, True);
  3288. sz := Length(aValues);
  3289. DynArraySetLength(data.FBuffer, aArrayTypeInfo, 1, @sz);
  3290. Result.FData.FValueData := data;
  3291. end else if aArrayTypeInfo^.Kind = tkArray then begin
  3292. if Result.GetArrayLength <> Length(aValues) then
  3293. raise ERtti.CreateFmt(SErrLengthOfArrayMismatch, [Length(aValues), Result.GetArrayLength]);
  3294. Result.FData.FValueData := TValueDataIntImpl.CreateCopy(Nil, Result.TypeData^.ArrayData.Size, aArrayTypeInfo, False);
  3295. end else
  3296. raise ERtti.CreateFmt(SErrTypeKindNotSupported, [aArrayTypeInfo^.Name]);
  3297. for i := 0 to High(aValues) do
  3298. Result.SetArrayElement(i, aValues[i]);
  3299. end;
  3300. class function TValue.FromVarRec(const aValue: TVarRec): TValue;
  3301. begin
  3302. Result:=Default(TValue);
  3303. case aValue.VType of
  3304. vtInteger: Result:=aValue.VInteger;
  3305. vtBoolean: Result:=aValue.VBoolean;
  3306. vtWideChar: TValue.Make(@aValue.VWideChar,System.TypeInfo(WideChar),Result);
  3307. vtInt64: Result:=aValue.VInt64^;
  3308. vtQWord: Result:=aValue.VQWord^;
  3309. vtChar: TValue.Make(@aValue.VChar,System.TypeInfo(AnsiChar),Result);
  3310. vtPChar: Result:=string(aValue.VPChar);
  3311. vtPWideChar: Result:=widestring(aValue.VPWideChar);
  3312. vtString: Result:=aValue.VString^;
  3313. vtWideString: Result:=WideString(aValue.VWideString);
  3314. vtAnsiString: Result:=AnsiString(aValue.VAnsiString);
  3315. vtUnicodeString: Result:=UnicodeString(aValue.VUnicodeString);
  3316. vtObject: Result:=TObject(aValue.VObject);
  3317. vtPointer: TValue.Make(@aValue.VPointer,System.TypeInfo(Pointer),Result);
  3318. vtInterface: Result:=IInterface(aValue.VInterface);
  3319. vtClass: Result:=aValue.VClass;
  3320. vtVariant: TValue.Make(@aValue.VVariant^,System.TypeInfo(Variant),result);
  3321. vtExtended: Result := aValue.VExtended^;
  3322. vtCurrency: Result := aValue.VCurrency^;
  3323. end;
  3324. end;
  3325. class function TValue.FromVariant(const aValue : Variant) : TValue;
  3326. var
  3327. aType : TVarType;
  3328. begin
  3329. Result:=Default(TValue);
  3330. aType:=TVarData(aValue).vtype;
  3331. case aType of
  3332. varEmpty,
  3333. VarNull : TValue.Make(@aValue,System.TypeInfo(Variant),Result);
  3334. varInteger : Result:=Integer(aValue);
  3335. varSmallInt : Result:=SmallInt(aValue);
  3336. varBoolean : Result:=Boolean(aValue);
  3337. varOleStr: Result:=WideString(aValue);
  3338. varInt64: Result:=Int64(aValue);
  3339. varQWord: Result:=QWord(aValue);
  3340. varShortInt: Result:=ShortInt(aValue);
  3341. varByte : Result:=Byte(aValue);
  3342. varWord : Result:=Word(aValue);
  3343. varLongWord : Result:=Cardinal(aValue);
  3344. varSingle : Result:=Single(aValue);
  3345. varDouble : Result:=Double(aValue);
  3346. varDate : TValue.Make(@TVarData(aValue).vDate,System.TypeInfo(TDateTime),Result);
  3347. varDispatch : TValue.Make(@TVarData(aValue).VDispatch,System.TypeInfo(IDispatch),Result);
  3348. varError : TValue.Make(@TVarData(aValue).vDate,System.TypeInfo(HRESULT),Result);
  3349. varUnknown : TValue.Make(@TVarData(aValue).vunknown,System.TypeInfo(IUnknown),Result);
  3350. varCurrency : Result:=Currency(aValue);
  3351. varString : Result:=AnsiString(aValue);
  3352. varUString : Result:=UnicodeString(TVarData(aValue).vustring);
  3353. else
  3354. raise EVariantTypeCastError.CreateFmt('Invalid variant cast from type %d',[aType]);
  3355. end;
  3356. end;
  3357. function TValue.GetIsEmpty: boolean;
  3358. begin
  3359. result := (FData.FTypeInfo=nil) or
  3360. ((Kind in [tkSString, tkObject, tkRecord, tkArray]) and not Assigned(FData.FValueData)) or
  3361. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw]) and not Assigned(FData.FAsPointer));
  3362. end;
  3363. function TValue.IsArray: boolean;
  3364. begin
  3365. result := kind in [tkArray, tkDynArray];
  3366. end;
  3367. function TValue.IsOpenArray: Boolean;
  3368. var
  3369. td: PTypeData;
  3370. begin
  3371. td := TypeData;
  3372. Result := (Kind = tkArray) and (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0)
  3373. end;
  3374. function TValue.AsUnicodeString: UnicodeString;
  3375. begin
  3376. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  3377. Result := ''
  3378. else
  3379. case Kind of
  3380. tkSString:
  3381. Result := UnicodeString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  3382. tkAString:
  3383. Result := UnicodeString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  3384. tkWString:
  3385. Result := UnicodeString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  3386. tkUString:
  3387. Result := UnicodeString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  3388. else
  3389. raise EInvalidCast.Create(SErrInvalidTypecast);
  3390. end;
  3391. end;
  3392. function TValue.AsAnsiString: AnsiString;
  3393. begin
  3394. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  3395. Result := ''
  3396. else
  3397. case Kind of
  3398. tkSString:
  3399. Result := AnsiString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  3400. tkAString:
  3401. Result := AnsiString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  3402. tkWString:
  3403. Result := AnsiString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  3404. tkUString:
  3405. Result := AnsiString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  3406. else
  3407. raise EInvalidCast.Create(SErrInvalidTypecast);
  3408. end;
  3409. end;
  3410. function TValue.AsExtended: Extended;
  3411. begin
  3412. if Kind = tkFloat then
  3413. begin
  3414. case TypeData^.FloatType of
  3415. ftSingle : result := FData.FAsSingle;
  3416. ftDouble : result := FData.FAsDouble;
  3417. ftExtended : result := FData.FAsExtended;
  3418. ftCurr : result := FData.FAsCurr;
  3419. ftComp : result := FData.FAsComp;
  3420. else
  3421. raise EInvalidCast.Create(SErrInvalidTypecast);
  3422. end;
  3423. end
  3424. else if Kind in [tkInteger, tkInt64, tkQWord] then
  3425. Result := AsInt64
  3426. else
  3427. raise EInvalidCast.Create(SErrInvalidTypecast);
  3428. end;
  3429. function TValue.TryCast(aTypeInfo: PTypeInfo; out aResult: TValue; const aEmptyAsAnyType: Boolean = True): Boolean;
  3430. begin
  3431. Result:=False;
  3432. if aEmptyAsAnyType and IsEmpty then
  3433. begin
  3434. aResult:=TValue.Empty;
  3435. if (aTypeInfo=nil) then
  3436. exit;
  3437. AResult.FData.FTypeInfo:=aTypeInfo;
  3438. Exit(True);
  3439. end;
  3440. if not aEmptyAsAnyType and (Self.TypeInfo=nil) then
  3441. Exit;
  3442. if (Self.TypeInfo=ATypeInfo) then
  3443. begin
  3444. aResult:=Self;
  3445. Exit(True);
  3446. end;
  3447. if Not Assigned(aTypeInfo) then
  3448. Exit;
  3449. if (aTypeInfo=System.TypeInfo(TValue)) then
  3450. begin
  3451. TValue.Make(@Self,System.TypeInfo(TValue),aResult);
  3452. Exit(True);
  3453. end;
  3454. CastFromType(Result,aResult,ATypeInfo);
  3455. end;
  3456. function TValue.Cast(aTypeInfo: PTypeInfo; const aEmptyAsAnyType: Boolean = True): TValue; overload;
  3457. begin
  3458. if not TryCast(aTypeInfo,Result,aEmptyAsAnyType) then
  3459. raise EInvalidCast.Create(SInvalidCast);
  3460. end;
  3461. {$ifndef NoGenericMethods}
  3462. generic function TValue.AsType<T>(const aEmptyAsAnyType: Boolean = True): T;
  3463. begin
  3464. if not (specialize TryAsType<T>(Result,aEmptyAsAnyType)) then
  3465. raise EInvalidCast.Create(SInvalidCast);
  3466. end;
  3467. generic function TValue.Cast<T>(const aEmptyAsAnyType: Boolean = True): TValue; overload;
  3468. var
  3469. Info : PTypeInfo;
  3470. begin
  3471. Info:=System.TypeInfo(T);
  3472. if not TryCast(Info,Result,aEmptyAsAnyType) then
  3473. raise EInvalidCast.Create(SInvalidCast);
  3474. end;
  3475. generic function TValue.TryAsType<T>(out aResult: T; const aEmptyAsAnyType: Boolean = True): Boolean; inline;
  3476. var
  3477. Tmp: TValue;
  3478. Info : PTypeInfo;
  3479. begin
  3480. Info:=System.TypeInfo(T);
  3481. Result:=TryCast(Info,Tmp,aEmptyAsAnyType);
  3482. if Result then
  3483. if Assigned(Tmp.TypeInfo) then
  3484. Tmp.ExtractRawData(@aResult)
  3485. else
  3486. aResult:=Default(T);
  3487. end;
  3488. {$endif}
  3489. function TValue.AsObject: TObject;
  3490. begin
  3491. if IsObject or (IsClass and not Assigned(FData.FAsObject)) then
  3492. result := TObject(FData.FAsObject)
  3493. else
  3494. raise EInvalidCast.Create(SErrInvalidTypecast);
  3495. end;
  3496. function TValue.AsClass: TClass;
  3497. begin
  3498. if IsClass then
  3499. result := FData.FAsClass
  3500. else
  3501. raise EInvalidCast.Create(SErrInvalidTypecast);
  3502. end;
  3503. function TValue.AsBoolean: boolean;
  3504. begin
  3505. if (Kind = tkBool) then
  3506. case TypeData^.OrdType of
  3507. otSByte: Result := ByteBool(FData.FAsSByte);
  3508. otUByte: Result := Boolean(FData.FAsUByte);
  3509. otSWord: Result := WordBool(FData.FAsSWord);
  3510. otUWord: Result := Boolean16(FData.FAsUWord);
  3511. otSLong: Result := LongBool(FData.FAsSLong);
  3512. otULong: Result := Boolean32(FData.FAsULong);
  3513. otSQWord: Result := QWordBool(FData.FAsSInt64);
  3514. otUQWord: Result := Boolean64(FData.FAsUInt64);
  3515. end
  3516. else
  3517. raise EInvalidCast.Create(SErrInvalidTypecast);
  3518. end;
  3519. function TValue.AsOrdinal: Int64;
  3520. begin
  3521. if IsOrdinal then
  3522. if Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown] then
  3523. Result := 0
  3524. else
  3525. case TypeData^.OrdType of
  3526. otSByte: Result := FData.FAsSByte;
  3527. otUByte: Result := FData.FAsUByte;
  3528. otSWord: Result := FData.FAsSWord;
  3529. otUWord: Result := FData.FAsUWord;
  3530. otSLong: Result := FData.FAsSLong;
  3531. otULong: Result := FData.FAsULong;
  3532. otSQWord: Result := FData.FAsSInt64;
  3533. otUQWord: Result := FData.FAsUInt64;
  3534. end
  3535. else
  3536. raise EInvalidCast.Create(SErrInvalidTypecast);
  3537. end;
  3538. function TValue.AsCurrency: Currency;
  3539. begin
  3540. if (Kind = tkFloat) and (TypeData^.FloatType=ftCurr) then
  3541. result := FData.FAsCurr
  3542. else
  3543. raise EInvalidCast.Create(SErrInvalidTypecast);
  3544. end;
  3545. function TValue.AsSingle: Single;
  3546. begin
  3547. if Kind = tkFloat then
  3548. begin
  3549. case TypeData^.FloatType of
  3550. ftSingle : result := FData.FAsSingle;
  3551. ftDouble : result := FData.FAsDouble;
  3552. ftExtended : result := FData.FAsExtended;
  3553. ftCurr : result := FData.FAsCurr;
  3554. ftComp : result := FData.FAsComp;
  3555. else
  3556. raise EInvalidCast.Create(SErrInvalidTypecast);
  3557. end;
  3558. end
  3559. else if Kind in [tkInteger, tkInt64, tkQWord] then
  3560. Result := AsInt64
  3561. else
  3562. raise EInvalidCast.Create(SErrInvalidTypecast);
  3563. end;
  3564. function TValue.AsDateTime: TDateTime;
  3565. begin
  3566. if (Kind = tkFloat) and (TypeData^.FloatType=ftDouble) and IsDateTimeType(TypeInfo) then
  3567. result := FData.FAsDouble
  3568. else
  3569. raise EInvalidCast.Create(SErrInvalidTypecast);
  3570. end;
  3571. function TValue.AsDouble: Double;
  3572. begin
  3573. if Kind = tkFloat then
  3574. begin
  3575. case TypeData^.FloatType of
  3576. ftSingle : result := FData.FAsSingle;
  3577. ftDouble : result := FData.FAsDouble;
  3578. ftExtended : result := FData.FAsExtended;
  3579. ftCurr : result := FData.FAsCurr;
  3580. ftComp : result := FData.FAsComp;
  3581. else
  3582. raise EInvalidCast.Create(SErrInvalidTypecast);
  3583. end;
  3584. end
  3585. else if Kind in [tkInteger, tkInt64, tkQWord] then
  3586. Result := AsInt64
  3587. else
  3588. raise EInvalidCast.Create(SErrInvalidTypecast);
  3589. end;
  3590. function TValue.AsError: HRESULT;
  3591. begin
  3592. if (Kind = tkInteger) and (TypeInfo=System.TypeInfo(HRESULT)) then
  3593. result := HResult(AsInteger)
  3594. else
  3595. raise EInvalidCast.Create(SErrInvalidTypecast);
  3596. end;
  3597. function TValue.AsInteger: Integer;
  3598. begin
  3599. if Kind in [tkInteger, tkInt64, tkQWord] then
  3600. case TypeData^.OrdType of
  3601. otSByte: Result := FData.FAsSByte;
  3602. otUByte: Result := FData.FAsUByte;
  3603. otSWord: Result := FData.FAsSWord;
  3604. otUWord: Result := FData.FAsUWord;
  3605. otSLong: Result := FData.FAsSLong;
  3606. otULong: Result := FData.FAsULong;
  3607. otSQWord: Result := FData.FAsSInt64;
  3608. otUQWord: Result := FData.FAsUInt64;
  3609. end
  3610. else
  3611. raise EInvalidCast.Create(SErrInvalidTypecast);
  3612. end;
  3613. function TValue.AsAnsiChar: AnsiChar;
  3614. begin
  3615. if Kind = tkChar then
  3616. Result := Chr(FData.FAsUByte)
  3617. else
  3618. raise EInvalidCast.Create(SErrInvalidTypecast);
  3619. end;
  3620. function TValue.AsWideChar: WideChar;
  3621. begin
  3622. if Kind = tkWChar then
  3623. Result := WideChar(FData.FAsUWord)
  3624. else
  3625. raise EInvalidCast.Create(SErrInvalidTypecast);
  3626. end;
  3627. function TValue.AsChar: AnsiChar;
  3628. begin
  3629. {$if SizeOf(AnsiChar) = 1}
  3630. Result := AsAnsiChar;
  3631. {$else}
  3632. Result := AsWideChar;
  3633. {$endif}
  3634. end;
  3635. function TValue.AsPointer : Pointer;
  3636. begin
  3637. if Kind in [tkPointer, tkInterface, tkInterfaceRaw, tkClass,tkClassRef,tkAString,tkWideString,tkUnicodeString] then
  3638. Result:=FData.FAsPointer
  3639. else
  3640. raise EInvalidCast.Create(SErrInvalidTypecast);
  3641. end;
  3642. function TValue.AsVariant : Variant;
  3643. begin
  3644. if (Kind=tkVariant) then
  3645. Result:= PVariant(FData.FValueData.GetReferenceToRawData)^
  3646. else
  3647. raise EInvalidCast.Create(SErrInvalidTypecast);
  3648. end;
  3649. function TValue.AsInt64: Int64;
  3650. begin
  3651. if Kind in [tkInteger, tkInt64, tkQWord] then
  3652. case TypeData^.OrdType of
  3653. otSByte: Result := FData.FAsSByte;
  3654. otUByte: Result := FData.FAsUByte;
  3655. otSWord: Result := FData.FAsSWord;
  3656. otUWord: Result := FData.FAsUWord;
  3657. otSLong: Result := FData.FAsSLong;
  3658. otULong: Result := FData.FAsULong;
  3659. otSQWord: Result := FData.FAsSInt64;
  3660. otUQWord: Result := FData.FAsUInt64;
  3661. end
  3662. else if (Kind = tkFloat) and (TypeData^.FloatType = ftComp) then
  3663. Result := Int64(FData.FAsComp)
  3664. else
  3665. raise EInvalidCast.Create(SErrInvalidTypecast);
  3666. end;
  3667. function TValue.AsUInt64: QWord;
  3668. begin
  3669. if Kind in [tkInteger, tkInt64, tkQWord] then
  3670. case TypeData^.OrdType of
  3671. otSByte: Result := FData.FAsSByte;
  3672. otUByte: Result := FData.FAsUByte;
  3673. otSWord: Result := FData.FAsSWord;
  3674. otUWord: Result := FData.FAsUWord;
  3675. otSLong: Result := FData.FAsSLong;
  3676. otULong: Result := FData.FAsULong;
  3677. otSQWord: Result := FData.FAsSInt64;
  3678. otUQWord: Result := FData.FAsUInt64;
  3679. end
  3680. else if (Kind = tkFloat) and (TypeData^.FloatType = ftComp) then
  3681. Result := QWord(FData.FAsComp)
  3682. else
  3683. raise EInvalidCast.Create(SErrInvalidTypecast);
  3684. end;
  3685. function TValue.AsInterface: IInterface;
  3686. begin
  3687. if Kind = tkInterface then
  3688. Result := PInterface(FData.FValueData.GetReferenceToRawData)^
  3689. else if (Kind in [tkClass, tkClassRef, tkUnknown]) and not Assigned(FData.FAsPointer) then
  3690. Result := Nil
  3691. else
  3692. raise EInvalidCast.Create(SErrInvalidTypecast);
  3693. end;
  3694. function TValue.ToString: String;
  3695. var
  3696. Obj : TObject;
  3697. begin
  3698. if IsEmpty then
  3699. Exit('(empty)');
  3700. case Kind of
  3701. tkWString,
  3702. tkUString : result := AsUnicodeString;
  3703. tkSString,
  3704. tkAString : result := AsAnsiString;
  3705. tkFloat : begin
  3706. Str(AsDouble:12:4,Result);
  3707. Result:=TrimLeft(Result)
  3708. end;
  3709. tkInteger : result := IntToStr(AsInteger);
  3710. tkQWord : result := IntToStr(AsUInt64);
  3711. tkInt64 : result := IntToStr(AsInt64);
  3712. tkBool : result := BoolToStr(AsBoolean, True);
  3713. tkPointer : result := '(pointer @ ' + HexStr(FData.FAsPointer) + ')';
  3714. tkInterface : result := '(interface @ ' + HexStr(PPointer(FData.FValueData.GetReferenceToRawData)^) + ')';
  3715. tkInterfaceRaw : result := '(raw interface @ ' + HexStr(FData.FAsPointer) + ')';
  3716. tkEnumeration: Result := GetEnumName(TypeInfo, Integer(AsOrdinal));
  3717. tkChar: Result := AnsiChar(FData.FAsUByte);
  3718. tkWChar: Result := UTF8Encode(WideChar(FData.FAsUWord));
  3719. tkClass :
  3720. begin
  3721. Obj:=AsObject;
  3722. if Assigned(Obj) then
  3723. Result:=Obj.ToString
  3724. else
  3725. Result:='<Nil>';
  3726. end;
  3727. {$IF SIZEOF(POINTER) = SIZEOF(CODEPOINTER)}
  3728. { if CodePointer is not the same as Pointer then it currently can't be
  3729. passed onto a array of const }
  3730. tkMethod: Result := Format('(method code=%p, data=%p)', [FData.FAsMethod.Code, FData.FAsMethod.Data]);
  3731. {$ENDIF}
  3732. else
  3733. result := '<unknown kind: '+GetEnumName(System.TypeInfo(TTypeKind),Ord(Kind))+'>';
  3734. end;
  3735. end;
  3736. function TValue.GetArrayLength: SizeInt;
  3737. var
  3738. td: PTypeData;
  3739. begin
  3740. if not IsArray then
  3741. raise EInvalidCast.Create(SErrInvalidTypecast);
  3742. if Kind = tkDynArray then
  3743. Result := DynArraySize(PPointer(FData.FValueData.GetReferenceToRawData)^)
  3744. else begin
  3745. td := TypeData;
  3746. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then
  3747. Result := FData.FArrLength
  3748. else
  3749. Result := td^.ArrayData.ElCount;
  3750. end;
  3751. end;
  3752. function TValue.GetArrayElement(AIndex: SizeInt): TValue;
  3753. var
  3754. data: Pointer;
  3755. eltype: PTypeInfo;
  3756. elsize: SizeInt;
  3757. td: PTypeData;
  3758. begin
  3759. if not IsArray then
  3760. raise EInvalidCast.Create(SErrInvalidTypecast);
  3761. if Kind = tkDynArray then begin
  3762. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  3763. eltype := TypeData^.elType2;
  3764. end else begin
  3765. td := TypeData;
  3766. eltype := td^.ArrayData.ElType;
  3767. { open array? }
  3768. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then begin
  3769. data := PPointer(FData.FValueData.GetReferenceToRawData)^;
  3770. elsize := FData.FElSize
  3771. end else begin
  3772. data := FData.FValueData.GetReferenceToRawData;
  3773. elsize := td^.ArrayData.Size div td^.ArrayData.ElCount;
  3774. end;
  3775. data := PByte(data) + AIndex * elsize;
  3776. end;
  3777. { MakeWithoutCopy? }
  3778. Make(data, eltype, Result);
  3779. end;
  3780. procedure TValue.SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
  3781. var
  3782. data: Pointer;
  3783. eltype: PTypeInfo;
  3784. elsize: SizeInt;
  3785. td, tdv: PTypeData;
  3786. begin
  3787. if not IsArray then
  3788. raise EInvalidCast.Create(SErrInvalidTypecast);
  3789. if Kind = tkDynArray then begin
  3790. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  3791. eltype := TypeData^.elType2;
  3792. end else begin
  3793. td := TypeData;
  3794. eltype := td^.ArrayData.ElType;
  3795. { open array? }
  3796. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then begin
  3797. data := PPointer(FData.FValueData.GetReferenceToRawData)^;
  3798. elsize := FData.FElSize
  3799. end else begin
  3800. data := FData.FValueData.GetReferenceToRawData;
  3801. elsize := td^.ArrayData.Size div td^.ArrayData.ElCount;
  3802. end;
  3803. data := PByte(data) + AIndex * elsize;
  3804. end;
  3805. { maybe we'll later on allow some typecasts, but for now be restrictive }
  3806. if eltype^.Kind <> AValue.Kind then
  3807. raise EInvalidCast.Create(SErrInvalidTypecast);
  3808. td := GetTypeData(eltype);
  3809. tdv := AValue.TypeData;
  3810. if ((eltype^.Kind in [tkInteger, tkBool, tkEnumeration, tkSet]) and (td^.OrdType <> tdv^.OrdType)) or
  3811. ((eltype^.Kind = tkFloat) and (td^.FloatType <> tdv^.FloatType)) then
  3812. raise EInvalidCast.Create(SErrInvalidTypecast);
  3813. if Assigned(AValue.FData.FValueData) and (eltype^.Kind <> tkSString) then
  3814. IntCopy(AValue.FData.FValueData.GetReferenceToRawData, data, eltype)
  3815. else
  3816. Move(AValue.GetReferenceToRawData^, data^, AValue.DataSize);
  3817. end;
  3818. function TValue.TryAsOrdinal(out AResult: int64): boolean;
  3819. begin
  3820. result := IsOrdinal;
  3821. if result then
  3822. AResult := AsOrdinal;
  3823. end;
  3824. function TValue.GetReferenceToRawData: Pointer;
  3825. begin
  3826. if not Assigned(FData.FTypeInfo) then
  3827. Result := Nil
  3828. else if Assigned(FData.FValueData) then
  3829. Result := FData.FValueData.GetReferenceToRawData
  3830. else begin
  3831. Result := Nil;
  3832. case Kind of
  3833. tkInteger,
  3834. tkEnumeration,
  3835. tkInt64,
  3836. tkQWord,
  3837. tkBool:
  3838. case TypeData^.OrdType of
  3839. otSByte:
  3840. Result := @FData.FAsSByte;
  3841. otUByte:
  3842. Result := @FData.FAsUByte;
  3843. otSWord:
  3844. Result := @FData.FAsSWord;
  3845. otUWord:
  3846. Result := @FData.FAsUWord;
  3847. otSLong:
  3848. Result := @FData.FAsSLong;
  3849. otULong:
  3850. Result := @FData.FAsULong;
  3851. otSQWord:
  3852. Result := @FData.FAsSInt64;
  3853. otUQWord:
  3854. Result := @FData.FAsUInt64;
  3855. end;
  3856. tkSet: begin
  3857. case TypeData^.OrdType of
  3858. otUByte: begin
  3859. case TypeData^.SetSize of
  3860. 1:
  3861. Result := @FData.FAsUByte;
  3862. 2:
  3863. Result := @FData.FAsUWord;
  3864. 3, 4:
  3865. Result := @FData.FAsULong;
  3866. 5..8:
  3867. Result := @FData.FAsUInt64;
  3868. else
  3869. { this should have gone through FAsValueData :/ }
  3870. Result := Nil;
  3871. end;
  3872. end;
  3873. otUWord:
  3874. Result := @FData.FAsUWord;
  3875. otULong:
  3876. Result := @FData.FAsULong;
  3877. else
  3878. Result := Nil;
  3879. end;
  3880. end;
  3881. tkChar:
  3882. Result := @FData.FAsUByte;
  3883. tkFloat:
  3884. case TypeData^.FloatType of
  3885. ftSingle:
  3886. Result := @FData.FAsSingle;
  3887. ftDouble:
  3888. Result := @FData.FAsDouble;
  3889. ftExtended:
  3890. Result := @FData.FAsExtended;
  3891. ftComp:
  3892. Result := @FData.FAsComp;
  3893. ftCurr:
  3894. Result := @FData.FAsCurr;
  3895. end;
  3896. tkMethod:
  3897. Result := @FData.FAsMethod;
  3898. tkClass:
  3899. Result := @FData.FAsObject;
  3900. tkWChar:
  3901. Result := @FData.FAsUWord;
  3902. tkInterfaceRaw:
  3903. Result := @FData.FAsPointer;
  3904. tkProcVar:
  3905. Result := @FData.FAsMethod.Code;
  3906. tkUChar:
  3907. Result := @FData.FAsUWord;
  3908. tkFile:
  3909. Result := @FData.FAsPointer;
  3910. tkClassRef:
  3911. Result := @FData.FAsClass;
  3912. tkPointer:
  3913. Result := @FData.FAsPointer;
  3914. tkVariant,
  3915. tkDynArray,
  3916. tkArray,
  3917. tkObject,
  3918. tkRecord,
  3919. tkInterface,
  3920. tkSString,
  3921. tkLString,
  3922. tkAString,
  3923. tkUString,
  3924. tkWString:
  3925. Assert(false, 'Managed/complex type not handled through IValueData');
  3926. else
  3927. // Silence compiler warning
  3928. end;
  3929. end;
  3930. end;
  3931. procedure TValue.ExtractRawData(ABuffer: Pointer);
  3932. begin
  3933. if Assigned(FData.FValueData) then
  3934. FData.FValueData.ExtractRawData(ABuffer)
  3935. else if Assigned(FData.FTypeInfo) then
  3936. Move((@FData.FAsPointer)^, ABuffer^, DataSize);
  3937. end;
  3938. procedure TValue.ExtractRawDataNoCopy(ABuffer: Pointer);
  3939. begin
  3940. if Assigned(FData.FValueData) then
  3941. FData.FValueData.ExtractRawDataNoCopy(ABuffer)
  3942. else if Assigned(FData.FTypeInfo) then
  3943. Move((@FData.FAsPointer)^, ABuffer^, DataSize);
  3944. end;
  3945. function Invoke(aCodeAddress: CodePointer; const aArgs: TValueArray;
  3946. aCallConv: TCallConv; aResultType: PTypeInfo; aIsStatic: Boolean;
  3947. aIsConstructor: Boolean): TValue;
  3948. var
  3949. funcargs: TFunctionCallParameterArray;
  3950. i: LongInt;
  3951. flags: TFunctionCallFlags;
  3952. begin
  3953. { sanity check }
  3954. if not Assigned(FuncCallMgr[aCallConv].Invoke) then
  3955. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  3956. { ToDo: handle IsConstructor }
  3957. if aIsConstructor then
  3958. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  3959. flags := [];
  3960. if aIsStatic then
  3961. Include(flags, fcfStatic)
  3962. else if Length(aArgs) = 0 then
  3963. raise EInvocationError.Create(SErrMissingSelfParam);
  3964. funcargs:=[];
  3965. SetLength(funcargs, Length(aArgs));
  3966. for i := Low(aArgs) to High(aArgs) do begin
  3967. funcargs[i - Low(aArgs) + Low(funcargs)].ValueRef := aArgs[i].GetReferenceToRawData;
  3968. funcargs[i - Low(aArgs) + Low(funcargs)].ValueSize := aArgs[i].DataSize;
  3969. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParamType := aArgs[i].TypeInfo;
  3970. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParamFlags := [];
  3971. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParaLocs := Nil;
  3972. end;
  3973. if Assigned(aResultType) then
  3974. TValue.Make(Nil, aResultType, Result)
  3975. else
  3976. Result := TValue.Empty;
  3977. FuncCallMgr[aCallConv].Invoke(aCodeAddress, funcargs, aCallConv, aResultType, Result.GetReferenceToRawData, flags);
  3978. end;
  3979. function Invoke(const aName: String; aCodeAddress: CodePointer; aCallConv: TCallConv; aStatic: Boolean; aInstance: TValue; constref aArgs: array of TValue; const aParams: TRttiParameterArray; aReturnType: TRttiType): TValue;
  3980. var
  3981. param: TRttiParameter;
  3982. unhidden, highs, i: SizeInt;
  3983. args: TFunctionCallParameterArray;
  3984. highargs: array of SizeInt;
  3985. restype: PTypeInfo;
  3986. resptr: Pointer;
  3987. mgr: TFunctionCallManager;
  3988. flags: TFunctionCallFlags;
  3989. hiddenVmt : Pointer;
  3990. begin
  3991. mgr := FuncCallMgr[aCallConv];
  3992. if not Assigned(mgr.Invoke) then
  3993. raise EInvocationError.CreateFmt(SErrCallConvNotSupported, [CCToStr(aCallConv)]);
  3994. if not Assigned(aCodeAddress) then
  3995. raise EInvocationError.CreateFmt(SErrInvokeNoCodeAddr, [aName]);
  3996. unhidden := 0;
  3997. highs := 0;
  3998. for param in aParams do begin
  3999. if unhidden < Length(aArgs) then begin
  4000. if pfArray in param.Flags then begin
  4001. if Assigned(aArgs[unhidden].TypeInfo) and not aArgs[unhidden].IsArray and (aArgs[unhidden].Kind <> param.ParamType.TypeKind) then
  4002. raise EInvocationError.CreateFmt(SErrInvokeArrayArgExpected, [param.Name, aName]);
  4003. end else if not (pfHidden in param.Flags) then begin
  4004. if Assigned(param.ParamType) and (aArgs[unhidden].Kind <> param.ParamType.TypeKind) then
  4005. raise EInvocationError.CreateFmt(SErrInvokeArgInvalidType, [param.Name, aName]);
  4006. end;
  4007. end;
  4008. if not (pfHidden in param.Flags) then
  4009. Inc(unhidden);
  4010. if pfHigh in param.Flags then
  4011. Inc(highs);
  4012. end;
  4013. if unhidden <> Length(aArgs) then
  4014. raise EInvocationError.CreateFmt(SErrInvokeArgCount, [aName, unhidden, Length(aArgs)]);
  4015. if Assigned(aReturnType) then begin
  4016. TValue.Make(Nil, aReturnType.FTypeInfo, Result);
  4017. resptr := Result.GetReferenceToRawData;
  4018. restype := aReturnType.FTypeInfo;
  4019. end else begin
  4020. Result := TValue.Empty;
  4021. resptr := Nil;
  4022. restype := Nil;
  4023. end;
  4024. highargs:=[];
  4025. args:=[];
  4026. SetLength(highargs, highs);
  4027. SetLength(args, Length(aParams));
  4028. unhidden := 0;
  4029. highs := 0;
  4030. for i := 0 to High(aParams) do begin
  4031. param := aParams[i];
  4032. if Assigned(param.ParamType) then
  4033. args[i].Info.ParamType := param.ParamType.FTypeInfo
  4034. else
  4035. args[i].Info.ParamType := Nil;
  4036. args[i].Info.ParamFlags := param.Flags;
  4037. args[i].Info.ParaLocs := Nil;
  4038. if pfHidden in param.Flags then begin
  4039. if pfSelf in param.Flags then
  4040. args[i].ValueRef := aInstance.GetReferenceToRawData
  4041. else if pfVmt in param.Flags then
  4042. begin
  4043. if aInstance.Kind=tkClassRef then
  4044. hiddenVmt:=aInstance.AsClass
  4045. else if aInstance.Kind=tkClass then
  4046. hiddenVmt:=aInstance.AsObject.ClassType;
  4047. args[i].ValueRef := @HiddenVmt;
  4048. end
  4049. else if pfResult in param.Flags then begin
  4050. if not Assigned(restype) then
  4051. raise EInvocationError.CreateFmt(SErrInvokeRttiDataError, [aName]);
  4052. args[i].ValueRef := resptr;
  4053. restype := Nil;
  4054. resptr := Nil;
  4055. end else if pfHigh in param.Flags then begin
  4056. { the corresponding array argument is the *previous* unhidden argument }
  4057. if aArgs[unhidden - 1].IsArray then
  4058. highargs[highs] := aArgs[unhidden - 1].GetArrayLength - 1
  4059. else if not Assigned(aArgs[unhidden - 1].TypeInfo) then
  4060. highargs[highs] := -1
  4061. else
  4062. highargs[highs] := 0;
  4063. args[i].ValueRef := @highargs[highs];
  4064. Inc(highs);
  4065. end;
  4066. end else begin
  4067. if (pfArray in param.Flags) then begin
  4068. if not Assigned(aArgs[unhidden].TypeInfo) then
  4069. args[i].ValueRef := Nil
  4070. else if aArgs[unhidden].Kind = tkDynArray then
  4071. args[i].ValueRef := PPointer(aArgs[unhidden].GetReferenceToRawData)^
  4072. else
  4073. args[i].ValueRef := aArgs[unhidden].GetReferenceToRawData;
  4074. end else
  4075. args[i].ValueRef := aArgs[unhidden].GetReferenceToRawData;
  4076. Inc(unhidden);
  4077. end;
  4078. end;
  4079. flags := [];
  4080. if aStatic then
  4081. Include(flags, fcfStatic);
  4082. mgr.Invoke(aCodeAddress, args, aCallConv, restype, resptr, flags);
  4083. end;
  4084. function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  4085. begin
  4086. if not Assigned(FuncCallMgr[aCallConv].CreateCallbackProc) then
  4087. raise ENotImplemented.Create(SErrCallbackNotImplemented);
  4088. if not Assigned(aHandler) then
  4089. raise EArgumentNilException.Create(SErrCallbackHandlerNil);
  4090. Result := FuncCallMgr[aCallConv].CreateCallbackProc(aHandler, aCallConv, aArgs, aResultType, aFlags, aContext);
  4091. end;
  4092. function CreateCallbackMethod(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  4093. begin
  4094. if not Assigned(FuncCallMgr[aCallConv].CreateCallbackMethod) then
  4095. raise ENotImplemented.Create(SErrCallbackNotImplemented);
  4096. if not Assigned(aHandler) then
  4097. raise EArgumentNilException.Create(SErrCallbackHandlerNil);
  4098. Result := FuncCallMgr[aCallConv].CreateCallbackMethod(aHandler, aCallConv, aArgs, aResultType, aFlags, aContext);
  4099. end;
  4100. function IsManaged(TypeInfo: PTypeInfo): boolean;
  4101. begin
  4102. if Assigned(TypeInfo) then
  4103. case TypeInfo^.Kind of
  4104. tkAString,
  4105. tkLString,
  4106. tkWString,
  4107. tkUString,
  4108. tkInterface,
  4109. tkVariant,
  4110. tkDynArray : Result := true;
  4111. tkArray : Result := IsManaged(GetTypeData(TypeInfo)^.ArrayData.ElType);
  4112. tkRecord,
  4113. tkObject :
  4114. with GetTypeData(TypeInfo)^.RecInitData^ do
  4115. Result := (ManagedFieldCount > 0) or Assigned(ManagementOp);
  4116. else
  4117. Result := false;
  4118. end
  4119. else
  4120. Result := false;
  4121. end;
  4122. function IsBoolType(ATypeInfo: PTypeInfo): Boolean;
  4123. begin
  4124. Result:=(ATypeInfo=TypeInfo(Boolean)) or
  4125. (ATypeInfo=TypeInfo(ByteBool)) or
  4126. (ATypeInfo=TypeInfo(WordBool)) or
  4127. (ATypeInfo=TypeInfo(LongBool));
  4128. end;
  4129. {$ifndef InLazIDE}
  4130. generic function OpenArrayToDynArrayValue<T>(constref aArray: array of T): TValue;
  4131. var
  4132. arr: specialize TArray<T>;
  4133. i: SizeInt;
  4134. begin
  4135. arr:=[];
  4136. SetLength(arr, Length(aArray));
  4137. for i := 0 to High(aArray) do
  4138. arr[i] := aArray[i];
  4139. Result := TValue.specialize From<specialize TArray<T>>(arr);
  4140. end;
  4141. {$endif}
  4142. function ArrayOfConstToTValueArray(const aValues: array of const): TValueArray;
  4143. var
  4144. I,Len: Integer;
  4145. begin
  4146. Result:=[];
  4147. Len:=Length(aValues);
  4148. SetLength(Result,Len);
  4149. for I:=0 to Len-1 do
  4150. Result[I]:=aValues[I];
  4151. end;
  4152. { TRttiPointerType }
  4153. function TRttiPointerType.GetReferredType: TRttiType;
  4154. begin
  4155. Result := GRttiPool[FUsePublishedOnly].GetType(FTypeData^.RefType);
  4156. end;
  4157. { TRttiArrayType }
  4158. function TRttiArrayType.GetDimensionCount: SizeUInt;
  4159. begin
  4160. Result := FTypeData^.ArrayData.DimCount;
  4161. end;
  4162. function TRttiArrayType.GetDimension(aIndex: SizeInt): TRttiType;
  4163. begin
  4164. if aIndex >= FTypeData^.ArrayData.DimCount then
  4165. raise ERtti.CreateFmt(SErrDimensionOutOfRange, [aIndex, FTypeData^.ArrayData.DimCount]);
  4166. Result := GRttiPool[FUsePublishedOnly].GetType(FTypeData^.ArrayData.Dims[Byte(aIndex)]);
  4167. end;
  4168. function TRttiArrayType.GetElementType: TRttiType;
  4169. begin
  4170. Result := GRttiPool[FUsePublishedOnly].GetType(FTypeData^.ArrayData.ElType);
  4171. end;
  4172. function TRttiArrayType.GetTotalElementCount: SizeInt;
  4173. begin
  4174. Result := FTypeData^.ArrayData.ElCount;
  4175. end;
  4176. { TRttiDynamicArrayType }
  4177. function TRttiDynamicArrayType.GetDeclaringUnitName: String;
  4178. begin
  4179. Result := FTypeData^.DynUnitName;
  4180. end;
  4181. function TRttiDynamicArrayType.GetElementSize: SizeUInt;
  4182. begin
  4183. Result := FTypeData^.elSize;
  4184. end;
  4185. function TRttiDynamicArrayType.GetElementType: TRttiType;
  4186. begin
  4187. Result := GRttiPool[FUsePublishedOnly].GetType(FTypeData^.ElType2);
  4188. end;
  4189. function TRttiDynamicArrayType.GetOleAutoVarType: TVarType;
  4190. begin
  4191. Result := Word(FTypeData^.varType);
  4192. end;
  4193. { TRttiRefCountedInterfaceType }
  4194. function TRttiRefCountedInterfaceType.IntfData: PInterfaceData;
  4195. begin
  4196. Result := PInterfaceData(FTypeData);
  4197. end;
  4198. function TRttiRefCountedInterfaceType.MethodTable: PIntfMethodTable;
  4199. begin
  4200. Result := IntfData^.MethodTable;
  4201. end;
  4202. function TRttiRefCountedInterfaceType.GetIntfBaseType: TRttiInterfaceType;
  4203. var
  4204. context: TRttiContext;
  4205. begin
  4206. if not Assigned(IntfData^.Parent) then
  4207. Exit(Nil);
  4208. context := TRttiContext.Create(FUsePublishedOnly);
  4209. try
  4210. Result := context.GetType(IntfData^.Parent^) as TRttiInterfaceType;
  4211. finally
  4212. context.Free;
  4213. end;
  4214. end;
  4215. function TRttiRefCountedInterfaceType.GetDeclaringUnitName: String;
  4216. begin
  4217. Result := IntfData^.UnitName;
  4218. end;
  4219. function TRttiRefCountedInterfaceType.GetGUID: TGUID;
  4220. begin
  4221. Result := IntfData^.GUID;
  4222. end;
  4223. function TRttiRefCountedInterfaceType.GetIntfFlags: TIntfFlags;
  4224. begin
  4225. Result := IntfData^.Flags;
  4226. end;
  4227. function TRttiRefCountedInterfaceType.GetIntfType: TInterfaceType;
  4228. begin
  4229. Result := itRefCounted;
  4230. end;
  4231. { TRttiRawInterfaceType }
  4232. function TRttiRawInterfaceType.IntfData: PInterfaceRawData;
  4233. begin
  4234. Result := PInterfaceRawData(FTypeData);
  4235. end;
  4236. function TRttiRawInterfaceType.MethodTable: PIntfMethodTable;
  4237. begin
  4238. { currently there is none! }
  4239. Result := Nil;
  4240. end;
  4241. function TRttiRawInterfaceType.GetIntfBaseType: TRttiInterfaceType;
  4242. var
  4243. context: TRttiContext;
  4244. begin
  4245. if not Assigned(IntfData^.Parent) then
  4246. Exit(Nil);
  4247. context := TRttiContext.Create(FUsePublishedOnly);
  4248. try
  4249. Result := context.GetType(IntfData^.Parent^) as TRttiInterfaceType;
  4250. finally
  4251. context.Free;
  4252. end;
  4253. end;
  4254. function TRttiRawInterfaceType.GetDeclaringUnitName: String;
  4255. begin
  4256. Result := IntfData^.UnitName;
  4257. end;
  4258. function TRttiRawInterfaceType.GetGUID: TGUID;
  4259. begin
  4260. Result := IntfData^.IID;
  4261. end;
  4262. function TRttiRawInterfaceType.GetGUIDStr: String;
  4263. begin
  4264. Result := IntfData^.IIDStr;
  4265. end;
  4266. function TRttiRawInterfaceType.GetIntfFlags: TIntfFlags;
  4267. begin
  4268. Result := IntfData^.Flags;
  4269. end;
  4270. function TRttiRawInterfaceType.GetIntfType: TInterfaceType;
  4271. begin
  4272. Result := itRaw;
  4273. end;
  4274. { TRttiVmtMethodParameter }
  4275. function TRttiVmtMethodParameter.GetHandle: Pointer;
  4276. begin
  4277. Result := FVmtMethodParam;
  4278. end;
  4279. function TRttiVmtMethodParameter.GetName: String;
  4280. begin
  4281. Result := FVmtMethodParam^.Name;
  4282. end;
  4283. function TRttiVmtMethodParameter.GetFlags: TParamFlags;
  4284. begin
  4285. Result := FVmtMethodParam^.Flags;
  4286. end;
  4287. function TRttiVmtMethodParameter.GetParamType: TRttiType;
  4288. var
  4289. context: TRttiContext;
  4290. begin
  4291. if not Assigned(FVmtMethodParam^.ParamType) then
  4292. Exit(Nil);
  4293. context := TRttiContext.Create(FUsePublishedOnly);
  4294. try
  4295. Result := context.GetType(FVmtMethodParam^.ParamType^);
  4296. finally
  4297. context.Free;
  4298. end;
  4299. end;
  4300. constructor TRttiVmtMethodParameter.Create(AVmtMethodParam: PVmtMethodParam);
  4301. begin
  4302. inherited Create;
  4303. FVmtMethodParam := AVmtMethodParam;
  4304. end;
  4305. function TRttiVmtMethodParameter.GetAttributes: TCustomAttributeArray;
  4306. begin
  4307. Result:=Nil;
  4308. end;
  4309. { TRttiMethodTypeParameter }
  4310. function TRttiMethodTypeParameter.GetHandle: Pointer;
  4311. begin
  4312. Result := fHandle;
  4313. end;
  4314. function TRttiMethodTypeParameter.GetName: String;
  4315. begin
  4316. Result := fName;
  4317. end;
  4318. function TRttiMethodTypeParameter.GetFlags: TParamFlags;
  4319. begin
  4320. Result := fFlags;
  4321. end;
  4322. function TRttiMethodTypeParameter.GetParamType: TRttiType;
  4323. var
  4324. context: TRttiContext;
  4325. begin
  4326. context := TRttiContext.Create(FUsePublishedOnly);
  4327. try
  4328. Result := context.GetType(FType);
  4329. finally
  4330. context.Free;
  4331. end;
  4332. end;
  4333. constructor TRttiMethodTypeParameter.Create(aHandle: Pointer; const aName: String; aFlags: TParamFlags; aType: PTypeInfo);
  4334. begin
  4335. fHandle := aHandle;
  4336. fName := aName;
  4337. fFlags := aFlags;
  4338. fType := aType;
  4339. end;
  4340. function TRttiMethodTypeParameter.GetAttributes: TCustomAttributeArray;
  4341. begin
  4342. Result:=Nil;
  4343. end;
  4344. { TRttiIntfMethod }
  4345. function TRttiIntfMethod.GetHandle: Pointer;
  4346. begin
  4347. Result := FIntfMethodEntry;
  4348. end;
  4349. function TRttiIntfMethod.GetName: String;
  4350. begin
  4351. Result := FIntfMethodEntry^.Name;
  4352. end;
  4353. function TRttiIntfMethod.GetCallingConvention: TCallConv;
  4354. begin
  4355. Result := FIntfMethodEntry^.CC;
  4356. end;
  4357. function TRttiIntfMethod.GetCodeAddress: CodePointer;
  4358. begin
  4359. Result := Nil;
  4360. end;
  4361. function TRttiIntfMethod.GetDispatchKind: TDispatchKind;
  4362. begin
  4363. Result := dkInterface;
  4364. end;
  4365. function TRttiIntfMethod.GetHasExtendedInfo: Boolean;
  4366. begin
  4367. Result := True;
  4368. end;
  4369. function TRttiIntfMethod.GetIsClassMethod: Boolean;
  4370. begin
  4371. Result := False;
  4372. end;
  4373. function TRttiIntfMethod.GetIsConstructor: Boolean;
  4374. begin
  4375. Result := False;
  4376. end;
  4377. function TRttiIntfMethod.GetIsDestructor: Boolean;
  4378. begin
  4379. Result := False;
  4380. end;
  4381. function TRttiIntfMethod.GetIsStatic: Boolean;
  4382. begin
  4383. Result := False;
  4384. end;
  4385. function TRttiIntfMethod.GetMethodKind: TMethodKind;
  4386. begin
  4387. Result := FIntfMethodEntry^.Kind;
  4388. end;
  4389. function TRttiIntfMethod.GetReturnType: TRttiType;
  4390. var
  4391. context: TRttiContext;
  4392. begin
  4393. if not Assigned(FIntfMethodEntry^.ResultType) then
  4394. Exit(Nil);
  4395. context := TRttiContext.Create(FUsePublishedOnly);
  4396. try
  4397. Result := context.GetType(FIntfMethodEntry^.ResultType^);
  4398. finally
  4399. context.Free;
  4400. end;
  4401. end;
  4402. function TRttiIntfMethod.GetVirtualIndex: SmallInt;
  4403. begin
  4404. Result := FIndex;
  4405. end;
  4406. constructor TRttiIntfMethod.Create(AParent: TRttiType; AIntfMethodEntry: PIntfMethodEntry; AIndex: SmallInt);
  4407. begin
  4408. inherited Create(AParent);
  4409. FIntfMethodEntry := AIntfMethodEntry;
  4410. FIndex := AIndex;
  4411. end;
  4412. function TRttiIntfMethod.GetAttributes: TCustomAttributeArray;
  4413. {var
  4414. i: SizeInt;
  4415. at: PAttributeTable;}
  4416. begin
  4417. FAttributes:=Nil;
  4418. FAttributesResolved:=True;
  4419. { // needs extended RTTI branch
  4420. if not FAttributesResolved then
  4421. begin
  4422. at := FIntfMethodEntry^.Attributes
  4423. if Assigned(at) then
  4424. begin
  4425. SetLength(FAttributes, at^.AttributeCount);
  4426. for i := 0 to High(FAttributes) do
  4427. FAttributes[i] := TCustomAttribute({$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}TypInfo.GetAttribute(at, i));
  4428. end;
  4429. FAttributesResolved:=true;
  4430. end;
  4431. }
  4432. result := FAttributes;
  4433. end;
  4434. function TRttiIntfMethod.GetParameters(aWithHidden: Boolean): TRttiParameterArray;
  4435. var
  4436. param: PVmtMethodParam;
  4437. total, visible: SizeInt;
  4438. context: TRttiContext;
  4439. obj: TRttiObject;
  4440. begin
  4441. if aWithHidden and (Length(FParamsAll) > 0) then
  4442. Exit(FParamsAll);
  4443. if not aWithHidden and (Length(FParams) > 0) then
  4444. Exit(FParams);
  4445. if FIntfMethodEntry^.ParamCount = 0 then
  4446. Exit(Nil);
  4447. SetLength(FParams, FIntfMethodEntry^.ParamCount);
  4448. SetLength(FParamsAll, FIntfMethodEntry^.ParamCount);
  4449. context := TRttiContext.Create(FUsePublishedOnly);
  4450. try
  4451. total := 0;
  4452. visible := 0;
  4453. param := FIntfMethodEntry^.Param[0];
  4454. while total < FIntfMethodEntry^.ParamCount do begin
  4455. obj := context.GetByHandle(param);
  4456. if Assigned(obj) then
  4457. FParamsAll[total] := obj as TRttiVmtMethodParameter
  4458. else begin
  4459. FParamsAll[total] := TRttiVmtMethodParameter.Create(param);
  4460. context.AddObject(FParamsAll[total]);
  4461. end;
  4462. if not (pfHidden in param^.Flags) then begin
  4463. FParams[visible] := FParamsAll[total];
  4464. Inc(visible);
  4465. end;
  4466. param := param^.Next;
  4467. Inc(total);
  4468. end;
  4469. if visible <> total then
  4470. SetLength(FParams, visible);
  4471. finally
  4472. context.Free;
  4473. end;
  4474. if aWithHidden then
  4475. Result := FParamsAll
  4476. else
  4477. Result := FParams;
  4478. end;
  4479. { TRttiInt64Type }
  4480. function TRttiInt64Type.GetMaxValue: Int64;
  4481. begin
  4482. Result := FTypeData^.MaxInt64Value;
  4483. end;
  4484. function TRttiInt64Type.GetMinValue: Int64;
  4485. begin
  4486. Result := FTypeData^.MinInt64Value;
  4487. end;
  4488. function TRttiInt64Type.GetUnsigned: Boolean;
  4489. begin
  4490. Result := FTypeData^.OrdType = otUQWord;
  4491. end;
  4492. function TRttiInt64Type.GetTypeSize: integer;
  4493. begin
  4494. Result := SizeOf(QWord);
  4495. end;
  4496. { TRttiOrdinalType }
  4497. function TRttiOrdinalType.GetMaxValue: LongInt;
  4498. begin
  4499. Result := FTypeData^.MaxValue;
  4500. end;
  4501. function TRttiOrdinalType.GetMinValue: LongInt;
  4502. begin
  4503. Result := FTypeData^.MinValue;
  4504. end;
  4505. function TRttiOrdinalType.GetOrdType: TOrdType;
  4506. begin
  4507. Result := FTypeData^.OrdType;
  4508. end;
  4509. function TRttiOrdinalType.GetTypeSize: Integer;
  4510. begin
  4511. case OrdType of
  4512. otSByte,
  4513. otUByte:
  4514. Result := SizeOf(Byte);
  4515. otSWord,
  4516. otUWord:
  4517. Result := SizeOf(Word);
  4518. otSLong,
  4519. otULong:
  4520. Result := SizeOf(LongWord);
  4521. otSQWord,
  4522. otUQWord:
  4523. Result := SizeOf(QWord);
  4524. end;
  4525. end;
  4526. { TRttiEnumerationType }
  4527. function TRttiEnumerationType.GetUnderlyingType: TRttiType;
  4528. begin
  4529. Result:=GRttiPool[FUsePublishedOnly].GetType(GetTypeData(Handle)^.BaseType);
  4530. end;
  4531. function TRttiEnumerationType.GetNames: TStringDynArray;
  4532. var
  4533. I : Integer;
  4534. begin
  4535. Result:=[];
  4536. SetLength(Result,GetEnumNameCount(Handle));
  4537. For I:=0 to Length(Result)-1 do
  4538. Result[I]:=GetEnumName(Handle,I);
  4539. end;
  4540. generic class function TRttiEnumerationType.GetName<T{: enum}>(AValue: T): string;
  4541. var
  4542. Info : PTypeInfo;
  4543. begin
  4544. Info:=PtypeInfo(TypeInfo(T));
  4545. if Not (Info^.kind in [tkBool,tkEnumeration]) then
  4546. raise EInvalidCast.CreateFmt(SErrNotEnumeratedType,[PtypeInfo(TypeInfo(T))^.name]);
  4547. Result:=GetEnumName(Info,Ord(aValue))
  4548. end;
  4549. generic class function TRttiEnumerationType.GetValue<T{: enum}>(const AName: string): T;
  4550. var
  4551. Info : PTypeInfo;
  4552. begin
  4553. Info:=PtypeInfo(TypeInfo(T));
  4554. if Not (Info^.kind in [tkBool,tkEnumeration]) then
  4555. raise EInvalidCast.CreateFmt(SErrNotEnumeratedType,[PtypeInfo(TypeInfo(T))^.name]);
  4556. Result:=T(GetEnumValue(Info,aName))
  4557. end;
  4558. { TRttiFloatType }
  4559. function TRttiFloatType.GetFloatType: TFloatType;
  4560. begin
  4561. result := FTypeData^.FloatType;
  4562. end;
  4563. function TRttiFloatType.GetTypeSize: integer;
  4564. begin
  4565. case FloatType of
  4566. ftSingle:
  4567. Result := SizeOf(Single);
  4568. ftDouble:
  4569. Result := SizeOf(Double);
  4570. ftExtended:
  4571. Result := SizeOf(Extended);
  4572. ftComp:
  4573. Result := SizeOf(Comp);
  4574. ftCurr:
  4575. Result := SizeOf(Currency);
  4576. end;
  4577. end;
  4578. { TRttiParameter }
  4579. function TRttiParameter.ToString: String;
  4580. var
  4581. f: TParamFlags;
  4582. n: String;
  4583. t: TRttiType;
  4584. begin
  4585. if FString = '' then begin
  4586. f := Flags;
  4587. if pfVar in f then
  4588. FString := 'var'
  4589. else if pfConst in f then
  4590. FString := 'const'
  4591. else if pfOut in f then
  4592. FString := 'out'
  4593. else if pfConstRef in f then
  4594. FString := 'constref';
  4595. if FString <> '' then
  4596. FString := FString + ' ';
  4597. n := Name;
  4598. if n = '' then
  4599. n := '<unknown>';
  4600. FString := FString + n;
  4601. t := ParamType;
  4602. if Assigned(t) then begin
  4603. FString := FString + ': ';
  4604. if pfArray in flags then
  4605. FString := 'array of ';
  4606. FString := FString + t.Name;
  4607. end;
  4608. end;
  4609. Result := FString;
  4610. end;
  4611. { TMethodImplementation }
  4612. function TMethodImplementation.GetCodeAddress: CodePointer;
  4613. begin
  4614. Result := fLowLevelCallback.CodeAddress;
  4615. end;
  4616. procedure TMethodImplementation.InitArgs;
  4617. var
  4618. i, refargs: SizeInt;
  4619. begin
  4620. i := 0;
  4621. refargs := 0;
  4622. SetLength(fRefArgs, Length(fArgs));
  4623. while i < Length(fArgs) do begin
  4624. if (fArgs[i].ParamFlags * [pfVar, pfOut] <> []) and not (pfHidden in fArgs[i].ParamFlags) then begin
  4625. fRefArgs[refargs] := fArgLen;
  4626. Inc(refargs);
  4627. end;
  4628. if pfArray in fArgs[i].ParamFlags then begin
  4629. Inc(i);
  4630. if (i = Length(fArgs)) or not (pfHigh in fArgs[i].ParamFlags) then
  4631. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  4632. Inc(fArgLen);
  4633. end else if not (pfHidden in fArgs[i].ParamFlags) or (pfSelf in fArgs[i].ParamFlags) then
  4634. Inc(fArgLen)
  4635. else if (pfResult in fArgs[i].ParamFlags) then
  4636. fResult := fArgs[i].ParamType;
  4637. Inc(i);
  4638. end;
  4639. SetLength(fRefArgs, refargs);
  4640. end;
  4641. procedure TMethodImplementation.HandleCallback(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
  4642. var
  4643. i, argidx, validx: SizeInt;
  4644. args: TValueArray;
  4645. res: TValue;
  4646. begin
  4647. Assert(fArgLen = Length(aArgs), 'Length of arguments does not match');
  4648. args:=[];
  4649. SetLength(args, fArgLen);
  4650. argidx := 0;
  4651. validx := 0;
  4652. i := 0;
  4653. while i < Length(fArgs) do begin
  4654. if pfArray in fArgs[i].ParamFlags then begin
  4655. Inc(validx);
  4656. Inc(i);
  4657. Assert((i < Length(fArgs)) and (pfHigh in fArgs[i].ParamFlags), 'Expected high parameter after open array parameter');
  4658. TValue.MakeOpenArray(aArgs[validx - 1], SizeInt(aArgs[validx]), fArgs[i].ParamType, args[argidx]);
  4659. Inc(argidx);
  4660. Inc(validx);
  4661. end else if not (pfHidden in fArgs[i].ParamFlags) or (pfSelf in fArgs[i].ParamFlags) then begin
  4662. if Assigned(fArgs[i].ParamType) then
  4663. TValue.Make(aArgs[validx], fArgs[i].ParamType, args[argidx])
  4664. else
  4665. TValue.Make(@aArgs[validx], TypeInfo(Pointer), args[argidx]);
  4666. Inc(argidx);
  4667. Inc(validx);
  4668. end;
  4669. Inc(i);
  4670. end;
  4671. if Assigned(fCallbackMethod) then
  4672. fCallbackMethod(aContext, args, res)
  4673. else
  4674. fCallbackProc(aContext, args, res);
  4675. { copy back var/out parameters }
  4676. for i := 0 to High(fRefArgs) do begin
  4677. args[fRefArgs[i]].ExtractRawData(aArgs[fRefArgs[i]]);
  4678. end;
  4679. if Assigned(fResult) then
  4680. res.ExtractRawData(aResult);
  4681. end;
  4682. constructor TMethodImplementation.Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod);
  4683. begin
  4684. fCC := aCC;
  4685. fArgs := aArgs;
  4686. fResult := aResult;
  4687. fFlags := aFlags;
  4688. fCallbackMethod := aCallback;
  4689. InitArgs;
  4690. fLowLevelCallback := CreateCallbackMethod(@HandleCallback, fCC, aArgs, aResult, aFlags, aUserData);
  4691. if not Assigned(fLowLevelCallback) then
  4692. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  4693. end;
  4694. constructor TMethodImplementation.Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackProc);
  4695. begin
  4696. fCC := aCC;
  4697. fArgs := aArgs;
  4698. fResult := aResult;
  4699. fFlags := aFlags;
  4700. fCallbackProc := aCallback;
  4701. InitArgs;
  4702. fLowLevelCallback := CreateCallbackMethod(@HandleCallback, fCC, aArgs, aResult, aFlags, aUserData);
  4703. if not Assigned(fLowLevelCallback) then
  4704. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  4705. end;
  4706. constructor TMethodImplementation.Create;
  4707. begin
  4708. raise EInvalidOpException.Create(SErrMethodImplCreateNoArg);
  4709. end;
  4710. destructor TMethodImplementation.Destroy;
  4711. begin
  4712. fLowLevelCallback.Free;
  4713. inherited Destroy;
  4714. end;
  4715. { TRttiMethod }
  4716. function TRttiMethod.GetHasExtendedInfo: Boolean;
  4717. begin
  4718. Result := True;
  4719. end;
  4720. function TRttiMethod.GetFlags: TFunctionCallFlags;
  4721. begin
  4722. Result := [];
  4723. if IsStatic then
  4724. Include(Result, fcfStatic);
  4725. end;
  4726. function TRttiMethod.GetParameters: TRttiParameterArray;
  4727. begin
  4728. Result := GetParameters(False);
  4729. end;
  4730. function TRttiMethod.ToString: String;
  4731. var
  4732. ret: TRttiType;
  4733. n: String;
  4734. params: TRttiParameterArray;
  4735. i: LongInt;
  4736. begin
  4737. if FString = '' then begin
  4738. n := Name;
  4739. if n = '' then
  4740. n := '<unknown>';
  4741. if not HasExtendedInfo then begin
  4742. FString := 'method ' + n;
  4743. end else begin
  4744. ret := ReturnType;
  4745. if IsClassMethod then
  4746. FString := 'class ';
  4747. if IsConstructor then
  4748. FString := FString + 'constructor'
  4749. else if IsDestructor then
  4750. FString := FString + 'destructor'
  4751. else if Assigned(ret) then
  4752. FString := FString + 'function'
  4753. else
  4754. FString := FString + 'procedure';
  4755. FString := FString + ' ' + n;
  4756. params := GetParameters;
  4757. if Length(params) > 0 then begin
  4758. FString := FString + '(';
  4759. for i := 0 to High(params) do begin
  4760. if i > 0 then
  4761. FString := FString + '; ';
  4762. FString := FString + params[i].ToString;
  4763. end;
  4764. FString := FString + ')';
  4765. end;
  4766. if Assigned(ret) then
  4767. FString := FString + ': ' + ret.Name;
  4768. if IsStatic then
  4769. FString := FString + '; static';
  4770. end;
  4771. end;
  4772. Result := FString;
  4773. end;
  4774. function TRttiMethod.Invoke(aInstance: TObject; const aArgs: array of TValue): TValue;
  4775. var
  4776. instance: TValue;
  4777. begin
  4778. TValue.Make(@aInstance, TypeInfo(TObject), instance);
  4779. Result := Invoke(instance, aArgs);
  4780. end;
  4781. function TRttiMethod.Invoke(aInstance: TClass; const aArgs: array of TValue): TValue;
  4782. var
  4783. instance: TValue;
  4784. begin
  4785. TValue.Make(@aInstance, TypeInfo(TClass), instance);
  4786. Result := Invoke(instance, aArgs);
  4787. end;
  4788. function TRttiMethod.Invoke(aInstance: TValue; const aArgs: array of TValue): TValue;
  4789. var
  4790. addr: CodePointer;
  4791. vmt: PCodePointer;
  4792. begin
  4793. if not HasExtendedInfo then
  4794. raise EInvocationError.Create(SErrInvokeInsufficientRtti);
  4795. if IsStatic and not aInstance.IsEmpty then
  4796. raise EInvocationError.CreateFmt(SErrInvokeStaticNoSelf, [Name]);
  4797. if not IsStatic and aInstance.IsEmpty then
  4798. raise EInvocationError.CreateFmt(SErrInvokeNotStaticNeedsSelf, [Name]);
  4799. if not IsStatic and IsClassMethod and not aInstance.IsClass then
  4800. raise EInvocationError.CreateFmt(SErrInvokeClassMethodClassSelf, [Name]);
  4801. addr := Nil;
  4802. if IsStatic or (GetVirtualIndex=-1) then
  4803. addr := CodeAddress
  4804. else
  4805. begin
  4806. vmt := Nil;
  4807. if aInstance.Kind in [tkInterface, tkInterfaceRaw] then
  4808. vmt := PCodePointer(PPPointer(aInstance.GetReferenceToRawData)^^);
  4809. { ToDo }
  4810. if Assigned(vmt) then
  4811. addr := vmt[VirtualIndex];
  4812. end;
  4813. Result := {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Rtti.Invoke(Name, addr, CallingConvention, IsStatic, aInstance, aArgs, GetParameters(True), ReturnType);
  4814. end;
  4815. function TRttiMethod.CreateImplementation(aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod): TMethodImplementation;
  4816. var
  4817. params: TRttiParameterArray;
  4818. args: specialize TArray<TFunctionCallParameterInfo>;
  4819. res: PTypeInfo;
  4820. restype: TRttiType;
  4821. resinparam: Boolean;
  4822. i: SizeInt;
  4823. begin
  4824. if not Assigned(aCallback) then
  4825. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  4826. resinparam := False;
  4827. params := GetParameters(True);
  4828. args:=[];
  4829. SetLength(args, Length(params));
  4830. for i := 0 to High(params) do begin
  4831. if Assigned(params[i].ParamType) then
  4832. args[i].ParamType := params[i].ParamType.FTypeInfo
  4833. else
  4834. args[i].ParamType := Nil;
  4835. args[i].ParamFlags := params[i].Flags;
  4836. args[i].ParaLocs := Nil;
  4837. if pfResult in params[i].Flags then
  4838. resinparam := True;
  4839. end;
  4840. restype := GetReturnType;
  4841. if Assigned(restype) and not resinparam then
  4842. res := restype.FTypeInfo
  4843. else
  4844. res := Nil;
  4845. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, aUserData, aCallback);
  4846. end;
  4847. function TRttiMethod.CreateImplementation(aUserData: Pointer; aCallback: TMethodImplementationCallbackProc): TMethodImplementation;
  4848. var
  4849. params: TRttiParameterArray;
  4850. args: specialize TArray<TFunctionCallParameterInfo>;
  4851. res: PTypeInfo;
  4852. restype: TRttiType;
  4853. resinparam: Boolean;
  4854. i: SizeInt;
  4855. begin
  4856. if not Assigned(aCallback) then
  4857. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  4858. resinparam := False;
  4859. params := GetParameters(True);
  4860. args:=[];
  4861. SetLength(args, Length(params));
  4862. for i := 0 to High(params) do begin
  4863. if Assigned(params[i].ParamType) then
  4864. args[i].ParamType := params[i].ParamType.FTypeInfo
  4865. else
  4866. args[i].ParamType := Nil;
  4867. args[i].ParamFlags := params[i].Flags;
  4868. args[i].ParaLocs := Nil;
  4869. if pfResult in params[i].Flags then
  4870. resinparam := True;
  4871. end;
  4872. restype := GetReturnType;
  4873. if Assigned(restype) and not resinparam then
  4874. res := restype.FTypeInfo
  4875. else
  4876. res := Nil;
  4877. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, aUserData, aCallback);
  4878. end;
  4879. { TRttiIndexedProperty }
  4880. procedure TRttiIndexedProperty.GetAccessors;
  4881. var
  4882. context: TRttiContext;
  4883. obj: TRttiObject;
  4884. begin
  4885. if Assigned(FReadMethod) or Assigned(FWriteMethod) or
  4886. not IsReadable and not IsWritable then
  4887. Exit;
  4888. // yet not implemented
  4889. end;
  4890. function TRttiIndexedProperty.GetPropertyType: TRttiType;
  4891. var
  4892. context: TRttiContext;
  4893. begin
  4894. context := TRttiContext.Create(FUsePublishedOnly);
  4895. try
  4896. Result := context.GetType(FPropInfo^.PropType);
  4897. finally
  4898. context.Free;
  4899. end;
  4900. end;
  4901. function TRttiIndexedProperty.GetIsReadable: boolean;
  4902. begin
  4903. Result := Assigned(FPropInfo^.GetProc);
  4904. end;
  4905. function TRttiIndexedProperty.GetIsWritable: boolean;
  4906. begin
  4907. Result := Assigned(FPropInfo^.SetProc);
  4908. end;
  4909. function TRttiIndexedProperty.GetReadMethod: TRttiMethod;
  4910. begin
  4911. //Result := FPropInfo^.GetProc;
  4912. Result := nil;
  4913. raise ENotImplemented.Create(SErrNotImplementedRtti);
  4914. end;
  4915. function TRttiIndexedProperty.GetWriteMethod: TRttiMethod;
  4916. begin
  4917. //Result := FPropInfo^.SetProc;
  4918. Result := nil;
  4919. raise ENotImplemented.Create(SErrNotImplementedRtti);
  4920. end;
  4921. function TRttiIndexedProperty.GetReadProc: CodePointer;
  4922. begin
  4923. Result := FPropInfo^.GetProc;
  4924. end;
  4925. function TRttiIndexedProperty.GetWriteProc: CodePointer;
  4926. begin
  4927. Result := FPropInfo^.SetProc;
  4928. end;
  4929. function TRttiIndexedProperty.GetName: string;
  4930. begin
  4931. Result := FPropInfo^.Name;
  4932. end;
  4933. function TRttiIndexedProperty.GetHandle: Pointer;
  4934. begin
  4935. Result := FPropInfo;
  4936. end;
  4937. constructor TRttiIndexedProperty.Create(AParent: TRttiType; APropInfo: PPropInfo);
  4938. begin
  4939. inherited Create(AParent);
  4940. FPropInfo := APropInfo;
  4941. end;
  4942. destructor TRttiIndexedProperty.Destroy;
  4943. var
  4944. attr: TCustomAttribute;
  4945. begin
  4946. for attr in FAttributes do
  4947. attr.Free;
  4948. inherited Destroy;
  4949. end;
  4950. function TRttiIndexedProperty.GetAttributes: TCustomAttributeArray;
  4951. var
  4952. i: SizeInt;
  4953. at: PAttributeTable;
  4954. begin
  4955. if not FAttributesResolved then
  4956. begin
  4957. at := FPropInfo^.AttributeTable;
  4958. if Assigned(at) then
  4959. begin
  4960. SetLength(FAttributes, at^.AttributeCount);
  4961. for i := 0 to High(FAttributes) do
  4962. FAttributes[i] := TCustomAttribute({$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}TypInfo.GetAttribute(at, i));
  4963. end;
  4964. FAttributesResolved:=true;
  4965. end;
  4966. result := FAttributes;
  4967. end;
  4968. function TRttiIndexedProperty.GetValue(aInstance: Pointer;
  4969. const aArgs: array of TValue): TValue;
  4970. var
  4971. getter: TRttiMethod;
  4972. begin
  4973. getter := ReadMethod;
  4974. if getter = nil then
  4975. raise EPropertyError.CreateFmt(SErrCannotReadIndexedProperty, [Name]);
  4976. if getter.IsStatic or getter.IsClassMethod then
  4977. Result := getter.Invoke(TClass(aInstance), aArgs)
  4978. else
  4979. Result := getter.Invoke(TObject(aInstance), aArgs);
  4980. end;
  4981. procedure TRttiIndexedProperty.SetValue(aInstance: Pointer;
  4982. const aArgs: array of TValue; const aValue: TValue);
  4983. var
  4984. setter: TRttiMethod;
  4985. argsV: TValueArray;
  4986. i: Integer;
  4987. begin
  4988. setter := WriteMethod;
  4989. if setter = nil then
  4990. raise EPropertyError.CreateFmt(SErrCannotWriteToIndexedProperty, [Name]);
  4991. SetLength(argsV, Length(aArgs) + 1);
  4992. for i := 0 to High(aArgs) do
  4993. argsV[i] := aArgs[i];
  4994. argsV[Length(aArgs)] := aValue;
  4995. if setter.IsStatic or setter.IsClassMethod then
  4996. setter.Invoke(TClass(aInstance), argsV)
  4997. else
  4998. setter.Invoke(TObject(aInstance), argsV);
  4999. end;
  5000. function TRttiIndexedProperty.ToString: string;
  5001. var
  5002. params: PPropParams;
  5003. param: TVmtMethodParam;
  5004. i: Integer;
  5005. begin
  5006. Result := 'indexed property ' + Name + '[';
  5007. params := FPropInfo^.PropParams;
  5008. for i := 0 to params^.Count - 2 do
  5009. begin
  5010. param := params^.Params[i];
  5011. Result := Result + param.Name + ': ' + param.ParamType^^.Name + ', ';
  5012. end;
  5013. param := params^.Params[params^.Count - 1];
  5014. Result := Result + param.Name + ': ' + param.ParamType^^.Name + ']: ' + PropertyType.Name;
  5015. end;
  5016. { TRttiInvokableType }
  5017. function TRttiInvokableType.GetParameters: TRttiParameterArray;
  5018. begin
  5019. Result := GetParameters(False);
  5020. end;
  5021. function TRttiInvokableType.CreateImplementation(aCallback: TCallbackMethod): TMethodImplementation;
  5022. var
  5023. params: TRttiParameterArray;
  5024. args: specialize TArray<TFunctionCallParameterInfo>;
  5025. res: PTypeInfo;
  5026. restype: TRttiType;
  5027. resinparam: Boolean;
  5028. i: SizeInt;
  5029. begin
  5030. if not Assigned(aCallback) then
  5031. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  5032. resinparam := False;
  5033. params := GetParameters(True);
  5034. args:=[];
  5035. SetLength(args, Length(params));
  5036. for i := 0 to High(params) do begin
  5037. if Assigned(params[i].ParamType) then
  5038. args[i].ParamType := params[i].ParamType.FTypeInfo
  5039. else
  5040. args[i].ParamType := Nil;
  5041. args[i].ParamFlags := params[i].Flags;
  5042. args[i].ParaLocs := Nil;
  5043. if pfResult in params[i].Flags then
  5044. resinparam := True;
  5045. end;
  5046. restype := GetReturnType;
  5047. if Assigned(restype) and not resinparam then
  5048. res := restype.FTypeInfo
  5049. else
  5050. res := Nil;
  5051. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, Self, TMethodImplementationCallbackMethod(aCallback));
  5052. end;
  5053. function TRttiInvokableType.CreateImplementation(aCallback: TCallbackProc): TMethodImplementation;
  5054. var
  5055. params: TRttiParameterArray;
  5056. args: specialize TArray<TFunctionCallParameterInfo>;
  5057. res: PTypeInfo;
  5058. restype: TRttiType;
  5059. resinparam: Boolean;
  5060. i: SizeInt;
  5061. begin
  5062. if not Assigned(aCallback) then
  5063. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  5064. resinparam := False;
  5065. params := GetParameters(True);
  5066. args:=[];
  5067. SetLength(args, Length(params));
  5068. for i := 0 to High(params) do begin
  5069. if Assigned(params[i].ParamType) then
  5070. args[i].ParamType := params[i].ParamType.FTypeInfo
  5071. else
  5072. args[i].ParamType := Nil;
  5073. args[i].ParamFlags := params[i].Flags;
  5074. args[i].ParaLocs := Nil;
  5075. if pfResult in params[i].Flags then
  5076. resinparam := True;
  5077. end;
  5078. restype := GetReturnType;
  5079. if Assigned(restype) and not resinparam then
  5080. res := restype.FTypeInfo
  5081. else
  5082. res := Nil;
  5083. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, Self, TMethodImplementationCallbackProc(aCallback));
  5084. end;
  5085. function TRttiInvokableType.ToString: string;
  5086. var
  5087. P : TRTTIParameter;
  5088. A : TRTTIParameterArray;
  5089. I : integer;
  5090. RT : TRttiType;
  5091. begin
  5092. RT:=GetReturnType;
  5093. if RT=nil then
  5094. Result:=name+' = procedure ('
  5095. else
  5096. Result:=name+' = function (';
  5097. A:=GetParameters(False);
  5098. for I:=0 to Length(a)-1 do
  5099. begin
  5100. P:=A[I];
  5101. if I>0 then
  5102. Result:=Result+'; ';
  5103. Result:=Result+P.Name;
  5104. if Assigned(P.ParamType) then
  5105. Result:=Result+' : '+P.ParamType.Name;
  5106. end;
  5107. result:=Result+')';
  5108. if Assigned(RT) then
  5109. Result:=Result+' : '+RT.Name;
  5110. end;
  5111. { TRttiMethodType }
  5112. function TRttiMethodType.GetParameters(aWithHidden: Boolean): TRttiParameterArray;
  5113. type
  5114. TParamInfo = record
  5115. Handle: Pointer;
  5116. Flags: TParamFlags;
  5117. Name: String;
  5118. end;
  5119. PParamFlags = ^TParamFlags;
  5120. PCallConv = ^TCallConv;
  5121. PPPTypeInfo = ^PPTypeInfo;
  5122. var
  5123. infos: array of TParamInfo;
  5124. total, visible, i: SizeInt;
  5125. ptr: PByte;
  5126. paramtypes: PPPTypeInfo;
  5127. paramtype: PTypeInfo;
  5128. context: TRttiContext;
  5129. obj: TRttiObject;
  5130. begin
  5131. if aWithHidden and (Length(FParamsAll) > 0) then
  5132. Exit(FParamsAll);
  5133. if not aWithHidden and (Length(FParams) > 0) then
  5134. Exit(FParams);
  5135. ptr := @FTypeData^.ParamList[0];
  5136. visible := 0;
  5137. total := 0;
  5138. if FTypeData^.ParamCount > 0 then begin
  5139. infos:=[];
  5140. SetLength(infos, FTypeData^.ParamCount);
  5141. while total < FTypeData^.ParamCount do begin
  5142. { align }
  5143. ptr := AlignTParamFlags(ptr);
  5144. infos[total].Handle := ptr;
  5145. infos[total].Flags := PParamFlags(ptr)^;
  5146. Inc(ptr, SizeOf(TParamFlags));
  5147. { handle name }
  5148. infos[total].Name := PShortString(ptr)^;
  5149. Inc(ptr, ptr^ + SizeOf(Byte));
  5150. { skip type name }
  5151. Inc(ptr, ptr^ + SizeOf(Byte));
  5152. if not (pfHidden in infos[total].Flags) then
  5153. Inc(visible);
  5154. Inc(total);
  5155. end;
  5156. end;
  5157. if FTypeData^.MethodKind in [mkFunction, mkClassFunction] then begin
  5158. { skip return type name }
  5159. ptr := AlignToPtr(PByte(ptr) + ptr^ + SizeOf(Byte));
  5160. { handle return type }
  5161. FReturnType := GRttiPool[FUsePublishedOnly].GetType(PPPTypeInfo(ptr)^^);
  5162. Inc(ptr, SizeOf(PPTypeInfo));
  5163. end;
  5164. { handle calling convention }
  5165. FCallConv := PCallConv(ptr)^;
  5166. Inc(ptr, SizeOf(TCallConv));
  5167. SetLength(FParamsAll, FTypeData^.ParamCount);
  5168. SetLength(FParams, visible);
  5169. if FTypeData^.ParamCount > 0 then begin
  5170. context := TRttiContext.Create(FUsePublishedOnly);
  5171. try
  5172. paramtypes := PPPTypeInfo(AlignTypeData(ptr));
  5173. visible := 0;
  5174. for i := 0 to FTypeData^.ParamCount - 1 do begin
  5175. obj := context.GetByHandle(infos[i].Handle);
  5176. if Assigned(obj) then
  5177. FParamsAll[i] := obj as TRttiMethodTypeParameter
  5178. else begin
  5179. if Assigned(paramtypes[i]) then
  5180. paramtype := paramtypes[i]^
  5181. else
  5182. paramtype := Nil;
  5183. FParamsAll[i] := TRttiMethodTypeParameter.Create(infos[i].Handle, infos[i].Name, infos[i].Flags, paramtype);
  5184. context.AddObject(FParamsAll[i]);
  5185. end;
  5186. if not (pfHidden in infos[i].Flags) then begin
  5187. FParams[visible] := FParamsAll[i];
  5188. Inc(visible);
  5189. end;
  5190. end;
  5191. finally
  5192. context.Free;
  5193. end;
  5194. end;
  5195. if aWithHidden then
  5196. Result := FParamsAll
  5197. else
  5198. Result := FParams;
  5199. end;
  5200. function TRttiMethodType.GetCallingConvention: TCallConv;
  5201. begin
  5202. { the calling convention is located after the parameters, so get the parameters
  5203. which will also initialize the calling convention }
  5204. GetParameters(True);
  5205. Result := FCallConv;
  5206. end;
  5207. function TRttiMethodType.GetReturnType: TRttiType;
  5208. begin
  5209. if FTypeData^.MethodKind in [mkFunction, mkClassFunction] then begin
  5210. { the return type is located after the parameters, so get the parameters
  5211. which will also initialize the return type }
  5212. GetParameters(True);
  5213. Result := FReturnType;
  5214. end else
  5215. Result := Nil;
  5216. end;
  5217. function TRttiMethodType.GetFlags: TFunctionCallFlags;
  5218. begin
  5219. Result := [];
  5220. end;
  5221. function TRttiMethodType.ToString: string;
  5222. begin
  5223. Result:=Inherited ToString;
  5224. Result:=Result+' of object';
  5225. end;
  5226. function TRttiMethodType.Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue;
  5227. var
  5228. method: PMethod;
  5229. inst: TValue;
  5230. begin
  5231. if aCallable.Kind <> tkMethod then
  5232. raise EInvocationError.CreateFmt(SErrInvokeCallableNotMethod, [Name]);
  5233. method := PMethod(aCallable.GetReferenceToRawData);
  5234. { by using a pointer we can also use this for non-class instance methods }
  5235. TValue.Make(@method^.Data, PTypeInfo(TypeInfo(Pointer)), inst);
  5236. Result := {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Rtti.Invoke(Name, method^.Code, CallingConvention, False, inst, aArgs, GetParameters(True), ReturnType);
  5237. end;
  5238. { TRttiProcedureType }
  5239. function TRttiProcedureType.GetParameters(aWithHidden: Boolean): TRttiParameterArray;
  5240. var
  5241. visible, i: SizeInt;
  5242. param: PProcedureParam;
  5243. obj: TRttiObject;
  5244. context: TRttiContext;
  5245. begin
  5246. if aWithHidden and (Length(FParamsAll) > 0) then
  5247. Exit(FParamsAll);
  5248. if not aWithHidden and (Length(FParams) > 0) then
  5249. Exit(FParams);
  5250. if FTypeData^.ProcSig.ParamCount = 0 then
  5251. Exit(Nil);
  5252. SetLength(FParamsAll, FTypeData^.ProcSig.ParamCount);
  5253. SetLength(FParams, FTypeData^.ProcSig.ParamCount);
  5254. context := TRttiContext.Create(FUsePublishedOnly);
  5255. try
  5256. param := AlignToPtr(PProcedureParam(@FTypeData^.ProcSig.ParamCount + SizeOf(FTypeData^.ProcSig.ParamCount)));
  5257. visible := 0;
  5258. for i := 0 to FTypeData^.ProcSig.ParamCount - 1 do begin
  5259. obj := context.GetByHandle(param);
  5260. if Assigned(obj) then
  5261. FParamsAll[i] := obj as TRttiMethodTypeParameter
  5262. else begin
  5263. FParamsAll[i] := TRttiMethodTypeParameter.Create(param, param^.Name, param^.ParamFlags, param^.ParamType);
  5264. context.AddObject(FParamsAll[i]);
  5265. end;
  5266. if not (pfHidden in param^.ParamFlags) then begin
  5267. FParams[visible] := FParamsAll[i];
  5268. Inc(visible);
  5269. end;
  5270. param := PProcedureParam(AlignToPtr(PByte(@param^.Name) + Length(param^.Name) + SizeOf(param^.Name[0])));
  5271. end;
  5272. SetLength(FParams, visible);
  5273. finally
  5274. context.Free;
  5275. end;
  5276. if aWithHidden then
  5277. Result := FParamsAll
  5278. else
  5279. Result := FParams;
  5280. end;
  5281. function TRttiProcedureType.GetCallingConvention: TCallConv;
  5282. begin
  5283. Result := FTypeData^.ProcSig.CC;
  5284. end;
  5285. function TRttiProcedureType.GetReturnType: TRttiType;
  5286. var
  5287. context: TRttiContext;
  5288. begin
  5289. if not Assigned(FTypeData^.ProcSig.ResultTypeRef) then
  5290. Exit(Nil);
  5291. context := TRttiContext.Create(FUsePublishedOnly);
  5292. try
  5293. Result := context.GetType(FTypeData^.ProcSig.ResultTypeRef^);
  5294. finally
  5295. context.Free;
  5296. end;
  5297. end;
  5298. function TRttiProcedureType.GetFlags: TFunctionCallFlags;
  5299. begin
  5300. Result := [fcfStatic];
  5301. end;
  5302. function TRttiProcedureType.Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue;
  5303. begin
  5304. if aCallable.Kind <> tkProcVar then
  5305. raise EInvocationError.CreateFmt(SErrInvokeCallableNotProc, [Name]);
  5306. Result := {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Rtti.Invoke(Name, PCodePointer(aCallable.GetReferenceToRawData)^, CallingConvention, True, TValue.Empty, aArgs, GetParameters(True), ReturnType);
  5307. end;
  5308. { TRttiStringType }
  5309. function TRttiStringType.GetStringKind: TRttiStringKind;
  5310. begin
  5311. case TypeKind of
  5312. tkSString : result := skShortString;
  5313. tkLString : result := skAnsiString;
  5314. tkAString : result := skAnsiString;
  5315. tkUString : result := skUnicodeString;
  5316. tkWString : result := skWideString;
  5317. else
  5318. Raise EConvertError.Create('Not a string type :'+GetEnumName(TypeInfo(TTypeKind),Ord(TypeKind)));
  5319. end;
  5320. end;
  5321. function TRttiAnsiStringType.GetCodePage: Word;
  5322. begin
  5323. Result:=FTypeData^.CodePage;
  5324. end;
  5325. { TRttiInterfaceType }
  5326. function TRttiInterfaceType.IntfMethodCount: Word;
  5327. var
  5328. parent: TRttiInterfaceType;
  5329. table: PIntfMethodTable;
  5330. begin
  5331. parent := GetIntfBaseType;
  5332. if Assigned(parent) then
  5333. Result := parent.IntfMethodCount
  5334. else
  5335. Result := 0;
  5336. table := MethodTable;
  5337. if Assigned(table) then
  5338. Inc(Result, table^.Count);
  5339. end;
  5340. function TRttiInterfaceType.GetBaseType: TRttiType;
  5341. begin
  5342. Result := GetIntfBaseType;
  5343. end;
  5344. function TRttiInterfaceType.GetGUIDStr: String;
  5345. begin
  5346. Result := GUIDToString(GUID);
  5347. end;
  5348. function TRttiInterfaceType.GetDeclaredMethods: specialize TArray<TRttiMethod>;
  5349. var
  5350. methtable: PIntfMethodTable;
  5351. count, index: Word;
  5352. method: PIntfMethodEntry;
  5353. context: TRttiContext;
  5354. obj: TRttiObject;
  5355. parent: TRttiInterfaceType;
  5356. parentmethodcount: Word;
  5357. begin
  5358. if Assigned(fDeclaredMethods) then
  5359. Exit(fDeclaredMethods);
  5360. methtable := MethodTable;
  5361. if not Assigned(methtable) then
  5362. Exit(Nil);
  5363. if (methtable^.Count = 0) or (methtable^.RTTICount = $ffff) then
  5364. Exit(Nil);
  5365. parent := GetIntfBaseType;
  5366. if Assigned(parent) then
  5367. parentmethodcount := parent.IntfMethodCount
  5368. else
  5369. parentmethodcount := 0;
  5370. SetLength(fDeclaredMethods, methtable^.Count);
  5371. context := TRttiContext.Create(FUsePublishedOnly);
  5372. try
  5373. method := methtable^.Method[0];
  5374. count := methtable^.Count;
  5375. while count > 0 do begin
  5376. index := methtable^.Count - count;
  5377. obj := context.GetByHandle(method);
  5378. if Assigned(obj) then
  5379. fDeclaredMethods[index] := obj as TRttiMethod
  5380. else begin
  5381. fDeclaredMethods[index] := TRttiIntfMethod.Create(Self, method, parentmethodcount + index);
  5382. context.AddObject(fDeclaredMethods[index]);
  5383. end;
  5384. method := method^.Next;
  5385. Dec(count);
  5386. end;
  5387. finally
  5388. context.Free;
  5389. end;
  5390. Result := fDeclaredMethods;
  5391. end;
  5392. { TRttiInstanceType }
  5393. function TRttiInstanceType.GetMetaClassType: TClass;
  5394. begin
  5395. result := FTypeData^.ClassType;
  5396. end;
  5397. function TRttiInstanceType.GetDeclaringUnitName: string;
  5398. begin
  5399. result := FTypeData^.UnitName;
  5400. end;
  5401. function TRttiInstanceType.GetBaseType: TRttiType;
  5402. var
  5403. AContext: TRttiContext;
  5404. begin
  5405. AContext := TRttiContext.Create(FUsePublishedOnly);
  5406. try
  5407. result := AContext.GetType(FTypeData^.ParentInfo);
  5408. finally
  5409. AContext.Free;
  5410. end;
  5411. end;
  5412. function TRttiInstanceType.GetIsInstance: boolean;
  5413. begin
  5414. Result:=True;
  5415. end;
  5416. function TRttiInstanceType.GetTypeSize: integer;
  5417. begin
  5418. Result:=sizeof(TObject);
  5419. end;
  5420. Procedure TRttiInstanceType.ResolveExtendedDeclaredProperties;
  5421. var
  5422. Table: PPropDataEx;
  5423. //List : PPropListEx;
  5424. Ctx: TRttiContext;
  5425. info : PPropInfoEx;
  5426. TP : PPropInfo;
  5427. Prop : TRttiProperty;
  5428. i,j,Idx,IdxCount,Len, PropCount : Integer;
  5429. obj: TRttiObject;
  5430. begin
  5431. Table:=PClassData(FTypeData)^.ExRTTITable;
  5432. Len:=Table^.PropCount;
  5433. PropCount:=Len;
  5434. SetLength(FDeclaredProperties,PropCount);
  5435. FPropertiesResolved:=True;
  5436. if Len=0 then
  5437. exit;
  5438. try
  5439. J := 0;
  5440. For I:=0 to Len-1 do
  5441. begin
  5442. Info := Table^.Prop[i];
  5443. TP:=Info^.Info;
  5444. if TP^.PropParams <> nil then
  5445. begin
  5446. Dec(PropCount);
  5447. SetLength(FDeclaredProperties, PropCount);
  5448. continue;
  5449. end;
  5450. Prop := TRttiProperty(GRttiPool[FUsePublishedOnly].GetByHandle(TP));
  5451. if Prop=nil then
  5452. begin
  5453. Prop:=TRttiProperty.Create(Self, TP);
  5454. GRttiPool[FUsePublishedOnly].AddObject(Prop);
  5455. end;
  5456. Prop.FVisibility:=MemberVisibilities[Info^.Visibility];
  5457. Prop.FStrictVisibility:=Info^.StrictVisibility;
  5458. FDeclaredProperties[J]:=Prop;
  5459. Inc(J);
  5460. end;
  5461. finally
  5462. end;
  5463. end;
  5464. Procedure TRttiInstanceType.ResolveClassicDeclaredProperties;
  5465. var
  5466. Table: PPropData;
  5467. lTypeInfo: PTypeInfo;
  5468. TypeRttiType: TRttiType;
  5469. TD: PTypeData;
  5470. TP: PPropInfo;
  5471. Idx,I,Len: longint;
  5472. Prop: TRttiProperty;
  5473. begin
  5474. Table:=PClassData(FTypeData)^.PropertyTable;
  5475. Len:=Table^.PropCount;
  5476. SetLength(FDeclaredProperties,Len);
  5477. FPropertiesResolved:=True;
  5478. if Len=0 then
  5479. exit;
  5480. try
  5481. TP:=PPropInfo(@Table^.PropList);
  5482. For I:=0 to Len-1 do
  5483. begin
  5484. Prop := TRttiProperty(GRttiPool[FUsePublishedOnly].GetByHandle(TP));
  5485. if Prop=nil then
  5486. begin
  5487. Prop:=TRttiProperty.Create(Self, TP);
  5488. Prop.FUsePublishedOnly:=FUsePublishedOnly;
  5489. GRttiPool[FUsePublishedOnly].AddObject(Prop);
  5490. end;
  5491. FDeclaredProperties[I]:=Prop;
  5492. TP:=TP^.Next;
  5493. end;
  5494. finally
  5495. end;
  5496. end;
  5497. function TRttiInstanceType.GetDeclaredProperties: TRttiPropertyArray;
  5498. begin
  5499. if Not FPropertiesResolved then
  5500. if fUsePublishedOnly then
  5501. ResolveClassicDeclaredProperties
  5502. else
  5503. ResolveExtendedDeclaredProperties;
  5504. result := FDeclaredProperties;
  5505. end;
  5506. Procedure TRttiInstanceType.ResolveDeclaredIndexedProperties;
  5507. var
  5508. Table: PPropDataEx;
  5509. Ctx: TRttiContext;
  5510. info : PPropInfoEx;
  5511. TP : PPropInfo;
  5512. IProp : TRttiIndexedProperty;
  5513. i,j,Idx,IdxCount,Len, PropCount : Integer;
  5514. obj: TRttiObject;
  5515. begin
  5516. Table:=PClassData(FTypeData)^.ExRTTITable;
  5517. Len:=Table^.PropCount;
  5518. PropCount:=0;
  5519. SetLength(FDeclaredIndexedProperties,0);
  5520. FIndexedPropertiesResolved:=True;
  5521. if Len=0 then
  5522. exit;
  5523. try
  5524. For I:=0 to Len-1 do
  5525. begin
  5526. Info := Table^.Prop[i];
  5527. TP:=Info^.Info;
  5528. if TP^.PropParams = nil then
  5529. begin
  5530. continue;
  5531. end;
  5532. Inc(PropCount);
  5533. SetLength(FDeclaredIndexedProperties, PropCount);
  5534. IProp := TRttiIndexedProperty(GRttiPool[FUsePublishedOnly].GetByHandle(TP));
  5535. if IProp=nil then
  5536. begin
  5537. IProp:=TRttiIndexedProperty.Create(Self, TP);
  5538. GRttiPool[FUsePublishedOnly].AddObject(IProp);
  5539. end;
  5540. IProp.FVisibility:=MemberVisibilities[Info^.Visibility];
  5541. IProp.FStrictVisibility:=Info^.StrictVisibility;
  5542. FDeclaredIndexedProperties[PropCount-1]:=IProp;
  5543. end;
  5544. finally
  5545. end;
  5546. end;
  5547. function TRttiInstanceType.GetDeclaredIndexedProperties: TRttiIndexedPropertyArray;
  5548. begin
  5549. if not FIndexedPropertiesResolved then
  5550. ResolveDeclaredIndexedProperties;
  5551. Result:=FDeclaredIndexedProperties;
  5552. end;
  5553. procedure TRttiInstanceType.ResolveDeclaredFields;
  5554. Var
  5555. Tbl : PExtendedFieldInfoTable;
  5556. aData: PExtendedVmtFieldEntry;
  5557. Fld : TRttiField;
  5558. i,Len : integer;
  5559. Ctx : TRttiContext;
  5560. begin
  5561. Tbl:=Nil;
  5562. Len:=GetFieldList(FTypeInfo,Tbl,[],False);
  5563. SetLength(FDeclaredFields,Len);
  5564. FFieldsResolved:=True;
  5565. if Len=0 then
  5566. begin
  5567. if Assigned(Tbl) then
  5568. FreeMem(Tbl);
  5569. exit;
  5570. end;
  5571. Ctx:=TRttiContext.Create(FUsePublishedOnly);
  5572. try
  5573. For I:=0 to Len-1 do
  5574. begin
  5575. aData:=Tbl^[i];
  5576. Fld:=TRttiField(Ctx.GetByHandle(aData));
  5577. if Fld=Nil then
  5578. begin
  5579. Fld:=TRttiField.Create(Self);
  5580. Fld.FHandle:=aData;
  5581. Fld.FName:=aData^.Name^;
  5582. Fld.FOffset:=aData^.FieldOffset;
  5583. Fld.FFieldType:=Ctx.GetType(aData^.FieldType^);
  5584. Fld.FVisibility:=MemberVisibilities[aData^.FieldVisibility];
  5585. Fld.FStrictVisibility:=aData^.StrictVisibility;
  5586. Ctx.AddObject(Fld);
  5587. end;
  5588. FDeclaredFields[I]:=Fld;
  5589. end;
  5590. finally
  5591. if Assigned(Tbl) then
  5592. FreeMem(Tbl);
  5593. Ctx.Free;
  5594. end;
  5595. end;
  5596. procedure TRttiInstanceType.ResolveDeclaredMethods;
  5597. Var
  5598. Tbl : PExtendedMethodInfoTable;
  5599. aData: PVmtMethodExEntry;
  5600. Meth : TRttiInstanceMethod;
  5601. i,idx,aCount,Len : integer;
  5602. Ctx : TRttiContext;
  5603. begin
  5604. tbl:=Nil;
  5605. Ctx:=TRttiContext.Create(FUsePublishedOnly);
  5606. try
  5607. FMethodsResolved:=True;
  5608. Len:=GetMethodList(FTypeInfo,Tbl,[],False);
  5609. if not FUsePublishedOnly then
  5610. aCount:=Len
  5611. else
  5612. begin
  5613. aCount:=0;
  5614. For I:=0 to Len-1 do
  5615. if Tbl^[I]^.MethodVisibility=vcPublished then
  5616. Inc(aCount);
  5617. end;
  5618. SetLength(FDeclaredMethods,aCount);
  5619. Idx:=0;
  5620. For I:=0 to Len-1 do
  5621. begin
  5622. aData:=Tbl^[i];
  5623. if (Not FUsePublishedOnly) or (aData^.MethodVisibility=vcPublished) then
  5624. begin
  5625. Meth:=TRttiInstanceMethod(Ctx.GetByHandle(aData));
  5626. if Meth=Nil then
  5627. begin
  5628. Meth:=TRttiInstanceMethod.Create(Self,aData);
  5629. Meth.FUsePublishedOnly:=Self.FUsePublishedOnly;
  5630. Meth.FVisibility:=MemberVisibilities[aData^.MethodVisibility];
  5631. Meth.FStrictVisibility:=aData^.StrictVisibility;
  5632. Ctx.AddObject(Meth);
  5633. end;
  5634. FDeclaredMethods[Idx]:=Meth;
  5635. Inc(Idx);
  5636. end;
  5637. end;
  5638. finally
  5639. if assigned(Tbl) then
  5640. FreeMem(Tbl);
  5641. Ctx.Free;
  5642. end;
  5643. end;
  5644. function TRttiInstanceType.GetDeclaredFields: TRttiFieldArray;
  5645. begin
  5646. if not FFieldsResolved then
  5647. ResolveDeclaredFields;
  5648. Result:=FDeclaredFields;
  5649. end;
  5650. function TRttiInstanceType.GetDeclaredMethods: TRttiMethodArray;
  5651. begin
  5652. if not FMethodsResolved then
  5653. ResolveDeclaredMethods;
  5654. Result:=FDeclaredMethods;
  5655. end;
  5656. { TRttiRecordType }
  5657. function TRttiRecordType.GetMethods: TRttiMethodArray;
  5658. begin
  5659. Result:=GetDeclaredMethods;
  5660. end;
  5661. procedure TRttiRecordType.ResolveFields;
  5662. Var
  5663. Tbl : PExtendedFieldInfoTable;
  5664. aData: PExtendedVmtFieldEntry;
  5665. Fld : TRttiField;
  5666. i,Len : integer;
  5667. Ctx : TRttiContext;
  5668. begin
  5669. Tbl:=Nil;
  5670. Len:=GetFieldList(FTypeInfo,Tbl);
  5671. SetLength(FDeclaredFields,Len);
  5672. FFieldsResolved:=True;
  5673. if Len=0 then
  5674. exit;
  5675. Ctx:=TRttiContext.Create(Self.FUsePublishedOnly);
  5676. try
  5677. For I:=0 to Len-1 do
  5678. begin
  5679. aData:=Tbl^[i];
  5680. Fld:=TRttiField(Ctx.GetByHandle(aData));
  5681. if Fld=Nil then
  5682. begin
  5683. Fld:=TRttiField.Create(Self);
  5684. Fld.FName:=aData^.Name^;
  5685. Fld.FOffset:=aData^.FieldOffset;
  5686. Fld.FFieldType:=Ctx.GetType(aData^.FieldType^);
  5687. Fld.FVisibility:=MemberVisibilities[aData^.FieldVisibility];
  5688. Fld.FStrictVisibility:=aData^.StrictVisibility;
  5689. Fld.FHandle:=aData;
  5690. Ctx.AddObject(Fld);
  5691. end;
  5692. FDeclaredFields[I]:=Fld;
  5693. end;
  5694. FFields:=FDeclaredFields;
  5695. finally
  5696. if assigned(Tbl) then
  5697. FreeMem(Tbl);
  5698. Ctx.Free;
  5699. end;
  5700. end;
  5701. procedure TRttiRecordType.ResolveMethods;
  5702. Var
  5703. Tbl : PRecordMethodInfoTable;
  5704. aData: PRecMethodExEntry;
  5705. Meth : TRttiRecordMethod;
  5706. i,idx,aCount : integer;
  5707. Ctx : TRttiContext;
  5708. begin
  5709. FMethodsResolved:=True;
  5710. if FUsePublishedOnly then
  5711. exit;
  5712. Ctx:=TRttiContext.Create(FUsePublishedOnly);
  5713. try
  5714. aCount:=GetMethodList(FTypeInfo,Tbl,[]);
  5715. SetLength(FDeclaredMethods,aCount);
  5716. Idx:=0;
  5717. For I:=0 to aCount-1 do
  5718. begin
  5719. aData:=Tbl^[i];
  5720. if (Not FUsePublishedOnly) or (aData^.MethodVisibility=vcPublished) then
  5721. begin
  5722. Meth:=TRttiRecordMethod(Ctx.GetByHandle(aData));
  5723. if Meth=Nil then
  5724. begin
  5725. Meth:=TRttiRecordMethod.Create(Self,aData);
  5726. Meth.FUsePublishedOnly:=Self.FUsePublishedOnly;
  5727. Ctx.AddObject(Meth)
  5728. end;
  5729. Meth.FVisibility:=MemberVisibilities[aData^.MethodVisibility];
  5730. Meth.FStrictVisibility:=aData^.StrictVisibility;
  5731. FDeclaredMethods[Idx]:=Meth;
  5732. Inc(Idx);
  5733. end;
  5734. end;
  5735. finally
  5736. if assigned(Tbl) then
  5737. FreeMem(Tbl);
  5738. Ctx.Free;
  5739. end;
  5740. end;
  5741. procedure TRttiRecordType.ResolveProperties;
  5742. var
  5743. List : PPropListEx;
  5744. info : PPropInfoEx;
  5745. TP : PPropInfo;
  5746. Prop : TRttiProperty;
  5747. i, j, PropCount, aCount : Integer;
  5748. obj: TRttiObject;
  5749. begin
  5750. List:=Nil;
  5751. FPropertiesResolved:=True;
  5752. if FUsePublishedOnly then
  5753. Exit;
  5754. aCount:=GetPropListEx(FTypeinfo,List);
  5755. PropCount:=aCount;
  5756. J := 0;
  5757. try
  5758. SetLength(FProperties,aCount);
  5759. For I:=0 to aCount-1 do
  5760. begin
  5761. Info:=List^[I];
  5762. TP:=Info^.Info;
  5763. if TP^.PropParams <> nil then
  5764. begin
  5765. Dec(PropCount);
  5766. SetLength(FProperties, PropCount);
  5767. continue;
  5768. end;
  5769. obj:=GRttiPool[FUsePublishedOnly].GetByHandle(TP);
  5770. if Assigned(obj) then
  5771. FProperties[J]:=obj as TRttiProperty
  5772. else
  5773. begin
  5774. Prop:=TRttiProperty.Create(Self, TP);
  5775. FProperties[J]:=Prop;
  5776. GRttiPool[FUsePublishedOnly].AddObject(Prop);
  5777. end;
  5778. Prop.FVisibility:=MemberVisibilities[Info^.Visibility];
  5779. Prop.FStrictVisibility:=Info^.StrictVisibility;
  5780. Inc(J);
  5781. end;
  5782. finally
  5783. if assigned(List) then
  5784. FreeMem(List);
  5785. end;
  5786. end;
  5787. Procedure TRttiRecordType.ResolveIndexedProperties;
  5788. var
  5789. List : PPropListEx;
  5790. info : PPropInfoEx;
  5791. TP : PPropInfo;
  5792. IProp : TRttiIndexedProperty;
  5793. i,Len, PropCount : Integer;
  5794. obj: TRttiObject;
  5795. begin
  5796. List:=Nil;
  5797. FIndexedPropertiesResolved:=True;
  5798. if FUsePublishedOnly then
  5799. exit;
  5800. Len:=GetPropListEx(FTypeInfo,List);
  5801. PropCount:=0;
  5802. SetLength(FDeclaredIndexedProperties,0);
  5803. FIndexedPropertiesResolved:=True;
  5804. if Len=0 then
  5805. begin
  5806. if Assigned(List) then
  5807. FreeMem(List);
  5808. exit;
  5809. end;
  5810. try
  5811. For I:=0 to Len-1 do
  5812. begin
  5813. Info := List^[I];
  5814. TP:=Info^.Info;
  5815. if TP^.PropParams = nil then
  5816. begin
  5817. continue;
  5818. end;
  5819. Inc(PropCount);
  5820. SetLength(FDeclaredIndexedProperties, PropCount);
  5821. IProp := TRttiIndexedProperty(GRttiPool[FUsePublishedOnly].GetByHandle(TP));
  5822. if IProp=nil then
  5823. begin
  5824. IProp:=TRttiIndexedProperty.Create(Self, TP);
  5825. GRttiPool[FUsePublishedOnly].AddObject(IProp);
  5826. end;
  5827. IProp.FVisibility:=MemberVisibilities[Info^.Visibility];
  5828. IProp.FStrictVisibility:=Info^.StrictVisibility;
  5829. FDeclaredIndexedProperties[PropCount-1]:=IProp;
  5830. end;
  5831. finally
  5832. if Assigned(List) then
  5833. FreeMem(List);
  5834. end;
  5835. end;
  5836. function TRttiRecordType.GetTypeSize: Integer;
  5837. begin
  5838. Result:=GetTypeData(PTypeInfo(Handle))^.RecSize;
  5839. end;
  5840. function TRttiRecordType.GetProperties: TRttiPropertyArray;
  5841. begin
  5842. if not FPropertiesResolved then
  5843. ResolveProperties;
  5844. Result:=FProperties;
  5845. end;
  5846. function TRttiRecordType.GetDeclaredFields: TRttiFieldArray;
  5847. begin
  5848. If not FFieldsResolved then
  5849. ResolveFields;
  5850. Result:=FDeclaredFields;
  5851. end;
  5852. function TRttiRecordType.GetDeclaredMethods: TRttiMethodArray;
  5853. begin
  5854. If not FMethodsResolved then
  5855. ResolveMethods;
  5856. Result:=FDeclaredMethods;
  5857. end;
  5858. function TRttiRecordType.GetDeclaredProperties: TRttiPropertyArray;
  5859. begin
  5860. if not FPropertiesResolved then
  5861. ResolveProperties;
  5862. Result:=FDeclaredProperties;
  5863. end;
  5864. function TRttiRecordType.GetDeclaredIndexedProperties: TRttiIndexedPropertyArray;
  5865. begin
  5866. if not FIndexedPropertiesResolved then
  5867. ResolveIndexedProperties;
  5868. Result:=FDeclaredIndexedProperties;
  5869. end;
  5870. function TRttiRecordType.GetAttributes: TCustomAttributeArray;
  5871. begin
  5872. Result:=inherited GetAttributes;
  5873. end;
  5874. { TRttiMember }
  5875. function TRttiMember.GetVisibility: TMemberVisibility;
  5876. begin
  5877. Result:=FVisibility;
  5878. end;
  5879. function TRttiMember.GetStrictVisibility: Boolean;
  5880. begin
  5881. Result:=FStrictVisibility;
  5882. end;
  5883. constructor TRttiMember.Create(AParent: TRttiType);
  5884. begin
  5885. inherited Create();
  5886. FParent := AParent;
  5887. FVisibility:=mvPublished;
  5888. end;
  5889. { TRttiProperty }
  5890. function TRttiProperty.GetDataType: TRttiType;
  5891. begin
  5892. Result:=GetPropertyType
  5893. end;
  5894. function TRttiProperty.GetPropertyType: TRttiType;
  5895. var
  5896. context: TRttiContext;
  5897. begin
  5898. context := TRttiContext.Create(FUsePublishedOnly);
  5899. try
  5900. Result := context.GetType(FPropInfo^.PropType);
  5901. finally
  5902. context.Free;
  5903. end;
  5904. end;
  5905. function TRttiProperty.GetIsReadable: boolean;
  5906. begin
  5907. result := assigned(FPropInfo^.GetProc);
  5908. end;
  5909. function TRttiProperty.GetIsWritable: boolean;
  5910. begin
  5911. result := assigned(FPropInfo^.SetProc);
  5912. end;
  5913. function TRttiProperty.GetName: string;
  5914. begin
  5915. Result:=FPropInfo^.Name;
  5916. end;
  5917. function TRttiProperty.GetHandle: Pointer;
  5918. begin
  5919. Result := FPropInfo;
  5920. end;
  5921. constructor TRttiProperty.Create(AParent: TRttiType; APropInfo: PPropInfo);
  5922. begin
  5923. inherited Create(AParent);
  5924. FPropInfo := APropInfo;
  5925. end;
  5926. destructor TRttiProperty.Destroy;
  5927. var
  5928. attr: TCustomAttribute;
  5929. begin
  5930. for attr in FAttributes do
  5931. attr.Free;
  5932. inherited Destroy;
  5933. end;
  5934. function TRttiProperty.GetAttributes: TCustomAttributeArray;
  5935. var
  5936. i: SizeInt;
  5937. at: PAttributeTable;
  5938. begin
  5939. if not FAttributesResolved then
  5940. begin
  5941. at := FPropInfo^.AttributeTable;
  5942. if Assigned(at) then
  5943. begin
  5944. SetLength(FAttributes, at^.AttributeCount);
  5945. for i := 0 to High(FAttributes) do
  5946. FAttributes[i] := TCustomAttribute({$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}TypInfo.GetAttribute(at, i));
  5947. end;
  5948. FAttributesResolved:=true;
  5949. end;
  5950. result := FAttributes;
  5951. end;
  5952. function TRttiProperty.GetValue(Instance: pointer): TValue;
  5953. procedure ValueFromBool(value: Int64);
  5954. var
  5955. b8: Boolean;
  5956. b16: Boolean16;
  5957. b32: Boolean32;
  5958. bb: ByteBool;
  5959. bw: WordBool;
  5960. bl: LongBool;
  5961. td: PTypeData;
  5962. p: Pointer;
  5963. begin
  5964. td := GetTypeData(FPropInfo^.PropType);
  5965. case td^.OrdType of
  5966. otUByte:
  5967. begin
  5968. b8 := Boolean(value);
  5969. p := @b8;
  5970. end;
  5971. otUWord:
  5972. begin
  5973. b16 := Boolean16(value);
  5974. p := @b16;
  5975. end;
  5976. otULong:
  5977. begin
  5978. b32 := Boolean32(value);
  5979. p := @b32;
  5980. end;
  5981. otSByte:
  5982. begin
  5983. bb := ByteBool(value);
  5984. p := @bb;
  5985. end;
  5986. otSWord:
  5987. begin
  5988. bw := WordBool(value);
  5989. p := @bw;
  5990. end;
  5991. otSLong:
  5992. begin
  5993. bl := LongBool(value);
  5994. p := @bl;
  5995. end;
  5996. else
  5997. // Silence compiler warning
  5998. end;
  5999. TValue.Make(p, FPropInfo^.PropType, result);
  6000. end;
  6001. procedure ValueFromInt(value: Int64);
  6002. var
  6003. i8: UInt8;
  6004. i16: UInt16;
  6005. i32: UInt32;
  6006. td: PTypeData;
  6007. p: Pointer;
  6008. begin
  6009. td := GetTypeData(FPropInfo^.PropType);
  6010. case td^.OrdType of
  6011. otUByte,
  6012. otSByte:
  6013. begin
  6014. i8 := value;
  6015. p := @i8;
  6016. end;
  6017. otUWord,
  6018. otSWord:
  6019. begin
  6020. i16 := value;
  6021. p := @i16;
  6022. end;
  6023. otULong,
  6024. otSLong:
  6025. begin
  6026. i32 := value;
  6027. p := @i32;
  6028. end;
  6029. else
  6030. // Silence compiler warning
  6031. end;
  6032. TValue.Make(p, FPropInfo^.PropType, result);
  6033. end;
  6034. var
  6035. Values: record
  6036. case Integer of
  6037. 0: (Enum: Int64);
  6038. 1: (Bool: Int64);
  6039. 2: (Int: Int64);
  6040. 3: (Ch: Byte);
  6041. 4: (Wch: Word);
  6042. 5: (I64: Int64);
  6043. 6: (Si: Single);
  6044. 7: (Db: Double);
  6045. 8: (Ex: Extended);
  6046. 9: (Cur: Currency);
  6047. 10: (Cp: Comp);
  6048. 11: (A: Pointer;)
  6049. end;
  6050. s: String;
  6051. ss: ShortString;
  6052. u : UnicodeString;
  6053. O: TObject;
  6054. M: TMethod;
  6055. Int: IUnknown;
  6056. begin
  6057. case FPropinfo^.PropType^.Kind of
  6058. tkSString:
  6059. begin
  6060. ss := ShortString(GetStrProp(TObject(Instance), FPropInfo));
  6061. TValue.Make(@ss, FPropInfo^.PropType, result);
  6062. end;
  6063. tkAString:
  6064. begin
  6065. s := GetStrProp(TObject(Instance), FPropInfo);
  6066. TValue.Make(@s, FPropInfo^.PropType, result);
  6067. end;
  6068. tkUString:
  6069. begin
  6070. U := GetUnicodeStrProp(TObject(Instance), FPropInfo);
  6071. TValue.Make(@U, FPropInfo^.PropType, result);
  6072. end;
  6073. tkWString:
  6074. begin
  6075. U := GetWideStrProp(TObject(Instance), FPropInfo);
  6076. TValue.Make(@U, FPropInfo^.PropType, result);
  6077. end;
  6078. tkEnumeration:
  6079. begin
  6080. Values.Enum := Integer(GetOrdProp(TObject(Instance), FPropInfo));
  6081. ValueFromInt(Values.Enum);
  6082. end;
  6083. tkBool:
  6084. begin
  6085. Values.Bool := GetOrdProp(TObject(Instance), FPropInfo);
  6086. ValueFromBool(Values.Bool);
  6087. end;
  6088. tkInteger:
  6089. begin
  6090. Values.Int := GetOrdProp(TObject(Instance), FPropInfo);
  6091. ValueFromInt(Values.Int);
  6092. end;
  6093. tkChar:
  6094. begin
  6095. Values.Ch := Byte(GetOrdProp(TObject(Instance), FPropInfo));
  6096. TValue.Make(@Values.Ch, FPropInfo^.PropType, result);
  6097. end;
  6098. tkWChar:
  6099. begin
  6100. Values.Wch := Word(GetOrdProp(TObject(Instance), FPropInfo));
  6101. TValue.Make(@Values.Wch, FPropInfo^.PropType, result);
  6102. end;
  6103. tkInt64,
  6104. tkQWord:
  6105. begin
  6106. Values.I64 := GetOrdProp(TObject(Instance), FPropInfo);
  6107. TValue.Make(@Values.I64, FPropInfo^.PropType, result);
  6108. end;
  6109. tkClass:
  6110. begin
  6111. O := GetObjectProp(TObject(Instance), FPropInfo);
  6112. TValue.Make(@O, FPropInfo^.PropType, Result);
  6113. end;
  6114. tkMethod:
  6115. begin
  6116. M := GetMethodProp(TObject(Instance), FPropInfo);
  6117. TValue.Make(@M, FPropInfo^.PropType, Result);
  6118. end;
  6119. tkInterface:
  6120. begin
  6121. Int := GetInterfaceProp(TObject(Instance), FPropInfo);
  6122. TValue.Make(@Int, FPropInfo^.PropType, Result);
  6123. end;
  6124. tkFloat:
  6125. begin
  6126. case GetTypeData(FPropInfo^.PropType)^.FloatType of
  6127. ftCurr :
  6128. begin
  6129. Values.Cur := Currency(GetFloatProp(TObject(Instance), FPropInfo));
  6130. TValue.Make(@Values.Cur, FPropInfo^.PropType, Result);
  6131. end;
  6132. ftSingle :
  6133. begin
  6134. Values.Si := Single(GetFloatProp(TObject(Instance), FPropInfo));
  6135. TValue.Make(@Values.Si, FPropInfo^.PropType, Result);
  6136. end;
  6137. ftDouble :
  6138. begin
  6139. Values.Db := Double(GetFloatProp(TObject(Instance), FPropInfo));
  6140. TValue.Make(@Values.Db, FPropInfo^.PropType, Result);
  6141. end;
  6142. ftExtended:
  6143. begin
  6144. Values.Ex := GetFloatProp(TObject(Instance), FPropInfo);
  6145. TValue.Make(@Values.Ex, FPropInfo^.PropType, Result);
  6146. end;
  6147. ftComp :
  6148. begin
  6149. Values.Cp := Comp(GetFloatProp(TObject(Instance), FPropInfo));
  6150. TValue.Make(@Values.Cp, FPropInfo^.PropType, Result);
  6151. end;
  6152. end;
  6153. end;
  6154. tkDynArray:
  6155. begin
  6156. Values.A := GetDynArrayProp(TObject(Instance), FPropInfo);
  6157. TValue.Make(@Values.A, FPropInfo^.PropType, Result);
  6158. end
  6159. else
  6160. result := TValue.Empty;
  6161. end
  6162. end;
  6163. procedure TRttiProperty.SetValue(Instance: pointer; const AValue: TValue);
  6164. begin
  6165. case FPropinfo^.PropType^.Kind of
  6166. tkSString,
  6167. tkAString:
  6168. SetStrProp(TObject(Instance), FPropInfo, AValue.AsString);
  6169. tkUString:
  6170. SetUnicodeStrProp(TObject(Instance), FPropInfo, AValue.AsUnicodeString);
  6171. tkWString:
  6172. SetWideStrProp(TObject(Instance), FPropInfo, AValue.AsUnicodeString);
  6173. tkInteger,
  6174. tkInt64,
  6175. tkQWord,
  6176. tkChar,
  6177. tkBool,
  6178. tkWChar,
  6179. tkEnumeration:
  6180. SetOrdProp(TObject(Instance), FPropInfo, AValue.AsOrdinal);
  6181. tkClass:
  6182. SetObjectProp(TObject(Instance), FPropInfo, AValue.AsObject);
  6183. tkMethod:
  6184. SetMethodProp(TObject(Instance), FPropInfo, TMethod(AValue.GetReferenceToRawData^));
  6185. tkInterface:
  6186. SetInterfaceProp(TObject(Instance), FPropInfo, AValue.AsInterface);
  6187. tkFloat:
  6188. SetFloatProp(TObject(Instance), FPropInfo, AValue.AsExtended);
  6189. tkDynArray:
  6190. SetDynArrayProp(TObject(Instance), FPropInfo, PPointer(AValue.GetReferenceToRawData)^);
  6191. else
  6192. raise exception.createFmt(SErrUnableToSetValueForType, [PropertyType.Name]);
  6193. end
  6194. end;
  6195. function TRttiProperty.ToString: String;
  6196. begin
  6197. Result := 'property ' + Name + ': ' + PropertyType.Name;
  6198. end;
  6199. { TRttiField }
  6200. function TRttiField.GetName: string;
  6201. begin
  6202. Result:=FName;
  6203. end;
  6204. function TRttiField.GetDataType: TRttiType;
  6205. begin
  6206. Result:=FFieldType;
  6207. end;
  6208. function TRttiField.GetIsReadable: Boolean;
  6209. begin
  6210. Result:=True;
  6211. end;
  6212. function TRttiField.GetIsWritable: Boolean;
  6213. begin
  6214. Result:=True;
  6215. end;
  6216. function TRttiField.GetHandle: Pointer;
  6217. begin
  6218. Result:=FHandle;
  6219. end;
  6220. destructor TRttiField.destroy;
  6221. var
  6222. Attr : TCustomAttribute;
  6223. I : Integer;
  6224. begin
  6225. For I:=0 to Length(FAttributes)-1 do
  6226. FAttributes[i].Free;
  6227. Inherited;
  6228. end;
  6229. Procedure TRttiField.ResolveAttributes;
  6230. var
  6231. tbl : PAttributeTable;
  6232. i : Integer;
  6233. begin
  6234. FAttributesResolved:=True;
  6235. Fattributes:=[];
  6236. tbl:=FHandle^.AttributeTable;
  6237. if not (assigned(Tbl) and (Tbl^.AttributeCount>0)) then
  6238. exit;
  6239. SetLength(FAttributes,Tbl^.AttributeCount);
  6240. For I:=0 to Length(FAttributes)-1 do
  6241. FAttributes[I]:={$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}TypInfo.GetAttribute(Tbl,I);
  6242. end;
  6243. function TRttiField.GetAttributes: TCustomAttributeArray;
  6244. begin
  6245. if not FAttributesResolved then
  6246. ResolveAttributes;
  6247. Result:=FAttributes;
  6248. end;
  6249. function TRttiField.GetValue(aInstance: Pointer): TValue;
  6250. begin
  6251. if Not Assigned(FieldType) then
  6252. raise EInsufficientRtti.Create(SErrNoFieldRtti);
  6253. TValue.Make(PByte(aInstance)+Offset,FieldType.Handle,Result);
  6254. end;
  6255. procedure TRttiField.SetValue(aInstance: Pointer; const aValue: TValue);
  6256. var
  6257. FldAddr : Pointer;
  6258. begin
  6259. if Not Assigned(FieldType) then
  6260. raise EInsufficientRtti.Create(SErrNoFieldRtti);
  6261. FldAddr:=PByte(aInstance)+Offset;
  6262. if aValue.TypeInfo=FieldType.Handle then
  6263. aValue.ExtractRawData(FldAddr)
  6264. else
  6265. aValue.Cast(FieldType.Handle).ExtractRawData(FldAddr);
  6266. end;
  6267. function TRttiField.ToString: string;
  6268. begin
  6269. if FieldType = nil then
  6270. Result := Name + ' @ ' + IntToHex(Offset, 2)
  6271. else
  6272. Result := Name + ': ' + FieldType.Name + ' @ ' + IntToHex(Offset, 2);
  6273. end;
  6274. function TRttiType.GetIsInstance: boolean;
  6275. begin
  6276. result := false;
  6277. end;
  6278. function TRttiType.GetIsManaged: boolean;
  6279. begin
  6280. result := {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Rtti.IsManaged(FTypeInfo);
  6281. end;
  6282. function TRttiType.GetIsOrdinal: boolean;
  6283. begin
  6284. result := false;
  6285. end;
  6286. function TRttiType.GetIsRecord: boolean;
  6287. begin
  6288. result := false;
  6289. end;
  6290. function TRttiType.GetIsSet: boolean;
  6291. begin
  6292. result := false;
  6293. end;
  6294. function TRttiType.GetAsInstance: TRttiInstanceType;
  6295. begin
  6296. // This is a ridicoulous design, but Delphi-compatible...
  6297. result := TRttiInstanceType(self);
  6298. end;
  6299. function TRttiType.GetBaseType: TRttiType;
  6300. begin
  6301. result := nil;
  6302. end;
  6303. function TRttiType.GetTypeKind: TTypeKind;
  6304. begin
  6305. result := FTypeInfo^.Kind;
  6306. end;
  6307. function TRttiType.GetTypeSize: integer;
  6308. begin
  6309. result := -1;
  6310. end;
  6311. function TRttiType.GetName: string;
  6312. begin
  6313. Result:=FTypeInfo^.Name;
  6314. end;
  6315. function TRttiType.GetHandle: Pointer;
  6316. begin
  6317. Result := FTypeInfo;
  6318. end;
  6319. constructor TRttiType.Create(ATypeInfo: PTypeInfo; aUsePublishedOnly: Boolean);
  6320. begin
  6321. inherited Create();
  6322. FTypeInfo:=ATypeInfo;
  6323. if assigned(FTypeInfo) then
  6324. FTypeData:=GetTypeData(ATypeInfo);
  6325. fUsePublishedOnly:=aUsePublishedOnly;
  6326. end;
  6327. constructor TRttiType.Create(ATypeInfo: PTypeInfo);
  6328. begin
  6329. Create(aTypeInfo,GlobalUsePublishedOnly);
  6330. end;
  6331. destructor TRttiType.Destroy;
  6332. var
  6333. attr: TCustomAttribute;
  6334. begin
  6335. for attr in FAttributes do
  6336. attr.Free;
  6337. inherited;
  6338. end;
  6339. function TRttiType.GetFields: TRttiFieldArray;
  6340. var
  6341. parentfields, selffields: TRttiFieldArray;
  6342. parent: TRttiType;
  6343. begin
  6344. if Assigned(fFields) then
  6345. Exit(fFields);
  6346. selffields := GetDeclaredFields;
  6347. parent := GetBaseType;
  6348. if Assigned(parent) then begin
  6349. parentfields := parent.GetFields;
  6350. end;
  6351. fFields := Concat(parentfields, selffields);
  6352. Result := fFields;
  6353. end;
  6354. function TRttiType.GetField(const aName: String): TRttiField;
  6355. var
  6356. Flds : TRttiFieldArray;
  6357. Fld: TRttiField;
  6358. begin
  6359. Flds:=GetFields;
  6360. For Fld in Flds do
  6361. if SameText(Fld.Name,aName) then
  6362. Exit(Fld);
  6363. Result:=Nil;
  6364. end;
  6365. function TRttiType.GetAttributes: TCustomAttributeArray;
  6366. var
  6367. i: Integer;
  6368. at: PAttributeTable;
  6369. begin
  6370. if not FAttributesResolved then
  6371. begin
  6372. at := GetAttributeTable(FTypeInfo);
  6373. if Assigned(at) then
  6374. begin
  6375. setlength(FAttributes,at^.AttributeCount);
  6376. for i := 0 to at^.AttributeCount-1 do
  6377. FAttributes[i]:={$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}TypInfo.GetAttribute(at,i);
  6378. end;
  6379. FAttributesResolved:=true;
  6380. end;
  6381. result := FAttributes;
  6382. end;
  6383. function TRttiType.GetDeclaredProperties: TRttiPropertyArray;
  6384. begin
  6385. Result := Nil;
  6386. end;
  6387. function TRttiType.GetProperties: TRttiPropertyArray;
  6388. var
  6389. parentproperties, selfproperties: TRttiPropertyArray;
  6390. parent: TRttiType;
  6391. prop: TRttiProperty;
  6392. NameIndexes : Array of Integer;
  6393. Idx, IdxCount, aCount, I: Integer;
  6394. Function IndexOfNameIndex(Idx : Integer) : integer;
  6395. begin
  6396. Result:=IdxCount-1;
  6397. While (Result>=0) and (NameIndexes[Result]<>Idx) do
  6398. Dec(Result);
  6399. end;
  6400. begin
  6401. NameIndexes:=[];
  6402. IdxCount:=0;
  6403. if Assigned(fProperties) then
  6404. Exit(fProperties);
  6405. selfproperties := GetDeclaredProperties;
  6406. parent := GetBaseType;
  6407. if Assigned(parent) then
  6408. parentproperties := parent.GetProperties
  6409. else
  6410. parentproperties := nil;
  6411. if (not Assigned(parent)) or (Length(parentproperties) = 0) then
  6412. begin
  6413. fProperties := selfproperties;
  6414. Exit(fProperties);
  6415. end
  6416. else if Length(selfproperties) = 0 then
  6417. begin
  6418. fProperties := parentproperties;
  6419. Exit(fProperties);
  6420. end;
  6421. aCount := Length(parentproperties) + Length(selfproperties);
  6422. SetLength(fProperties,aCount);
  6423. SetLength(NameIndexes,aCount);
  6424. IdxCount := 0;
  6425. For I:=0 to Length(selfproperties)-1 do
  6426. begin
  6427. prop := selfproperties[I];
  6428. NameIndexes[IdxCount]:=Prop.FPropInfo^.NameIndex;
  6429. fProperties[IdxCount]:=Prop;
  6430. Inc(IdxCount);
  6431. end;
  6432. For I:=0 to Length(parentproperties)-1 do
  6433. begin
  6434. Prop := parentproperties[I];
  6435. Idx:=IndexOfNameIndex(Prop.FPropInfo^.NameIndex);
  6436. if Idx = -1 then
  6437. begin
  6438. NameIndexes[IdxCount]:=Prop.FPropInfo^.NameIndex;
  6439. fProperties[IdxCount]:=Prop;
  6440. Inc(IdxCount);
  6441. end;
  6442. end;
  6443. SetLength(fProperties, IdxCount);
  6444. Result := fProperties;
  6445. end;
  6446. function TRttiType.GetIndexedProperties: TRttiIndexedPropertyArray;
  6447. var
  6448. parentproperties, selfproperties: TRttiIndexedPropertyArray;
  6449. parent: TRttiType;
  6450. iprop: TRttiIndexedProperty;
  6451. NameIndexes : Array of Integer;
  6452. Idx, IdxCount, aCount, I: Integer;
  6453. Function IndexOfNameIndex(Idx : Integer) : integer;
  6454. begin
  6455. Result:=IdxCount-1;
  6456. While (Result>=0) and (NameIndexes[Result]<>Idx) do
  6457. Dec(Result);
  6458. end;
  6459. begin
  6460. NameIndexes:=[];
  6461. IdxCount:=0;
  6462. if Assigned(fIndexedProperties) then
  6463. Exit(fIndexedProperties);
  6464. selfproperties := GetDeclaredIndexedProperties;
  6465. parent := GetBaseType;
  6466. if Assigned(parent) then
  6467. parentproperties := parent.GetIndexedProperties
  6468. else
  6469. parentproperties := nil;
  6470. if (not Assigned(parent)) or (Length(parentproperties) = 0) then
  6471. begin
  6472. fIndexedProperties := selfproperties;
  6473. Exit(fIndexedProperties);
  6474. end
  6475. else if Length(selfproperties) = 0 then
  6476. begin
  6477. fIndexedProperties := parentproperties;
  6478. Exit(fIndexedProperties);
  6479. end;
  6480. aCount := Length(parentproperties) + Length(selfproperties);
  6481. SetLength(fIndexedProperties,aCount);
  6482. SetLength(NameIndexes,aCount);
  6483. IdxCount := 0;
  6484. For I:=0 to Length(selfproperties)-1 do
  6485. begin
  6486. IProp := selfproperties[I];
  6487. NameIndexes[IdxCount]:=IProp.FPropInfo^.NameIndex;
  6488. fIndexedProperties[IdxCount]:=IProp;
  6489. Inc(IdxCount);
  6490. end;
  6491. For I:=0 to Length(parentproperties)-1 do
  6492. begin
  6493. IProp := parentproperties[I];
  6494. Idx:=IndexOfNameIndex(IProp.FPropInfo^.NameIndex);
  6495. if Idx = -1 then
  6496. begin
  6497. NameIndexes[IdxCount]:=IProp.FPropInfo^.NameIndex;
  6498. fIndexedProperties[IdxCount]:=IProp;
  6499. Inc(IdxCount);
  6500. end;
  6501. end;
  6502. SetLength(fIndexedProperties, IdxCount);
  6503. Result := fIndexedProperties;
  6504. end;
  6505. function TRttiType.GetProperty(const AName: string): TRttiProperty;
  6506. var
  6507. FPropList: TRttiPropertyArray;
  6508. i: Integer;
  6509. begin
  6510. result := nil;
  6511. FPropList := GetProperties;
  6512. for i := 0 to length(FPropList)-1 do
  6513. if sametext(FPropList[i].Name,AName) then
  6514. begin
  6515. result := FPropList[i];
  6516. break;
  6517. end;
  6518. end;
  6519. function TRttiType.GetIndexedProperty(const AName: string): TRttiIndexedProperty;
  6520. var
  6521. FPropList: TRttiIndexedPropertyArray;
  6522. i: Integer;
  6523. begin
  6524. result := nil;
  6525. FPropList := GetIndexedProperties;
  6526. for i := 0 to length(FPropList)-1 do
  6527. if sametext(FPropList[i].Name,AName) then
  6528. begin
  6529. result := FPropList[i];
  6530. break;
  6531. end;
  6532. end;
  6533. function TRttiType.GetMethods: TRttiMethodArray;
  6534. var
  6535. parentmethods, selfmethods: TRttiMethodArray;
  6536. parent: TRttiType;
  6537. begin
  6538. if Assigned(fMethods) then
  6539. Exit(fMethods);
  6540. selfmethods := GetDeclaredMethods;
  6541. parent := GetBaseType;
  6542. if Assigned(parent) then begin
  6543. parentmethods := parent.GetMethods;
  6544. end;
  6545. fMethods := Concat(parentmethods, selfmethods);
  6546. Result := fMethods;
  6547. end;
  6548. function TRttiType.GetMethod(const aName: String): TRttiMethod;
  6549. var
  6550. methods: specialize TArray<TRttiMethod>;
  6551. method: TRttiMethod;
  6552. begin
  6553. methods := GetMethods;
  6554. for method in methods do
  6555. if SameText(method.Name, AName) then
  6556. Exit(method);
  6557. Result := Nil;
  6558. end;
  6559. function TRttiType.GetMethods(const aName: string): TRttiMethodArray;
  6560. var
  6561. methods: specialize TArray<TRttiMethod>;
  6562. method: TRttiMethod;
  6563. count: Integer;
  6564. begin
  6565. methods := Self.GetMethods;
  6566. count := 0;
  6567. Result := nil;
  6568. for method in methods do
  6569. if SameText(method.Name, aName) then
  6570. begin
  6571. SetLength(Result, count + 1);
  6572. Result[count] := method;
  6573. Inc(count);
  6574. end;
  6575. end;
  6576. function TRttiType.GetDeclaredMethods: TRttiMethodArray;
  6577. begin
  6578. Result := Nil;
  6579. end;
  6580. function TRttiType.GetDeclaredFields: TRttiFieldArray;
  6581. begin
  6582. Result:=Nil;
  6583. end;
  6584. function TRttiType.GetDeclaredIndexedProperties: TRttiIndexedPropertyArray;
  6585. begin
  6586. Result:=Nil;
  6587. end;
  6588. { TRttiNamedObject }
  6589. function TRttiNamedObject.GetName: string;
  6590. begin
  6591. result := '';
  6592. end;
  6593. function TRttiNamedObject.HasName(const aName: string): Boolean;
  6594. begin
  6595. Result:=SameText(Name,AName);
  6596. end;
  6597. { TRttiContext }
  6598. class function TRttiContext.Create: TRttiContext;
  6599. begin
  6600. result.FContextToken := nil;
  6601. result.UsePublishedOnly:=DefaultUsePublishedOnly;
  6602. end;
  6603. class function TRttiContext.Create(aUsePublishedOnly: Boolean): TRttiContext;
  6604. begin
  6605. Result:=Create;
  6606. Result.UsePublishedOnly:=aUsePublishedOnly;
  6607. end;
  6608. class procedure TRttiContext.DropContext;
  6609. begin
  6610. FKeptContexts[False] := nil;
  6611. FKeptContexts[True] := nil;
  6612. end;
  6613. class procedure TRttiContext.KeepContext;
  6614. begin
  6615. FKeptContexts[False] := TPoolToken.Create(False);
  6616. FKeptContexts[True] := TPoolToken.Create(True);
  6617. end;
  6618. procedure TRttiContext.Free;
  6619. begin
  6620. FContextToken := nil;
  6621. end;
  6622. function TRttiContext.GetByHandle(AHandle: Pointer): TRttiObject;
  6623. begin
  6624. if not Assigned(FContextToken) then
  6625. FContextToken := TPoolToken.Create(UsePublishedOnly);
  6626. Result := (FContextToken as IPooltoken).RttiPool.GetByHandle(AHandle);
  6627. end;
  6628. procedure TRttiContext.AddObject(AObject: TRttiObject);
  6629. begin
  6630. if not Assigned(FContextToken) then
  6631. FContextToken := TPoolToken.Create(UsePublishedOnly);
  6632. (FContextToken as IPooltoken).RttiPool.AddObject(AObject);
  6633. AObject.FUsePublishedOnly := UsePublishedOnly;
  6634. end;
  6635. function TRttiContext.GetType(ATypeInfo: PTypeInfo): TRttiType;
  6636. begin
  6637. if not assigned(FContextToken) then
  6638. FContextToken := TPoolToken.Create(UsePublishedOnly);
  6639. result := (FContextToken as IPooltoken).RttiPool.GetType(ATypeInfo,UsePublishedOnly);
  6640. end;
  6641. function TRttiContext.GetType(AClass: TClass): TRttiType;
  6642. begin
  6643. if assigned(AClass) then
  6644. result := GetType(PTypeInfo(AClass.ClassInfo))
  6645. else
  6646. result := nil;
  6647. end;
  6648. {function TRttiContext.GetTypes: specialize TArray<TRttiType>;
  6649. begin
  6650. if not assigned(FContextToken) then
  6651. FContextToken := TPoolToken.Create;
  6652. result := (FContextToken as IPooltoken).RttiPool.GetTypes;
  6653. end;}
  6654. { TVirtualInterface }
  6655. {.$define DEBUG_VIRTINTF}
  6656. constructor TVirtualInterface.Create(aPIID: PTypeInfo);
  6657. const
  6658. BytesToPopQueryInterface =
  6659. {$ifdef cpui386}
  6660. 3 * SizeOf(Pointer); { aIID + aObj + $RetAddr }
  6661. {$else}
  6662. 0;
  6663. {$endif}
  6664. BytesToPopAddRef =
  6665. {$ifdef cpui386}
  6666. 1 * SizeOf(Pointer); { $RetAddr }
  6667. {$else}
  6668. 0;
  6669. {$endif}
  6670. BytesToPopRelease =
  6671. {$ifdef cpui386}
  6672. 1 * SizeOf(Pointer); { $RetAddr }
  6673. {$else}
  6674. 0;
  6675. {$endif}
  6676. var
  6677. t: TRttiType;
  6678. ti: PTypeInfo;
  6679. td: PInterfaceData;
  6680. methods: specialize TArray<TRttiMethod>;
  6681. m: TRttiMethod;
  6682. mt: PIntfMethodTable;
  6683. count, i: SizeInt;
  6684. begin
  6685. if not Assigned(aPIID) then
  6686. raise EArgumentNilException.Create(SErrVirtIntfTypeNil);
  6687. { ToDo: add support for raw interfaces once they support RTTI }
  6688. if aPIID^.Kind <> tkInterface then
  6689. raise EArgumentException.CreateFmt(SErrVirtIntfTypeMustBeIntf, [aPIID^.Name]);
  6690. fContext := TRttiContext.Create;
  6691. t := fContext.GetType(aPIID);
  6692. if not Assigned(t) then
  6693. raise EInsufficientRtti.CreateFmt(SErrVirtIntfTypeNotFound, [aPIID^.Name]);
  6694. { check whether the interface and all its parents have RTTI enabled (the only
  6695. exception is IInterface as we know the methods of that) }
  6696. td := PInterfaceData(GetTypeData(aPIID));
  6697. fGUID := td^.GUID;
  6698. fThunks[0] := AllocateRawThunk(TMethod(@QueryInterface).Code, Pointer(Self), BytesToPopQueryInterface);
  6699. fThunks[1] := AllocateRawThunk(TMethod(@_AddRef).Code, Pointer(Self), BytesToPopAddRef);
  6700. fThunks[2] := AllocateRawThunk(TMethod(@_Release).Code, Pointer(Self), BytesToPopRelease);
  6701. for i := Low(fThunks) to High(fThunks) do
  6702. if not Assigned(fThunks[i]) then
  6703. raise ENotImplemented.CreateFmt(SErrVirtIntfCreateThunk, [aPIID^.Name]);
  6704. ti := aPIID;
  6705. { ignore the three methods of IInterface }
  6706. count := 0;
  6707. while ti <> TypeInfo(IInterface) do begin
  6708. mt := td^.MethodTable;
  6709. if (mt^.Count > 0) and (mt^.RTTICount <> mt^.Count) then
  6710. raise EInsufficientRtti.CreateFmt(SErrVirtIntfNotAllMethodsRTTI, [aPIID^.Name]);
  6711. Inc(count, mt^.Count);
  6712. ti := td^.Parent^;
  6713. td := PInterfaceData(GetTypeData(ti));
  6714. end;
  6715. SetLength(fImpls, count);
  6716. methods := t.GetMethods;
  6717. for m in methods do begin
  6718. if m.VirtualIndex > High(fImpls) + Length(fThunks) then
  6719. raise ERtti.CreateFmt(SErrVirtIntfInvalidVirtIdx, [aPIID^.Name, m.Name, m.VirtualIndex]);
  6720. if m.VirtualIndex < Length(fThunks) then
  6721. raise ERtti.CreateFmt(SErrVirtIntfInvalidVirtIdx, [aPIID^.Name, m.Name, m.VirtualIndex]);
  6722. { we use the childmost entry, except for the IInterface methods }
  6723. if Assigned(fImpls[m.VirtualIndex - Length(fThunks)]) then begin
  6724. {$IFDEF DEBUG_VIRTINTF}Writeln('Ignoring duplicate implementation for index ', m.VirtualIndex);{$ENDIF}
  6725. Continue;
  6726. end;
  6727. fImpls[m.VirtualIndex - Length(fThunks)] := m.CreateImplementation(m, @HandleUserCallback);
  6728. end;
  6729. for i := 0 to High(fImpls) do
  6730. if not Assigned(fImpls) then
  6731. raise ERtti.CreateFmt(SErrVirtIntfMethodNil, [aPIID^.Name, i]);
  6732. fVmt := GetMem(Length(fImpls) * SizeOf(CodePointer) + Length(fThunks) * SizeOf(CodePointer));
  6733. if not Assigned(fVmt) then
  6734. raise ERtti.CreateFmt(SErrVirtIntfCreateVmt, [aPIID^.Name]);
  6735. for i := 0 to High(fThunks) do begin
  6736. fVmt[i] := fThunks[i];
  6737. {$IFDEF DEBUG_VIRTINTF}Writeln('VMT ', i, ': ', HexStr(fVmt[i]));{$ENDIF}
  6738. end;
  6739. for i := 0 to High(fImpls) do begin
  6740. fVmt[i + Length(fThunks)] := fImpls[i].CodeAddress;
  6741. {$IFDEF DEBUG_VIRTINTF}Writeln('VMT ', i + Length(fThunks), ': ', HexStr(fVmt[i + Length(fThunks)]));{$ENDIF}
  6742. end;
  6743. end;
  6744. constructor TVirtualInterface.Create(aPIID: PTypeInfo; aInvokeEvent: TVirtualInterfaceInvokeEvent);
  6745. begin
  6746. Create(aPIID);
  6747. OnInvoke := aInvokeEvent;
  6748. end;
  6749. destructor TVirtualInterface.Destroy;
  6750. var
  6751. impl: TMethodImplementation;
  6752. thunk: CodePointer;
  6753. begin
  6754. {$IFDEF DEBUG_VIRTINTF}Writeln('Freeing implementations');{$ENDIF}
  6755. for impl in fImpls do
  6756. impl.Free;
  6757. {$IFDEF DEBUG_VIRTINTF}Writeln('Freeing thunks');{$ENDIF}
  6758. for thunk in fThunks do
  6759. FreeRawThunk(thunk);
  6760. {$IFDEF DEBUG_VIRTINTF}Writeln('Freeing VMT');{$ENDIF}
  6761. if Assigned(fVmt) then
  6762. FreeMem(fVmt);
  6763. {$IFDEF DEBUG_VIRTINTF}Writeln('Freeing Context');{$ENDIF}
  6764. fContext.Free;
  6765. {$IFDEF DEBUG_VIRTINTF}Writeln('Done');{$ENDIF}
  6766. inherited Destroy;
  6767. end;
  6768. function TVirtualInterface.QueryInterface(constref aIID: TGuid; out aObj): LongInt;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  6769. begin
  6770. {$IFDEF DEBUG_VIRTINTF}Writeln('QueryInterface for ', GUIDToString(aIID));{$ENDIF}
  6771. if IsEqualGUID(aIID, fGUID) then begin
  6772. {$IFDEF DEBUG_VIRTINTF}Writeln('Returning ', HexStr(@fVmt));{$ENDIF}
  6773. Pointer(aObj) := @fVmt;
  6774. { QueryInterface increases the reference count }
  6775. _AddRef;
  6776. Result := S_OK;
  6777. end else
  6778. Result := inherited QueryInterface(aIID, aObj);
  6779. end;
  6780. function TVirtualInterface._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  6781. begin
  6782. Result:=Inherited _AddRef;
  6783. end;
  6784. function TVirtualInterface._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  6785. begin
  6786. Result:=Inherited _Release;
  6787. end;
  6788. procedure TVirtualInterface.HandleUserCallback(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue);
  6789. begin
  6790. {$IFDEF DEBUG_VIRTINTF}Writeln('Call for ', TRttiMethod(aUserData).Name);{$ENDIF}
  6791. if Assigned(fOnInvoke) then
  6792. fOnInvoke(TRttiMethod(aUserData), aArgs, aResult);
  6793. end;
  6794. function TRttiObject.GetAttribute(aClass: TCustomAttributeClass): TCustomAttribute;
  6795. var
  6796. attrarray : TCustomAttributeArray;
  6797. a: TCustomAttribute;
  6798. begin
  6799. Result:=nil;
  6800. attrarray:=GetAttributes;
  6801. for a in attrarray do
  6802. if a.InheritsFrom(aClass) then
  6803. Exit(a);
  6804. end;
  6805. function TRttiObject.HasAttribute(aClass: TCustomAttributeClass): Boolean;
  6806. begin
  6807. Result:=Assigned(GetAttribute(aClass));
  6808. end;
  6809. generic function TRttiObject.GetAttribute<T>: T;
  6810. begin
  6811. Result:=T(GetAttribute(T));
  6812. end;
  6813. generic function TRttiObject.HasAttribute<T>: Boolean;
  6814. begin
  6815. Result:=HasAttribute(T);
  6816. end;
  6817. { TRttiRecordMethod }
  6818. constructor TRttiRecordMethod.Create(AParent: TRttiType; aHandle: PRecMethodExEntry);
  6819. begin
  6820. inherited create(aParent);
  6821. FHandle:=aHandle;
  6822. end;
  6823. function TRttiRecordMethod.GetCallingConvention: TCallConv;
  6824. begin
  6825. Result:=Fhandle^.CC;
  6826. end;
  6827. function TRttiRecordMethod.GetReturnType: TRttiType;
  6828. var
  6829. context: TRttiContext;
  6830. begin
  6831. if not Assigned(FHandle^.ResultType) then
  6832. Exit(Nil);
  6833. context := TRttiContext.Create(FUsePublishedOnly);
  6834. try
  6835. Result := context.GetType(FHandle^.ResultType^);
  6836. finally
  6837. context.Free;
  6838. end;
  6839. end;
  6840. function TRttiRecordMethod.GetDispatchKind: TDispatchKind;
  6841. begin
  6842. Result := dkStatic;
  6843. end;
  6844. function TRttiRecordMethod.GetHasExtendedInfo: Boolean;
  6845. begin
  6846. Result:=True
  6847. end;
  6848. function TRttiRecordMethod.GetCodeAddress: CodePointer;
  6849. begin
  6850. Result := FHandle^.CodeAddress;
  6851. end;
  6852. function TRttiRecordMethod.GetIsClassMethod: Boolean;
  6853. begin
  6854. Result := GetMethodKind in [mkClassProcedure, mkClassFunction, mkOperatorOverload];
  6855. end;
  6856. function TRttiRecordMethod.GetIsStatic: Boolean;
  6857. begin
  6858. Result:=not (GetMethodKind in [mkProcedure, mkFunction]);
  6859. end;
  6860. function TRttiRecordMethod.GetVisibility: TMemberVisibility;
  6861. begin
  6862. Result:=MemberVisibilities[FHandle^.MethodVisibility];
  6863. end;
  6864. function TRttiRecordMethod.GetHandle: Pointer;
  6865. begin
  6866. Result:=FHandle;
  6867. end;
  6868. function TRttiRecordMethod.GetVirtualIndex: SmallInt;
  6869. begin
  6870. Result:=-1;
  6871. end;
  6872. Procedure TRttiRecordMethod.ResolveParams;
  6873. var
  6874. param: PVmtMethodParam;
  6875. total, visible: SizeInt;
  6876. context: TRttiContext;
  6877. obj: TRttiObject;
  6878. prtti : TRttiVmtMethodParameter ;
  6879. begin
  6880. total := 0;
  6881. visible := 0;
  6882. SetLength(FParams[False],FHandle^.ParamCount);
  6883. SetLength(FParams[True],FHandle^.ParamCount);
  6884. context := TRttiContext.Create(FUsePublishedOnly);
  6885. try
  6886. param := FHandle^.Param[0];
  6887. while total < FHandle^.ParamCount do
  6888. begin
  6889. obj := context.GetByHandle(param);
  6890. if Assigned(obj) then
  6891. prtti := obj as TRttiVmtMethodParameter
  6892. else
  6893. begin
  6894. prtti := TRttiVmtMethodParameter.Create(param);
  6895. context.AddObject(prtti);
  6896. end;
  6897. FParams[True][total]:=prtti;
  6898. if not (pfHidden in param^.Flags) then
  6899. begin
  6900. FParams[False][visible]:=prtti;
  6901. Inc(visible);
  6902. end;
  6903. param := param^.Next;
  6904. Inc(total);
  6905. end;
  6906. if visible <> total then
  6907. SetLength(FParams[False], visible);
  6908. finally
  6909. context.Free;
  6910. end;
  6911. end;
  6912. function TRttiRecordMethod.GetParameters(aWithHidden : Boolean): TRttiParameterArray;
  6913. begin
  6914. if (Length(FParams[aWithHidden]) > 0) then
  6915. Exit(FParams[aWithHidden]);
  6916. if FHandle^.ParamCount = 0 then
  6917. Exit(Nil);
  6918. ResolveParams;
  6919. Result := FParams[aWithHidden];
  6920. end;
  6921. function TRttiRecordMethod.GetAttributes: TCustomAttributeArray;
  6922. begin
  6923. Result:=Nil;
  6924. end;
  6925. function TRttiRecordMethod.GetMethodKind: TMethodKind;
  6926. begin
  6927. Result:=FHandle^.Kind;
  6928. end;
  6929. function TRttiRecordMethod.GetName: string;
  6930. begin
  6931. Result:=FHandle^.Name;
  6932. end;
  6933. function TRttiRecordMethod.GetIsConstructor: Boolean;
  6934. begin
  6935. Result:=GetMethodKind in [mkConstructor,mkClassConstructor];
  6936. end;
  6937. function TRttiRecordMethod.GetIsDestructor: Boolean;
  6938. begin
  6939. Result:=False;
  6940. end;
  6941. {$ifndef InLazIDE}
  6942. {$if defined(CPUI386) or (defined(CPUX86_64) and defined(WIN64))}
  6943. {$I invoke.inc}
  6944. {$endif}
  6945. {$endif}
  6946. initialization
  6947. PoolRefCount[False] := 0;
  6948. PoolRefCount[True] := 0;
  6949. InitDefaultFunctionCallManager;
  6950. {$ifdef SYSTEM_HAS_INVOKE}
  6951. InitSystemFunctionCallManager;
  6952. {$endif}
  6953. end.