variants.pp 133 KB

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