variants.pp 122 KB

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