variants.pp 133 KB

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