2
0

variants.pp 132 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678
  1. {
  2. This include file contains the variants
  3. support for FPC
  4. This file is part of the Free Pascal run time library.
  5. Copyright (c) 2001-2005 by the Free Pascal development team
  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. {$IFDEF fpc}
  13. {$mode objfpc}
  14. {$ENDIF}
  15. {$h+}
  16. { Using inlining for small system functions/wrappers }
  17. {$inline on}
  18. {$define VARIANTINLINE}
  19. unit variants;
  20. interface
  21. uses
  22. sysutils,sysconst,rtlconsts,typinfo;
  23. type
  24. EVariantParamNotFoundError = class(EVariantError);
  25. EVariantInvalidOpError = class(EVariantError);
  26. EVariantTypeCastError = class(EVariantError);
  27. EVariantOverflowError = class(EVariantError);
  28. EVariantInvalidArgError = class(EVariantError);
  29. EVariantBadVarTypeError = class(EVariantError);
  30. EVariantBadIndexError = class(EVariantError);
  31. EVariantArrayLockedError = class(EVariantError);
  32. EVariantNotAnArrayError = class(EVariantError);
  33. EVariantArrayCreateError = class(EVariantError);
  34. EVariantNotImplError = class(EVariantError);
  35. EVariantOutOfMemoryError = class(EVariantError);
  36. EVariantUnexpectedError = class(EVariantError);
  37. EVariantDispatchError = class(EVariantError);
  38. EVariantRangeCheckError = class(EVariantOverflowError);
  39. EVariantInvalidNullOpError = class(EVariantInvalidOpError);
  40. TVariantRelationship = (vrEqual, vrLessThan, vrGreaterThan, vrNotEqual);
  41. TNullCompareRule = (ncrError, ncrStrict, ncrLoose);
  42. TBooleanToStringRule = (bsrAsIs, bsrLower, bsrUpper);
  43. Const
  44. OrdinalVarTypes = [varSmallInt, varInteger, varBoolean, varShortInt,
  45. varByte, varWord,varLongWord,varInt64];
  46. FloatVarTypes = [
  47. {$ifndef FPUNONE}
  48. varSingle, varDouble,
  49. {$endif}
  50. varCurrency];
  51. { Variant support procedures and functions }
  52. function VarType(const V: Variant): TVarType; inline;
  53. function VarTypeDeRef(const V: Variant): TVarType; overload;
  54. function VarTypeDeRef(const V: TVarData): TVarType; overload; inline;
  55. function VarAsType(const V: Variant; aVarType: TVarType): Variant;
  56. function VarIsType(const V: Variant; aVarType: TVarType): Boolean; overload; inline;
  57. function VarIsType(const V: Variant; const AVarTypes: array of TVarType): Boolean; overload;
  58. function VarIsByRef(const V: Variant): Boolean; inline;
  59. function VarIsEmpty(const V: Variant): Boolean; inline;
  60. procedure VarCheckEmpty(const V: Variant); inline;
  61. function VarIsNull(const V: Variant): Boolean; inline;
  62. function VarIsClear(const V: Variant): Boolean; inline;
  63. function VarIsCustom(const V: Variant): Boolean; inline;
  64. function VarIsOrdinal(const V: Variant): Boolean; inline;
  65. function VarIsFloat(const V: Variant): Boolean; inline;
  66. function VarIsNumeric(const V: Variant): Boolean; inline;
  67. function VarIsStr(const V: Variant): Boolean;
  68. function VarIsBool(const V: Variant): Boolean; inline;
  69. function VarToStr(const V: Variant): string;
  70. function VarToStrDef(const V: Variant; const ADefault: string): string;
  71. function VarToWideStr(const V: Variant): WideString;
  72. function VarToWideStrDef(const V: Variant; const ADefault: WideString): WideString;
  73. function VarToUnicodeStr(const V: Variant): UnicodeString;
  74. function VarToUnicodeStrDef(const V: Variant; const ADefault: UnicodeString): UnicodeString;
  75. {$ifndef FPUNONE}
  76. function VarToDateTime(const V: Variant): TDateTime;
  77. function VarFromDateTime(const DateTime: TDateTime): Variant;
  78. {$endif}
  79. function VarInRange(const AValue, AMin, AMax: Variant): Boolean;
  80. function VarEnsureRange(const AValue, AMin, AMax: Variant): Variant;
  81. function VarSameValue(const A, B: Variant): Boolean;
  82. function VarCompareValue(const A, B: Variant): TVariantRelationship;
  83. function VarIsEmptyParam(const V: Variant): Boolean; inline;
  84. procedure VarClear(var V: Variant);{$IFDEF VARIANTINLINE}inline;{$ENDIF VARIANTINLINE}
  85. procedure VarClear(var V: OleVariant);{$IFDEF VARIANTINLINE}inline;{$ENDIF VARIANTINLINE}
  86. procedure SetClearVarToEmptyParam(var V: TVarData);
  87. function VarIsError(const V: Variant; out AResult: HRESULT): Boolean;
  88. function VarIsError(const V: Variant): Boolean; inline;
  89. function VarAsError(AResult: HRESULT): Variant;
  90. function VarSupports(const V: Variant; const IID: TGUID; out Intf): Boolean;
  91. function VarSupports(const V: Variant; const IID: TGUID): Boolean;
  92. { Variant copy support }
  93. procedure VarCopyNoInd(var Dest: Variant; const Source: Variant);
  94. { Variant array support procedures and functions }
  95. function VarArrayCreate(const Bounds: array of SizeInt; aVarType: TVarType): Variant;
  96. function VarArrayCreate(const Bounds: PVarArrayBoundArray; Dims : SizeInt; aVarType: TVarType): Variant;
  97. function VarArrayOf(const Values: array of Variant): Variant;
  98. function VarArrayAsPSafeArray(const A: Variant): PVarArray;
  99. function VarArrayDimCount(const A: Variant) : LongInt;
  100. function VarArrayLowBound(const A: Variant; Dim : LongInt) : LongInt;
  101. function VarArrayHighBound(const A: Variant; Dim : LongInt) : LongInt;
  102. function VarArrayLock(const A: Variant): Pointer;
  103. procedure VarArrayUnlock(const A: Variant);
  104. function VarArrayRef(const A: Variant): Variant;
  105. function VarIsArray(const A: Variant): Boolean; inline;
  106. function VarIsArray(const A: Variant; AResolveByRef: Boolean): Boolean;
  107. function VarTypeIsValidArrayType(const aVarType: TVarType): Boolean;
  108. function VarTypeIsValidElementType(const aVarType: TVarType): Boolean;
  109. { Variant <--> Dynamic Arrays }
  110. procedure DynArrayToVariant(var V: Variant; const DynArray: Pointer; TypeInfo: Pointer);
  111. procedure DynArrayFromVariant(var DynArray: Pointer; const V: Variant; TypeInfo: Pointer);
  112. { Global constants }
  113. function Unassigned: Variant; // Unassigned standard constant
  114. function Null: Variant; // Null standard constant
  115. var
  116. EmptyParam: OleVariant;
  117. { Custom Variant base class }
  118. type
  119. TVarCompareResult = (crLessThan, crEqual, crGreaterThan);
  120. TCustomVariantType = class(TObject, IInterface)
  121. private
  122. FVarType: TVarType;
  123. protected
  124. function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; virtual; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  125. function _AddRef: Longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  126. function _Release: Longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  127. procedure SimplisticClear(var V: TVarData);
  128. procedure SimplisticCopy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean = False);
  129. procedure RaiseInvalidOp;
  130. procedure RaiseCastError;
  131. procedure RaiseDispError;
  132. function LeftPromotion(const V: TVarData; const Operation: TVarOp; out RequiredVarType: TVarType): Boolean; virtual;
  133. function RightPromotion(const V: TVarData; const Operation: TVarOp; out RequiredVarType: TVarType): Boolean; virtual;
  134. function OlePromotion(const V: TVarData; out RequiredVarType: TVarType): Boolean; virtual;
  135. procedure DispInvoke(Dest: PVarData; var Source: TVarData; CallDesc: PCallDesc; Params: Pointer); virtual;
  136. procedure VarDataInit(var Dest: TVarData);
  137. procedure VarDataClear(var Dest: TVarData);
  138. procedure VarDataCopy(var Dest: TVarData; const Source: TVarData);
  139. procedure VarDataCopyNoInd(var Dest: TVarData; const Source: TVarData);
  140. procedure VarDataCast(var Dest: TVarData; const Source: TVarData);
  141. procedure VarDataCastTo(var Dest: TVarData; const Source: TVarData; const aVarType: TVarType); overload;
  142. procedure VarDataCastTo(var Dest: TVarData; const aVarType: TVarType); overload;
  143. procedure VarDataCastToOleStr(var Dest: TVarData);
  144. procedure VarDataFromStr(var V: TVarData; const Value: string);
  145. procedure VarDataFromOleStr(var V: TVarData; const Value: WideString);
  146. function VarDataToStr(const V: TVarData): string;
  147. function VarDataIsEmptyParam(const V: TVarData): Boolean;
  148. function VarDataIsByRef(const V: TVarData): Boolean;
  149. function VarDataIsArray(const V: TVarData): Boolean;
  150. function VarDataIsOrdinal(const V: TVarData): Boolean;
  151. function VarDataIsFloat(const V: TVarData): Boolean;
  152. function VarDataIsNumeric(const V: TVarData): Boolean;
  153. function VarDataIsStr(const V: TVarData): Boolean;
  154. public
  155. constructor Create; overload;
  156. constructor Create(RequestedVarType: TVarType); overload;
  157. destructor Destroy; override;
  158. function IsClear(const V: TVarData): Boolean; virtual;
  159. procedure Cast(var Dest: TVarData; const Source: TVarData); virtual;
  160. procedure CastTo(var Dest: TVarData; const Source: TVarData; const aVarType: TVarType); virtual;
  161. procedure CastToOle(var Dest: TVarData; const Source: TVarData); virtual;
  162. procedure Clear(var V: TVarData); virtual; abstract;
  163. procedure Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean); virtual; abstract;
  164. procedure BinaryOp(var Left: TVarData; const Right: TVarData; const Operation: TVarOp); virtual;
  165. procedure UnaryOp(var Right: TVarData; const Operation: TVarOp); virtual;
  166. function CompareOp(const Left, Right: TVarData; const Operation: TVarOp): Boolean; virtual;
  167. procedure Compare(const Left, Right: TVarData; var Relationship: TVarCompareResult); virtual;
  168. property VarType: TVarType read FVarType;
  169. end;
  170. TCustomVariantTypeClass = class of TCustomVariantType;
  171. TVarDataArray = array of TVarData;
  172. IVarInvokeable = interface
  173. ['{1CB65C52-BBCB-41A6-9E58-7FB916BEEB2D}']
  174. function DoFunction(var Dest: TVarData; const V: TVarData;
  175. const Name: string; const Arguments: TVarDataArray): Boolean;
  176. function DoProcedure(const V: TVarData; const Name: string;
  177. const Arguments: TVarDataArray): Boolean;
  178. function GetProperty(var Dest: TVarData; const V: TVarData;
  179. const Name: string): Boolean;
  180. function SetProperty(var V: TVarData; const Name: string;
  181. const Value: TVarData): Boolean;
  182. end;
  183. TInvokeableVariantType = class(TCustomVariantType, IVarInvokeable)
  184. protected
  185. procedure DispInvoke(Dest: PVarData; var Source: TVarData;
  186. CallDesc: PCallDesc; Params: Pointer); override;
  187. public
  188. { IVarInvokeable }
  189. function DoFunction(var Dest: TVarData; const V: TVarData;
  190. const Name: string; const Arguments: TVarDataArray): Boolean; virtual;
  191. function DoProcedure(const V: TVarData; const Name: string;
  192. const Arguments: TVarDataArray): Boolean; virtual;
  193. function GetProperty(var Dest: TVarData; const V: TVarData;
  194. const Name: string): Boolean; virtual;
  195. function SetProperty(var V: TVarData; const Name: string;
  196. const Value: TVarData): Boolean; virtual;
  197. end;
  198. IVarInstanceReference = interface
  199. ['{5C176802-3F89-428D-850E-9F54F50C2293}']
  200. function GetInstance(const V: TVarData): TObject;
  201. end;
  202. TPublishableVariantType = class(TInvokeableVariantType, IVarInstanceReference)
  203. protected
  204. { IVarInstanceReference }
  205. function GetInstance(const V: TVarData): TObject; virtual; abstract;
  206. public
  207. function GetProperty(var Dest: TVarData; const V: TVarData;
  208. const Name: string): Boolean; override;
  209. function SetProperty(var V: TVarData; const Name: string;
  210. const Value: TVarData): Boolean; override;
  211. end;
  212. function FindCustomVariantType(const aVarType: TVarType;
  213. out CustomVariantType: TCustomVariantType): Boolean; overload;
  214. function FindCustomVariantType(const TypeName: string;
  215. out CustomVariantType: TCustomVariantType): Boolean; overload;
  216. type
  217. TAnyProc = procedure (var V: TVarData);
  218. TVarDispProc = procedure (Dest: PVariant; const Source: Variant;
  219. CallDesc: PCallDesc; Params: Pointer); cdecl;
  220. Const
  221. CMaxNumberOfCustomVarTypes = $0EFF;
  222. CMinVarType = $0100;
  223. CMaxVarType = CMinVarType + CMaxNumberOfCustomVarTypes;
  224. CIncVarType = $000F;
  225. CFirstUserType = CMinVarType + CIncVarType;
  226. var
  227. NullEqualityRule: TNullCompareRule = ncrLoose;
  228. NullMagnitudeRule: TNullCompareRule = ncrLoose;
  229. NullStrictConvert: Boolean = true;
  230. NullAsStringValue: string = '';
  231. PackVarCreation: Boolean = True;
  232. {$ifndef FPUNONE}
  233. OleVariantInt64AsDouble: Boolean = False;
  234. {$endif}
  235. VarDispProc: TVarDispProc;
  236. ClearAnyProc: TAnyProc; { Handler clearing a varAny }
  237. ChangeAnyProc: TAnyProc; { Handler to change any to Variant }
  238. RefAnyProc: TAnyProc; { Handler to add a reference to an varAny }
  239. InvalidCustomVariantType : TCustomVariantType;
  240. procedure VarCastError;
  241. procedure VarCastError(const ASourceType, ADestType: TVarType);
  242. procedure VarCastErrorOle(const ASourceType: TVarType);
  243. procedure VarInvalidOp;
  244. procedure VarInvalidOp(const aLeft, aRight: TVarType; aOpCode: TVarOp);
  245. procedure VarInvalidOp(const aRight: TVarType; aOpCode: TVarOp);
  246. procedure VarInvalidNullOp;
  247. procedure VarBadTypeError;
  248. procedure VarOverflowError;
  249. procedure VarOverflowError(const ASourceType, ADestType: TVarType);
  250. procedure VarBadIndexError;
  251. procedure VarArrayLockedError;
  252. procedure VarNotImplError;
  253. procedure VarOutOfMemoryError;
  254. procedure VarInvalidArgError;
  255. procedure VarInvalidArgError(AType: TVarType);
  256. procedure VarUnexpectedError;
  257. procedure VarRangeCheckError(const AType: TVarType);
  258. procedure VarRangeCheckError(const ASourceType, ADestType: TVarType);
  259. procedure VarArrayCreateError;
  260. procedure VarResultCheck(AResult: HRESULT);{$IFDEF VARIANTINLINE}inline;{$ENDIF VARIANTINLINE}
  261. procedure VarResultCheck(AResult: HRESULT; ASourceType, ADestType: TVarType);
  262. procedure HandleConversionException(const ASourceType, ADestType: TVarType);
  263. function VarTypeAsText(const AType: TVarType): string;
  264. function FindVarData(const V: Variant): PVarData;
  265. const
  266. VarOpAsText : array[TVarOp] of string = (
  267. '+', {opAdd}
  268. '-', {opSubtract}
  269. '*', {opMultiply}
  270. '/', {opDivide}
  271. 'div', {opIntDivide}
  272. 'mod', {opModulus}
  273. 'shl', {opShiftLeft}
  274. 'shr', {opShiftRight}
  275. 'and', {opAnd}
  276. 'or', {opOr}
  277. 'xor', {opXor}
  278. '', {opCompare}
  279. '-', {opNegate}
  280. 'not', {opNot}
  281. '=', {opCmpEq}
  282. '<>', {opCmpNe}
  283. '<', {opCmpLt}
  284. '<=', {opCmpLe}
  285. '>', {opCmpGt}
  286. '>=', {opCmpGe}
  287. '**' {opPower}
  288. );
  289. { Typinfo unit Variant routines have been moved here, so as not to make TypInfo dependent on variants }
  290. Function GetPropValue(Instance: TObject; PropInfo: PPropInfo; PreferStrings: Boolean): Variant;
  291. Procedure SetPropValue(Instance: TObject; PropInfo: PPropInfo; const Value: Variant);
  292. Function GetVariantProp(Instance: TObject; PropInfo : PPropInfo): Variant;
  293. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  294. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  295. Procedure SetVariantProp(Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  296. {$IFDEF DEBUG_VARIANTS}
  297. var
  298. __DEBUG_VARIANTS: Boolean = False;
  299. {$ENDIF}
  300. implementation
  301. uses
  302. Math,
  303. VarUtils;
  304. var
  305. customvarianttypes : array of TCustomVariantType;
  306. customvarianttypelock : trtlcriticalsection;
  307. customvariantcurrtype : LongInt;
  308. const
  309. { all variants for which vType and varComplexType = 0 do not require
  310. finalization. }
  311. varComplexType = $BFE8;
  312. procedure DoVarClearComplex(var v : TVarData); forward;
  313. procedure DoVarCopy(var Dest : TVarData; const Source : TVarData); forward;
  314. procedure DoVarCast(var aDest : TVarData; const aSource : TVarData; aVarType : LongInt); forward;
  315. procedure DoVarClear(var v : TVarData); inline;
  316. begin
  317. if v.vType and varComplexType <> 0 then
  318. DoVarClearComplex(v)
  319. else
  320. v.vType := varEmpty;
  321. end;
  322. procedure DoVarClearIfComplex(var v : TVarData); inline;
  323. begin
  324. if v.vType and varComplexType <> 0 then
  325. DoVarClearComplex(v);
  326. end;
  327. function AlignToPtr(p : Pointer) : Pointer;inline;
  328. begin
  329. {$IFDEF FPC_REQUIRES_PROPER_ALIGNMENT}
  330. Result:=align(p,SizeOf(p));
  331. {$ELSE FPC_REQUIRES_PROPER_ALIGNMENT}
  332. Result:=p;
  333. {$ENDIF FPC_REQUIRES_PROPER_ALIGNMENT}
  334. end;
  335. { ---------------------------------------------------------------------
  336. String Messages
  337. ---------------------------------------------------------------------}
  338. ResourceString
  339. SErrVarIsEmpty = 'Variant is empty';
  340. SErrInvalidIntegerRange = 'Invalid Integer range: %d';
  341. { ---------------------------------------------------------------------
  342. Auxiliary routines
  343. ---------------------------------------------------------------------}
  344. Procedure VariantError (Const Msg : String); inline;
  345. begin
  346. Raise EVariantError.Create(Msg);
  347. end;
  348. Procedure NotSupported(Meth: String);
  349. begin
  350. Raise EVariantError.CreateFmt('Method %s not yet supported.',[Meth]);
  351. end;
  352. type
  353. TVariantArrayIterator = object
  354. Bounds : PVarArrayBoundArray;
  355. Coords : PVarArrayCoorArray;
  356. Dims : SizeInt;
  357. constructor Init(aDims: SizeInt; aBounds : PVarArrayBoundArray);
  358. destructor Done;
  359. function Next : Boolean;
  360. { returns true if the iterator reached the end of the variant array }
  361. function AtEnd: Boolean;
  362. end;
  363. {$push}
  364. {$r-}
  365. constructor TVariantArrayIterator.Init(aDims: SizeInt; aBounds : PVarArrayBoundArray);
  366. var
  367. i : sizeint;
  368. begin
  369. Dims := aDims;
  370. Bounds := aBounds;
  371. GetMem(Coords, SizeOf(SizeInt) * Dims);
  372. { initialize coordinate counter }
  373. for i:= 0 to Pred(Dims) do
  374. Coords^[i] := Bounds^[i].LowBound;
  375. end;
  376. function TVariantArrayIterator.Next: Boolean;
  377. var
  378. Finished : Boolean;
  379. procedure IncDim(Dim : SizeInt);
  380. begin
  381. if Finished then
  382. Exit;
  383. Inc(Coords^[Dim]);
  384. if Coords^[Dim] >= Bounds^[Dim].LowBound + Bounds^[Dim].ElementCount then begin
  385. Coords^[Dim]:=Bounds^[Dim].LowBound;
  386. if Dim > 0 then
  387. IncDim(Pred(Dim))
  388. else
  389. Finished := True;
  390. end;
  391. end;
  392. begin
  393. Finished := False;
  394. IncDim(Pred(Dims));
  395. Result := not Finished;
  396. end;
  397. function TVariantArrayIterator.AtEnd: Boolean;
  398. var
  399. i,l : sizeint;
  400. begin
  401. result:=false;
  402. l:=Pred(dims);
  403. I:=0;
  404. While (not Result) and (I<=L) do
  405. begin
  406. Result:=Coords^[i] >= (Bounds^[i].LowBound + Bounds^[i].ElementCount);
  407. inc(i);
  408. end;
  409. end;
  410. {$pop}// {$r-} for TVariantArrayIterator
  411. destructor TVariantArrayIterator.done;
  412. begin
  413. FreeMem(Coords);
  414. end;
  415. type
  416. tdynarraybounds = array of SizeInt;
  417. tdynarraycoords = tdynarraybounds;
  418. tdynarrayelesize = tdynarraybounds;
  419. tdynarraypositions = array of Pointer;
  420. tdynarrayiter = object
  421. Bounds : tdynarraybounds;
  422. Coords : tdynarraycoords;
  423. elesize : tdynarrayelesize;
  424. positions : tdynarraypositions;
  425. Dims : SizeInt;
  426. data : Pointer;
  427. constructor init(d : Pointer;typeInfo : Pointer;_dims: SizeInt;b : tdynarraybounds);
  428. function next : Boolean;
  429. destructor done;
  430. end;
  431. constructor tdynarrayiter.init(d : Pointer;typeInfo : Pointer;_dims: SizeInt;b : tdynarraybounds);
  432. var
  433. i : sizeint;
  434. begin
  435. Bounds:=b;
  436. Dims:=_dims;
  437. SetLength(Coords,Dims);
  438. SetLength(elesize,Dims);
  439. SetLength(positions,Dims);
  440. positions[0]:=d;
  441. { initialize coordinate counter and elesize }
  442. for i:=0 to Dims-1 do
  443. begin
  444. Coords[i]:=0;
  445. if i>0 then
  446. positions[i]:=Pointer(positions[i-1]^);
  447. { skip kind and name }
  448. typeInfo:=aligntoptr(typeInfo+2+Length(PTypeInfo(typeInfo)^.Name));
  449. elesize[i]:=PTypeData(typeInfo)^.elSize;
  450. typeInfo:=PTypeData(typeInfo)^.elType2;
  451. end;
  452. data:=positions[Dims-1];
  453. end;
  454. function tdynarrayiter.next : Boolean;
  455. var
  456. Finished : Boolean;
  457. procedure incdim(d : SizeInt);
  458. begin
  459. if Finished then
  460. exit;
  461. inc(Coords[d]);
  462. inc(Pointer(positions[d]),elesize[d]);
  463. if Coords[d]>=Bounds[d] then
  464. begin
  465. Coords[d]:=0;
  466. if d>0 then
  467. begin
  468. incdim(d-1);
  469. positions[d]:=Pointer(positions[d-1]^);
  470. end
  471. else
  472. Finished:=true;
  473. end;
  474. end;
  475. begin
  476. Finished:=False;
  477. incdim(Dims-1);
  478. data:=positions[Dims-1];
  479. Result:=not(Finished);
  480. end;
  481. destructor tdynarrayiter.done;
  482. begin
  483. Bounds:=nil;
  484. Coords:=nil;
  485. elesize:=nil;
  486. positions:=nil;
  487. end;
  488. { ---------------------------------------------------------------------
  489. VariantManager support
  490. ---------------------------------------------------------------------}
  491. procedure sysvarinit(var v : Variant);
  492. begin
  493. TVarData(V).vType := varEmpty;
  494. end;
  495. procedure sysvarclear(var v : Variant);
  496. begin
  497. if TVarData(v).vType and varComplexType <> 0 then
  498. VarClearProc(TVarData(V))
  499. else
  500. TVarData(v).vType := varEmpty;
  501. end;
  502. function Sysvartoint (const v : Variant) : Longint;
  503. begin
  504. if VarType(v) = varNull then
  505. if NullStrictConvert then
  506. VarCastError(varNull, varInt64)
  507. else
  508. Result := 0
  509. else
  510. Result := VariantToLongInt(TVarData(V));
  511. end;
  512. function Sysvartoint64 (const v : Variant) : Int64;
  513. begin
  514. if VarType(v) = varNull then
  515. if NullStrictConvert then
  516. VarCastError(varNull, varInt64)
  517. else
  518. Result := 0
  519. else
  520. Result := VariantToInt64(TVarData(V));
  521. end;
  522. function sysvartoword64 (const v : Variant) : QWord;
  523. begin
  524. if VarType(v) = varNull then
  525. if NullStrictConvert then
  526. VarCastError(varNull, varQWord)
  527. else
  528. Result := 0
  529. else
  530. Result := VariantToQWord (TVarData(V));
  531. end;
  532. function sysvartobool (const v : Variant) : Boolean;
  533. begin
  534. if VarType(v) = varNull then
  535. if NullStrictConvert then
  536. VarCastError(varNull, varBoolean)
  537. else
  538. Result := False
  539. else
  540. Result := VariantToBoolean(TVarData(V));
  541. end;
  542. {$ifndef FPUNONE}
  543. function sysvartoreal (const v : Variant) : Extended;
  544. var Handler: TCustomVariantType;
  545. dest: TVarData;
  546. begin
  547. if VarType(v) = varNull then
  548. if NullStrictConvert then
  549. VarCastError(varNull, varDouble)
  550. else
  551. Result := 0
  552. { TODO: performance: custom variants must be handled after standard ones }
  553. else if FindCustomVariantType(TVarData(v).vType, Handler) then
  554. begin
  555. VariantInit(dest);
  556. Handler.CastTo(dest, TVarData(v), varDouble);
  557. Result := dest.vDouble;
  558. end
  559. else
  560. Result := VariantToDouble(TVarData(V));
  561. end;
  562. {$endif}
  563. function sysvartocurr (const v : Variant) : Currency;
  564. begin
  565. if VarType(v) = varNull then
  566. if NullStrictConvert then
  567. VarCastError(varNull, varCurrency)
  568. else
  569. Result := 0
  570. else
  571. Result := VariantToCurrency(TVarData(V));
  572. end;
  573. function CustomVarToLStr(const v: TVarData; out s: AnsiString): Boolean;
  574. var
  575. handler: TCustomVariantType;
  576. temp: TVarData;
  577. begin
  578. result := FindCustomVariantType(v.vType, handler);
  579. if result then
  580. begin
  581. VariantInit(temp);
  582. handler.CastTo(temp, v, varString);
  583. { out-semantic ensures that s is finalized,
  584. so just copy the pointer and don't finalize the temp }
  585. Pointer(s) := temp.vString;
  586. end;
  587. end;
  588. procedure sysvartolstr (var s : AnsiString; const v : Variant);
  589. begin
  590. if VarType(v) = varNull then
  591. if NullStrictConvert then
  592. VarCastError(varNull, varString)
  593. else
  594. s := NullAsStringValue
  595. { TODO: performance: custom variants must be handled after standard ones }
  596. else if not CustomVarToLStr(TVarData(v), s) then
  597. S := VariantToAnsiString(TVarData(V));
  598. end;
  599. procedure sysvartopstr (var s; const v : Variant);
  600. var
  601. tmp: AnsiString;
  602. begin
  603. sysvartolstr(tmp, v);
  604. ShortString(s) := tmp;
  605. end;
  606. procedure sysvartowstr (var s : WideString; const v : Variant);
  607. begin
  608. if VarType(v) = varNull then
  609. if NullStrictConvert then
  610. VarCastError(varNull, varOleStr)
  611. else
  612. s := NullAsStringValue
  613. else
  614. S := VariantToWideString(TVarData(V));
  615. end;
  616. procedure sysvartointf (var Intf : IInterface; const v : Variant);
  617. begin
  618. case TVarData(v).vType of
  619. varEmpty:
  620. Intf := nil;
  621. varNull:
  622. if NullStrictConvert then
  623. VarCastError(varNull, varUnknown)
  624. else
  625. Intf := nil;
  626. varUnknown:
  627. Intf := IInterface(TVarData(v).vUnknown);
  628. varUnknown or varByRef:
  629. Intf := IInterface(TVarData(v).vPointer^);
  630. varDispatch:
  631. Intf := IInterface(TVarData(v).vDispatch);
  632. varDispatch or varByRef:
  633. Intf := IInterface(TVarData(v).vPointer^);
  634. varVariant, varVariant or varByRef: begin
  635. if not Assigned(TVarData(v).vPointer) then
  636. VarBadTypeError;
  637. sysvartointf(Intf, Variant(PVarData(TVarData(v).vPointer)^) );
  638. end;
  639. else
  640. VarCastError(TVarData(v).vType, varUnknown);
  641. end;
  642. end;
  643. procedure sysvartodisp (var Disp : IDispatch; const v : Variant);
  644. begin
  645. case TVarData(v).vType of
  646. varEmpty:
  647. Disp := nil;
  648. varNull:
  649. if NullStrictConvert then
  650. VarCastError(varNull, varDispatch)
  651. else
  652. Disp := nil;
  653. varUnknown:
  654. if IInterface(TVarData(v).vUnknown).QueryInterface(IDispatch, Disp) <> S_OK then
  655. VarCastError(varUnknown, varDispatch);
  656. varUnknown or varByRef:
  657. if IInterface(TVarData(v).vPointer^).QueryInterface(IDispatch, Disp) <> S_OK then
  658. VarCastError(varUnknown or varByRef, varDispatch);
  659. varDispatch:
  660. Disp := IDispatch(TVarData(v).vDispatch);
  661. varDispatch or varByRef:
  662. Disp := IDispatch(TVarData(v).vPointer^);
  663. varVariant, varVariant or varByRef: begin
  664. if not Assigned(TVarData(v).vPointer) then
  665. VarBadTypeError;
  666. sysvartodisp(Disp, Variant(PVarData(TVarData(v).vPointer)^) );
  667. end;
  668. else
  669. VarCastError(TVarData(v).vType, varDispatch);
  670. end;
  671. end;
  672. {$ifndef FPUNONE}
  673. function sysvartotdatetime (const v : Variant) : TDateTime;
  674. begin
  675. if VarType(v) = varNull then
  676. if NullStrictConvert then
  677. VarCastError(varNull, varDate)
  678. else
  679. Result := 0
  680. else
  681. Result:=VariantToDate(TVarData(v));
  682. end;
  683. {$endif}
  684. function DynamicArrayIsRectangular(p : Pointer;TypeInfo : Pointer) : Boolean;
  685. var
  686. arraysize,i : sizeint;
  687. begin
  688. Result := False;
  689. { get TypeInfo of second level }
  690. { skip kind and name }
  691. TypeInfo:=aligntoptr(TypeInfo+2+Length(PTypeInfo(TypeInfo)^.Name));
  692. TypeInfo:=PTypeData(TypeInfo)^.elType2;
  693. { check recursively? }
  694. if assigned(TypeInfo) and (PTypeInfo(TypeInfo)^.kind=tkDynArray) then
  695. begin
  696. { set to dimension of first element }
  697. arraysize:=psizeint(ppointer(p)^-SizeOf(sizeint))^;
  698. { walk through all elements }
  699. for i:=1 to psizeint(p-SizeOf(sizeint))^ do
  700. begin
  701. { ... and check dimension }
  702. if psizeint(ppointer(p)^-SizeOf(sizeint))^<>arraysize then
  703. exit;
  704. if not(DynamicArrayIsRectangular(ppointer(p)^,TypeInfo)) then
  705. exit;
  706. inc(p,SizeOf(Pointer));
  707. end;
  708. end;
  709. Result:=true;
  710. end;
  711. procedure sysvartodynarray (var dynarr : Pointer; const v : Variant; TypeInfo : Pointer);
  712. begin
  713. DynArrayFromVariant(dynarr, v, TypeInfo);
  714. end;
  715. procedure sysvarfrombool (var Dest : Variant; const Source : Boolean);
  716. begin
  717. DoVarClearIfComplex(TVarData(Dest));
  718. with TVarData(Dest) do begin
  719. vType := varBoolean;
  720. vBoolean := Source;
  721. end;
  722. end;
  723. procedure VariantErrorInvalidIntegerRange(Range: LongInt);
  724. begin
  725. VariantError(Format(SErrInvalidIntegerRange,[Range]));
  726. end;
  727. procedure sysvarfromint (var Dest : Variant; const Source, Range : LongInt);
  728. begin
  729. DoVarClearIfComplex(TVarData(Dest));
  730. with TVarData(Dest) do
  731. if PackVarCreation then
  732. case Range of
  733. -4 : begin
  734. vType := varInteger;
  735. vInteger := Source;
  736. end;
  737. -2 : begin
  738. vType := varSmallInt;
  739. vSmallInt := Source;
  740. end;
  741. -1 : Begin
  742. vType := varShortInt;
  743. vshortint := Source;
  744. end;
  745. 1 : begin
  746. vType := varByte;
  747. vByte := Source;
  748. end;
  749. 2 : begin
  750. vType := varWord;
  751. vWord := Source;
  752. end;
  753. 4 : Begin
  754. vType := varLongWord;
  755. {use vInteger, not vLongWord as the value came passed in as an Integer }
  756. vInteger := Source;
  757. end;
  758. else
  759. VariantErrorInvalidIntegerRange(Range);
  760. end
  761. else begin
  762. vType := varInteger;
  763. vInteger := Source;
  764. end;
  765. end;
  766. procedure sysvarfromint64 (var Dest : Variant; const Source : Int64);
  767. begin
  768. DoVarClearIfComplex(TVarData(Dest));
  769. with TVarData(Dest) do begin
  770. vType := varInt64;
  771. vInt64 := Source;
  772. end;
  773. end;
  774. procedure sysvarfromword64 (var Dest : Variant; const Source : QWord);
  775. begin
  776. DoVarClearIfComplex(TVarData(Dest));
  777. with TVarData(Dest) do begin
  778. vType := varQWord;
  779. vQWord := Source;
  780. end;
  781. end;
  782. {$ifndef FPUNONE}
  783. procedure sysvarfromreal (var Dest : Variant; const Source : Extended);
  784. begin
  785. DoVarClearIfComplex(TVarData(Dest));
  786. with TVarData(Dest) do begin
  787. vType := varDouble;
  788. vDouble := Source;
  789. end;
  790. end;
  791. procedure sysvarfromsingle (var Dest : Variant; const Source : single);
  792. begin
  793. DoVarClearIfComplex(TVarData(Dest));
  794. with TVarData(Dest) do begin
  795. vType := varSingle;
  796. vSingle := Source;
  797. end;
  798. end;
  799. procedure sysvarfromdouble (var Dest : Variant; const Source : double);
  800. begin
  801. DoVarClearIfComplex(TVarData(Dest));
  802. with TVarData(Dest) do begin
  803. vType := varDouble;
  804. vDouble := Source;
  805. end;
  806. end;
  807. {$endif}
  808. procedure sysvarfromcurr (var Dest : Variant; const Source : Currency);
  809. begin
  810. DoVarClearIfComplex(TVarData(Dest));
  811. with TVarData(Dest) do begin
  812. vType := varCurrency;
  813. vCurrency := Source;
  814. end;
  815. end;
  816. {$ifndef FPUNONE}
  817. procedure sysvarfromtdatetime (var Dest : Variant; const Source : TDateTime);
  818. begin
  819. DoVarClearIfComplex(TVarData(Dest));
  820. with TVarData(Dest) do begin
  821. vType := varDate;
  822. vDate := Source;
  823. end;
  824. end;
  825. {$endif}
  826. procedure sysvarfrompstr (var Dest : Variant; const Source : ShortString);
  827. begin
  828. DoVarClearIfComplex(TVarData(Dest));
  829. with TVarData(Dest) do begin
  830. vType := varString;
  831. vString := nil;
  832. AnsiString(vString) := Source;
  833. end;
  834. end;
  835. procedure sysvarfromlstr (var Dest : Variant; const Source : AnsiString);
  836. begin
  837. DoVarClearIfComplex(TVarData(Dest));
  838. with TVarData(Dest) do begin
  839. vType := varString;
  840. vString := nil;
  841. AnsiString(vString) := Source;
  842. end;
  843. end;
  844. procedure sysvarfromwstr (var Dest : Variant; const Source : WideString);
  845. begin
  846. DoVarClearIfComplex(TVarData(Dest));
  847. with TVarData(Dest) do begin
  848. vType := varOleStr;
  849. vOleStr := nil;
  850. WideString(Pointer(vOleStr)) := Source;
  851. end;
  852. end;
  853. procedure sysvarfromintf(var Dest : Variant; const Source : IInterface);
  854. begin
  855. DoVarClearIfComplex(TVarData(Dest));
  856. with TVarData(Dest) do begin
  857. vUnknown := nil;
  858. IInterface(vUnknown) := Source;
  859. vType := varUnknown;
  860. end;
  861. end;
  862. procedure sysvarfromdisp(var Dest : Variant; const Source : IDispatch);
  863. begin
  864. DoVarClearIfComplex(TVarData(Dest));
  865. with TVarData(Dest) do begin
  866. vUnknown := nil;
  867. IDispatch(vDispatch) := Source;
  868. vType := varDispatch;
  869. end;
  870. end;
  871. type
  872. TCommonType = (ctEmpty,ctAny,ctError,ctLongInt,ctBoolean,
  873. {$ifndef FPUNONE}
  874. ctFloat,ctDate,ctCurrency,
  875. {$endif}
  876. ctInt64,ctNull,ctWideStr,ctString);
  877. TCommonVarType = varEmpty..varQWord;
  878. const
  879. {$ifdef FPUNONE}
  880. ctFloat = ctError;
  881. ctDate = ctError;
  882. ctCurrency = ctError;
  883. {$endif}
  884. { get the basic type for a Variant type }
  885. VarTypeToCommonType : array[TCommonVarType] of TCommonType =
  886. (ctEmpty, // varEmpty = 0;
  887. ctNull, // varNull = 1;
  888. ctLongInt, // varSmallInt = 2;
  889. ctLongInt, // varInteger = 3;
  890. ctFloat, // varSingle = 4;
  891. ctFloat, // varDouble = 5;
  892. ctCurrency, // varCurrency = 6;
  893. ctDate, // varDate = 7;
  894. ctWideStr, // varOleStr = 8;
  895. ctError, // varDispatch = 9;
  896. ctError, // varError = 10;
  897. ctBoolean, // varBoolean = 11;
  898. ctError, // varVariant = 12;
  899. ctError, // varUnknown = 13;
  900. ctError, // ??? 15
  901. ctError, // varDecimal = 14;
  902. ctLongInt, // varShortInt = 16;
  903. ctLongInt, // varByte = 17;
  904. ctLongInt, // varWord = 18;
  905. ctInt64, // varLongWord = 19;
  906. ctInt64, // varInt64 = 20;
  907. ctInt64 // varQWord = 21;
  908. );
  909. { map a basic type back to a Variant type }
  910. { Not used yet
  911. CommonTypeToVarType : array[TCommonType] of TVarType =
  912. (
  913. varEmpty,
  914. varany,
  915. varError,
  916. varInteger,
  917. varDouble,
  918. varBoolean,
  919. varInt64,
  920. varNull,
  921. varOleStr,
  922. varDate,
  923. varCurrency,
  924. varString
  925. );
  926. }
  927. function MapToCommonType(const vType : TVarType) : TCommonType;
  928. begin
  929. case vType of
  930. Low(TCommonVarType)..High(TCommonVarType):
  931. Result := VarTypeToCommonType[vType];
  932. varString:
  933. Result:=ctString;
  934. varAny:
  935. Result:=ctAny;
  936. else
  937. Result:=ctError;
  938. end;
  939. end;
  940. const
  941. FindCmpCommonType : array[TCommonType, TCommonType] of TCommonType = (
  942. { ctEmpty ctAny ctError ctLongInt ctBoolean ctFloat ctDate ctCurrency ctInt64 ctNull ctWideStr ctString }
  943. ({ ctEmpty } ctEmpty, ctEmpty, ctError, ctEmpty, ctEmpty, {$ifndef FPUNONE}ctEmpty, ctEmpty, ctEmpty, {$endif}ctEmpty, ctEmpty, ctEmpty, ctEmpty ),
  944. ({ ctAny } ctEmpty, ctAny, ctError, ctAny, ctAny, {$ifndef FPUNONE}ctAny, ctAny, ctAny, {$endif}ctAny, ctAny, ctAny, ctAny ),
  945. ({ ctError } ctError, ctError, ctError, ctError, ctError, {$ifndef FPUNONE}ctError, ctError, ctError, {$endif}ctError, ctError, ctError, ctError ),
  946. ({ ctLongInt } ctEmpty, ctAny, ctError, ctLongInt, ctBoolean, {$ifndef FPUNONE}ctFloat, ctDate, ctCurrency, {$endif}ctInt64, ctNull, ctFloat, ctFloat ),
  947. ({ ctBoolean } ctEmpty, ctAny, ctError, ctLongInt, ctBoolean, {$ifndef FPUNONE}ctFloat, ctDate, ctCurrency, {$endif}ctInt64, ctNull, ctWideStr, ctString ),
  948. {$ifndef FPUNONE}
  949. ({ ctFloat } ctEmpty, ctAny, ctError, ctFloat, ctFloat, ctFloat, ctDate, ctCurrency, ctFloat, ctNull, ctFloat, ctFloat ),
  950. ({ ctDate } ctEmpty, ctAny, ctError, ctDate, ctDate, ctDate, ctDate, ctDate, ctDate, ctNull, ctDate, ctDate ),
  951. ({ ctCurrency } ctEmpty, ctAny, ctError, ctCurrency, ctCurrency, ctCurrency,ctDate, ctCurrency, ctCurrency, ctNull, ctCurrency, ctCurrency ),
  952. {$endif}
  953. ({ ctInt64 } ctEmpty, ctAny, ctError, ctInt64, ctInt64, {$ifndef FPUNONE}ctFloat, ctDate, ctCurrency, {$endif}ctInt64, ctNull, ctFloat, ctFloat ),
  954. ({ ctNull } ctEmpty, ctAny, ctError, ctNull, ctNull, {$ifndef FPUNONE}ctNull, ctNull, ctNull, {$endif}ctNull, ctNull, ctNull, ctNull ),
  955. ({ ctWideStr } ctEmpty, ctAny, ctError, ctFloat, ctWideStr, {$ifndef FPUNONE}ctFloat, ctDate, ctCurrency, {$endif}ctFloat, ctNull, ctWideStr, ctWideStr ),
  956. ({ ctString } ctEmpty, ctAny, ctError, ctFloat, ctString, {$ifndef FPUNONE}ctFloat, ctDate, ctCurrency, {$endif}ctFloat, ctNull, ctWideStr, ctString )
  957. );
  958. function DoVarCmpSimple (const Left, Right, Common: TCommonType) : ShortInt; inline;
  959. begin
  960. if Left = Common then
  961. if Right = Common then
  962. Result := 0
  963. else
  964. Result := -1
  965. else
  966. Result := 1;
  967. end;
  968. function DoVarCmpAny(const Left, Right: TVarData; const OpCode: TVarOp) : ShortInt;
  969. begin
  970. VarInvalidOp(Left.vType, Right.vType, OpCode);
  971. Result:=0;
  972. end;
  973. function DoVarCmpLongInt(const Left, Right: LongInt): ShortInt; inline;
  974. begin
  975. if Left < Right then
  976. Result := -1
  977. else if Left > Right then
  978. Result := 1
  979. else
  980. Result := 0;
  981. end;
  982. {$ifndef FPUNONE}
  983. function DoVarCmpFloat(const Left, Right: Double; const OpCode: TVarOp): ShortInt;
  984. begin
  985. if Left = Right then
  986. Result := 0
  987. else if (OpCode in [opCmpEq, opCmpNe]) or (Left < Right) then
  988. Result := -1
  989. else
  990. Result := 1;
  991. end;
  992. {$endif}
  993. function DoVarCmpInt64(const Left, Right: Int64): ShortInt;
  994. begin
  995. if Left < Right then
  996. Result := -1
  997. else if Left > Right then
  998. Result := 1
  999. else
  1000. Result := 0;
  1001. end;
  1002. function DoVarCmpNull(const Left, Right: TCommonType; const OpCode: TVarOp) : ShortInt;
  1003. const
  1004. ResultMap: array [Boolean, opCmpEq..opCmpGe] of ShortInt =
  1005. ( ( -1, 0, 0, 1, 0, -1 ), ( 0, -1, -1, -1, 1, 1 ) );
  1006. begin
  1007. if OpCode in [opCmpEq, opCmpNe] then
  1008. case NullEqualityRule of
  1009. ncrError: VarInvalidNullOp;
  1010. ncrStrict: Result := ResultMap[False, OpCode];
  1011. ncrLoose: Result := ResultMap[(Left = Right) xor (OpCode = opCmpNe), OpCode];
  1012. end
  1013. else
  1014. case NullMagnitudeRule of
  1015. ncrError: VarInvalidNullOp;
  1016. ncrStrict: Result := ResultMap[False, OpCode];
  1017. ncrLoose: Result := DoVarCmpSimple(Left, Right, ctNull);
  1018. end;
  1019. end;
  1020. function DoVarCmpCurr(const Left, Right: Currency): ShortInt;
  1021. begin
  1022. if Left < Right then
  1023. Result := -1
  1024. else if Left > Right then
  1025. Result := 1
  1026. else
  1027. Result := 0;
  1028. end;
  1029. function DoVarCmpWStrDirect(const Left, Right: Pointer; const OpCode: TVarOp): ShortInt; inline;
  1030. begin
  1031. { we can do this without ever copying the string }
  1032. if OpCode in [opCmpEq, opCmpNe] then
  1033. if Length(WideString(Left)) <> Length(WideString(Right)) then
  1034. Exit(-1);
  1035. Result := WideCompareStr(
  1036. WideString(Left),
  1037. WideString(Right)
  1038. );
  1039. end;
  1040. function DoVarCmpWStr(const Left, Right: TVarData; const OpCode: TVarOp): ShortInt;
  1041. begin
  1042. { keep the temps away from the main proc }
  1043. Result := DoVarCmpWStrDirect(Pointer(VariantToWideString(Left)),
  1044. Pointer(VariantToWideString(Right)), OpCode);
  1045. end;
  1046. function DoVarCmpLStrDirect(const Left, Right: Pointer; const OpCode: TVarOp): ShortInt; inline;
  1047. begin
  1048. { we can do this without ever copying the string }
  1049. if OpCode in [opCmpEq, opCmpNe] then
  1050. if Length(AnsiString(Left)) <> Length(AnsiString(Right)) then
  1051. Exit(-1);
  1052. Result := CompareStr(
  1053. AnsiString(Left),
  1054. AnsiString(Right)
  1055. );
  1056. end;
  1057. function DoVarCmpLStr(const Left, Right: TVarData; const OpCode: TVarOp): ShortInt;
  1058. begin
  1059. { keep the temps away from the main proc }
  1060. Result := DoVarCmpLStrDirect(Pointer(VariantToAnsiString(Left)),
  1061. Pointer(VariantToAnsiString(Right)), OpCode);
  1062. end;
  1063. function DoVarCmpComplex(const Left, Right: TVarData; const OpCode: TVarOp): ShortInt;
  1064. var Handler: TCustomVariantType;
  1065. CmpRes: boolean;
  1066. begin
  1067. if (Left.vType=varnull) or (Right.vType=varnull) then
  1068. // don't bother custom variant handlers with conversion to NULL
  1069. begin
  1070. if OpCode in [opCmpEq,opCmpNe] then
  1071. begin
  1072. if (Left.vType=Right.vType) xor (OpCode=opCmpNe) then
  1073. result:=0
  1074. else
  1075. result:=-1;
  1076. end
  1077. else
  1078. if Left.vType=varnull then
  1079. begin
  1080. if Right.vType=varnull then
  1081. Result := 0
  1082. else
  1083. Result := -1;
  1084. end
  1085. else
  1086. Result := 1;
  1087. end
  1088. else
  1089. begin
  1090. if FindCustomVariantType(Left.vType, Handler) then
  1091. CmpRes := Handler.CompareOp(Left, Right, OpCode)
  1092. else if FindCustomVariantType(Right.vType, Handler) then
  1093. CmpRes := Handler.CompareOp(Left, Right, OpCode)
  1094. else
  1095. VarInvalidOp(Left.vType, Right.vType, OpCode);
  1096. case OpCode of
  1097. opCmpEq:
  1098. if CmpRes then
  1099. Result:=0
  1100. else
  1101. Result:=1;
  1102. opCmpNe:
  1103. if CmpRes then
  1104. Result:=1
  1105. else
  1106. Result:=0;
  1107. opCmpLt,
  1108. opCmpLe:
  1109. if CmpRes then
  1110. Result:=-1
  1111. else
  1112. Result:=1;
  1113. opCmpGt,
  1114. opCmpGe:
  1115. if CmpRes then
  1116. Result:=1
  1117. else
  1118. Result:=-1;
  1119. end;
  1120. end;
  1121. end;
  1122. function DoVarCmp(const vl, vr : TVarData; const OpCode : TVarOp) : ShortInt;
  1123. var
  1124. lct: TCommonType;
  1125. rct: TCommonType;
  1126. begin
  1127. { as the function in cvarutil.inc can handle varByRef correctly we simply
  1128. resolve the final type }
  1129. lct := MapToCommonType(VarTypeDeRef(vl));
  1130. rct := MapToCommonType(VarTypeDeRef(vr));
  1131. {$IFDEF DEBUG_VARIANTS}
  1132. if __DEBUG_VARIANTS then begin
  1133. WriteLn('DoVarCmp $', IntToHex(Cardinal(@vl),8), ' ', GetEnumName(TypeInfo(TVarOp), Ord(OpCode)) ,' $', IntToHex(Cardinal(@vr),8));
  1134. DumpVariant('DoVarCmp/vl', vl);
  1135. WriteLn('lct ', GetEnumName(TypeInfo(TCommonType), Ord(lct)));
  1136. DumpVariant('DoVarCmp/vr', vr);
  1137. WriteLn('rct ', GetEnumName(TypeInfo(TCommonType), Ord(rct)));
  1138. WriteLn('common ', GetEnumName(TypeInfo(TCommonType), Ord(FindCmpCommonType[lct, rct])));
  1139. end;
  1140. {$ENDIF}
  1141. case FindCmpCommonType[lct, rct] of
  1142. ctEmpty: Result := DoVarCmpSimple(lct, rct, ctEmpty);
  1143. ctAny: Result := DoVarCmpAny(vl, vr, OpCode);
  1144. ctLongInt: Result := DoVarCmpLongInt(VariantToLongInt(vl), VariantToLongInt(vr));
  1145. {$ifndef FPUNONE}
  1146. ctFloat: Result := DoVarCmpFloat(VariantToDouble(vl), VariantToDouble(vr), OpCode);
  1147. {$endif}
  1148. ctBoolean: Result := DoVarCmpLongInt(LongInt(VariantToBoolean(vl)), LongInt(VariantToBoolean(vr)));
  1149. ctInt64: Result := DoVarCmpInt64(VariantToInt64(vl), VariantToInt64(vr));
  1150. ctNull: Result := DoVarCmpNull(lct, rct, OpCode);
  1151. ctWideStr:
  1152. if (vl.vType = varOleStr) and (vr.vType = varOleStr) then
  1153. Result := DoVarCmpWStrDirect(Pointer(vl.vOleStr), Pointer(vr.vOleStr), OpCode)
  1154. else
  1155. Result := DoVarCmpWStr(vl, vr, OpCode);
  1156. {$ifndef FPUNONE}
  1157. ctDate: Result := DoVarCmpFloat(VariantToDate(vl), VariantToDate(vr), OpCode);
  1158. ctCurrency: Result := DoVarCmpCurr(VariantToCurrency(vl), VariantToCurrency(vr));
  1159. {$endif}
  1160. ctString:
  1161. if (vl.vType = varString) and (vr.vType = varString) then
  1162. Result := DoVarCmpLStrDirect(Pointer(vl.vString), Pointer(vr.vString), OpCode)
  1163. else
  1164. Result := DoVarCmpLStr(vl, vr, OpCode);
  1165. else
  1166. Result := DoVarCmpComplex(vl, vr, OpCode);
  1167. end;
  1168. end;
  1169. function syscmpop (const Left, Right : Variant; const OpCode : TVarOp) : Boolean;
  1170. var
  1171. CmpRes : ShortInt;
  1172. begin
  1173. CmpRes:=DoVarCmp(TVarData(Left),TVarData(Right),OpCode);
  1174. case OpCode of
  1175. opCmpEq:
  1176. Result:=CmpRes=0;
  1177. opCmpNe:
  1178. Result:=CmpRes<>0;
  1179. opCmpLt:
  1180. Result:=CmpRes<0;
  1181. opCmpLe:
  1182. Result:=CmpRes<=0;
  1183. opCmpGt:
  1184. Result:=CmpRes>0;
  1185. opCmpGe:
  1186. Result:=CmpRes>=0;
  1187. else
  1188. VarInvalidOp;
  1189. end;
  1190. end;
  1191. const
  1192. FindOpCommonType : array[TCommonType,TCommonType] of TCommonType = (
  1193. { ctEmpty ctAny ctError ctLongInt ctBoolean ctFloat ctDate ctCurrency ctInt64 ctNull ctWideStr ctString }
  1194. ({ ctEmpty } ctEmpty, ctAny, ctError, ctEmpty, ctEmpty, {$ifndef FPUNONE}ctEmpty, ctEmpty, ctEmpty, {$endif}ctEmpty, ctEmpty, ctEmpty, ctEmpty ),
  1195. ({ ctAny } ctAny, ctAny, ctError, ctAny, ctAny, {$ifndef FPUNONE}ctAny, ctAny, ctAny, {$endif}ctAny, ctAny, ctAny, ctAny ),
  1196. ({ ctError } ctError, ctError, ctError, ctError, ctError, {$ifndef FPUNONE}ctError, ctError, ctError, {$endif}ctError, ctError, ctError, ctError ),
  1197. ({ ctLongInt } ctEmpty, ctAny, ctError, ctLongInt, ctBoolean, {$ifndef FPUNONE}ctFloat, ctDate, ctCurrency, {$endif}ctInt64, ctNull, ctFloat, ctFloat ),
  1198. ({ ctBoolean } ctEmpty, ctAny, ctError, ctLongInt, ctBoolean, {$ifndef FPUNONE}ctFloat, ctDate, ctCurrency, {$endif}ctInt64, ctNull, ctBoolean, ctBoolean ),
  1199. {$ifndef FPUNONE}
  1200. ({ ctFloat } ctEmpty, ctAny, ctError, ctFloat, ctFloat, ctFloat, ctDate, ctCurrency, ctFloat, ctNull, ctFloat, ctFloat ),
  1201. ({ ctDate } ctEmpty, ctAny, ctError, ctDate, ctDate, ctDate, ctDate, ctDate, ctDate, ctNull, ctDate, ctDate ),
  1202. ({ ctCurrency } ctEmpty, ctAny, ctError, ctCurrency, ctCurrency, ctCurrency, ctDate, ctCurrency, ctCurrency, ctNull, ctCurrency, ctCurrency ),
  1203. {$endif}
  1204. ({ ctInt64 } ctEmpty, ctAny, ctError, ctInt64, ctInt64, {$ifndef FPUNONE}ctFloat, ctDate, ctCurrency, {$endif}ctInt64, ctNull, ctFloat, ctFloat ),
  1205. ({ ctNull } ctEmpty, ctAny, ctError, ctNull, ctNull, {$ifndef FPUNONE}ctNull, ctNull, ctNull, {$endif}ctNull, ctNull, ctNull, ctNull ),
  1206. ({ ctWideStr } ctEmpty, ctAny, ctError, ctFloat, ctBoolean, {$ifndef FPUNONE}ctFloat, ctDate, ctCurrency, {$endif}ctFloat, ctNull, ctWideStr, ctWideStr ),
  1207. ({ ctString } ctEmpty, ctAny, ctError, ctFloat, ctBoolean, {$ifndef FPUNONE}ctFloat, ctDate, ctCurrency, {$endif}ctFloat, ctNull, ctWideStr, ctString )
  1208. );
  1209. procedure DoVarOpFloat(var vl :TVarData; const vr : TVarData; const OpCode : TVarOp);
  1210. {$ifndef FPUNONE}
  1211. var
  1212. l, r : Double;
  1213. begin
  1214. l := VariantToDouble(vl);
  1215. r := VariantToDouble(vr);
  1216. case OpCode of
  1217. opAdd : l := l + r;
  1218. opSubtract : l := l - r;
  1219. opMultiply : l := l * r;
  1220. opDivide : l := l / r;
  1221. opPower : l := l ** r;
  1222. else
  1223. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1224. end;
  1225. DoVarClearIfComplex(vl);
  1226. vl.vType := varDouble;
  1227. vl.vDouble := l;
  1228. {$else}
  1229. begin
  1230. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1231. {$endif}
  1232. end;
  1233. procedure DoVarOpAny(var vl : TVarData; const vr : TVarData; const OpCode : TVarOp);
  1234. begin
  1235. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1236. end;
  1237. procedure DoVarOpLongInt(var vl : TVarData; const vr : TVarData; const OpCode : TVarOp);
  1238. var
  1239. l, r: LongInt;
  1240. begin
  1241. l := VariantToLongint(vl);
  1242. r := VariantToLongint(vr);
  1243. case OpCode of
  1244. opIntDivide : l := l div r;
  1245. opModulus : l := l mod r;
  1246. opShiftLeft : l := l shl r;
  1247. opShiftRight : l := l shr r;
  1248. opAnd : l := l and r;
  1249. opOr : l := l or r;
  1250. opXor : l := l xor r;
  1251. else
  1252. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1253. end;
  1254. DoVarClearIfComplex(vl);
  1255. vl.vType := varInteger;
  1256. vl.vInteger := l;
  1257. end;
  1258. procedure DoVarOpInt64(var vl : TVarData; const vr : TVarData; const OpCode : TVarOp);
  1259. var
  1260. l, r : Int64;
  1261. Overflow : Boolean;
  1262. begin
  1263. l := VariantToInt64(vl);
  1264. r := VariantToInt64(vr);
  1265. Overflow := False;
  1266. case OpCode of
  1267. {$push}
  1268. {$R+}{$Q+}
  1269. opAdd..opMultiply,opPower: try
  1270. case OpCode of
  1271. opAdd : l := l + r;
  1272. opSubtract : l := l - r;
  1273. opMultiply : l := l * r;
  1274. {$ifndef FPUNONE}
  1275. opPower : l := l ** r;
  1276. {$endif}
  1277. end;
  1278. except
  1279. on E: SysUtils.ERangeError do
  1280. Overflow := True;
  1281. on E: SysUtils.EIntOverflow do
  1282. Overflow := True;
  1283. end;
  1284. {$pop}
  1285. opIntDivide : l := l div r;
  1286. opModulus : l := l mod r;
  1287. opShiftLeft : l := l shl r;
  1288. opShiftRight : l := l shr r;
  1289. opAnd : l := l and r;
  1290. opOr : l := l or r;
  1291. opXor : l := l xor r;
  1292. else
  1293. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1294. end;
  1295. if Overflow then
  1296. DoVarOpFloat(vl,vr,OpCode)
  1297. else begin
  1298. DoVarClearIfComplex(vl);
  1299. vl.vType := varInt64;
  1300. vl.vInt64 := l;
  1301. end;
  1302. end;
  1303. procedure DoVarOpInt64to32(var vl : TVarData; const vr : TVarData; const OpCode : TVarOp);
  1304. begin
  1305. { can't do this well without an efficent way to check for overflows,
  1306. let the Int64 version handle it and check the Result if we can downgrade it
  1307. to integer }
  1308. DoVarOpInt64(vl, vr, OpCode);
  1309. with vl do
  1310. if (vType = varInt64) and (vInt64 >= Low(LongInt)) and (vInt64 <= High(LongInt)) then begin
  1311. vInteger := vInt64;
  1312. vType := varInteger;
  1313. end;
  1314. end;
  1315. procedure DoVarOpBool(var vl : TVarData; const vr : TVarData; const OpCode : TVarOp);
  1316. var
  1317. l,r: Boolean;
  1318. begin
  1319. l := VariantToBoolean(vl);
  1320. r := VariantToBoolean(vr);
  1321. case OpCode of
  1322. opAnd : l := l and r;
  1323. opOr : l := l or r;
  1324. opXor : l := l xor r;
  1325. else
  1326. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1327. end;
  1328. DoVarClearIfComplex(vl);
  1329. vl.vType := varBoolean;
  1330. vl.vBoolean := l;
  1331. end;
  1332. procedure DoVarOpNull(var vl : TVarData; const vr : TVarData; const OpCode : TVarOp);
  1333. begin
  1334. if (OpCode = opAnd) or (OpCode = opOr) then
  1335. if vl.vType = varNull then begin
  1336. if vr.vType = varNull then begin
  1337. {both null, do nothing }
  1338. end else begin
  1339. {Left null, Right not}
  1340. if OpCode = opAnd then begin
  1341. if not VariantToBoolean(vr) then
  1342. VarCopyProc(vl, vr);
  1343. end else {OpCode = opOr} begin
  1344. if VariantToBoolean(vr) then
  1345. VarCopyProc(vl, vr);
  1346. end;
  1347. end;
  1348. end else begin
  1349. if vr.vType = varNull then begin
  1350. {Right null, Left not}
  1351. if OpCode = opAnd then begin
  1352. if VariantToBoolean(vl) then begin
  1353. DoVarClearIfComplex(vl);
  1354. vl.vType := varNull;
  1355. end;
  1356. end else {OpCode = opOr} begin
  1357. if not VariantToBoolean(vl) then begin
  1358. DoVarClearIfComplex(vl);
  1359. vl.vType := varNull;
  1360. end;
  1361. end;
  1362. end else begin
  1363. { both not null, shouldn't happen }
  1364. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1365. end;
  1366. end
  1367. else begin
  1368. DoVarClearIfComplex(vl);
  1369. vl.vType := varNull;
  1370. end;
  1371. end;
  1372. procedure DoVarOpWStrCat(var vl : TVarData; const vr : TVarData);
  1373. var
  1374. ws: WideString;
  1375. begin
  1376. ws := VariantToWideString(vl) + VariantToWideString(vr);
  1377. DoVarClearIfComplex(vl);
  1378. vl.vType := varOleStr;
  1379. { transfer the WideString without making a copy }
  1380. Pointer(vl.vOleStr) := Pointer(ws);
  1381. { prevent the WideString from being freed, the reference has been transfered
  1382. from the local to the variant and will be correctly finalized when the
  1383. variant is finalized. }
  1384. Pointer(ws) := nil;
  1385. end;
  1386. procedure DoVarOpLStrCat(var vl: TVarData; const vr : TVarData);
  1387. var
  1388. s: AnsiString;
  1389. begin
  1390. s := VariantToAnsiString(vl) + VariantToAnsiString(vr);
  1391. DoVarClearIfComplex(vl);
  1392. vl.vType := varString;
  1393. { transfer the AnsiString without making a copy }
  1394. Pointer(vl.vString) := Pointer(s);
  1395. { prevent the AnsiString from being freed, the reference has been transfered
  1396. from the local to the variant and will be correctly finalized when the
  1397. variant is finalized. }
  1398. Pointer(s) := nil;
  1399. end;
  1400. procedure DoVarOpDate(var vl : TVarData; const vr : TVarData; const OpCode : TVarOp);
  1401. {$ifndef FPUNONE}
  1402. var
  1403. l, r : TDateTime;
  1404. begin
  1405. l := VariantToDate(vl);
  1406. r := VariantToDate(vr);
  1407. case OpCode of
  1408. opAdd : l := l + r;
  1409. opSubtract : l := l - r;
  1410. else
  1411. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1412. end;
  1413. DoVarClearIfComplex(vl);
  1414. vl.vType := varDate;
  1415. vl.vDate := l;
  1416. {$else}
  1417. begin
  1418. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1419. {$endif}
  1420. end;
  1421. procedure DoVarOpCurr(var vl : TVarData; const vr : TVarData; const OpCode : TVarOp; const lct, rct : TCommonType);
  1422. {$ifndef FPUNONE}
  1423. var
  1424. c : Currency;
  1425. d : Double;
  1426. begin
  1427. case OpCode of
  1428. opAdd:
  1429. c := VariantToCurrency(vl) + VariantToCurrency(vr);
  1430. opSubtract:
  1431. c := VariantToCurrency(vl) - VariantToCurrency(vr);
  1432. opMultiply:
  1433. if lct = ctCurrency then
  1434. if rct = ctCurrency then {both Currency}
  1435. c := VariantToCurrency(vl) * VariantToCurrency(vr)
  1436. else {Left Currency}
  1437. c := VariantToCurrency(vl) * VariantToDouble(vr)
  1438. else
  1439. if rct = ctCurrency then {rigth Currency}
  1440. c := VariantToDouble(vl) * VariantToCurrency(vr)
  1441. else {non Currency, error}
  1442. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1443. opDivide:
  1444. if lct = ctCurrency then
  1445. if rct = ctCurrency then {both Currency}
  1446. c := VariantToCurrency(vl) / VariantToCurrency(vr)
  1447. else {Left Currency}
  1448. c := VariantToCurrency(vl) / VariantToDouble(vr)
  1449. else
  1450. if rct = ctCurrency then begin {rigth Currency}
  1451. d := VariantToCurrency(vl) / VariantToCurrency(vr);
  1452. DoVarClearIfComplex(vl);
  1453. vl.vType := varDouble;
  1454. vl.vDouble := d;
  1455. Exit;
  1456. end else {non Currency, error}
  1457. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1458. opPower:
  1459. if lct = ctCurrency then
  1460. if rct = ctCurrency then {both Currency}
  1461. c := VariantToCurrency(vl) ** VariantToCurrency(vr)
  1462. else {Left Currency}
  1463. c := VariantToCurrency(vl) ** VariantToDouble(vr)
  1464. else
  1465. if rct = ctCurrency then {rigth Currency}
  1466. c := VariantToDouble(vl) ** VariantToCurrency(vr)
  1467. else {non Currency, error}
  1468. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1469. else
  1470. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1471. end;
  1472. DoVarClearIfComplex(vl);
  1473. vl.vType := varCurrency;
  1474. vl.vCurrency := c;
  1475. {$else}
  1476. begin
  1477. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1478. {$endif}
  1479. end;
  1480. procedure DoVarOpComplex(var vl : TVarData; const vr : TVarData; const OpCode : TVarOp);
  1481. var Handler: TCustomVariantType;
  1482. begin
  1483. if FindCustomVariantType(vl.vType, Handler) then
  1484. Handler.BinaryOp(vl, vr, OpCode)
  1485. else if FindCustomVariantType(vr.vType, Handler) then
  1486. Handler.BinaryOp(vl, vr, OpCode)
  1487. else
  1488. VarInvalidOp(vl.vType, vr.vType, OpCode);
  1489. end;
  1490. procedure SysVarOp(var Left : Variant; const Right : Variant; OpCode : TVarOp);
  1491. var
  1492. lct: TCommonType;
  1493. rct: TCommonType;
  1494. {$IFDEF DEBUG_VARIANTS}
  1495. i: Integer;
  1496. {$ENDIF}
  1497. begin
  1498. { as the function in cvarutil.inc can handle varByRef correctly we simply
  1499. resolve the final type }
  1500. lct := MapToCommonType(VarTypeDeRef(Left));
  1501. rct := MapToCommonType(VarTypeDeRef(Right));
  1502. {$IFDEF DEBUG_VARIANTS}
  1503. if __DEBUG_VARIANTS then begin
  1504. WriteLn('SysVarOp $', IntToHex(Cardinal(@TVarData(Left)),8), ' ', GetEnumName(TypeInfo(TVarOp), Ord(OpCode)) ,' $', IntToHex(Cardinal(@TVarData(Right)),8));
  1505. DumpVariant('SysVarOp/TVarData(Left)', TVarData(Left));
  1506. WriteLn('lct ', GetEnumName(TypeInfo(TCommonType), Ord(lct)));
  1507. DumpVariant('SysVarOp/TVarData(Right)', TVarData(Right));
  1508. WriteLn('rct ', GetEnumName(TypeInfo(TCommonType), Ord(rct)));
  1509. WriteLn('common ', GetEnumName(TypeInfo(TCommonType), Ord(FindOpCommonType[lct, rct])));
  1510. end;
  1511. {$ENDIF}
  1512. case FindOpCommonType[lct, rct] of
  1513. ctEmpty:
  1514. case OpCode of
  1515. opDivide:
  1516. Error(reZeroDivide);
  1517. opIntDivide, opModulus:
  1518. Error(reDivByZero);
  1519. else
  1520. DoVarClear(TVarData(Left));
  1521. end;
  1522. ctAny:
  1523. DoVarOpAny(TVarData(Left),TVarData(Right),OpCode);
  1524. ctLongInt:
  1525. case OpCode of
  1526. opAdd..opMultiply,opPower:
  1527. DoVarOpInt64to32(TVarData(Left),TVarData(Right),OpCode);
  1528. opDivide:
  1529. DoVarOpFloat(TVarData(Left),TVarData(Right),OpCode);
  1530. else
  1531. DoVarOpLongInt(TVarData(Left),TVarData(Right),OpCode);
  1532. end;
  1533. {$ifndef FPUNONE}
  1534. ctFloat:
  1535. if OpCode in [opAdd,opSubtract,opMultiply,opDivide] then
  1536. DoVarOpFloat(TVarData(Left),TVarData(Right),OpCode)
  1537. else
  1538. DoVarOpInt64to32(TVarData(Left),TVarData(Right),OpCode);
  1539. {$endif}
  1540. ctBoolean:
  1541. case OpCode of
  1542. opAdd..opMultiply, opPower:
  1543. DoVarOpFloat(TVarData(Left),TVarData(Right),OpCode);
  1544. opIntDivide..opShiftRight:
  1545. DoVarOpLongInt(TVarData(Left),TVarData(Right),OpCode);
  1546. opAnd..opXor:
  1547. DoVarOpBool(TVarData(Left),TVarData(Right),OpCode);
  1548. else
  1549. VarInvalidOp(TVarData(Left).vType, TVarData(Right).vType, OpCode);
  1550. end;
  1551. ctInt64:
  1552. if OpCode <> opDivide then
  1553. DoVarOpInt64(TVarData(Left),TVarData(Right),OpCode)
  1554. else
  1555. DoVarOpFloat(TVarData(Left),TVarData(Right),OpCode);
  1556. ctNull:
  1557. DoVarOpNull(TVarData(Left),TVarData(Right),OpCode);
  1558. ctWideStr:
  1559. case OpCode of
  1560. opAdd:
  1561. DoVarOpWStrCat(TVarData(Left),TVarData(Right));
  1562. opSubtract..opDivide,opPower:
  1563. DoVarOpFloat(TVarData(Left),TVarData(Right),OpCode);
  1564. opIntDivide..opXor:
  1565. DoVarOpInt64to32(TVarData(Left),TVarData(Right),OpCode);
  1566. else
  1567. VarInvalidOp(TVarData(Left).vType, TVarData(Right).vType, OpCode);
  1568. end;
  1569. {$ifndef FPUNONE}
  1570. ctDate:
  1571. case OpCode of
  1572. opAdd:
  1573. DoVarOpDate(TVarData(Left),TVarData(Right),OpCode);
  1574. opSubtract: begin
  1575. DoVarOpDate(TVarData(Left),TVarData(Right),OpCode);
  1576. if lct = rct then {both are date}
  1577. TVarData(Left).vType := varDouble;
  1578. end;
  1579. opMultiply, opDivide:
  1580. DoVarOpFloat(TVarData(Left),TVarData(Right),OpCode);
  1581. else
  1582. DoVarOpInt64to32(TVarData(Left),TVarData(Right),OpCode);
  1583. end;
  1584. ctCurrency:
  1585. if OpCode in [opAdd..opDivide, opPower] then
  1586. DoVarOpCurr(TVarData(Left),TVarData(Right),OpCode, lct, rct)
  1587. else
  1588. DoVarOpInt64to32(TVarData(Left),TVarData(Right),OpCode);
  1589. {$endif}
  1590. ctString:
  1591. case OpCode of
  1592. opAdd:
  1593. DoVarOpLStrCat(TVarData(Left),TVarData(Right));
  1594. opSubtract..opDivide,opPower:
  1595. DoVarOpFloat(TVarData(Left),TVarData(Right),OpCode);
  1596. opIntDivide..opXor:
  1597. DoVarOpInt64to32(TVarData(Left),TVarData(Right),OpCode);
  1598. else
  1599. VarInvalidOp(TVarData(Left).vType, TVarData(Right).vType, OpCode);
  1600. end;
  1601. else
  1602. { more complex case }
  1603. DoVarOpComplex(TVarData(Left),TVarData(Right),OpCode);
  1604. end;
  1605. end;
  1606. procedure DoVarNegAny(var v: TVarData);
  1607. begin
  1608. VarInvalidOp(v.vType, opNegate);
  1609. end;
  1610. procedure DoVarNegComplex(var v: TVarData);
  1611. begin
  1612. { custom variants? }
  1613. VarInvalidOp(v.vType, opNegate);
  1614. end;
  1615. procedure sysvarneg(var v: Variant);
  1616. const
  1617. BoolMap: array [Boolean] of SmallInt = (0, -1);
  1618. begin
  1619. with TVarData(v) do case vType of
  1620. varEmpty: begin
  1621. vSmallInt := 0;
  1622. vType := varSmallInt;
  1623. end;
  1624. varNull:;
  1625. varSmallint: vSmallInt := -vSmallInt;
  1626. varInteger: vInteger := -vInteger;
  1627. {$ifndef FPUNONE}
  1628. varSingle: vSingle := -vSingle;
  1629. varDouble: vDouble := -vDouble;
  1630. varCurrency: vCurrency := -vCurrency;
  1631. varDate: vDate := -vDate;
  1632. varOleStr: sysvarfromreal(v, -VariantToDouble(TVarData(v)));
  1633. {$else}
  1634. varOleStr: sysvarfromint64(v, -VariantToInt64(TVarData(v)));
  1635. {$endif}
  1636. varBoolean: begin
  1637. vSmallInt := BoolMap[vBoolean];
  1638. vType := varSmallInt;
  1639. end;
  1640. varShortInt: vShortInt := -vShortInt;
  1641. varByte: begin
  1642. vSmallInt := -vByte;
  1643. vType := varSmallInt;
  1644. end;
  1645. varWord: begin
  1646. vInteger := -vWord;
  1647. vType := varInteger;
  1648. end;
  1649. varLongWord:
  1650. if vLongWord and $80000000 <> 0 then begin
  1651. vInt64 := -vLongWord;
  1652. vType := varInt64;
  1653. end else begin
  1654. vInteger := -vLongWord;
  1655. vType := varInteger;
  1656. end;
  1657. varInt64: vInt64 := -vInt64;
  1658. varQWord: begin
  1659. if vQWord and $8000000000000000 <> 0 then
  1660. VarRangeCheckError(varQWord, varInt64);
  1661. vInt64 := -vQWord;
  1662. vType := varInt64;
  1663. end;
  1664. varVariant: v := -Variant(PVarData(vPointer)^);
  1665. else {with TVarData(v) do case vType of}
  1666. case vType of
  1667. {$ifndef FPUNONE}
  1668. varString: sysvarfromreal(v, -VariantToDouble(TVarData(v)));
  1669. {$else}
  1670. varString: sysvarfromint64(v, -VariantToInt64(TVarData(v)));
  1671. {$endif}
  1672. varAny: DoVarNegAny(TVarData(v));
  1673. else {case vType of}
  1674. if (vType and not varTypeMask) = varByRef then
  1675. case vType and varTypeMask of
  1676. varSmallInt: begin
  1677. vSmallInt := -PSmallInt(vPointer)^;
  1678. vType := varSmallInt;
  1679. end;
  1680. varInteger: begin
  1681. vInteger := -PInteger(vPointer)^;
  1682. vType := varInteger;
  1683. end;
  1684. {$ifndef FPUNONE}
  1685. varSingle: begin
  1686. vSingle := -PSingle(vPointer)^;
  1687. vType := varSingle;
  1688. end;
  1689. varDouble: begin
  1690. vDouble := -PDouble(vPointer)^;
  1691. vType := varDouble;
  1692. end;
  1693. varCurrency: begin
  1694. vCurrency := -PCurrency(vPointer)^;
  1695. vType := varCurrency;
  1696. end;
  1697. varDate: begin
  1698. vDate := -PDate(vPointer)^;
  1699. vType := varDate;
  1700. end;
  1701. varOleStr: sysvarfromreal(v, -VariantToDouble(TVarData(v)));
  1702. {$else}
  1703. varOleStr: sysvarfromint64(v, -VariantToInt64(TVarData(v)));
  1704. {$endif}
  1705. varBoolean: begin
  1706. vSmallInt := BoolMap[PWordBool(vPointer)^];
  1707. vType := varSmallInt;
  1708. end;
  1709. varShortInt: begin
  1710. vShortInt := -PShortInt(vPointer)^;
  1711. vType := varShortInt;
  1712. end;
  1713. varByte: begin
  1714. vSmallInt := -PByte(vPointer)^;
  1715. vType := varSmallInt;
  1716. end;
  1717. varWord: begin
  1718. vInteger := -PWord(vPointer)^;
  1719. vType := varInteger;
  1720. end;
  1721. varLongWord:
  1722. if PLongWord(vPointer)^ and $80000000 <> 0 then begin
  1723. vInt64 := -PLongWord(vPointer)^;
  1724. vType := varInt64;
  1725. end else begin
  1726. vInteger := -PLongWord(vPointer)^;
  1727. vType := varInteger;
  1728. end;
  1729. varInt64: begin
  1730. vInt64 := -PInt64(vPointer)^;
  1731. vType := varInt64;
  1732. end;
  1733. varQWord: begin
  1734. if PQWord(vPointer)^ and $8000000000000000 <> 0 then
  1735. VarRangeCheckError(varQWord, varInt64);
  1736. vInt64 := -PQWord(vPointer)^;
  1737. vType := varInt64;
  1738. end;
  1739. varVariant:
  1740. v := -Variant(PVarData(vPointer)^);
  1741. else {case vType and varTypeMask of}
  1742. DoVarNegComplex(TVarData(v));
  1743. end {case vType and varTypeMask of}
  1744. else {if (vType and not varTypeMask) = varByRef}
  1745. DoVarNegComplex(TVarData(v));
  1746. end; {case vType of}
  1747. end; {with TVarData(v) do case vType of}
  1748. end;
  1749. procedure DoVarNotAny(var v: TVarData);
  1750. begin
  1751. VarInvalidOp(v.vType, opNot);
  1752. end;
  1753. procedure DoVarNotOrdinal(var v: TVarData);
  1754. var
  1755. i: Int64;
  1756. begin
  1757. { only called for types that do no require finalization }
  1758. i := VariantToInt64(v);
  1759. with v do
  1760. if (i < Low(Integer)) or (i > High(Integer)) then begin
  1761. vInt64 := not i;
  1762. vType := varInt64;
  1763. end else begin
  1764. vInteger := not Integer(i);
  1765. vType := varInteger;
  1766. end
  1767. end;
  1768. procedure DoVarNotWStr(var v: TVarData; const p: Pointer);
  1769. var
  1770. i: Int64;
  1771. e: Word;
  1772. b: Boolean;
  1773. begin
  1774. Val(WideString(p), i, e);
  1775. with v do
  1776. if e = 0 then begin
  1777. DoVarClearIfComplex(v);
  1778. if (i < Low(Integer)) or (i > High(Integer)) then begin
  1779. vInt64 := not i;
  1780. vType := varInt64;
  1781. end else begin
  1782. vInteger := not Integer(i);
  1783. vType := varInteger;
  1784. end
  1785. end else begin
  1786. if not TryStrToBool(WideString(p), b) then
  1787. VarInvalidOp(vType, opNot);
  1788. DoVarClearIfComplex(v);
  1789. vBoolean := not b;
  1790. vType := varBoolean;
  1791. end;
  1792. end;
  1793. procedure DoVarNotLStr(var v: TVarData; const p: Pointer);
  1794. var
  1795. i: Int64;
  1796. e: Word;
  1797. b: Boolean;
  1798. begin
  1799. Val(AnsiString(p), i, e);
  1800. with v do
  1801. if e = 0 then begin
  1802. DoVarClearIfComplex(v);
  1803. if (i < Low(Integer)) or (i > High(Integer)) then begin
  1804. vInt64 := not i;
  1805. vType := varInt64;
  1806. end else begin
  1807. vInteger := not Integer(i);
  1808. vType := varInteger;
  1809. end
  1810. end else begin
  1811. if not TryStrToBool(AnsiString(p), b) then
  1812. VarInvalidOp(v.vType, opNot);
  1813. DoVarClearIfComplex(v);
  1814. vBoolean := not b;
  1815. vType := varBoolean;
  1816. end;
  1817. end;
  1818. procedure DoVarNotComplex(var v: TVarData);
  1819. begin
  1820. { custom variant support ?}
  1821. VarInvalidOp(v.vType, opNot);
  1822. end;
  1823. procedure sysvarnot(var v: Variant);
  1824. begin
  1825. with TVarData(v) do case vType of
  1826. varEmpty: v := -1;
  1827. varNull:;
  1828. varSmallint: vSmallInt := not vSmallInt;
  1829. varInteger: vInteger := not vInteger;
  1830. {$ifndef FPUNONE}
  1831. varSingle,
  1832. varDouble,
  1833. varCurrency,
  1834. varDate: DoVarNotOrdinal(TVarData(v));
  1835. {$endif}
  1836. varOleStr: DoVarNotWStr(TVarData(v), Pointer(vOleStr));
  1837. varBoolean: vBoolean := not vBoolean;
  1838. varShortInt: vShortInt := not vShortInt;
  1839. varByte: vByte := not vByte;
  1840. varWord: vWord := not vWord;
  1841. varLongWord: vLongWord := not vLongWord;
  1842. varInt64: vInt64 := not vInt64;
  1843. varQWord: vQWord := not vQWord;
  1844. varVariant: v := not Variant(PVarData(vPointer)^);
  1845. else {with TVarData(v) do case vType of}
  1846. case vType of
  1847. varString: DoVarNotLStr(TVarData(v), Pointer(vString));
  1848. varAny: DoVarNotAny(TVarData(v));
  1849. else {case vType of}
  1850. if (vType and not varTypeMask) = varByRef then
  1851. case vType and varTypeMask of
  1852. varSmallInt: begin
  1853. vSmallInt := not PSmallInt(vPointer)^;
  1854. vType := varSmallInt;
  1855. end;
  1856. varInteger: begin
  1857. vInteger := not PInteger(vPointer)^;
  1858. vType := varInteger;
  1859. end;
  1860. {$ifndef FPUNONE}
  1861. varSingle,
  1862. varDouble,
  1863. varCurrency,
  1864. varDate: DoVarNotOrdinal(TVarData(v));
  1865. {$endif}
  1866. varOleStr: DoVarNotWStr(TVarData(v), PPointer(vPointer)^);
  1867. varBoolean: begin
  1868. vBoolean := not PWordBool(vPointer)^;
  1869. vType := varBoolean;
  1870. end;
  1871. varShortInt: begin
  1872. vShortInt := not PShortInt(vPointer)^;
  1873. vType := varShortInt;
  1874. end;
  1875. varByte: begin
  1876. vByte := not PByte(vPointer)^;
  1877. vType := varByte;
  1878. end;
  1879. varWord: begin
  1880. vWord := not PWord(vPointer)^;
  1881. vType := varWord;
  1882. end;
  1883. varLongWord: begin
  1884. vLongWord := not PLongWord(vPointer)^;
  1885. vType := varLongWord;
  1886. end;
  1887. varInt64: begin
  1888. vInt64 := not PInt64(vPointer)^;
  1889. vType := varInt64;
  1890. end;
  1891. varQWord: begin
  1892. vQWord := not PQWord(vPointer)^;
  1893. vType := varQWord;
  1894. end;
  1895. varVariant:
  1896. v := not Variant(PVarData(vPointer)^);
  1897. else {case vType and varTypeMask of}
  1898. DoVarNotComplex(TVarData(v));
  1899. end {case vType and varTypeMask of}
  1900. else {if (vType and not varTypeMask) = varByRef}
  1901. DoVarNotComplex(TVarData(v));
  1902. end; {case vType of}
  1903. end; {with TVarData(v) do case vType of}
  1904. end;
  1905. {
  1906. This procedure is needed to destroy and clear non-standard variant type array elements,
  1907. which can not be handled by SafeArrayDestroy.
  1908. If array element type is varVariant, then clear each element individually before
  1909. calling VariantClear for array. VariantClear just calls SafeArrayDestroy.
  1910. }
  1911. procedure DoVarClearArray(var VArray: TVarData);
  1912. var
  1913. arr: pvararray;
  1914. i, cnt: cardinal;
  1915. data: pvardata;
  1916. begin
  1917. if VArray.vtype and varTypeMask = varVariant then begin
  1918. if WordBool(VArray.vType and varByRef) then
  1919. arr:=PVarArray(VArray.vPointer^)
  1920. else
  1921. arr:=VArray.vArray;
  1922. VarResultCheck(SafeArrayAccessData(arr, data));
  1923. try
  1924. { Calculation total number of elements in the array }
  1925. cnt:=1;
  1926. {$push}
  1927. { arr^.bounds[] is an array[0..0] }
  1928. {$r-}
  1929. for i:=0 to arr^.dimcount - 1 do
  1930. cnt:=cnt*cardinal(arr^.Bounds[i].ElementCount);
  1931. {$pop}
  1932. { Clearing each element }
  1933. for i:=1 to cnt do begin
  1934. DoVarClear(data^);
  1935. Inc(pointer(data), arr^.ElementSize);
  1936. end;
  1937. finally
  1938. VarResultCheck(SafeArrayUnaccessData(arr));
  1939. end;
  1940. end;
  1941. VariantClear(VArray);
  1942. end;
  1943. procedure DoVarClearComplex(var v : TVarData);
  1944. var
  1945. Handler : TCustomVariantType;
  1946. begin
  1947. with v do
  1948. if vType < varInt64 then
  1949. VarResultCheck(VariantClear(v))
  1950. else if vType = varString then
  1951. begin
  1952. AnsiString(vString) := '';
  1953. vType := varEmpty;
  1954. end
  1955. else if vType = varUString then
  1956. begin
  1957. UnicodeString(vString) := '';
  1958. vType := varEmpty;
  1959. end
  1960. else if vType = varAny then
  1961. ClearAnyProc(v)
  1962. else if vType and varArray <> 0 then
  1963. DoVarClearArray(v)
  1964. else if FindCustomVariantType(vType, Handler) then
  1965. Handler.Clear(v)
  1966. else begin
  1967. { ignore errors, if the OS doesn't know how to free it, we don't either }
  1968. VariantClear(v);
  1969. vType := varEmpty;
  1970. end;
  1971. end;
  1972. type
  1973. TVarArrayCopyCallback = procedure(var aDest: TVarData; const aSource: TVarData);
  1974. procedure DoVarCopyArray(var aDest: TVarData; const aSource: TVarData; aCallback: TVarArrayCopyCallback);
  1975. var
  1976. SourceArray : PVarArray;
  1977. SourcePtr : Pointer;
  1978. DestArray : PVarArray;
  1979. DestPtr : Pointer;
  1980. Bounds : array[0..63] of TVarArrayBound;
  1981. Iterator : TVariantArrayIterator;
  1982. Dims : Integer;
  1983. HighBound : Longint;
  1984. i : Integer;
  1985. begin
  1986. with aSource do begin
  1987. if vType and varArray = 0 then
  1988. VarResultCheck(VAR_INVALIDARG);
  1989. if (vType and varTypeMask) = varVariant then begin
  1990. if (vType and varByRef) <> 0 then
  1991. SourceArray := PVarArray(vPointer^)
  1992. else
  1993. SourceArray := vArray;
  1994. Dims := SourceArray^.DimCount;
  1995. for i := 0 to Pred(Dims) do
  1996. with Bounds[i] do begin
  1997. VarResultCheck(SafeArrayGetLBound(SourceArray, Succ(i), LowBound));
  1998. VarResultCheck(SafeArrayGetUBound(SourceArray, Succ(i), HighBound));
  1999. ElementCount := HighBound - LowBound + 1;
  2000. end;
  2001. DestArray := SafeArrayCreate(varVariant, Dims, PVarArrayBoundArray(@Bounds)^);
  2002. if not Assigned(DestArray) then
  2003. VarArrayCreateError;
  2004. DoVarClearIfComplex(aDest);
  2005. with aDest do begin
  2006. vType := varVariant or varArray;
  2007. vArray := DestArray;
  2008. end;
  2009. Iterator.Init(Dims, @Bounds);
  2010. try
  2011. if not(Iterator.AtEnd) then
  2012. repeat
  2013. VarResultCheck(SafeArrayPtrOfIndex(SourceArray, Iterator.Coords, SourcePtr));
  2014. VarResultCheck(SafeArrayPtrOfIndex(DestArray, Iterator.Coords, DestPtr));
  2015. aCallback(PVarData(DestPtr)^, PVarData(SourcePtr)^);
  2016. until not Iterator.Next;
  2017. finally
  2018. Iterator.Done;
  2019. end;
  2020. end else
  2021. VarResultCheck(VariantCopy(aDest, aSource));
  2022. end;
  2023. end;
  2024. procedure DoVarCopyComplex(var Dest: TVarData; const Source: TVarData);
  2025. var
  2026. Handler: TCustomVariantType;
  2027. begin
  2028. DoVarClearIfComplex(Dest);
  2029. with Source do
  2030. if vType < varInt64 then
  2031. VarResultCheck(VariantCopy(Dest, Source))
  2032. else if vType = varString then begin
  2033. Dest.vType := varString;
  2034. Dest.vString := nil;
  2035. AnsiString(Dest.vString) := AnsiString(vString);
  2036. end else if vType = varOleStr then begin
  2037. Dest.vType := varOleStr;
  2038. Dest.vOleStr := nil;
  2039. WideString(Pointer(Dest.vOleStr)) := WideString(Pointer(vOleStr));
  2040. end else if vType = varAny then begin
  2041. Dest := Source;
  2042. RefAnyProc(Dest);
  2043. end else if vType and varArray <> 0 then
  2044. DoVarCopyArray(Dest, Source, @DoVarCopy)
  2045. else if (vType and varByRef <> 0) and
  2046. (((vType xor varByRef) = varString)
  2047. or ((vType xor varByRef)= varOleStr)) then
  2048. Dest := Source
  2049. else if FindCustomVariantType(vType, Handler) then
  2050. Handler.Copy(Dest, Source, False)
  2051. else
  2052. VarResultCheck(VariantCopy(Dest, Source));
  2053. end;
  2054. procedure DoVarCopy(var Dest : TVarData; const Source : TVarData);
  2055. begin
  2056. if @Dest <> @Source then
  2057. if (Source.vType and varComplexType) = 0 then begin
  2058. DoVarClearIfComplex(Dest);
  2059. Dest := Source;
  2060. end else
  2061. DoVarCopyComplex(Dest, Source);
  2062. end;
  2063. procedure sysvarcopy (var Dest : Variant; const Source : Variant);
  2064. begin
  2065. DoVarCopy(TVarData(Dest),TVarData(Source));
  2066. end;
  2067. procedure DoVarAddRef(var v : TVarData); inline;
  2068. var
  2069. Dummy : TVarData;
  2070. begin
  2071. Dummy := v;
  2072. v.vType := varEmpty;
  2073. DoVarCopy(v, Dummy);
  2074. end;
  2075. procedure sysvaraddref(var v : Variant);
  2076. begin
  2077. DoVarAddRef(TVarData(v));
  2078. end;
  2079. procedure DoVarCastWStr(var aDest : TVarData; const aSource : TVarData);
  2080. begin
  2081. SysVarFromWStr(Variant(aDest), VariantToWideString(aSource));
  2082. end;
  2083. procedure DoVarCastLStr(var aDest : TVarData; const aSource : TVarData);
  2084. begin
  2085. SysVarFromLStr(Variant(aDest), VariantToAnsiString(aSource));
  2086. end;
  2087. procedure DoVarCastDispatch(var aDest : TVarData; const aSource : TVarData);
  2088. var
  2089. Disp: IDispatch;
  2090. begin
  2091. SysVarToDisp(Disp, Variant(aSource));
  2092. SysVarFromDisp(Variant(aDest), Disp);
  2093. end;
  2094. procedure DoVarCastInterface(var aDest : TVarData; const aSource : TVarData);
  2095. var
  2096. Intf: IInterface;
  2097. begin
  2098. SysVarToIntf(Intf, Variant(aSource));
  2099. SysVarFromIntf(Variant(aDest), Intf);
  2100. end;
  2101. procedure DoVarCastAny(var aDest : TVarData; const aSource : TVarData; aVarType : LongInt);
  2102. begin
  2103. VarCastError(aSource.vType, aVarType)
  2104. end;
  2105. procedure DoVarCastFallback(var aDest : TVarData; const aSource : TVarData; aVarType : LongInt);
  2106. begin
  2107. if aSource.vType and varTypeMask >= varInt64 then begin
  2108. DoVarCast(aDest, aSource, varOleStr);
  2109. VarResultCheck(VariantChangeTypeEx(aDest, aDest, VAR_LOCALE_USER_DEFAULT,
  2110. 0, aVarType), aSource.vType, aVarType);
  2111. end else if aVarType and varTypeMask < varInt64 then
  2112. VarResultCheck(VariantChangeTypeEx(aDest, aSource, VAR_LOCALE_USER_DEFAULT,
  2113. 0, aVarType), aSource.vType, aVarType)
  2114. else
  2115. VarCastError(aSource.vType, aVarType);
  2116. end;
  2117. procedure DoVarCastComplex(var aDest : TVarData; const aSource : TVarData; aVarType : LongInt);
  2118. var
  2119. Handler: TCustomVariantType;
  2120. begin
  2121. if aSource.vType = varAny then
  2122. DoVarCastAny(aDest, aSource, aVarType)
  2123. else if FindCustomVariantType(aSource.vType, Handler) then
  2124. Handler.CastTo(aDest, aSource, aVarType)
  2125. else if FindCustomVariantType(aVarType, Handler) then
  2126. Handler.Cast(aDest, aSource)
  2127. else
  2128. DoVarCastFallback(aDest, aSource, aVarType);
  2129. end;
  2130. procedure DoVarCast(var aDest : TVarData; const aSource : TVarData; aVarType : LongInt);
  2131. begin
  2132. with aSource do
  2133. if vType = aVarType then
  2134. DoVarCopy(aDest, aSource)
  2135. else begin
  2136. if (vType = varNull) and NullStrictConvert then
  2137. VarCastError(varNull, aVarType);
  2138. case aVarType of
  2139. varEmpty, varNull: begin
  2140. DoVarClearIfComplex(aDest);
  2141. aDest.vType := aVarType;
  2142. end;
  2143. varSmallInt: SysVarFromInt(Variant(aDest), VariantToSmallInt(aSource), -2);
  2144. varInteger: SysVarFromInt(Variant(aDest), VariantToLongInt(aSource), -4);
  2145. {$ifndef FPUNONE}
  2146. varSingle: SysVarFromSingle(Variant(aDest), VariantToSingle(aSource));
  2147. varDouble: SysVarFromDouble(Variant(aDest), VariantToDouble(aSource));
  2148. varCurrency: SysVarFromCurr(Variant(aDest), VariantToCurrency(aSource));
  2149. varDate: SysVarFromTDateTime(Variant(aDest), VariantToDate(aSource));
  2150. {$endif}
  2151. varOleStr: DoVarCastWStr(aDest, aSource);
  2152. varBoolean: SysVarFromBool(Variant(aDest), VariantToBoolean(aSource));
  2153. varShortInt: SysVarFromInt(Variant(aDest), VariantToShortInt(aSource), -1);
  2154. varByte: SysVarFromInt(Variant(aDest), VariantToByte(aSource), 1);
  2155. varWord: SysVarFromInt(Variant(aDest), VariantToLongInt(aSource), 2);
  2156. varLongWord: SysVarFromInt(Variant(aDest), Integer(VariantToCardinal(aSource)), 4);
  2157. varInt64: SysVarFromInt64(Variant(aDest), VariantToInt64(aSource));
  2158. varQWord: SysVarFromWord64(Variant(aDest), VariantToQWord(aSource));
  2159. varDispatch: DoVarCastDispatch(aDest, aSource);
  2160. varUnknown: DoVarCastInterface(aDest, aSource);
  2161. else
  2162. case aVarType of
  2163. varString: DoVarCastLStr(aDest, aSource);
  2164. varAny: VarCastError(vType, varAny);
  2165. else
  2166. DoVarCastComplex(aDest, aSource, aVarType);
  2167. end;
  2168. end;
  2169. end;
  2170. end;
  2171. procedure sysvarcast (var aDest : Variant; const aSource : Variant; aVarType : LongInt);
  2172. begin
  2173. DoVarCast(TVarData(aDest), TVarData(aSource), aVarType);
  2174. end;
  2175. procedure sysvarfromdynarray(var Dest : Variant; const Source : Pointer; TypeInfo: Pointer);
  2176. begin
  2177. DynArrayToVariant(Dest,Source,TypeInfo);
  2178. if VarIsEmpty(Dest) then
  2179. VarCastError;
  2180. end;
  2181. procedure sysolevarfrompstr(var Dest : olevariant; const Source : ShortString);
  2182. begin
  2183. sysvarfromwstr(Variant(TVarData(Dest)), Source);
  2184. end;
  2185. procedure sysolevarfromlstr(var Dest : olevariant; const Source : AnsiString);
  2186. begin
  2187. sysvarfromwstr(Variant(TVarData(Dest)), Source);
  2188. end;
  2189. procedure DoOleVarFromAny(var aDest : TVarData; const aSource : TVarData);
  2190. begin
  2191. VarCastErrorOle(aSource.vType);
  2192. end;
  2193. procedure DoOleVarFromVar(var aDest : TVarData; const aSource : TVarData);
  2194. var
  2195. Handler: TCustomVariantType;
  2196. begin
  2197. with aSource do
  2198. if vType = varByRef or varVariant then
  2199. DoOleVarFromVar(aDest, PVarData(vPointer)^)
  2200. else begin
  2201. case vType of
  2202. varShortInt, varByte, varWord:
  2203. DoVarCast(aDest, aSource, varInteger);
  2204. varLongWord:
  2205. if vLongWord and $80000000 = 0 then
  2206. DoVarCast(aDest, aSource, varInteger)
  2207. else
  2208. {$ifndef FPUNONE}
  2209. if OleVariantInt64AsDouble then
  2210. DoVarCast(aDest, aSource, varDouble)
  2211. else
  2212. {$endif}
  2213. DoVarCast(aDest, aSource, varInt64);
  2214. varInt64:
  2215. if (vInt64 < Low(Integer)) or (vInt64 > High(Integer)) then
  2216. {$ifndef FPUNONE}
  2217. if OleVariantInt64AsDouble then
  2218. DoVarCast(aDest, aSource, varDouble)
  2219. else
  2220. {$endif}
  2221. DoVarCast(aDest, aSource, varInt64)
  2222. else
  2223. DoVarCast(aDest, aSource, varInteger);
  2224. varQWord:
  2225. if vQWord > High(Integer) then
  2226. {$ifndef FPUNONE}
  2227. if OleVariantInt64AsDouble or (vQWord and $8000000000000000 <> 0) then
  2228. DoVarCast(aDest, aSource, varDouble)
  2229. else
  2230. {$endif}
  2231. DoVarCast(aDest, aSource, varInt64)
  2232. else
  2233. DoVarCast(aDest, aSource, varInteger);
  2234. varString:
  2235. DoVarCast(aDest, aSource, varOleStr);
  2236. varAny:
  2237. DoOleVarFromAny(aDest, aSource);
  2238. else
  2239. if (vType and varArray) <> 0 then
  2240. DoVarCopyArray(aDest, aSource, @DoOleVarFromVar)
  2241. else if (vType and varTypeMask) < CFirstUserType then
  2242. DoVarCopy(aDest, aSource)
  2243. else if FindCustomVariantType(vType, Handler) then
  2244. Handler.CastToOle(aDest, aSource)
  2245. else
  2246. VarCastErrorOle(vType);
  2247. end;
  2248. end;
  2249. end;
  2250. procedure sysolevarfromvar(var aDest : OleVariant; const aSource : Variant);
  2251. begin
  2252. DoOleVarFromVar(TVarData(aDest), TVarData(aSource));
  2253. end;
  2254. procedure sysolevarfromint(var Dest : olevariant; const Source : LongInt; const range : ShortInt);
  2255. begin
  2256. DoVarClearIfComplex(TVarData(Dest));
  2257. with TVarData(Dest) do begin
  2258. vInteger := Source;
  2259. vType := varInteger;
  2260. end;
  2261. end;
  2262. procedure DoVarCastOle(var aDest: TVarData; const aSource: TVarData; aVarType: LongInt);
  2263. var
  2264. Handler: TCustomVariantType;
  2265. begin
  2266. with aSource do
  2267. if vType = varByRef or varVariant then
  2268. DoVarCastOle(aDest, PVarData(VPointer)^, aVarType)
  2269. else
  2270. if (aVarType = varString) or (aVarType = varAny) then
  2271. VarCastError(vType, aVarType)
  2272. else if FindCustomVariantType(vType, Handler) then
  2273. Handler.CastTo(aDest, aSource, aVarType)
  2274. else
  2275. DoVarCast(aDest, aSource, aVarType);
  2276. end;
  2277. procedure sysvarcastole(var Dest : Variant; const Source : Variant; aVarType : LongInt);
  2278. begin
  2279. DoVarCastOle(TVarData(Dest), TVarData(Source), aVarType);
  2280. end;
  2281. procedure sysdispinvoke(Dest : PVarData; var source : TVarData;calldesc : pcalldesc;params : Pointer);cdecl;
  2282. var
  2283. temp : TVarData;
  2284. tempp : ^TVarData;
  2285. customvarianttype : TCustomVariantType;
  2286. begin
  2287. if Source.vType=(varByRef or varVariant) then
  2288. sysdispinvoke(Dest,PVarData(Source.vPointer)^,calldesc,params)
  2289. else
  2290. begin
  2291. try
  2292. { get a defined Result }
  2293. if not(assigned(Dest)) then
  2294. tempp:=nil
  2295. else
  2296. begin
  2297. fillchar(temp,SizeOf(temp),0);
  2298. tempp:=@temp;
  2299. end;
  2300. case Source.vType of
  2301. varDispatch,
  2302. varAny,
  2303. varUnknown,
  2304. varDispatch or varByRef,
  2305. varAny or varByRef,
  2306. varUnknown or varByRef:
  2307. VarDispProc(pvariant(tempp),Variant(Source),calldesc,params);
  2308. else
  2309. begin
  2310. if FindCustomVariantType(Source.vType,customvarianttype) then
  2311. customvarianttype.DispInvoke(tempp,Source,calldesc,params)
  2312. else
  2313. VarInvalidOp;
  2314. end;
  2315. end;
  2316. finally
  2317. if assigned(tempp) then
  2318. begin
  2319. DoVarCopy(Dest^,tempp^);
  2320. DoVarClear(temp);
  2321. end;
  2322. end;
  2323. end;
  2324. end;
  2325. procedure sysvararrayredim(var a : Variant;highbound : SizeInt);
  2326. var
  2327. src : TVarData;
  2328. p : pvararray;
  2329. newbounds : tvararraybound;
  2330. begin
  2331. src:=TVarData(a);
  2332. { get final Variant }
  2333. while src.vType=varByRef or varVariant do
  2334. src:=TVarData(src.vPointer^);
  2335. if (src.vType and varArray)<>0 then
  2336. begin
  2337. { get Pointer to the array }
  2338. if (src.vType and varByRef)<>0 then
  2339. p:=pvararray(src.vPointer^)
  2340. else
  2341. p:=src.vArray;
  2342. {$push}
  2343. {$r-}
  2344. if highbound<p^.Bounds[p^.dimcount-1].LowBound-1 then
  2345. VarInvalidArgError;
  2346. newbounds.LowBound:=p^.Bounds[p^.dimcount-1].LowBound;
  2347. {$pop}
  2348. newbounds.ElementCount:=highbound-newbounds.LowBound+1;
  2349. VarResultCheck(SafeArrayRedim(p,newbounds));
  2350. end
  2351. else
  2352. VarInvalidArgError(src.vType);
  2353. end;
  2354. function getfinalvartype(const v : TVarData) : TVarType;{$IFDEF VARIANTINLINE}inline;{$ENDIF VARIANTINLINE}
  2355. var
  2356. p: PVarData;
  2357. begin
  2358. p := @v;
  2359. while p^.vType = varByRef or varVariant do
  2360. p := PVarData(p^.vPointer);
  2361. Result := p^.vType;
  2362. end;
  2363. function sysvararrayget(const a : Variant;indexcount : SizeInt;indices : plongint) : Variant;cdecl;
  2364. var
  2365. src : TVarData;
  2366. p : pvararray;
  2367. arraysrc : pvariant;
  2368. arrayelementtype : TVarType;
  2369. begin
  2370. src:=TVarData(a);
  2371. { get final Variant }
  2372. while src.vType=varByRef or varVariant do
  2373. src:=TVarData(src.vPointer^);
  2374. if (src.vType and varArray)<>0 then
  2375. begin
  2376. { get Pointer to the array }
  2377. if (src.vType and varByRef)<>0 then
  2378. p:=pvararray(src.vPointer^)
  2379. else
  2380. p:=src.vArray;
  2381. { number of indices ok? }
  2382. if p^.DimCount<>indexcount then
  2383. VarInvalidArgError;
  2384. arrayelementtype:=src.vType and varTypeMask;
  2385. if arrayelementtype=varVariant then
  2386. begin
  2387. VarResultCheck(SafeArrayPtrOfIndex(p,PVarArrayCoorArray(indices),arraysrc));
  2388. Result:=arraysrc^;
  2389. end
  2390. else
  2391. begin
  2392. TVarData(Result).vType:=arrayelementtype;
  2393. VarResultCheck(SafeArrayGetElement(p,PVarArrayCoorArray(indices),@TVarData(Result).vPointer));
  2394. end;
  2395. end
  2396. else
  2397. VarInvalidArgError(src.vType);
  2398. end;
  2399. procedure sysvararrayput(var a : Variant; const value : Variant;indexcount : SizeInt;indices : plongint);cdecl;
  2400. var
  2401. Dest : TVarData;
  2402. p : pvararray;
  2403. arraydest : pvariant;
  2404. valuevtype,
  2405. arrayelementtype : TVarType;
  2406. tempvar : Variant;
  2407. begin
  2408. Dest:=TVarData(a);
  2409. { get final Variant }
  2410. while Dest.vType=varByRef or varVariant do
  2411. Dest:=TVarData(Dest.vPointer^);
  2412. valuevtype:=getfinalvartype(TVarData(value));
  2413. if not(VarTypeIsValidElementType(valuevtype)) and
  2414. { varString isn't a valid varArray type but it is converted
  2415. later }
  2416. (valuevtype<>varString) then
  2417. VarCastError(valuevtype,Dest.vType);
  2418. if (Dest.vType and varArray)<>0 then
  2419. begin
  2420. { get Pointer to the array }
  2421. if (Dest.vType and varByRef)<>0 then
  2422. p:=pvararray(Dest.vPointer^)
  2423. else
  2424. p:=Dest.vArray;
  2425. { number of indices ok? }
  2426. if p^.DimCount<>indexcount then
  2427. VarInvalidArgError;
  2428. arrayelementtype:=Dest.vType and varTypeMask;
  2429. if arrayelementtype=varVariant then
  2430. begin
  2431. VarResultCheck(SafeArrayPtrOfIndex(p,PVarArrayCoorArray(indices),arraydest));
  2432. { we can't store ansistrings in Variant arrays so we convert the string to
  2433. an olestring }
  2434. if valuevtype=varString then
  2435. begin
  2436. tempvar:=VarToWideStr(value);
  2437. arraydest^:=tempvar;
  2438. end
  2439. else
  2440. arraydest^:=value;
  2441. end
  2442. else
  2443. begin
  2444. VarCast(tempvar,value,arrayelementtype);
  2445. if arrayelementtype in [varOleStr,varDispatch,varUnknown] then
  2446. VarResultCheck(SafeArrayPutElement(p,PVarArrayCoorArray(indices),TVarData(tempvar).vPointer))
  2447. else
  2448. VarResultCheck(SafeArrayPutElement(p,PVarArrayCoorArray(indices),@TVarData(tempvar).vPointer));
  2449. end;
  2450. end
  2451. else
  2452. VarInvalidArgError(Dest.vType);
  2453. end;
  2454. { import from system unit }
  2455. Procedure fpc_Write_Text_AnsiStr (Len : LongInt; Var f : Text; S : RawByteString); external name 'FPC_WRITE_TEXT_ANSISTR';
  2456. function syswritevariant(var t : text; const v : Variant;width : LongInt) : Pointer;
  2457. var
  2458. s : AnsiString;
  2459. variantmanager : tvariantmanager;
  2460. begin
  2461. GetVariantManager(variantmanager);
  2462. variantmanager.vartolstr(s,v);
  2463. fpc_write_text_ansistr(width,t,s);
  2464. Result:=nil; // Pointer to what should be returned?
  2465. end;
  2466. function syswrite0Variant(var t : text; const v : Variant) : Pointer;
  2467. var
  2468. s : AnsiString;
  2469. variantmanager : tvariantmanager;
  2470. begin
  2471. getVariantManager(variantmanager);
  2472. variantmanager.vartolstr(s,v);
  2473. fpc_write_text_ansistr(-1,t,s);
  2474. Result:=nil; // Pointer to what should be returned?
  2475. end;
  2476. Const
  2477. SysVariantManager : TVariantManager = (
  2478. vartoint : @sysvartoint;
  2479. vartoint64 : @sysvartoint64;
  2480. vartoword64 : @sysvartoword64;
  2481. vartobool : @sysvartobool;
  2482. {$ifndef FPUNONE}
  2483. vartoreal : @sysvartoreal;
  2484. vartotdatetime: @sysvartotdatetime;
  2485. {$endif}
  2486. vartocurr : @sysvartocurr;
  2487. vartopstr : @sysvartopstr;
  2488. vartolstr : @sysvartolstr;
  2489. vartowstr : @sysvartowstr;
  2490. vartointf : @sysvartointf;
  2491. vartodisp : @sysvartodisp;
  2492. vartodynarray : @sysvartodynarray;
  2493. varfrombool : @sysvarfromBool;
  2494. varfromint : @sysvarfromint;
  2495. varfromint64 : @sysvarfromint64;
  2496. varfromword64 : @sysvarfromword64;
  2497. {$ifndef FPUNONE}
  2498. varfromreal : @sysvarfromreal;
  2499. varfromtdatetime: @sysvarfromtdatetime;
  2500. {$endif}
  2501. varfromcurr : @sysvarfromcurr;
  2502. varfrompstr : @sysvarfrompstr;
  2503. varfromlstr : @sysvarfromlstr;
  2504. varfromwstr : @sysvarfromwstr;
  2505. varfromintf : @sysvarfromintf;
  2506. varfromdisp : @sysvarfromdisp;
  2507. varfromdynarray: @sysvarfromdynarray;
  2508. olevarfrompstr: @sysolevarfrompstr;
  2509. olevarfromlstr: @sysolevarfromlstr;
  2510. olevarfromvar : @sysolevarfromvar;
  2511. olevarfromint : @sysolevarfromint;
  2512. varop : @SysVarOp;
  2513. cmpop : @syscmpop;
  2514. varneg : @sysvarneg;
  2515. varnot : @sysvarnot;
  2516. varinit : @sysvarinit;
  2517. varclear : @sysvarclear;
  2518. varaddref : @sysvaraddref;
  2519. varcopy : @sysvarcopy;
  2520. varcast : @sysvarcast;
  2521. varcastole : @sysvarcastole;
  2522. dispinvoke : @sysdispinvoke;
  2523. vararrayredim : @sysvararrayredim;
  2524. vararrayget : @sysvararrayget;
  2525. vararrayput : @sysvararrayput;
  2526. writevariant : @syswritevariant;
  2527. write0Variant : @syswrite0variant;
  2528. );
  2529. Var
  2530. PrevVariantManager : TVariantManager;
  2531. Procedure SetSysVariantManager;
  2532. begin
  2533. GetVariantManager(PrevVariantManager);
  2534. SetVariantManager(SysVariantManager);
  2535. end;
  2536. Procedure UnsetSysVariantManager;
  2537. begin
  2538. SetVariantManager(PrevVariantManager);
  2539. end;
  2540. { ---------------------------------------------------------------------
  2541. Variant support procedures and functions
  2542. ---------------------------------------------------------------------}
  2543. function VarType(const V: Variant): TVarType;
  2544. begin
  2545. Result:=TVarData(V).vType;
  2546. end;
  2547. function VarTypeDeRef(const V: Variant): TVarType;
  2548. var
  2549. p: PVarData;
  2550. begin
  2551. p := @TVarData(V);
  2552. Result := p^.vType and not varByRef;
  2553. while Result = varVariant do begin
  2554. p := p^.vPointer;
  2555. if not Assigned(p) then
  2556. VarBadTypeError;
  2557. Result := p^.vType and not varByRef;
  2558. end;
  2559. end;
  2560. function VarTypeDeRef(const V: TVarData): TVarType;
  2561. begin
  2562. Result := VarTypeDeRef(Variant(v));
  2563. end;
  2564. function VarAsType(const V: Variant; aVarType: TVarType): Variant;
  2565. begin
  2566. sysvarcast(Result,V,aVarType);
  2567. end;
  2568. function VarIsType(const V: Variant; aVarType: TVarType): Boolean; overload;
  2569. begin
  2570. Result:=((TVarData(V).vType and varTypeMask)=aVarType);
  2571. end;
  2572. function VarIsType(const V: Variant; const AVarTypes: array of TVarType): Boolean; overload;
  2573. Var
  2574. I : Integer;
  2575. begin
  2576. I:=Low(AVarTypes);
  2577. Result:=False;
  2578. While Not Result and (I<=High(AVarTypes)) do
  2579. begin
  2580. Result:=((TVarData(V).vType and varTypeMask)=AVarTypes[I]);
  2581. inc(i);
  2582. end;
  2583. end;
  2584. function VarIsByRef(const V: Variant): Boolean;
  2585. begin
  2586. Result:=(TVarData(V).vType and varByRef)<>0;
  2587. end;
  2588. function VarIsEmpty(const V: Variant): Boolean;
  2589. begin
  2590. Result:=TVarData(V).vType=varEmpty;
  2591. end;
  2592. procedure VarCheckEmpty(const V: Variant);
  2593. begin
  2594. If VarIsEmpty(V) Then
  2595. VariantError(SErrVarIsEmpty);
  2596. end;
  2597. procedure VarClear(var V: Variant);{$IFDEF VARIANTINLINE}inline;{$ENDIF VARIANTINLINE}
  2598. begin
  2599. sysvarclear(v);
  2600. end;
  2601. procedure VarClear(var V: OleVariant);{$IFDEF VARIANTINLINE}inline;{$ENDIF VARIANTINLINE}
  2602. begin
  2603. { strange casting using TVarData to avoid call of helper olevariant->Variant }
  2604. sysvarclear(Variant(TVarData(v)));
  2605. end;
  2606. function VarIsNull(const V: Variant): Boolean;
  2607. begin
  2608. Result:=TVarData(V).vType=varNull;
  2609. end;
  2610. function VarIsClear(const V: Variant): Boolean;
  2611. Var
  2612. VT : TVarType;
  2613. CustomType: TCustomVariantType;
  2614. begin
  2615. VT:=TVarData(V).vType and varTypeMask;
  2616. if VT<CFirstUserType then
  2617. Result:=(VT=varEmpty) or
  2618. (((VT=varDispatch) or (VT=varUnknown))
  2619. and (TVarData(V).vDispatch=Nil))
  2620. else
  2621. Result:=FindCustomVariantType(VT,CustomType) and CustomType.IsClear(TVarData(V));
  2622. end;
  2623. function VarIsCustom(const V: Variant): Boolean;
  2624. begin
  2625. Result:=TVarData(V).vType>=CFirstUserType;
  2626. end;
  2627. function VarIsOrdinal(const V: Variant): Boolean;
  2628. begin
  2629. Result:=(TVarData(V).vType and varTypeMask) in OrdinalVarTypes;
  2630. end;
  2631. function VarIsFloat(const V: Variant): Boolean;
  2632. begin
  2633. Result:=(TVarData(V).vType and varTypeMask) in FloatVarTypes;
  2634. end;
  2635. function VarIsNumeric(const V: Variant): Boolean;
  2636. begin
  2637. Result:=(TVarData(V).vType and varTypeMask) in (OrdinalVarTypes + FloatVarTypes);
  2638. end;
  2639. function VarIsStr(const V: Variant): Boolean;
  2640. begin
  2641. case (TVarData(V).vType and varTypeMask) of
  2642. varOleStr,
  2643. varUString,
  2644. varString :
  2645. Result:=True;
  2646. else
  2647. Result:=False;
  2648. end;
  2649. end;
  2650. function VarIsBool(const V: Variant): Boolean;
  2651. begin
  2652. Result := (TVarData(V).vType and varTypeMask) = varboolean;
  2653. end;
  2654. function VarToStr(const V: Variant): string;
  2655. begin
  2656. Result:=VarToStrDef(V,'');
  2657. end;
  2658. function VarToStrDef(const V: Variant; const ADefault: string): string;
  2659. begin
  2660. If TVarData(V).vType<>varNull then
  2661. Result:=V
  2662. else
  2663. Result:=ADefault;
  2664. end;
  2665. function VarToWideStr(const V: Variant): WideString;
  2666. begin
  2667. Result:=VarToWideStrDef(V,'');
  2668. end;
  2669. function VarToWideStrDef(const V: Variant; const ADefault: WideString): WideString;
  2670. begin
  2671. If TVarData(V).vType<>varNull then
  2672. Result:=V
  2673. else
  2674. Result:=ADefault;
  2675. end;
  2676. function VarToUnicodeStr(const V: Variant): UnicodeString;
  2677. begin
  2678. Result:=VarToUnicodeStrDef(V,'');
  2679. end;
  2680. function VarToUnicodeStrDef(const V: Variant; const ADefault: UnicodeString): UnicodeString;
  2681. begin
  2682. If TVarData(V).vType<>varNull then
  2683. Result:=V
  2684. else
  2685. Result:=ADefault;
  2686. end;
  2687. {$ifndef FPUNONE}
  2688. function VarToDateTime(const V: Variant): TDateTime;
  2689. begin
  2690. Result:=VariantToDate(TVarData(V));
  2691. end;
  2692. function VarFromDateTime(const DateTime: TDateTime): Variant;
  2693. begin
  2694. SysVarClear(Result);
  2695. with TVarData(Result) do
  2696. begin
  2697. vType:=varDate;
  2698. vdate:=DateTime;
  2699. end;
  2700. end;
  2701. {$endif}
  2702. function VarInRange(const AValue, AMin, AMax: Variant): Boolean;
  2703. begin
  2704. Result:=(AValue>=AMin) and (AValue<=AMax);
  2705. end;
  2706. function VarEnsureRange(const AValue, AMin, AMax: Variant): Variant;
  2707. begin
  2708. If AValue>AMAx then
  2709. Result:=AMax
  2710. else If AValue<AMin Then
  2711. Result:=AMin
  2712. else
  2713. Result:=AValue;
  2714. end;
  2715. function VarSameValue(const A, B: Variant): Boolean;
  2716. var
  2717. v1,v2 : TVarData;
  2718. begin
  2719. v1:=FindVarData(a)^;
  2720. v2:=FindVarData(b)^;
  2721. if v1.vType in [varEmpty,varNull] then
  2722. Result:=v1.vType=v2.vType
  2723. else if v2.vType in [varEmpty,varNull] then
  2724. Result:=False
  2725. else
  2726. Result:=A=B;
  2727. end;
  2728. function VarCompareValue(const A, B: Variant): TVariantRelationship;
  2729. var
  2730. v1,v2 : TVarData;
  2731. begin
  2732. Result:=vrNotEqual;
  2733. v1:=FindVarData(a)^;
  2734. v2:=FindVarData(b)^;
  2735. if (v1.vType in [varEmpty,varNull]) and (v1.vType=v2.vType) then
  2736. Result:=vrEqual
  2737. else if not(v2.vType in [varEmpty,varNull]) and
  2738. not(v1.vType in [varEmpty,varNull]) then
  2739. begin
  2740. if a=b then
  2741. Result:=vrEqual
  2742. else if a>b then
  2743. Result:=vrGreaterThan
  2744. else
  2745. Result:=vrLessThan;
  2746. end;
  2747. end;
  2748. function VarIsEmptyParam(const V: Variant): Boolean;
  2749. begin
  2750. Result:=(TVarData(V).vType = varError) and
  2751. (TVarData(V).vError=VAR_PARAMNOTFOUND);
  2752. end;
  2753. procedure SetClearVarToEmptyParam(var V: TVarData);
  2754. begin
  2755. VariantClear(V);
  2756. V.vType := varError;
  2757. V.vError := VAR_PARAMNOTFOUND;
  2758. end;
  2759. function VarIsError(const V: Variant; out aResult: HRESULT): Boolean;
  2760. begin
  2761. Result := TVarData(V).vType = varError;
  2762. if Result then
  2763. aResult := TVarData(v).vError;
  2764. end;
  2765. function VarIsError(const V: Variant): Boolean;
  2766. begin
  2767. Result := TVarData(V).vType = varError;
  2768. end;
  2769. function VarAsError(AResult: HRESULT): Variant;
  2770. begin
  2771. TVarData(Result).vType:=varError;
  2772. TVarData(Result).vError:=AResult;
  2773. end;
  2774. function VarSupports(const V: Variant; const IID: TGUID; out Intf): Boolean;
  2775. begin
  2776. case TVarData(v).vType of
  2777. varUnknown:
  2778. Result := Assigned(TVarData(v).vUnknown) and (IInterface(TVarData(v).vUnknown).QueryInterface(IID, Intf) = S_OK);
  2779. varUnknown or varByRef:
  2780. Result := Assigned(TVarData(v).vPointer) and Assigned(pointer(TVarData(v).vPointer^)) and (IInterface(TVarData(v).vPointer^).QueryInterface(IID, Intf) = S_OK);
  2781. varDispatch:
  2782. Result := Assigned(TVarData(v).vDispatch) and (IInterface(TVarData(v).vDispatch).QueryInterface(IID, Intf) = S_OK);
  2783. varDispatch or varByRef:
  2784. Result := Assigned(TVarData(v).vPointer) and Assigned(pointer(TVarData(v).vPointer^)) and (IInterface(TVarData(v).vPointer^).QueryInterface(IID, Intf) = S_OK);
  2785. varVariant, varVariant or varByRef:
  2786. Result := Assigned(TVarData(v).vPointer) and VarSupports(Variant(PVarData(TVarData(v).vPointer)^), IID, Intf);
  2787. else
  2788. Result := False;
  2789. end;
  2790. end;
  2791. function VarSupports(const V: Variant; const IID: TGUID): Boolean;
  2792. var
  2793. Dummy: IInterface;
  2794. begin
  2795. Result := VarSupports(V, IID, Dummy);
  2796. end;
  2797. { Variant copy support }
  2798. {$push}
  2799. {$warnings off}
  2800. procedure VarCopyNoInd(var Dest: Variant; const Source: Variant);
  2801. begin
  2802. NotSupported('VarCopyNoInd');
  2803. end;
  2804. {$pop}
  2805. {****************************************************************************
  2806. Variant array support procedures and functions
  2807. ****************************************************************************}
  2808. {$push}
  2809. {$r-}
  2810. function VarArrayCreate(const Bounds: array of SizeInt; aVarType: TVarType): Variant;
  2811. var
  2812. hp : PVarArrayBoundArray;
  2813. p : pvararray;
  2814. i,lengthb : SizeInt;
  2815. begin
  2816. if not(VarTypeIsValidArrayType(aVarType)) or odd(length(Bounds)) then
  2817. VarArrayCreateError;
  2818. lengthb:=length(Bounds) div 2;
  2819. try
  2820. GetMem(hp,lengthb*SizeOf(TVarArrayBound));
  2821. for i:=0 to lengthb-1 do
  2822. begin
  2823. hp^[i].LowBound:=Bounds[i*2];
  2824. hp^[i].ElementCount:=Bounds[i*2+1]-Bounds[i*2]+1;
  2825. end;
  2826. SysVarClear(Result);
  2827. p:=SafeArrayCreate(aVarType,lengthb,hp^);
  2828. if not(assigned(p)) then
  2829. VarArrayCreateError;
  2830. TVarData(Result).vType:=aVarType or varArray;
  2831. TVarData(Result).vArray:=p;
  2832. finally
  2833. FreeMem(hp);
  2834. end;
  2835. end;
  2836. {$pop}
  2837. function VarArrayCreate(const Bounds: PVarArrayBoundArray; Dims : SizeInt; aVarType: TVarType): Variant;
  2838. var
  2839. p : pvararray;
  2840. begin
  2841. if not(VarTypeIsValidArrayType(aVarType)) then
  2842. VarArrayCreateError;
  2843. SysVarClear(Result);
  2844. p:=SafeArrayCreate(aVarType,Dims,Bounds^);
  2845. if not(assigned(p)) then
  2846. VarArrayCreateError;
  2847. TVarData(Result).vType:=aVarType or varArray;
  2848. TVarData(Result).vArray:=p;
  2849. end;
  2850. function VarArrayOf(const Values: array of Variant): Variant;
  2851. var
  2852. i : SizeInt;
  2853. begin
  2854. Result:=VarArrayCreate([0,high(Values)],varVariant);
  2855. for i:=0 to high(Values) do
  2856. Result[i]:=Values[i];
  2857. end;
  2858. function VarArrayAsPSafeArray(const A: Variant): PVarArray;
  2859. var
  2860. v : TVarData;
  2861. begin
  2862. v:=TVarData(a);
  2863. while v.vType=varByRef or varVariant do
  2864. v:=TVarData(v.vPointer^);
  2865. if (v.vType and varArray)=varArray then
  2866. begin
  2867. if (v.vType and varByRef)<>0 then
  2868. Result:=pvararray(v.vPointer^)
  2869. else
  2870. Result:=v.vArray;
  2871. end
  2872. else
  2873. VarResultCheck(VAR_INVALIDARG);
  2874. end;
  2875. function VarArrayDimCount(const A: Variant) : LongInt;
  2876. var
  2877. hv : TVarData;
  2878. begin
  2879. hv:=TVarData(a);
  2880. { get final Variant }
  2881. while hv.vType=varByRef or varVariant do
  2882. hv:=TVarData(hv.vPointer^);
  2883. if (hv.vType and varArray)<>0 then
  2884. Result:=hv.vArray^.DimCount
  2885. else
  2886. Result:=0;
  2887. end;
  2888. function VarArrayLowBound(const A: Variant; Dim: LongInt) : LongInt;
  2889. begin
  2890. VarResultCheck(SafeArrayGetLBound(VarArrayAsPSafeArray(A),Dim,Result));
  2891. end;
  2892. function VarArrayHighBound(const A: Variant; Dim: LongInt) : LongInt;
  2893. begin
  2894. VarResultCheck(SafeArrayGetUBound(VarArrayAsPSafeArray(A),Dim,Result));
  2895. end;
  2896. function VarArrayLock(const A: Variant): Pointer;
  2897. begin
  2898. VarResultCheck(SafeArrayAccessData(VarArrayAsPSafeArray(A),Result));
  2899. end;
  2900. procedure VarArrayUnlock(const A: Variant);
  2901. begin
  2902. VarResultCheck(SafeArrayUnaccessData(VarArrayAsPSafeArray(A)));
  2903. end;
  2904. function VarArrayRef(const A: Variant): Variant;
  2905. begin
  2906. if (TVarData(a).vType and varArray)=0 then
  2907. VarInvalidArgError(TVarData(a).vType);
  2908. TVarData(Result).vType:=TVarData(a).vType or varByRef;
  2909. if (TVarData(a).vType and varByRef)=0 then
  2910. TVarData(Result).vPointer:=@TVarData(a).vArray
  2911. else
  2912. TVarData(Result).vPointer:=@TVarData(a).vPointer;
  2913. end;
  2914. function VarIsArray(const A: Variant; AResolveByRef: Boolean): Boolean;
  2915. var
  2916. v : TVarData;
  2917. begin
  2918. v:=TVarData(a);
  2919. if AResolveByRef then
  2920. while v.vType=varByRef or varVariant do
  2921. v:=TVarData(v.vPointer^);
  2922. Result:=(v.vType and varArray)=varArray;
  2923. end;
  2924. function VarIsArray(const A: Variant): Boolean;
  2925. begin
  2926. VarIsArray:=VarIsArray(A,true);
  2927. end;
  2928. function VarTypeIsValidArrayType(const aVarType: TVarType): Boolean;
  2929. begin
  2930. Result:=aVarType in [varSmallInt,varInteger,
  2931. {$ifndef FPUNONE}
  2932. varSingle,varDouble,varDate,
  2933. {$endif}
  2934. varCurrency,varOleStr,varDispatch,varError,varBoolean,
  2935. varVariant,varUnknown,varShortInt,varByte,varWord,varLongWord];
  2936. end;
  2937. function VarTypeIsValidElementType(const aVarType: TVarType): Boolean;
  2938. var
  2939. customvarianttype : TCustomVariantType;
  2940. begin
  2941. Result:=((aVarType and not(varByRef) and not(varArray)) in [varEmpty,varNull,varSmallInt,varInteger,
  2942. {$ifndef FPUNONE}
  2943. varSingle,varDouble,varDate,
  2944. {$endif}
  2945. varCurrency,varOleStr,varDispatch,varError,varBoolean,
  2946. varVariant,varUnknown,varShortInt,varByte,varWord,varLongWord,varInt64]) or
  2947. FindCustomVariantType(aVarType,customvarianttype);
  2948. end;
  2949. { ---------------------------------------------------------------------
  2950. Variant <-> Dynamic arrays support
  2951. ---------------------------------------------------------------------}
  2952. function DynArrayGetVariantInfo(p : Pointer; var Dims : sizeint) : sizeint;
  2953. begin
  2954. Result:=varNull;
  2955. { skip kind and name }
  2956. p:=aligntoptr(p+2+Length(PTypeInfo(p)^.Name));
  2957. { search recursive? }
  2958. if PTypeInfo(PTypeData(p)^.elType2)^.kind=tkDynArray then
  2959. Result:=DynArrayGetVariantInfo(PTypeData(p)^.elType2,Dims)
  2960. else
  2961. Result:=PTypeData(p)^.varType;
  2962. inc(Dims);
  2963. end;
  2964. {$push}
  2965. {$r-}
  2966. procedure DynArrayToVariant(var V: Variant; const DynArray: Pointer; TypeInfo: Pointer);
  2967. var
  2968. i,
  2969. Dims : sizeint;
  2970. vararrtype,
  2971. dynarrvartype : LongInt;
  2972. vararraybounds : PVarArrayBoundArray;
  2973. iter : TVariantArrayIterator;
  2974. dynarriter : tdynarrayiter;
  2975. p : Pointer;
  2976. temp : Variant;
  2977. dynarraybounds : tdynarraybounds;
  2978. type
  2979. TDynArray = array of Pointer;
  2980. begin
  2981. DoVarClear(TVarData(v));
  2982. Dims:=0;
  2983. dynarrvartype:=DynArrayGetVariantInfo(TypeInfo,Dims);
  2984. vararrtype:=dynarrvartype;
  2985. if (Dims>1) and not(DynamicArrayIsRectangular(DynArray,TypeInfo)) then
  2986. exit;
  2987. { retrieve Bounds array }
  2988. Setlength(dynarraybounds,Dims);
  2989. GetMem(vararraybounds,Dims*SizeOf(TVarArrayBound));
  2990. try
  2991. p:=DynArray;
  2992. for i:=0 to Dims-1 do
  2993. begin
  2994. vararraybounds^[i].LowBound:=0;
  2995. vararraybounds^[i].ElementCount:=length(TDynArray(p));
  2996. dynarraybounds[i]:=length(TDynArray(p));
  2997. if dynarraybounds[i]>0 then
  2998. { we checked that the array is rectangular }
  2999. p:=TDynArray(p)[0];
  3000. end;
  3001. { .. create Variant array }
  3002. V:=VarArrayCreate(vararraybounds,Dims,vararrtype);
  3003. VarArrayLock(V);
  3004. try
  3005. iter.init(Dims,PVarArrayBoundArray(vararraybounds));
  3006. dynarriter.init(DynArray,TypeInfo,Dims,dynarraybounds);
  3007. if not iter.AtEnd then
  3008. repeat
  3009. case vararrtype of
  3010. varSmallInt:
  3011. temp:=PSmallInt(dynarriter.data)^;
  3012. varInteger:
  3013. temp:=PInteger(dynarriter.data)^;
  3014. {$ifndef FPUNONE}
  3015. varSingle:
  3016. temp:=PSingle(dynarriter.data)^;
  3017. varDouble:
  3018. temp:=PDouble(dynarriter.data)^;
  3019. varDate:
  3020. temp:=PDouble(dynarriter.data)^;
  3021. {$endif}
  3022. varCurrency:
  3023. temp:=PCurrency(dynarriter.data)^;
  3024. varOleStr:
  3025. temp:=PWideString(dynarriter.data)^;
  3026. varDispatch:
  3027. temp:=PDispatch(dynarriter.data)^;
  3028. varError:
  3029. temp:=PError(dynarriter.data)^;
  3030. varBoolean:
  3031. temp:=PBoolean(dynarriter.data)^;
  3032. varVariant:
  3033. temp:=PVariant(dynarriter.data)^;
  3034. varUnknown:
  3035. temp:=PUnknown(dynarriter.data)^;
  3036. varShortInt:
  3037. temp:=PShortInt(dynarriter.data)^;
  3038. varByte:
  3039. temp:=PByte(dynarriter.data)^;
  3040. varWord:
  3041. temp:=PWord(dynarriter.data)^;
  3042. varLongWord:
  3043. temp:=PLongWord(dynarriter.data)^;
  3044. varInt64:
  3045. temp:=PInt64(dynarriter.data)^;
  3046. varQWord:
  3047. temp:=PQWord(dynarriter.data)^;
  3048. else
  3049. VarClear(temp);
  3050. end;
  3051. dynarriter.next;
  3052. VarArrayPut(V,temp,Slice(iter.Coords^,Dims));
  3053. until not(iter.next);
  3054. finally
  3055. iter.done;
  3056. dynarriter.done;
  3057. VarArrayUnlock(V);
  3058. end;
  3059. finally
  3060. FreeMem(vararraybounds);
  3061. end;
  3062. end;
  3063. procedure DynArrayFromVariant(var DynArray: Pointer; const V: Variant; TypeInfo: Pointer);
  3064. var
  3065. DynArrayDims,
  3066. VarArrayDims : SizeInt;
  3067. iter : TVariantArrayIterator;
  3068. dynarriter : tdynarrayiter;
  3069. temp : Variant;
  3070. dynarrvartype : LongInt;
  3071. vararraybounds : PVarArrayBoundArray;
  3072. dynarraybounds : tdynarraybounds;
  3073. i : SizeInt;
  3074. type
  3075. TDynArray = array of Pointer;
  3076. begin
  3077. VarArrayDims:=VarArrayDimCount(V);
  3078. DynArrayDims:=0;
  3079. dynarrvartype:=DynArrayGetVariantInfo(TypeInfo,DynArrayDims);
  3080. if (VarArrayDims=0) or (VarArrayDims<>DynArrayDims) then
  3081. VarResultCheck(VAR_INVALIDARG);
  3082. { retrieve Bounds array }
  3083. Setlength(dynarraybounds,VarArrayDims);
  3084. GetMem(vararraybounds,VarArrayDims*SizeOf(TVarArrayBound));
  3085. try
  3086. for i:=0 to VarArrayDims-1 do
  3087. begin
  3088. vararraybounds^[i].LowBound:=VarArrayLowBound(V,i+1);
  3089. vararraybounds^[i].ElementCount:=VarArrayHighBound(V,i+1)-vararraybounds^[i].LowBound+1;
  3090. dynarraybounds[i]:=vararraybounds^[i].ElementCount;
  3091. end;
  3092. DynArraySetLength(DynArray,TypeInfo,VarArrayDims,PSizeInt(dynarraybounds));
  3093. VarArrayLock(V);
  3094. try
  3095. iter.init(VarArrayDims,PVarArrayBoundArray(vararraybounds));
  3096. dynarriter.init(DynArray,TypeInfo,VarArrayDims,dynarraybounds);
  3097. if not iter.AtEnd then
  3098. repeat
  3099. temp:=VarArrayGet(V,Slice(iter.Coords^,VarArrayDims));
  3100. case dynarrvartype of
  3101. varSmallInt:
  3102. PSmallInt(dynarriter.data)^:=temp;
  3103. varInteger:
  3104. PInteger(dynarriter.data)^:=temp;
  3105. {$ifndef FPUNONE}
  3106. varSingle:
  3107. PSingle(dynarriter.data)^:=temp;
  3108. varDouble:
  3109. PDouble(dynarriter.data)^:=temp;
  3110. varDate:
  3111. PDouble(dynarriter.data)^:=temp;
  3112. {$endif}
  3113. varCurrency:
  3114. PCurrency(dynarriter.data)^:=temp;
  3115. varOleStr:
  3116. PWideString(dynarriter.data)^:=temp;
  3117. varDispatch:
  3118. PDispatch(dynarriter.data)^:=temp;
  3119. varError:
  3120. PError(dynarriter.data)^:=temp;
  3121. varBoolean:
  3122. PBoolean(dynarriter.data)^:=temp;
  3123. varVariant:
  3124. PVariant(dynarriter.data)^:=temp;
  3125. varUnknown:
  3126. PUnknown(dynarriter.data)^:=temp;
  3127. varShortInt:
  3128. PShortInt(dynarriter.data)^:=temp;
  3129. varByte:
  3130. PByte(dynarriter.data)^:=temp;
  3131. varWord:
  3132. PWord(dynarriter.data)^:=temp;
  3133. varLongWord:
  3134. PLongWord(dynarriter.data)^:=temp;
  3135. varInt64:
  3136. PInt64(dynarriter.data)^:=temp;
  3137. varQWord:
  3138. PQWord(dynarriter.data)^:=temp;
  3139. else
  3140. VarCastError;
  3141. end;
  3142. dynarriter.next;
  3143. until not(iter.next);
  3144. finally
  3145. iter.done;
  3146. dynarriter.done;
  3147. VarArrayUnlock(V);
  3148. end;
  3149. finally
  3150. FreeMem(vararraybounds);
  3151. end;
  3152. end;
  3153. {$pop}//{$r-} for DynArray[From|To]Variant
  3154. function FindCustomVariantType(const aVarType: TVarType; out CustomVariantType: TCustomVariantType): Boolean; overload;
  3155. begin
  3156. Result:=(aVarType>=CMinVarType);
  3157. if Result then
  3158. begin
  3159. EnterCriticalSection(customvarianttypelock);
  3160. try
  3161. Result:=(aVarType-CMinVarType)<=high(customvarianttypes);
  3162. if Result then
  3163. begin
  3164. CustomVariantType:=customvarianttypes[aVarType-CMinVarType];
  3165. Result:=assigned(CustomVariantType) and
  3166. (CustomVariantType<>InvalidCustomVariantType);
  3167. end;
  3168. finally
  3169. LeaveCriticalSection(customvarianttypelock);
  3170. end;
  3171. end;
  3172. end;
  3173. function FindCustomVariantType(const TypeName: string; out CustomVariantType: TCustomVariantType): Boolean; overload;
  3174. var
  3175. i: Integer;
  3176. tmp: TCustomVariantType;
  3177. ShortTypeName: shortstring;
  3178. begin
  3179. ShortTypeName:=TypeName; // avoid conversion in the loop
  3180. result:=False;
  3181. EnterCriticalSection(customvarianttypelock);
  3182. try
  3183. for i:=low(customvarianttypes) to high(customvarianttypes) do
  3184. begin
  3185. tmp:=customvarianttypes[i];
  3186. result:=Assigned(tmp) and (tmp<>InvalidCustomVariantType) and
  3187. tmp.ClassNameIs(ShortTypeName);
  3188. if result then
  3189. begin
  3190. CustomVariantType:=tmp;
  3191. Exit;
  3192. end;
  3193. end;
  3194. finally
  3195. LeaveCriticalSection(customvarianttypelock);
  3196. end;
  3197. end;
  3198. function Unassigned: Variant; // Unassigned standard constant
  3199. begin
  3200. SysVarClear(Result);
  3201. TVarData(Result).vType := varEmpty;
  3202. end;
  3203. function Null: Variant; // Null standard constant
  3204. begin
  3205. SysVarClear(Result);
  3206. TVarData(Result).vType := varNull;
  3207. end;
  3208. procedure VarDispInvokeError;
  3209. begin
  3210. raise EVariantDispatchError.Create(SDispatchError);
  3211. end;
  3212. { ---------------------------------------------------------------------
  3213. TCustomVariantType Class.
  3214. ---------------------------------------------------------------------}
  3215. { All TCustomVariantType descendants are singletons, they ignore automatic refcounting. }
  3216. function TCustomVariantType.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  3217. begin
  3218. if GetInterface(IID, obj) then
  3219. result := S_OK
  3220. else
  3221. result := E_NOINTERFACE;
  3222. end;
  3223. function TCustomVariantType._AddRef: Longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  3224. begin
  3225. result := -1;
  3226. end;
  3227. function TCustomVariantType._Release: Longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  3228. begin
  3229. result := -1;
  3230. end;
  3231. {$warnings off}
  3232. procedure TCustomVariantType.SimplisticClear(var V: TVarData);
  3233. begin
  3234. VarDataInit(V);
  3235. end;
  3236. procedure TCustomVariantType.SimplisticCopy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean = False);
  3237. begin
  3238. NotSupported('TCustomVariantType.SimplisticCopy');
  3239. end;
  3240. procedure TCustomVariantType.RaiseInvalidOp;
  3241. begin
  3242. VarInvalidOp;
  3243. end;
  3244. procedure TCustomVariantType.RaiseCastError;
  3245. begin
  3246. VarCastError;
  3247. end;
  3248. procedure TCustomVariantType.RaiseDispError;
  3249. begin
  3250. VarDispInvokeError;
  3251. end;
  3252. function TCustomVariantType.LeftPromotion(const V: TVarData; const Operation: TVarOp; out RequiredVarType: TVarType): Boolean;
  3253. begin
  3254. NotSupported('TCustomVariantType.LeftPromotion');
  3255. end;
  3256. function TCustomVariantType.RightPromotion(const V: TVarData; const Operation: TVarOp; out RequiredVarType: TVarType): Boolean;
  3257. begin
  3258. NotSupported('TCustomVariantType.RightPromotion');
  3259. end;
  3260. function TCustomVariantType.OlePromotion(const V: TVarData; out RequiredVarType: TVarType): Boolean;
  3261. begin
  3262. NotSupported('TCustomVariantType.OlePromotion');
  3263. end;
  3264. procedure TCustomVariantType.DispInvoke(Dest: PVarData; var Source: TVarData; CallDesc: PCallDesc; Params: Pointer);
  3265. begin
  3266. RaiseDispError;
  3267. end;
  3268. procedure TCustomVariantType.VarDataInit(var Dest: TVarData);
  3269. begin
  3270. FillChar(Dest,SizeOf(Dest),0);
  3271. end;
  3272. procedure TCustomVariantType.VarDataClear(var Dest: TVarData);
  3273. begin
  3274. VarClearProc(Dest);
  3275. end;
  3276. procedure TCustomVariantType.VarDataCopy(var Dest: TVarData; const Source: TVarData);
  3277. begin
  3278. DoVarCopy(Dest,Source)
  3279. end;
  3280. procedure TCustomVariantType.VarDataCopyNoInd(var Dest: TVarData; const Source: TVarData);
  3281. begin
  3282. // This is probably not correct, but there is no DoVarCopyInd
  3283. DoVarCopy(Dest,Source);
  3284. end;
  3285. procedure TCustomVariantType.VarDataCast(var Dest: TVarData; const Source: TVarData);
  3286. begin
  3287. DoVarCast(Dest, Source, VarType);
  3288. end;
  3289. procedure TCustomVariantType.VarDataCastTo(var Dest: TVarData; const Source: TVarData; const aVarType: TVarType);
  3290. begin
  3291. DoVarCast(Dest, Source, AVarType);
  3292. end;
  3293. procedure TCustomVariantType.VarDataCastTo(var Dest: TVarData; const aVarType: TVarType);
  3294. begin
  3295. DoVarCast(Dest,Dest,AVarType);
  3296. end;
  3297. procedure TCustomVariantType.VarDataCastToOleStr(var Dest: TVarData);
  3298. begin
  3299. VarDataCastTo(Dest, Dest, varOleStr);
  3300. end;
  3301. procedure TCustomVariantType.VarDataFromStr(var V: TVarData; const Value: string);
  3302. begin
  3303. sysvarfromlstr(Variant(V),Value);
  3304. end;
  3305. procedure TCustomVariantType.VarDataFromOleStr(var V: TVarData; const Value: WideString);
  3306. begin
  3307. sysvarfromwstr(variant(V),Value);
  3308. end;
  3309. function TCustomVariantType.VarDataToStr(const V: TVarData): string;
  3310. begin
  3311. sysvartolstr(Result,Variant(V));
  3312. end;
  3313. function TCustomVariantType.VarDataIsEmptyParam(const V: TVarData): Boolean;
  3314. begin
  3315. Result:=VarIsEmptyParam(Variant(V));
  3316. end;
  3317. function TCustomVariantType.VarDataIsByRef(const V: TVarData): Boolean;
  3318. begin
  3319. Result:=(V.vType and varByRef)=varByRef;
  3320. end;
  3321. function TCustomVariantType.VarDataIsArray(const V: TVarData): Boolean;
  3322. begin
  3323. Result:=(V.vType and varArray)=varArray;
  3324. end;
  3325. function TCustomVariantType.VarDataIsOrdinal(const V: TVarData): Boolean;
  3326. begin
  3327. Result:=(V.vType and varTypeMask) in OrdinalVarTypes;
  3328. end;
  3329. function TCustomVariantType.VarDataIsFloat(const V: TVarData): Boolean;
  3330. begin
  3331. Result:=(V.vType and varTypeMask) in FloatVarTypes;
  3332. end;
  3333. function TCustomVariantType.VarDataIsNumeric(const V: TVarData): Boolean;
  3334. begin
  3335. Result:=(V.vType and varTypeMask) in (OrdinalVarTypes + FloatVarTypes);
  3336. end;
  3337. function TCustomVariantType.VarDataIsStr(const V: TVarData): Boolean;
  3338. begin
  3339. Result:=
  3340. ((V.vType and varTypeMask) = varOleStr) or
  3341. ((V.vType and varTypeMask) = varString);
  3342. end;
  3343. procedure RegisterCustomVariantType(obj: TCustomVariantType; RequestedVarType: TVarType;
  3344. UseFirstAvailable: Boolean);
  3345. var
  3346. index,L: Integer;
  3347. begin
  3348. EnterCriticalSection(customvarianttypelock);
  3349. try
  3350. L:=Length(customvarianttypes);
  3351. if UseFirstAvailable then
  3352. begin
  3353. repeat
  3354. inc(customvariantcurrtype);
  3355. if customvariantcurrtype>=CMaxVarType then
  3356. raise EVariantError.Create(SVarTypeTooManyCustom);
  3357. until ((customvariantcurrtype-CMinVarType)>=L) or
  3358. (customvarianttypes[customvariantcurrtype-CMinVarType]=nil);
  3359. RequestedVarType:=customvariantcurrtype;
  3360. end
  3361. else if (RequestedVarType<CFirstUserType) or (RequestedVarType>CMaxVarType) then
  3362. raise EVariantError.CreateFmt(SVarTypeOutOfRangeWithPrefix, ['$', RequestedVarType]);
  3363. index:=RequestedVarType-CMinVarType;
  3364. if index>=L then
  3365. SetLength(customvarianttypes,L+1);
  3366. if Assigned(customvarianttypes[index]) then
  3367. begin
  3368. if customvarianttypes[index]=InvalidCustomVariantType then
  3369. raise EVariantError.CreateFmt(SVarTypeNotUsableWithPrefix, ['$', RequestedVarType])
  3370. else
  3371. raise EVariantError.CreateFmt(SVarTypeAlreadyUsedWithPrefix,
  3372. ['$', RequestedVarType, customvarianttypes[index].ClassName]);
  3373. end;
  3374. customvarianttypes[index]:=obj;
  3375. obj.FVarType:=RequestedVarType;
  3376. finally
  3377. LeaveCriticalSection(customvarianttypelock);
  3378. end;
  3379. end;
  3380. constructor TCustomVariantType.Create;
  3381. begin
  3382. RegisterCustomVariantType(Self,0,True);
  3383. end;
  3384. constructor TCustomVariantType.Create(RequestedVarType: TVarType);
  3385. begin
  3386. RegisterCustomVariantType(Self,RequestedVarType,False);
  3387. end;
  3388. destructor TCustomVariantType.Destroy;
  3389. begin
  3390. EnterCriticalSection(customvarianttypelock);
  3391. try
  3392. if FVarType<>0 then
  3393. customvarianttypes[FVarType-CMinVarType]:=InvalidCustomVariantType;
  3394. finally
  3395. LeaveCriticalSection(customvarianttypelock);
  3396. end;
  3397. inherited Destroy;
  3398. end;
  3399. function TCustomVariantType.IsClear(const V: TVarData): Boolean;
  3400. begin
  3401. result:=False;
  3402. end;
  3403. procedure TCustomVariantType.Cast(var Dest: TVarData; const Source: TVarData);
  3404. begin
  3405. DoVarCast(Dest,Source,VarType);
  3406. end;
  3407. procedure TCustomVariantType.CastTo(var Dest: TVarData; const Source: TVarData; const aVarType: TVarType);
  3408. begin
  3409. DoVarCast(Dest,Source,AVarType);
  3410. end;
  3411. procedure TCustomVariantType.CastToOle(var Dest: TVarData; const Source: TVarData);
  3412. begin
  3413. NotSupported('TCustomVariantType.CastToOle');
  3414. end;
  3415. procedure TCustomVariantType.BinaryOp(var Left: TVarData; const Right: TVarData; const Operation: TVarOp);
  3416. begin
  3417. RaiseInvalidOp;
  3418. end;
  3419. procedure TCustomVariantType.UnaryOp(var Right: TVarData; const Operation: TVarOp);
  3420. begin
  3421. RaiseInvalidOp;
  3422. end;
  3423. function TCustomVariantType.CompareOp(const Left, Right: TVarData; const Operation: TVarOp): Boolean;
  3424. begin
  3425. NotSupported('TCustomVariantType.CompareOp');
  3426. end;
  3427. procedure TCustomVariantType.Compare(const Left, Right: TVarData; var Relationship: TVarCompareResult);
  3428. begin
  3429. NotSupported('TCustomVariantType.Compare');
  3430. end;
  3431. {$warnings on}
  3432. { ---------------------------------------------------------------------
  3433. TInvokeableVariantType implementation
  3434. ---------------------------------------------------------------------}
  3435. procedure TInvokeableVariantType.DispInvoke(Dest: PVarData; var Source: TVarData;
  3436. CallDesc: PCallDesc; Params: Pointer);
  3437. var
  3438. method_name: ansistring;
  3439. arg_count: byte;
  3440. args: TVarDataArray;
  3441. arg_idx: byte;
  3442. arg_type: byte;
  3443. arg_byref, has_result: boolean;
  3444. arg_ptr: pointer;
  3445. arg_data: PVarData;
  3446. dummy_data: TVarData;
  3447. arg_advanced: boolean;
  3448. const
  3449. argtype_mask = $7F;
  3450. argref_mask = $80;
  3451. begin
  3452. arg_count := CallDesc^.ArgCount;
  3453. method_name := ansistring(pchar(@CallDesc^.ArgTypes[arg_count]));
  3454. setLength(args, arg_count);
  3455. if arg_count > 0 then
  3456. begin
  3457. arg_ptr := Params;
  3458. for arg_idx := 0 to arg_count - 1 do
  3459. begin
  3460. arg_type := CallDesc^.ArgTypes[arg_idx] and argtype_mask;
  3461. arg_byref := (CallDesc^.ArgTypes[arg_idx] and argref_mask) <> 0;
  3462. arg_data := @args[arg_count - arg_idx - 1];
  3463. case arg_type of
  3464. varUStrArg: arg_data^.vType := varUString;
  3465. varStrArg: arg_data^.vType := varString;
  3466. else
  3467. arg_data^.vType := arg_type
  3468. end;
  3469. if arg_byref then
  3470. begin
  3471. arg_data^.vType := arg_data^.vType or varByRef;
  3472. arg_data^.vPointer := PPointer(arg_ptr)^;
  3473. Inc(arg_ptr,sizeof(Pointer));
  3474. end
  3475. else
  3476. begin
  3477. arg_advanced:=false;
  3478. case arg_type of
  3479. varError:
  3480. begin
  3481. arg_data^.vError:=VAR_PARAMNOTFOUND;
  3482. arg_advanced := true;
  3483. end;
  3484. varVariant:
  3485. arg_data^ := PVarData(PPointer(arg_ptr)^)^;
  3486. varDouble, varCurrency, varDate, varInt64, varQWord:
  3487. begin
  3488. arg_data^.vQWord := PQWord(arg_ptr)^; // 64bit on all platforms
  3489. inc(arg_ptr,sizeof(QWord));
  3490. arg_advanced := true;
  3491. end;
  3492. { values potentially smaller than sizeof(pointer) must be handled
  3493. explicitly to guarantee endian safety and to prevent copying/
  3494. skipping data (they are always copied into a 4 byte element
  3495. by the compiler, although it will still skip sizeof(pointer)
  3496. bytes afterwards) }
  3497. varSingle:
  3498. arg_data^.vSingle := PSingle(arg_ptr)^;
  3499. varSmallint:
  3500. arg_data^.vSmallInt := PLongint(arg_ptr)^;
  3501. varInteger:
  3502. arg_data^.vInteger := PLongint(arg_ptr)^;
  3503. varBoolean:
  3504. arg_data^.vBoolean := WordBool(PLongint(arg_ptr)^);
  3505. varShortInt:
  3506. arg_data^.vShortInt := PLongint(arg_ptr)^;
  3507. varByte:
  3508. arg_data^.vByte := PLongint(arg_ptr)^;
  3509. varWord:
  3510. arg_data^.vWord := PLongint(arg_ptr)^;
  3511. else
  3512. arg_data^.vAny := PPointer(arg_ptr)^; // 32 or 64bit
  3513. end;
  3514. if not arg_advanced then
  3515. inc(arg_ptr,sizeof(pointer));
  3516. end;
  3517. end;
  3518. end;
  3519. has_result := (Dest <> nil);
  3520. if has_result then
  3521. variant(Dest^) := Unassigned;
  3522. case CallDesc^.CallType of
  3523. 1: { DISPATCH_METHOD }
  3524. if has_result then
  3525. begin
  3526. if arg_count = 0 then
  3527. begin
  3528. // no args -- try GetProperty first, then DoFunction
  3529. if not (GetProperty(Dest^,Source,method_name) or
  3530. DoFunction(Dest^,Source,method_name,args)) then
  3531. RaiseDispError
  3532. end
  3533. else
  3534. if not DoFunction(Dest^,Source,method_name,args) then
  3535. RaiseDispError;
  3536. end
  3537. else
  3538. begin
  3539. // may be procedure?
  3540. if not DoProcedure(Source,method_name,args) then
  3541. // may be function?
  3542. try
  3543. variant(dummy_data) := Unassigned;
  3544. if not DoFunction(dummy_data,Source,method_name,args) then
  3545. RaiseDispError;
  3546. finally
  3547. VarDataClear(dummy_data)
  3548. end;
  3549. end;
  3550. 2: { DISPATCH_PROPERTYGET -- currently never generated by compiler for Variant Dispatch }
  3551. if has_result then
  3552. begin
  3553. // must be property...
  3554. if not GetProperty(Dest^,Source,method_name) then
  3555. // may be function?
  3556. if not DoFunction(Dest^,Source,method_name,args) then
  3557. RaiseDispError
  3558. end
  3559. else
  3560. RaiseDispError;
  3561. 4: { DISPATCH_PROPERTYPUT }
  3562. if has_result or (arg_count<>1) or // must be no result and a single arg
  3563. (not SetProperty(Source,method_name,args[0])) then
  3564. RaiseDispError;
  3565. else
  3566. RaiseDispError;
  3567. end;
  3568. end;
  3569. function TInvokeableVariantType.DoFunction(var Dest: TVarData; const V: TVarData; const Name: string; const Arguments: TVarDataArray): Boolean;
  3570. begin
  3571. result := False;
  3572. end;
  3573. function TInvokeableVariantType.DoProcedure(const V: TVarData; const Name: string; const Arguments: TVarDataArray): Boolean;
  3574. begin
  3575. result := False
  3576. end;
  3577. function TInvokeableVariantType.GetProperty(var Dest: TVarData; const V: TVarData; const Name: string): Boolean;
  3578. begin
  3579. result := False;
  3580. end;
  3581. function TInvokeableVariantType.SetProperty(var V: TVarData; const Name: string; const Value: TVarData): Boolean;
  3582. begin
  3583. result := False;
  3584. end;
  3585. { ---------------------------------------------------------------------
  3586. TPublishableVariantType implementation
  3587. ---------------------------------------------------------------------}
  3588. function TPublishableVariantType.GetProperty(var Dest: TVarData; const V: TVarData; const Name: string): Boolean;
  3589. begin
  3590. Result:=true;
  3591. Variant(Dest):=TypInfo.GetPropValue(getinstance(v),name);
  3592. end;
  3593. function TPublishableVariantType.SetProperty(var V: TVarData; const Name: string; const Value: TVarData): Boolean;
  3594. begin
  3595. Result:=true;
  3596. TypInfo.SetPropValue(getinstance(v),name,Variant(value));
  3597. end;
  3598. procedure VarCastError;
  3599. begin
  3600. raise EVariantTypeCastError.Create(SInvalidVarCast);
  3601. end;
  3602. procedure VarCastError(const ASourceType, ADestType: TVarType);
  3603. begin
  3604. raise EVariantTypeCastError.CreateFmt(SVarTypeCouldNotConvert,
  3605. [VarTypeAsText(ASourceType),VarTypeAsText(ADestType)]);
  3606. end;
  3607. procedure VarCastErrorOle(const ASourceType: TVarType);
  3608. begin
  3609. raise EVariantTypeCastError.CreateFmt(SVarTypeCouldNotConvert,
  3610. [VarTypeAsText(ASourceType),'(OleVariant)']);
  3611. end;
  3612. procedure VarInvalidOp;
  3613. begin
  3614. raise EVariantInvalidOpError.Create(SInvalidVarOp);
  3615. end;
  3616. procedure VarInvalidOp(const aLeft, aRight: TVarType; aOpCode: TVarOp);
  3617. begin
  3618. raise EVariantInvalidOpError.CreateFmt(SInvalidBinaryVarOp,
  3619. [VarTypeAsText(aLeft),VarOpAsText[aOpCode],VarTypeAsText(aRight)]);
  3620. end;
  3621. procedure VarInvalidOp(const aRight: TVarType; aOpCode: TVarOp);
  3622. begin
  3623. raise EVariantInvalidOpError.CreateFmt(SInvalidUnaryVarOp,
  3624. [VarOpAsText[aOpCode],VarTypeAsText(aRight)]);
  3625. end;
  3626. procedure VarInvalidNullOp;
  3627. begin
  3628. raise EVariantInvalidOpError.Create(SInvalidvarNullOp);
  3629. end;
  3630. procedure VarParamNotFoundError;
  3631. begin
  3632. raise EVariantParamNotFoundError.Create(SVarParamNotFound);
  3633. end;
  3634. procedure VarBadTypeError;
  3635. begin
  3636. raise EVariantBadVarTypeError.Create(SVarBadType);
  3637. end;
  3638. procedure VarOverflowError;
  3639. begin
  3640. raise EVariantOverflowError.Create(SVarOverflow);
  3641. end;
  3642. procedure VarOverflowError(const ASourceType, ADestType: TVarType);
  3643. begin
  3644. raise EVariantOverflowError.CreateFmt(SVarTypeConvertOverflow,
  3645. [VarTypeAsText(ASourceType),VarTypeAsText(ADestType)]);
  3646. end;
  3647. procedure VarRangeCheckError(const AType: TVarType);
  3648. begin
  3649. raise EVariantOverflowError.CreateFmt(SVarTypeRangeCheck1,
  3650. [VarTypeAsText(AType)])
  3651. end;
  3652. procedure VarRangeCheckError(const ASourceType, ADestType: TVarType);
  3653. begin
  3654. if ASourceType<>ADestType then
  3655. raise EVariantOverflowError.CreateFmt(SVarTypeRangeCheck2,
  3656. [VarTypeAsText(ASourceType),VarTypeAsText(ADestType)])
  3657. else
  3658. VarRangeCheckError(ASourceType);
  3659. end;
  3660. procedure VarBadIndexError;
  3661. begin
  3662. raise EVariantBadIndexError.Create(SVarArrayBounds);
  3663. end;
  3664. procedure VarArrayLockedError;
  3665. begin
  3666. raise EVariantArrayLockedError.Create(SVarArrayLocked);
  3667. end;
  3668. procedure VarNotImplError;
  3669. begin
  3670. raise EVariantNotImplError.Create(SVarNotImplemented);
  3671. end;
  3672. procedure VarOutOfMemoryError;
  3673. begin
  3674. raise EVariantOutOfMemoryError.Create(SOutOfMemory);
  3675. end;
  3676. procedure VarInvalidArgError;
  3677. begin
  3678. raise EVariantInvalidArgError.Create(SVarInvalid);
  3679. end;
  3680. procedure VarInvalidArgError(AType: TVarType);
  3681. begin
  3682. raise EVariantInvalidArgError.CreateFmt(SVarInvalid1,
  3683. [VarTypeAsText(AType)])
  3684. end;
  3685. procedure VarUnexpectedError;
  3686. begin
  3687. raise EVariantUnexpectedError.Create(SVarUnexpected);
  3688. end;
  3689. procedure VarArrayCreateError;
  3690. begin
  3691. raise EVariantArrayCreateError.Create(SVarArrayCreate);
  3692. end;
  3693. procedure RaiseVarException(res : HRESULT);
  3694. begin
  3695. case res of
  3696. VAR_PARAMNOTFOUND:
  3697. VarParamNotFoundError;
  3698. VAR_TYPEMISMATCH:
  3699. VarCastError;
  3700. VAR_BADVARTYPE:
  3701. VarBadTypeError;
  3702. VAR_EXCEPTION:
  3703. VarInvalidOp;
  3704. VAR_OVERFLOW:
  3705. VarOverflowError;
  3706. VAR_BADINDEX:
  3707. VarBadIndexError;
  3708. VAR_ARRAYISLOCKED:
  3709. VarArrayLockedError;
  3710. VAR_NOTIMPL:
  3711. VarNotImplError;
  3712. VAR_OUTOFMEMORY:
  3713. VarOutOfMemoryError;
  3714. VAR_INVALIDARG:
  3715. VarInvalidArgError;
  3716. VAR_UNEXPECTED:
  3717. VarUnexpectedError;
  3718. else
  3719. raise EVariantError.CreateFmt(SInvalidVarOpWithHResultWithPrefix,
  3720. ['$',res,'']);
  3721. end;
  3722. end;
  3723. procedure VarResultCheck(AResult: HRESULT);{$IFDEF VARIANTINLINE}inline;{$ENDIF VARIANTINLINE}
  3724. begin
  3725. if AResult<>VAR_OK then
  3726. RaiseVarException(AResult);
  3727. end;
  3728. procedure VarResultCheck(AResult: HRESULT; ASourceType, ADestType: TVarType);
  3729. begin
  3730. case AResult of
  3731. VAR_OK:
  3732. ;
  3733. VAR_OVERFLOW:
  3734. VarOverflowError(ASourceType,ADestType);
  3735. VAR_TYPEMISMATCH:
  3736. VarCastError(ASourceType,ADestType);
  3737. else
  3738. RaiseVarException(AResult);
  3739. end;
  3740. end;
  3741. procedure HandleConversionException(const ASourceType, ADestType: TVarType);
  3742. begin
  3743. if exceptobject is econverterror then
  3744. VarCastError(asourcetype,adesttype)
  3745. else if (exceptobject is eoverflow) or
  3746. (exceptobject is erangeerror) then
  3747. varoverflowerror(asourcetype,adesttype)
  3748. else
  3749. raise exception(acquireexceptionobject);
  3750. end;
  3751. function VarTypeAsText(const AType: TVarType): string;
  3752. var
  3753. customvarianttype : TCustomVariantType;
  3754. const
  3755. names : array[varEmpty..varQWord] of string[8] = (
  3756. 'Empty','Null','Smallint','Integer','Single','Double','Currency','Date','OleStr','Dispatch','Error','Boolean','Variant',
  3757. 'Unknown','Decimal','???','ShortInt','Byte','Word','DWord','Int64','QWord');
  3758. begin
  3759. if ((AType and varTypeMask)>=low(names)) and ((AType and varTypeMask)<=high(names)) then
  3760. Result:=names[AType and varTypeMask]
  3761. else
  3762. case AType and varTypeMask of
  3763. varString:
  3764. Result:='String';
  3765. varAny:
  3766. Result:='Any';
  3767. else
  3768. begin
  3769. if FindCustomVariantType(AType and varTypeMask,customvarianttype) then
  3770. Result:=customvarianttype.classname
  3771. else
  3772. Result:='$'+IntToHex(AType and varTypeMask,4)
  3773. end;
  3774. end;
  3775. if (AType and vararray)<>0 then
  3776. Result:='Array of '+Result;
  3777. if (AType and varByRef)<>0 then
  3778. Result:='Ref to '+Result;
  3779. end;
  3780. function FindVarData(const V: Variant): PVarData;
  3781. begin
  3782. Result:=PVarData(@V);
  3783. while Result^.vType=varVariant or varByRef do
  3784. Result:=PVarData(Result^.vPointer);
  3785. end;
  3786. { ---------------------------------------------------------------------
  3787. Variant properties from typinfo
  3788. ---------------------------------------------------------------------}
  3789. function GetVariantProp(Instance : TObject;PropInfo : PPropInfo) : Variant;
  3790. type
  3791. TGetVariantProc = function:Variant of object;
  3792. TGetVariantProcIndex = function(Index: integer): Variant of object;
  3793. var
  3794. AMethod : TMethod;
  3795. begin
  3796. Result:=Null;
  3797. case PropInfo^.PropProcs and 3 of
  3798. ptField:
  3799. Result:=PVariant(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  3800. ptStatic,
  3801. ptVirtual:
  3802. begin
  3803. if (PropInfo^.PropProcs and 3)=ptStatic then
  3804. AMethod.Code:=PropInfo^.GetProc
  3805. else
  3806. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  3807. AMethod.Data:=Instance;
  3808. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  3809. Result:=TGetVariantProc(AMethod)()
  3810. else
  3811. Result:=TGetVariantProcIndex(AMethod)(PropInfo^.Index);
  3812. end;
  3813. end;
  3814. end;
  3815. Procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo; const Value : Variant);
  3816. type
  3817. TSetVariantProc = procedure(const AValue: Variant) of object;
  3818. TSetVariantProcIndex = procedure(Index: integer; AValue: Variant) of object;
  3819. Var
  3820. AMethod : TMethod;
  3821. begin
  3822. case (PropInfo^.PropProcs shr 2) and 3 of
  3823. ptfield:
  3824. PVariant(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  3825. ptVirtual,ptStatic:
  3826. begin
  3827. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  3828. AMethod.Code:=PropInfo^.SetProc
  3829. else
  3830. AMethod.Code:=PCodePointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  3831. AMethod.Data:=Instance;
  3832. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  3833. TSetVariantProc(AMethod)(Value)
  3834. else
  3835. TSetVariantProcIndex(AMethod)(PropInfo^.Index,Value);
  3836. end;
  3837. end;
  3838. end;
  3839. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  3840. begin
  3841. Result:=GetVariantProp(Instance,FindPropInfo(Instance,PropName));
  3842. end;
  3843. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  3844. begin
  3845. SetVariantprop(instance,FindpropInfo(Instance,PropName),Value);
  3846. end;
  3847. { ---------------------------------------------------------------------
  3848. All properties through Variant.
  3849. ---------------------------------------------------------------------}
  3850. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  3851. begin
  3852. Result:=TypInfo.GetPropValue(Instance,PropName,True);
  3853. end;
  3854. Function GetPropValue(Instance: TObject; PropInfo: PPropInfo; PreferStrings: Boolean): Variant;
  3855. begin
  3856. Result := Null; //at worst
  3857. // call the Right GetxxxProp
  3858. case PropInfo^.PropType^.Kind of
  3859. tkInteger, tkChar, tkWChar, tkClass, tkBool:
  3860. Result := GetOrdProp(Instance, PropInfo);
  3861. tkEnumeration:
  3862. if PreferStrings then
  3863. Result := GetEnumProp(Instance, PropInfo)
  3864. else
  3865. Result := GetOrdProp(Instance, PropInfo);
  3866. tkSet:
  3867. if PreferStrings then
  3868. Result := GetSetProp(Instance, PropInfo, False)
  3869. else
  3870. Result := GetOrdProp(Instance, PropInfo);
  3871. {$ifndef FPUNONE}
  3872. tkFloat:
  3873. Result := GetFloatProp(Instance, PropInfo);
  3874. {$endif}
  3875. tkMethod:
  3876. Result := PropInfo^.PropType^.Name;
  3877. tkString, tkLString, tkAString:
  3878. Result := GetStrProp(Instance, PropInfo);
  3879. tkWString:
  3880. Result := GetWideStrProp(Instance, PropInfo);
  3881. tkUString:
  3882. Result := GetUnicodeStrProp(Instance, PropInfo);
  3883. tkVariant:
  3884. Result := GetVariantProp(Instance, PropInfo);
  3885. tkInt64:
  3886. Result := GetInt64Prop(Instance, PropInfo);
  3887. tkQWord:
  3888. Result := QWord(GetInt64Prop(Instance, PropInfo));
  3889. else
  3890. raise EPropertyConvertError.CreateFmt('Invalid Property Type: %s',[PropInfo^.PropType^.Name]);
  3891. end;
  3892. end;
  3893. Procedure SetPropValue(Instance: TObject; PropInfo: PPropInfo; const Value: Variant);
  3894. var
  3895. TypeData: PTypeData;
  3896. O: Integer;
  3897. I64: Int64;
  3898. Qw: QWord;
  3899. S: String;
  3900. B: Boolean;
  3901. begin
  3902. TypeData := GetTypeData(PropInfo^.PropType);
  3903. // call Right SetxxxProp
  3904. case PropInfo^.PropType^.Kind of
  3905. tkBool:
  3906. begin
  3907. { to support the strings 'true' and 'false' }
  3908. if (VarType(Value)=varOleStr) or
  3909. (VarType(Value)=varString) or
  3910. (VarType(Value)=varBoolean) then
  3911. begin
  3912. B:=Value;
  3913. SetOrdProp(Instance, PropInfo, ord(B));
  3914. end
  3915. else
  3916. begin
  3917. I64:=Value;
  3918. if (I64<TypeData^.MinValue) or (I64>TypeData^.MaxValue) then
  3919. raise ERangeError.Create(SRangeError);
  3920. SetOrdProp(Instance, PropInfo, I64);
  3921. end;
  3922. end;
  3923. tkInteger, tkChar, tkWChar:
  3924. begin
  3925. I64:=Value;
  3926. if (TypeData^.OrdType=otULong) then
  3927. if (I64<LongWord(TypeData^.MinValue)) or (I64>LongWord(TypeData^.MaxValue)) then
  3928. raise ERangeError.Create(SRangeError)
  3929. else
  3930. else
  3931. if (I64<TypeData^.MinValue) or (I64>TypeData^.MaxValue) then
  3932. raise ERangeError.Create(SRangeError);
  3933. SetOrdProp(Instance, PropInfo, I64);
  3934. end;
  3935. tkEnumeration :
  3936. begin
  3937. if (VarType(Value)=varOleStr) or (VarType(Value)=varString) then
  3938. begin
  3939. S:=Value;
  3940. SetEnumProp(Instance,PropInfo,S);
  3941. end
  3942. else
  3943. begin
  3944. I64:=Value;
  3945. if (I64<TypeData^.MinValue) or (I64>TypeData^.MaxValue) then
  3946. raise ERangeError.Create(SRangeError);
  3947. SetOrdProp(Instance, PropInfo, I64);
  3948. end;
  3949. end;
  3950. tkSet :
  3951. begin
  3952. if (VarType(Value)=varOleStr) or (VarType(Value)=varString) then
  3953. begin
  3954. S:=Value;
  3955. SetSetProp(Instance,PropInfo,S);
  3956. end
  3957. else
  3958. begin
  3959. O:=Value;
  3960. SetOrdProp(Instance, PropInfo, O);
  3961. end;
  3962. end;
  3963. {$ifndef FPUNONE}
  3964. tkFloat:
  3965. SetFloatProp(Instance, PropInfo, Value);
  3966. {$endif}
  3967. tkString, tkLString, tkAString:
  3968. SetStrProp(Instance, PropInfo, VarToStr(Value));
  3969. tkWString:
  3970. SetWideStrProp(Instance, PropInfo, VarToWideStr(Value));
  3971. tkUString:
  3972. SetUnicodeStrProp(Instance, PropInfo, VarToUnicodeStr(Value));
  3973. tkVariant:
  3974. SetVariantProp(Instance, PropInfo, Value);
  3975. tkInt64:
  3976. begin
  3977. I64:=Value;
  3978. if (I64<TypeData^.MinInt64Value) or (I64>TypeData^.MaxInt64Value) then
  3979. raise ERangeError.Create(SRangeError);
  3980. SetInt64Prop(Instance, PropInfo, I64);
  3981. end;
  3982. tkQWord:
  3983. begin
  3984. Qw:=Value;
  3985. if (Qw<TypeData^.MinQWordValue) or (Qw>TypeData^.MaxQWordValue) then
  3986. raise ERangeError.Create(SRangeError);
  3987. SetInt64Prop(Instance, PropInfo,Qw);
  3988. end
  3989. else
  3990. raise EPropertyConvertError.CreateFmt('SetPropValue: Invalid Property Type %s',
  3991. [PropInfo^.PropType^.Name]);
  3992. end;
  3993. end;
  3994. var
  3995. i : LongInt;
  3996. Initialization
  3997. InitCriticalSection(customvarianttypelock);
  3998. // start with one-less value, so first increment yields CFirstUserType
  3999. customvariantcurrtype:=CFirstUserType-1;
  4000. SetSysVariantManager;
  4001. SetClearVarToEmptyParam(TVarData(EmptyParam));
  4002. VarClearProc:=@DoVarClear;
  4003. VarAddRefProc:=@DoVarAddRef;
  4004. VarCopyProc:=@DoVarCopy;
  4005. // Typinfo Variant support
  4006. OnGetVariantProp:=@GetVariantprop;
  4007. OnSetVariantProp:=@SetVariantprop;
  4008. OnSetPropValue:=@SetPropValue;
  4009. OnGetPropValue:=@GetPropValue;
  4010. InvalidCustomVariantType:=TCustomVariantType(-1);
  4011. SetLength(customvarianttypes,CFirstUserType);
  4012. Finalization
  4013. EnterCriticalSection(customvarianttypelock);
  4014. try
  4015. for i:=0 to high(customvarianttypes) do
  4016. if customvarianttypes[i]<>InvalidCustomVariantType then
  4017. customvarianttypes[i].Free;
  4018. finally
  4019. LeaveCriticalSection(customvarianttypelock);
  4020. end;
  4021. UnSetSysVariantManager;
  4022. DoneCriticalSection(customvarianttypelock);
  4023. end.