variants.pp 131 KB

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