rtti.pp 199 KB

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