variants.pp 128 KB

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