variants.pp 131 KB

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