variants.pp 132 KB

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