rtti.pp 219 KB

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