variants.pp 123 KB

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