variants.pp 132 KB

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