rtti.pp 219 KB

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