rtti.pp 221 KB

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