variants.pp 130 KB

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