2
0

variants.pp 135 KB

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