variants.pp 127 KB

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