variants.pp 131 KB

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