rtti.pp 245 KB

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