variants.pp 131 KB

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