variants.pp 131 KB

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