variants.pp 131 KB

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