variants.pp 123 KB

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