variants.pp 131 KB

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