variants.pp 125 KB

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