classes.pas 225 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036
  1. {
  2. This file is part of the Pas2JS run time library.
  3. Copyright (c) 2017 by Mattias Gaertner
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit Classes;
  11. {$mode objfpc}
  12. interface
  13. uses
  14. RTLConsts, Types, SysUtils, JS, TypInfo;
  15. type
  16. TNotifyEvent = procedure(Sender: TObject) of object;
  17. // Notification operations :
  18. // Observer has changed, is freed, item added to/deleted from list, custom event.
  19. TFPObservedOperation = (ooChange,ooFree,ooAddItem,ooDeleteItem,ooCustom);
  20. EStreamError = class(Exception);
  21. EFCreateError = class(EStreamError);
  22. EFOpenError = class(EStreamError);
  23. EFilerError = class(EStreamError);
  24. EReadError = class(EFilerError);
  25. EWriteError = class(EFilerError);
  26. EClassNotFound = class(EFilerError);
  27. EMethodNotFound = class(EFilerError);
  28. EInvalidImage = class(EFilerError);
  29. EResNotFound = class(Exception);
  30. EListError = class(Exception);
  31. EBitsError = class(Exception);
  32. EStringListError = class(EListError);
  33. EComponentError = class(Exception);
  34. EParserError = class(Exception);
  35. EOutOfResources = class(EOutOfMemory);
  36. EInvalidOperation = class(Exception);
  37. TListAssignOp = (laCopy, laAnd, laOr, laXor, laSrcUnique, laDestUnique);
  38. TListSortCompare = function(Item1, Item2: JSValue): Integer;
  39. TListCallback = Types.TListCallback;
  40. TListStaticCallback = Types.TListStaticCallback;
  41. TAlignment = (taLeftJustify, taRightJustify, taCenter);
  42. // Forward class definitions
  43. TFPList = Class;
  44. TReader = Class;
  45. TWriter = Class;
  46. TFiler = Class;
  47. { TFPListEnumerator }
  48. TFPListEnumerator = class
  49. private
  50. FList: TFPList;
  51. FPosition: Integer;
  52. public
  53. constructor Create(AList: TFPList); reintroduce;
  54. function GetCurrent: JSValue;
  55. function MoveNext: Boolean;
  56. property Current: JSValue read GetCurrent;
  57. end;
  58. { TFPList }
  59. TFPList = class(TObject)
  60. private
  61. FList: TJSValueDynArray;
  62. FCount: Integer;
  63. FCapacity: Integer;
  64. procedure CopyMove(aList: TFPList);
  65. procedure MergeMove(aList: TFPList);
  66. procedure DoCopy(ListA, ListB: TFPList);
  67. procedure DoSrcUnique(ListA, ListB: TFPList);
  68. procedure DoAnd(ListA, ListB: TFPList);
  69. procedure DoDestUnique(ListA, ListB: TFPList);
  70. procedure DoOr(ListA, ListB: TFPList);
  71. procedure DoXOr(ListA, ListB: TFPList);
  72. protected
  73. function Get(Index: Integer): JSValue; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  74. procedure Put(Index: Integer; Item: JSValue); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  75. procedure SetCapacity(NewCapacity: Integer);
  76. procedure SetCount(NewCount: Integer);
  77. Procedure RaiseIndexError(Index: Integer);
  78. public
  79. //Type
  80. // TDirection = (FromBeginning, FromEnd);
  81. destructor Destroy; override;
  82. procedure AddList(AList: TFPList);
  83. function Add(Item: JSValue): Integer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  84. procedure Clear;
  85. procedure Delete(Index: Integer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  86. class procedure Error(const Msg: string; const Data: String);
  87. procedure Exchange(Index1, Index2: Integer);
  88. function Expand: TFPList; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  89. function Extract(Item: JSValue): JSValue;
  90. function First: JSValue;
  91. function GetEnumerator: TFPListEnumerator;
  92. function IndexOf(Item: JSValue): Integer;
  93. function IndexOfItem(Item: JSValue; Direction: TDirection): Integer;
  94. procedure Insert(Index: Integer; Item: JSValue); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  95. function Last: JSValue;
  96. procedure Move(CurIndex, NewIndex: Integer);
  97. procedure Assign (ListA: TFPList; AOperator: TListAssignOp=laCopy; ListB: TFPList=nil);
  98. function Remove(Item: JSValue): Integer;
  99. procedure Pack;
  100. procedure Sort(const Compare: TListSortCompare);
  101. procedure ForEachCall(const proc2call: TListCallback; const arg: JSValue);
  102. procedure ForEachCall(const proc2call: TListStaticCallback; const arg: JSValue);
  103. property Capacity: Integer read FCapacity write SetCapacity;
  104. property Count: Integer read FCount write SetCount;
  105. property Items[Index: Integer]: JSValue read Get write Put; default;
  106. property List: TJSValueDynArray read FList;
  107. end;
  108. TListNotification = (lnAdded, lnExtracted, lnDeleted);
  109. TList = class;
  110. { TListEnumerator }
  111. TListEnumerator = class
  112. private
  113. FList: TList;
  114. FPosition: Integer;
  115. public
  116. constructor Create(AList: TList); reintroduce;
  117. function GetCurrent: JSValue;
  118. function MoveNext: Boolean;
  119. property Current: JSValue read GetCurrent;
  120. end;
  121. { TList }
  122. TList = class(TObject)
  123. private
  124. FList: TFPList;
  125. procedure CopyMove (aList : TList);
  126. procedure MergeMove (aList : TList);
  127. procedure DoCopy(ListA, ListB : TList);
  128. procedure DoSrcUnique(ListA, ListB : TList);
  129. procedure DoAnd(ListA, ListB : TList);
  130. procedure DoDestUnique(ListA, ListB : TList);
  131. procedure DoOr(ListA, ListB : TList);
  132. procedure DoXOr(ListA, ListB : TList);
  133. protected
  134. function Get(Index: Integer): JSValue;
  135. procedure Put(Index: Integer; Item: JSValue);
  136. procedure Notify(aValue: JSValue; Action: TListNotification); virtual;
  137. procedure SetCapacity(NewCapacity: Integer);
  138. function GetCapacity: integer;
  139. procedure SetCount(NewCount: Integer);
  140. function GetCount: integer;
  141. function GetList: TJSValueDynArray;
  142. property FPList : TFPList Read FList;
  143. public
  144. constructor Create; reintroduce;
  145. destructor Destroy; override;
  146. Procedure AddList(AList : TList);
  147. function Add(Item: JSValue): Integer;
  148. procedure Clear; virtual;
  149. procedure Delete(Index: Integer);
  150. class procedure Error(const Msg: string; Data: String); virtual;
  151. procedure Exchange(Index1, Index2: Integer);
  152. function Expand: TList;
  153. function Extract(Item: JSValue): JSValue;
  154. function First: JSValue;
  155. function GetEnumerator: TListEnumerator;
  156. function IndexOf(Item: JSValue): Integer;
  157. procedure Insert(Index: Integer; Item: JSValue);
  158. function Last: JSValue;
  159. procedure Move(CurIndex, NewIndex: Integer);
  160. procedure Assign (ListA: TList; AOperator: TListAssignOp=laCopy; ListB: TList=nil);
  161. function Remove(Item: JSValue): Integer;
  162. procedure Pack;
  163. procedure Sort(const Compare: TListSortCompare);
  164. property Capacity: Integer read GetCapacity write SetCapacity;
  165. property Count: Integer read GetCount write SetCount;
  166. property Items[Index: Integer]: JSValue read Get write Put; default;
  167. property List: TJSValueDynArray read GetList;
  168. end;
  169. { TPersistent }
  170. {$M+}
  171. TPersistent = class(TObject)
  172. private
  173. //FObservers : TFPList;
  174. procedure AssignError(Source: TPersistent);
  175. protected
  176. procedure DefineProperties(Filer: TFiler); virtual;
  177. procedure AssignTo(Dest: TPersistent); virtual;
  178. function GetOwner: TPersistent; virtual;
  179. public
  180. procedure Assign(Source: TPersistent); virtual;
  181. //procedure FPOAttachObserver(AObserver : TObject);
  182. //procedure FPODetachObserver(AObserver : TObject);
  183. //procedure FPONotifyObservers(ASender : TObject; AOperation: TFPObservedOperation; Data: TObject);
  184. function GetNamePath: string; virtual;
  185. end;
  186. TPersistentClass = Class of TPersistent;
  187. { TInterfacedPersistent }
  188. TInterfacedPersistent = class(TPersistent, IInterface)
  189. private
  190. FOwnerInterface: IInterface;
  191. protected
  192. function _AddRef: Integer;
  193. function _Release: Integer;
  194. public
  195. function QueryInterface(const IID: TGUID; out Obj): integer; virtual;
  196. procedure AfterConstruction; override;
  197. end;
  198. TStrings = Class;
  199. { TStringsEnumerator class }
  200. TStringsEnumerator = class
  201. private
  202. FStrings: TStrings;
  203. FPosition: Integer;
  204. public
  205. constructor Create(AStrings: TStrings); reintroduce;
  206. function GetCurrent: String;
  207. function MoveNext: Boolean;
  208. property Current: String read GetCurrent;
  209. end;
  210. { TStrings class }
  211. TStrings = class(TPersistent)
  212. private
  213. FSpecialCharsInited : boolean;
  214. FAlwaysQuote: Boolean;
  215. FQuoteChar : Char;
  216. FDelimiter : Char;
  217. FNameValueSeparator : Char;
  218. FUpdateCount: Integer;
  219. FLBS : TTextLineBreakStyle;
  220. FSkipLastLineBreak : Boolean;
  221. FStrictDelimiter : Boolean;
  222. FLineBreak : String;
  223. function GetCommaText: string;
  224. function GetName(Index: Integer): string;
  225. function GetValue(const Name: string): string;
  226. Function GetLBS : TTextLineBreakStyle;
  227. Procedure SetLBS (AValue : TTextLineBreakStyle);
  228. procedure SetCommaText(const Value: string);
  229. procedure SetValue(const Name, Value: string);
  230. procedure SetDelimiter(c:Char);
  231. procedure SetQuoteChar(c:Char);
  232. procedure SetNameValueSeparator(c:Char);
  233. procedure DoSetTextStr(const Value: string; DoClear : Boolean);
  234. Function GetDelimiter : Char;
  235. Function GetNameValueSeparator : Char;
  236. Function GetQuoteChar: Char;
  237. Function GetLineBreak : String;
  238. procedure SetLineBreak(const S : String);
  239. Function GetSkipLastLineBreak : Boolean;
  240. procedure SetSkipLastLineBreak(const AValue : Boolean);
  241. protected
  242. procedure Error(const Msg: string; Data: Integer);
  243. function Get(Index: Integer): string; virtual; abstract;
  244. function GetCapacity: Integer; virtual;
  245. function GetCount: Integer; virtual; abstract;
  246. function GetObject(Index: Integer): TObject; virtual;
  247. function GetTextStr: string; virtual;
  248. procedure Put(Index: Integer; const S: string); virtual;
  249. procedure PutObject(Index: Integer; AObject: TObject); virtual;
  250. procedure SetCapacity(NewCapacity: Integer); virtual;
  251. procedure SetTextStr(const Value: string); virtual;
  252. procedure SetUpdateState(Updating: Boolean); virtual;
  253. property UpdateCount: Integer read FUpdateCount;
  254. Function DoCompareText(const s1,s2 : string) : PtrInt; virtual;
  255. Function GetDelimitedText: string;
  256. Procedure SetDelimitedText(Const AValue: string);
  257. Function GetValueFromIndex(Index: Integer): string;
  258. Procedure SetValueFromIndex(Index: Integer; const Value: string);
  259. Procedure CheckSpecialChars;
  260. // Class Function GetNextLine (Const Value : String; Var S : String; Var P : Integer) : Boolean;
  261. Function GetNextLinebreak (Const Value : String; Out S : String; Var P : Integer) : Boolean;
  262. public
  263. constructor Create; reintroduce;
  264. destructor Destroy; override;
  265. function Add(const S: string): Integer; virtual; overload;
  266. // function AddFmt(const Fmt : string; const Args : Array of const): Integer; overload;
  267. function AddObject(const S: string; AObject: TObject): Integer; virtual; overload;
  268. // function AddObject(const Fmt: string; Args : Array of const; AObject: TObject): Integer; overload;
  269. procedure Append(const S: string);
  270. procedure AddStrings(TheStrings: TStrings); overload; virtual;
  271. procedure AddStrings(TheStrings: TStrings; ClearFirst : Boolean); overload;
  272. procedure AddStrings(const TheStrings: array of string); overload; virtual;
  273. procedure AddStrings(const TheStrings: array of string; ClearFirst : Boolean); overload;
  274. function AddPair(const AName, AValue: string): TStrings; overload;
  275. function AddPair(const AName, AValue: string; AObject: TObject): TStrings; overload;
  276. Procedure AddText(Const S : String); virtual;
  277. procedure Assign(Source: TPersistent); override;
  278. procedure BeginUpdate;
  279. procedure Clear; virtual; abstract;
  280. procedure Delete(Index: Integer); virtual; abstract;
  281. procedure EndUpdate;
  282. function Equals(Obj: TObject): Boolean; override; overload;
  283. function Equals(TheStrings: TStrings): Boolean; overload;
  284. procedure Exchange(Index1, Index2: Integer); virtual;
  285. function GetEnumerator: TStringsEnumerator;
  286. function IndexOf(const S: string): Integer; virtual;
  287. function IndexOfName(const Name: string): Integer; virtual;
  288. function IndexOfObject(AObject: TObject): Integer; virtual;
  289. procedure Insert(Index: Integer; const S: string); virtual; abstract;
  290. procedure InsertObject(Index: Integer; const S: string; AObject: TObject);
  291. procedure Move(CurIndex, NewIndex: Integer); virtual;
  292. procedure GetNameValue(Index : Integer; Out AName,AValue : String);
  293. function ExtractName(Const S:String):String;
  294. Property TextLineBreakStyle : TTextLineBreakStyle Read GetLBS Write SetLBS;
  295. property Delimiter: Char read GetDelimiter write SetDelimiter;
  296. property DelimitedText: string read GetDelimitedText write SetDelimitedText;
  297. property LineBreak : string Read GetLineBreak write SetLineBreak;
  298. Property StrictDelimiter : Boolean Read FStrictDelimiter Write FStrictDelimiter;
  299. property AlwaysQuote: Boolean read FAlwaysQuote write FAlwaysQuote;
  300. property QuoteChar: Char read GetQuoteChar write SetQuoteChar;
  301. Property NameValueSeparator : Char Read GetNameValueSeparator Write SetNameValueSeparator;
  302. property ValueFromIndex[Index: Integer]: string read GetValueFromIndex write SetValueFromIndex;
  303. property Capacity: Integer read GetCapacity write SetCapacity;
  304. property CommaText: string read GetCommaText write SetCommaText;
  305. property Count: Integer read GetCount;
  306. property Names[Index: Integer]: string read GetName;
  307. property Objects[Index: Integer]: TObject read GetObject write PutObject;
  308. property Values[const Name: string]: string read GetValue write SetValue;
  309. property Strings[Index: Integer]: string read Get write Put; default;
  310. property Text: string read GetTextStr write SetTextStr;
  311. Property SkipLastLineBreak : Boolean Read GetSkipLastLineBreak Write SetSkipLastLineBreak;
  312. end;
  313. { TStringList}
  314. TStringItem = record
  315. FString: string;
  316. FObject: TObject;
  317. end;
  318. TStringItemArray = Array of TStringItem;
  319. TStringList = class;
  320. TStringListSortCompare = function(List: TStringList; Index1, Index2: Integer): Integer;
  321. TStringsSortStyle = (sslNone,sslUser,sslAuto);
  322. TStringsSortStyles = Set of TStringsSortStyle;
  323. TStringList = class(TStrings)
  324. private
  325. FList: TStringItemArray;
  326. FCount: Integer;
  327. FOnChange: TNotifyEvent;
  328. FOnChanging: TNotifyEvent;
  329. FDuplicates: TDuplicates;
  330. FCaseSensitive : Boolean;
  331. FForceSort : Boolean;
  332. FOwnsObjects : Boolean;
  333. FSortStyle: TStringsSortStyle;
  334. procedure ExchangeItemsInt(Index1, Index2: Integer);
  335. function GetSorted: Boolean;
  336. procedure Grow;
  337. procedure InternalClear(FromIndex : Integer = 0; ClearOnly : Boolean = False);
  338. procedure QuickSort(L, R: Integer; CompareFn: TStringListSortCompare);
  339. procedure SetSorted(Value: Boolean);
  340. procedure SetCaseSensitive(b : boolean);
  341. procedure SetSortStyle(AValue: TStringsSortStyle);
  342. protected
  343. Procedure CheckIndex(AIndex : Integer);
  344. procedure ExchangeItems(Index1, Index2: Integer); virtual;
  345. procedure Changed; virtual;
  346. procedure Changing; virtual;
  347. function Get(Index: Integer): string; override;
  348. function GetCapacity: Integer; override;
  349. function GetCount: Integer; override;
  350. function GetObject(Index: Integer): TObject; override;
  351. procedure Put(Index: Integer; const S: string); override;
  352. procedure PutObject(Index: Integer; AObject: TObject); override;
  353. procedure SetCapacity(NewCapacity: Integer); override;
  354. procedure SetUpdateState(Updating: Boolean); override;
  355. procedure InsertItem(Index: Integer; const S: string); virtual;
  356. procedure InsertItem(Index: Integer; const S: string; O: TObject); virtual;
  357. Function DoCompareText(const s1,s2 : string) : PtrInt; override;
  358. function CompareStrings(const s1,s2 : string) : Integer; virtual;
  359. public
  360. destructor Destroy; override;
  361. function Add(const S: string): Integer; override;
  362. procedure Clear; override;
  363. procedure Delete(Index: Integer); override;
  364. procedure Exchange(Index1, Index2: Integer); override;
  365. function Find(const S: string; Out Index: Integer): Boolean; virtual;
  366. function IndexOf(const S: string): Integer; override;
  367. procedure Insert(Index: Integer; const S: string); override;
  368. procedure Sort; virtual;
  369. procedure CustomSort(CompareFn: TStringListSortCompare); virtual;
  370. property Duplicates: TDuplicates read FDuplicates write FDuplicates;
  371. property Sorted: Boolean read GetSorted write SetSorted;
  372. property CaseSensitive: Boolean read FCaseSensitive write SetCaseSensitive;
  373. property OnChange: TNotifyEvent read FOnChange write FOnChange;
  374. property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
  375. property OwnsObjects : boolean read FOwnsObjects write FOwnsObjects;
  376. Property SortStyle : TStringsSortStyle Read FSortStyle Write SetSortStyle;
  377. end;
  378. TCollection = class;
  379. { TCollectionItem }
  380. TCollectionItem = class(TPersistent)
  381. private
  382. FCollection: TCollection;
  383. FID: Integer;
  384. FUpdateCount: Integer;
  385. function GetIndex: Integer;
  386. protected
  387. procedure SetCollection(Value: TCollection);virtual;
  388. procedure Changed(AllItems: Boolean);
  389. function GetOwner: TPersistent; override;
  390. function GetDisplayName: string; virtual;
  391. procedure SetIndex(Value: Integer); virtual;
  392. procedure SetDisplayName(const Value: string); virtual;
  393. property UpdateCount: Integer read FUpdateCount;
  394. public
  395. constructor Create(ACollection: TCollection); virtual; reintroduce;
  396. destructor Destroy; override;
  397. function GetNamePath: string; override;
  398. property Collection: TCollection read FCollection write SetCollection;
  399. property ID: Integer read FID;
  400. property Index: Integer read GetIndex write SetIndex;
  401. property DisplayName: string read GetDisplayName write SetDisplayName;
  402. end;
  403. TCollectionEnumerator = class
  404. private
  405. FCollection: TCollection;
  406. FPosition: Integer;
  407. public
  408. constructor Create(ACollection: TCollection); reintroduce;
  409. function GetCurrent: TCollectionItem;
  410. function MoveNext: Boolean;
  411. property Current: TCollectionItem read GetCurrent;
  412. end;
  413. TCollectionItemClass = class of TCollectionItem;
  414. TCollectionNotification = (cnAdded, cnExtracting, cnDeleting);
  415. TCollectionSortCompare = function (Item1, Item2: TCollectionItem): Integer;
  416. TCollection = class(TPersistent)
  417. private
  418. FItemClass: TCollectionItemClass;
  419. FItems: TFpList;
  420. FUpdateCount: Integer;
  421. FNextID: Integer;
  422. FPropName: string;
  423. function GetCount: Integer;
  424. function GetPropName: string;
  425. procedure InsertItem(Item: TCollectionItem);
  426. procedure RemoveItem(Item: TCollectionItem);
  427. procedure DoClear;
  428. protected
  429. { Design-time editor support }
  430. function GetAttrCount: Integer; virtual;
  431. function GetAttr(Index: Integer): string; virtual;
  432. function GetItemAttr(Index, ItemIndex: Integer): string; virtual;
  433. procedure Changed;
  434. function GetItem(Index: Integer): TCollectionItem;
  435. procedure SetItem(Index: Integer; Value: TCollectionItem);
  436. procedure SetItemName(Item: TCollectionItem); virtual;
  437. procedure SetPropName; virtual;
  438. procedure Update(Item: TCollectionItem); virtual;
  439. procedure Notify(Item: TCollectionItem;Action: TCollectionNotification); virtual;
  440. property PropName: string read GetPropName write FPropName;
  441. property UpdateCount: Integer read FUpdateCount;
  442. public
  443. constructor Create(AItemClass: TCollectionItemClass); reintroduce;
  444. destructor Destroy; override;
  445. function Owner: TPersistent;
  446. function Add: TCollectionItem;
  447. procedure Assign(Source: TPersistent); override;
  448. procedure BeginUpdate; virtual;
  449. procedure Clear;
  450. procedure EndUpdate; virtual;
  451. procedure Delete(Index: Integer);
  452. function GetEnumerator: TCollectionEnumerator;
  453. function GetNamePath: string; override;
  454. function Insert(Index: Integer): TCollectionItem;
  455. function FindItemID(ID: Integer): TCollectionItem;
  456. procedure Exchange(Const Index1, index2: integer);
  457. procedure Sort(Const Compare : TCollectionSortCompare);
  458. property Count: Integer read GetCount;
  459. property ItemClass: TCollectionItemClass read FItemClass;
  460. property Items[Index: Integer]: TCollectionItem read GetItem write SetItem;
  461. end;
  462. TOwnedCollection = class(TCollection)
  463. private
  464. FOwner: TPersistent;
  465. protected
  466. Function GetOwner: TPersistent; override;
  467. public
  468. Constructor Create(AOwner: TPersistent; AItemClass: TCollectionItemClass); reintroduce;
  469. end;
  470. TComponent = Class;
  471. TOperation = (opInsert, opRemove);
  472. TComponentStateItem = ( csLoading, csReading, csWriting, csDestroying,
  473. csDesigning, csAncestor, csUpdating, csFixups, csFreeNotification,
  474. csInline, csDesignInstance);
  475. TComponentState = set of TComponentStateItem;
  476. TComponentStyleItem = (csInheritable, csCheckPropAvail, csSubComponent, csTransient);
  477. TComponentStyle = set of TComponentStyleItem;
  478. TGetChildProc = procedure (Child: TComponent) of object;
  479. TComponentName = string;
  480. { TComponentEnumerator }
  481. TComponentEnumerator = class
  482. private
  483. FComponent: TComponent;
  484. FPosition: Integer;
  485. public
  486. constructor Create(AComponent: TComponent); reintroduce;
  487. function GetCurrent: TComponent;
  488. function MoveNext: Boolean;
  489. property Current: TComponent read GetCurrent;
  490. end;
  491. TComponent = class(TPersistent, IInterface)
  492. private
  493. FOwner: TComponent;
  494. FName: TComponentName;
  495. FTag: Ptrint;
  496. FComponents: TFpList;
  497. FFreeNotifies: TFpList;
  498. FDesignInfo: Longint;
  499. FComponentState: TComponentState;
  500. function GetComponent(AIndex: Integer): TComponent;
  501. function GetComponentCount: Integer;
  502. function GetComponentIndex: Integer;
  503. procedure Insert(AComponent: TComponent);
  504. procedure Remove(AComponent: TComponent);
  505. procedure RemoveNotification(AComponent: TComponent);
  506. procedure SetComponentIndex(Value: Integer);
  507. procedure SetReference(Enable: Boolean);
  508. protected
  509. FComponentStyle: TComponentStyle;
  510. procedure ChangeName(const NewName: TComponentName);
  511. procedure GetChildren(Proc: TGetChildProc; Root: TComponent); virtual;
  512. function GetChildOwner: TComponent; virtual;
  513. function GetChildParent: TComponent; virtual;
  514. function GetOwner: TPersistent; override;
  515. procedure Loaded; virtual;
  516. procedure Loading; virtual;
  517. procedure SetWriting(Value: Boolean); virtual;
  518. procedure SetReading(Value: Boolean); virtual;
  519. procedure Notification(AComponent: TComponent; Operation: TOperation); virtual;
  520. procedure PaletteCreated; virtual;
  521. procedure ReadState(Reader: TReader); virtual;
  522. procedure SetAncestor(Value: Boolean);
  523. procedure SetDesigning(Value: Boolean; SetChildren : Boolean = True);
  524. procedure SetDesignInstance(Value: Boolean);
  525. procedure SetInline(Value: Boolean);
  526. procedure SetName(const NewName: TComponentName); virtual;
  527. procedure SetChildOrder(Child: TComponent; Order: Integer); virtual;
  528. procedure SetParentComponent(Value: TComponent); virtual;
  529. procedure Updating; virtual;
  530. procedure Updated; virtual;
  531. procedure ValidateRename(AComponent: TComponent; const CurName, NewName: string); virtual;
  532. procedure ValidateContainer(AComponent: TComponent); virtual;
  533. procedure ValidateInsert(AComponent: TComponent); virtual;
  534. protected
  535. function _AddRef: Integer;
  536. function _Release: Integer;
  537. public
  538. constructor Create(AOwner: TComponent); virtual; reintroduce;
  539. destructor Destroy; override;
  540. procedure BeforeDestruction; override;
  541. procedure DestroyComponents;
  542. procedure Destroying;
  543. function QueryInterface(const IID: TGUID; out Obj): integer; virtual;
  544. procedure WriteState(Writer: TWriter); virtual;
  545. // function ExecuteAction(Action: TBasicAction): Boolean; virtual;
  546. function FindComponent(const AName: string): TComponent;
  547. procedure FreeNotification(AComponent: TComponent);
  548. procedure RemoveFreeNotification(AComponent: TComponent);
  549. function GetNamePath: string; override;
  550. function GetParentComponent: TComponent; virtual;
  551. function HasParent: Boolean; virtual;
  552. procedure InsertComponent(AComponent: TComponent);
  553. procedure RemoveComponent(AComponent: TComponent);
  554. procedure SetSubComponent(ASubComponent: Boolean);
  555. function GetEnumerator: TComponentEnumerator;
  556. // function UpdateAction(Action: TBasicAction): Boolean; dynamic;
  557. property Components[Index: Integer]: TComponent read GetComponent;
  558. property ComponentCount: Integer read GetComponentCount;
  559. property ComponentIndex: Integer read GetComponentIndex write SetComponentIndex;
  560. property ComponentState: TComponentState read FComponentState;
  561. property ComponentStyle: TComponentStyle read FComponentStyle;
  562. property DesignInfo: Longint read FDesignInfo write FDesignInfo;
  563. property Owner: TComponent read FOwner;
  564. published
  565. property Name: TComponentName read FName write SetName stored False;
  566. property Tag: PtrInt read FTag write FTag default 0;
  567. end;
  568. TComponentClass = Class of TComponent;
  569. TSeekOrigin = (soBeginning, soCurrent, soEnd);
  570. { TStream }
  571. TStream = class(TObject)
  572. private
  573. FEndian: TEndian;
  574. function MakeInt(B: TBytes; aSize: Integer; Signed: Boolean): NativeInt;
  575. function MakeBytes(B: NativeInt; aSize: Integer; Signed: Boolean): TBytes;
  576. protected
  577. procedure InvalidSeek; virtual;
  578. procedure Discard(const Count: NativeInt);
  579. procedure DiscardLarge(Count: NativeInt; const MaxBufferSize: Longint);
  580. procedure FakeSeekForward(Offset: NativeInt; const Origin: TSeekOrigin; const Pos: NativeInt);
  581. function GetPosition: NativeInt; virtual;
  582. procedure SetPosition(const Pos: NativeInt); virtual;
  583. function GetSize: NativeInt; virtual;
  584. procedure SetSize(const NewSize: NativeInt); virtual;
  585. procedure SetSize64(const NewSize: NativeInt); virtual;
  586. procedure ReadNotImplemented;
  587. procedure WriteNotImplemented;
  588. function ReadMaxSizeData(Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
  589. Procedure ReadExactSizeData(Buffer : TBytes; aSize,aCount : NativeInt);
  590. function WriteMaxSizeData(Const Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
  591. Procedure WriteExactSizeData(Const Buffer : TBytes; aSize,aCount : NativeInt);
  592. public
  593. function Read(var Buffer: TBytes; Count: Longint): Longint; overload;
  594. function Read(Buffer : TBytes; aOffset, Count: Longint): Longint; virtual; abstract; overload;
  595. function Write(const Buffer: TBytes; Count: Longint): Longint; virtual; overload;
  596. function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; virtual; abstract; overload;
  597. function Seek(const Offset: NativeInt; Origin: TSeekOrigin): NativeInt; virtual; abstract; overload;
  598. function ReadData(Buffer: TBytes; Count: NativeInt): NativeInt; overload;
  599. function ReadData(var Buffer: Boolean): NativeInt; overload;
  600. function ReadData(var Buffer: Boolean; Count: NativeInt): NativeInt; overload;
  601. function ReadData(var Buffer: WideChar): NativeInt; overload;
  602. function ReadData(var Buffer: WideChar; Count: NativeInt): NativeInt; overload;
  603. function ReadData(var Buffer: Int8): NativeInt; overload;
  604. function ReadData(var Buffer: Int8; Count: NativeInt): NativeInt; overload;
  605. function ReadData(var Buffer: UInt8): NativeInt; overload;
  606. function ReadData(var Buffer: UInt8; Count: NativeInt): NativeInt; overload;
  607. function ReadData(var Buffer: Int16): NativeInt; overload;
  608. function ReadData(var Buffer: Int16; Count: NativeInt): NativeInt; overload;
  609. function ReadData(var Buffer: UInt16): NativeInt; overload;
  610. function ReadData(var Buffer: UInt16; Count: NativeInt): NativeInt; overload;
  611. function ReadData(var Buffer: Int32): NativeInt; overload;
  612. function ReadData(var Buffer: Int32; Count: NativeInt): NativeInt; overload;
  613. function ReadData(var Buffer: UInt32): NativeInt; overload;
  614. function ReadData(var Buffer: UInt32; Count: NativeInt): NativeInt; overload;
  615. // NativeLargeint. Stored as a float64, Read as float64.
  616. function ReadData(var Buffer: NativeLargeInt): NativeInt; overload;
  617. function ReadData(var Buffer: NativeLargeInt; Count: NativeInt): NativeInt; overload;
  618. function ReadData(var Buffer: NativeLargeUInt): NativeInt; overload;
  619. function ReadData(var Buffer: NativeLargeUInt; Count: NativeInt): NativeInt; overload;
  620. function ReadData(var Buffer: Double): NativeInt; overload;
  621. function ReadData(var Buffer: Double; Count: NativeInt): NativeInt; overload;
  622. procedure ReadBuffer(var Buffer: TBytes; Count: NativeInt); overload;
  623. procedure ReadBuffer(var Buffer: TBytes; Offset, Count: NativeInt); overload;
  624. procedure ReadBufferData(var Buffer: Boolean); overload;
  625. procedure ReadBufferData(var Buffer: Boolean; Count: NativeInt); overload;
  626. procedure ReadBufferData(var Buffer: WideChar); overload;
  627. procedure ReadBufferData(var Buffer: WideChar; Count: NativeInt); overload;
  628. procedure ReadBufferData(var Buffer: Int8); overload;
  629. procedure ReadBufferData(var Buffer: Int8; Count: NativeInt); overload;
  630. procedure ReadBufferData(var Buffer: UInt8); overload;
  631. procedure ReadBufferData(var Buffer: UInt8; Count: NativeInt); overload;
  632. procedure ReadBufferData(var Buffer: Int16); overload;
  633. procedure ReadBufferData(var Buffer: Int16; Count: NativeInt); overload;
  634. procedure ReadBufferData(var Buffer: UInt16); overload;
  635. procedure ReadBufferData(var Buffer: UInt16; Count: NativeInt); overload;
  636. procedure ReadBufferData(var Buffer: Int32); overload;
  637. procedure ReadBufferData(var Buffer: Int32; Count: NativeInt); overload;
  638. procedure ReadBufferData(var Buffer: UInt32); overload;
  639. procedure ReadBufferData(var Buffer: UInt32; Count: NativeInt); overload;
  640. // NativeLargeint. Stored as a float64, Read as float64.
  641. procedure ReadBufferData(var Buffer: NativeLargeInt); overload;
  642. procedure ReadBufferData(var Buffer: NativeLargeInt; Count: NativeInt); overload;
  643. procedure ReadBufferData(var Buffer: NativeLargeUInt); overload;
  644. procedure ReadBufferData(var Buffer: NativeLargeUInt; Count: NativeInt); overload;
  645. procedure ReadBufferData(var Buffer: Double); overload;
  646. procedure ReadBufferData(var Buffer: Double; Count: NativeInt); overload;
  647. procedure WriteBuffer(const Buffer: TBytes; Count: NativeInt); overload;
  648. procedure WriteBuffer(const Buffer: TBytes; Offset, Count: NativeInt); overload;
  649. function WriteData(const Buffer: TBytes; Count: NativeInt): NativeInt; overload;
  650. function WriteData(const Buffer: Boolean): NativeInt; overload;
  651. function WriteData(const Buffer: Boolean; Count: NativeInt): NativeInt; overload;
  652. function WriteData(const Buffer: WideChar): NativeInt; overload;
  653. function WriteData(const Buffer: WideChar; Count: NativeInt): NativeInt; overload;
  654. function WriteData(const Buffer: Int8): NativeInt; overload;
  655. function WriteData(const Buffer: Int8; Count: NativeInt): NativeInt; overload;
  656. function WriteData(const Buffer: UInt8): NativeInt; overload;
  657. function WriteData(const Buffer: UInt8; Count: NativeInt): NativeInt; overload;
  658. function WriteData(const Buffer: Int16): NativeInt; overload;
  659. function WriteData(const Buffer: Int16; Count: NativeInt): NativeInt; overload;
  660. function WriteData(const Buffer: UInt16): NativeInt; overload;
  661. function WriteData(const Buffer: UInt16; Count: NativeInt): NativeInt; overload;
  662. function WriteData(const Buffer: Int32): NativeInt; overload;
  663. function WriteData(const Buffer: Int32; Count: NativeInt): NativeInt; overload;
  664. function WriteData(const Buffer: UInt32): NativeInt; overload;
  665. function WriteData(const Buffer: UInt32; Count: NativeInt): NativeInt; overload;
  666. // NativeLargeint. Stored as a float64, Read as float64.
  667. function WriteData(const Buffer: NativeLargeInt): NativeInt; overload;
  668. function WriteData(const Buffer: NativeLargeInt; Count: NativeInt): NativeInt; overload;
  669. function WriteData(const Buffer: NativeLargeUInt): NativeInt; overload;
  670. function WriteData(const Buffer: NativeLargeUInt; Count: NativeInt): NativeInt; overload;
  671. function WriteData(const Buffer: Double): NativeInt; overload;
  672. function WriteData(const Buffer: Double; Count: NativeInt): NativeInt; overload;
  673. {$IFDEF FPC_HAS_TYPE_EXTENDED}
  674. function WriteData(const Buffer: Extended): NativeInt; overload;
  675. function WriteData(const Buffer: Extended; Count: NativeInt): NativeInt; overload;
  676. function WriteData(const Buffer: TExtended80Rec): NativeInt; overload;
  677. function WriteData(const Buffer: TExtended80Rec; Count: NativeInt): NativeInt; overload;
  678. {$ENDIF}
  679. procedure WriteBufferData(Buffer: Int32); overload;
  680. procedure WriteBufferData(Buffer: Int32; Count: NativeInt); overload;
  681. procedure WriteBufferData(Buffer: Boolean); overload;
  682. procedure WriteBufferData(Buffer: Boolean; Count: NativeInt); overload;
  683. procedure WriteBufferData(Buffer: WideChar); overload;
  684. procedure WriteBufferData(Buffer: WideChar; Count: NativeInt); overload;
  685. procedure WriteBufferData(Buffer: Int8); overload;
  686. procedure WriteBufferData(Buffer: Int8; Count: NativeInt); overload;
  687. procedure WriteBufferData(Buffer: UInt8); overload;
  688. procedure WriteBufferData(Buffer: UInt8; Count: NativeInt); overload;
  689. procedure WriteBufferData(Buffer: Int16); overload;
  690. procedure WriteBufferData(Buffer: Int16; Count: NativeInt); overload;
  691. procedure WriteBufferData(Buffer: UInt16); overload;
  692. procedure WriteBufferData(Buffer: UInt16; Count: NativeInt); overload;
  693. procedure WriteBufferData(Buffer: UInt32); overload;
  694. procedure WriteBufferData(Buffer: UInt32; Count: NativeInt); overload;
  695. // NativeLargeint. Stored as a float64, Read as float64.
  696. procedure WriteBufferData(Buffer: NativeLargeInt); overload;
  697. procedure WriteBufferData(Buffer: NativeLargeInt; Count: NativeInt); overload;
  698. procedure WriteBufferData(Buffer: NativeLargeUInt); overload;
  699. procedure WriteBufferData(Buffer: NativeLargeUInt; Count: NativeInt); overload;
  700. procedure WriteBufferData(Buffer: Double); overload;
  701. procedure WriteBufferData(Buffer: Double; Count: NativeInt); overload;
  702. function CopyFrom(Source: TStream; Count: NativeInt): NativeInt;
  703. function ReadComponent(Instance: TComponent): TComponent;
  704. function ReadComponentRes(Instance: TComponent): TComponent;
  705. procedure WriteComponent(Instance: TComponent);
  706. procedure WriteComponentRes(const ResName: string; Instance: TComponent);
  707. procedure WriteDescendent(Instance, Ancestor: TComponent);
  708. procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
  709. procedure WriteResourceHeader(const ResName: string; {!!!:out} var FixupInfo: Longint);
  710. procedure FixupResourceHeader(FixupInfo: Longint);
  711. procedure ReadResHeader;
  712. function ReadByte : Byte;
  713. function ReadWord : Word;
  714. function ReadDWord : Cardinal;
  715. function ReadQWord : NativeLargeUInt;
  716. procedure WriteByte(b : Byte);
  717. procedure WriteWord(w : Word);
  718. procedure WriteDWord(d : Cardinal);
  719. procedure WriteQWord(q : NativeLargeUInt);
  720. property Position: NativeInt read GetPosition write SetPosition;
  721. property Size: NativeInt read GetSize write SetSize64;
  722. Property Endian: TEndian Read FEndian Write FEndian;
  723. end;
  724. { TCustomMemoryStream abstract class }
  725. TCustomMemoryStream = class(TStream)
  726. private
  727. FMemory: TJSArrayBuffer;
  728. FDataView : TJSDataView;
  729. FDataArray : TJSUint8Array;
  730. FSize, FPosition: PtrInt;
  731. FSizeBoundsSeek : Boolean;
  732. function GetDataArray: TJSUint8Array;
  733. function GetDataView: TJSDataview;
  734. protected
  735. Function GetSize : NativeInt; Override;
  736. function GetPosition: NativeInt; Override;
  737. procedure SetPointer(Ptr: TJSArrayBuffer; ASize: PtrInt);
  738. Property DataView : TJSDataview Read GetDataView;
  739. Property DataArray : TJSUint8Array Read GetDataArray;
  740. public
  741. Class Function MemoryToBytes(Mem : TJSArrayBuffer) : TBytes; overload;
  742. Class Function MemoryToBytes(Mem : TJSUint8Array) : TBytes; overload;
  743. Class Function BytesToMemory(aBytes : TBytes) : TJSArrayBuffer;
  744. function Read(Buffer : TBytes; Offset, Count: LongInt): LongInt; override;
  745. function Seek(const Offset: NativeInt; Origin: TSeekOrigin): NativeInt; override;
  746. procedure SaveToStream(Stream: TStream);
  747. property Memory: TJSArrayBuffer read FMemory;
  748. Property SizeBoundsSeek : Boolean Read FSizeBoundsSeek Write FSizeBoundsSeek;
  749. end;
  750. { TMemoryStream }
  751. TMemoryStream = class(TCustomMemoryStream)
  752. private
  753. FCapacity: PtrInt;
  754. procedure SetCapacity(NewCapacity: PtrInt);
  755. protected
  756. function Realloc(var NewCapacity: PtrInt): TJSArrayBuffer; virtual;
  757. property Capacity: PtrInt read FCapacity write SetCapacity;
  758. public
  759. destructor Destroy; override;
  760. procedure Clear;
  761. procedure LoadFromStream(Stream: TStream);
  762. procedure SetSize(const NewSize: NativeInt); override;
  763. function Write(const Buffer: TBytes; Offset, Count: LongInt): LongInt; override;
  764. end;
  765. { TBytesStream }
  766. TBytesStream = class(TMemoryStream)
  767. private
  768. function GetBytes: TBytes;
  769. public
  770. constructor Create(const ABytes: TBytes); virtual; overload;
  771. property Bytes: TBytes read GetBytes;
  772. end;
  773. TFilerFlag = (ffInherited, ffChildPos, ffInline);
  774. TFilerFlags = set of TFilerFlag;
  775. TReaderProc = procedure(Reader: TReader) of object;
  776. TWriterProc = procedure(Writer: TWriter) of object;
  777. TStreamProc = procedure(Stream: TStream) of object;
  778. TFiler = class(TObject)
  779. private
  780. FRoot: TComponent;
  781. FLookupRoot: TComponent;
  782. FAncestor: TPersistent;
  783. FIgnoreChildren: Boolean;
  784. protected
  785. procedure SetRoot(ARoot: TComponent); virtual;
  786. public
  787. procedure DefineProperty(const Name: string;
  788. ReadData: TReaderProc; WriteData: TWriterProc;
  789. HasData: Boolean); virtual; abstract;
  790. procedure DefineBinaryProperty(const Name: string;
  791. ReadData, WriteData: TStreamProc;
  792. HasData: Boolean); virtual; abstract;
  793. Procedure FlushBuffer; virtual; abstract;
  794. property Root: TComponent read FRoot write SetRoot;
  795. property LookupRoot: TComponent read FLookupRoot;
  796. property Ancestor: TPersistent read FAncestor write FAncestor;
  797. property IgnoreChildren: Boolean read FIgnoreChildren write FIgnoreChildren;
  798. end;
  799. TValueType = (
  800. vaNull, vaList, vaInt8, vaInt16, vaInt32, vaDouble,
  801. vaString, vaIdent, vaFalse, vaTrue, vaBinary, vaSet,
  802. vaNil, vaCollection, vaCurrency, vaDate, vaNativeInt
  803. );
  804. { TAbstractObjectReader }
  805. TAbstractObjectReader = class
  806. public
  807. Procedure FlushBuffer; virtual;
  808. function NextValue: TValueType; virtual; abstract;
  809. function ReadValue: TValueType; virtual; abstract;
  810. procedure BeginRootComponent; virtual; abstract;
  811. procedure BeginComponent(var Flags: TFilerFlags; var AChildPos: Integer;
  812. var CompClassName, CompName: String); virtual; abstract;
  813. function BeginProperty: String; virtual; abstract;
  814. //Please don't use read, better use ReadBinary whenever possible
  815. procedure Read(var Buffer : TBytes; Count: Longint); virtual;abstract;
  816. { All ReadXXX methods are called _after_ the value type has been read! }
  817. procedure ReadBinary(const DestData: TMemoryStream); virtual; abstract;
  818. function ReadFloat: Extended; virtual; abstract;
  819. function ReadCurrency: Currency; virtual; abstract;
  820. function ReadIdent(ValueType: TValueType): String; virtual; abstract;
  821. function ReadInt8: ShortInt; virtual; abstract;
  822. function ReadInt16: SmallInt; virtual; abstract;
  823. function ReadInt32: LongInt; virtual; abstract;
  824. function ReadNativeInt: NativeInt; virtual; abstract;
  825. function ReadSet(EnumType: TTypeInfoEnum): Integer; virtual; abstract;
  826. procedure ReadSignature; virtual; abstract;
  827. function ReadStr: String; virtual; abstract;
  828. function ReadString(StringType: TValueType): String; virtual; abstract;
  829. function ReadWideString: WideString;virtual;abstract;
  830. function ReadUnicodeString: UnicodeString;virtual;abstract;
  831. procedure SkipComponent(SkipComponentInfos: Boolean); virtual; abstract;
  832. procedure SkipValue; virtual; abstract;
  833. end;
  834. { TBinaryObjectReader }
  835. TBinaryObjectReader = class(TAbstractObjectReader)
  836. protected
  837. FStream: TStream;
  838. function ReadWord : word;
  839. function ReadDWord : longword;
  840. procedure SkipProperty;
  841. procedure SkipSetBody;
  842. public
  843. constructor Create(Stream: TStream);
  844. function NextValue: TValueType; override;
  845. function ReadValue: TValueType; override;
  846. procedure BeginRootComponent; override;
  847. procedure BeginComponent(var Flags: TFilerFlags; var AChildPos: Integer;
  848. var CompClassName, CompName: String); override;
  849. function BeginProperty: String; override;
  850. //Please don't use read, better use ReadBinary whenever possible
  851. procedure Read(var Buffer : TBytes; Count: Longint); override;
  852. procedure ReadBinary(const DestData: TMemoryStream); override;
  853. function ReadFloat: Extended; override;
  854. function ReadCurrency: Currency; override;
  855. function ReadIdent(ValueType: TValueType): String; override;
  856. function ReadInt8: ShortInt; override;
  857. function ReadInt16: SmallInt; override;
  858. function ReadInt32: LongInt; override;
  859. function ReadNativeInt: NativeInt; override;
  860. function ReadSet(EnumType: TTypeInfoEnum): Integer; override;
  861. procedure ReadSignature; override;
  862. function ReadStr: String; override;
  863. function ReadString(StringType: TValueType): String; override;
  864. function ReadWideString: WideString;override;
  865. function ReadUnicodeString: UnicodeString;override;
  866. procedure SkipComponent(SkipComponentInfos: Boolean); override;
  867. procedure SkipValue; override;
  868. end;
  869. TFindMethodEvent = procedure(Reader: TReader; const MethodName: string; var Address: CodePointer; var Error: Boolean) of object;
  870. TSetNameEvent = procedure(Reader: TReader; Component: TComponent; var Name: string) of object;
  871. TReferenceNameEvent = procedure(Reader: TReader; var Name: string) of object;
  872. TAncestorNotFoundEvent = procedure(Reader: TReader; const ComponentName: string; ComponentClass: TPersistentClass; var Component: TComponent) of object;
  873. TReadComponentsProc = procedure(Component: TComponent) of object;
  874. TReaderError = procedure(Reader: TReader; const Message: string; var Handled: Boolean) of object;
  875. TPropertyNotFoundEvent = procedure(Reader: TReader; Instance: TPersistent; var PropName: string; IsPath: boolean; var Handled, Skip: Boolean) of object;
  876. TFindComponentClassEvent = procedure(Reader: TReader; const ClassName: string; var ComponentClass: TComponentClass) of object;
  877. TCreateComponentEvent = procedure(Reader: TReader; ComponentClass: TComponentClass; var Component: TComponent) of object;
  878. TSetMethodPropertyEvent = procedure(Reader: TReader; Instance: TPersistent; PropInfo: TTypeMemberProperty; const TheMethodName: string;
  879. var Handled: boolean) of object;
  880. TReadWriteStringPropertyEvent = procedure(Sender:TObject; const Instance: TPersistent; PropInfo: TTypeMemberProperty; var Content:string) of object;
  881. { TReader }
  882. TReader = class(TFiler)
  883. private
  884. FDriver: TAbstractObjectReader;
  885. FOwner: TComponent;
  886. FParent: TComponent;
  887. FFixups: TObject;
  888. FLoaded: TFpList;
  889. FOnFindMethod: TFindMethodEvent;
  890. FOnSetMethodProperty: TSetMethodPropertyEvent;
  891. FOnSetName: TSetNameEvent;
  892. FOnReferenceName: TReferenceNameEvent;
  893. FOnAncestorNotFound: TAncestorNotFoundEvent;
  894. FOnError: TReaderError;
  895. FOnPropertyNotFound: TPropertyNotFoundEvent;
  896. FOnFindComponentClass: TFindComponentClassEvent;
  897. FOnCreateComponent: TCreateComponentEvent;
  898. FPropName: string;
  899. FCanHandleExcepts: Boolean;
  900. FOnReadStringProperty:TReadWriteStringPropertyEvent;
  901. procedure DoFixupReferences;
  902. function FindComponentClass(const AClassName: string): TComponentClass;
  903. protected
  904. function Error(const Message: string): Boolean; virtual;
  905. function FindMethod(ARoot: TComponent; const AMethodName: string): CodePointer; virtual;
  906. procedure ReadProperty(AInstance: TPersistent);
  907. procedure ReadPropValue(Instance: TPersistent; PropInfo: TTypeMemberProperty);
  908. procedure PropertyError;
  909. procedure ReadData(Instance: TComponent);
  910. property PropName: string read FPropName;
  911. property CanHandleExceptions: Boolean read FCanHandleExcepts;
  912. function CreateDriver(Stream: TStream): TAbstractObjectReader; virtual;
  913. public
  914. constructor Create(Stream: TStream);
  915. destructor Destroy; override;
  916. Procedure FlushBuffer; override;
  917. procedure BeginReferences;
  918. procedure CheckValue(Value: TValueType);
  919. procedure DefineProperty(const Name: string;
  920. AReadData: TReaderProc; WriteData: TWriterProc;
  921. HasData: Boolean); override;
  922. procedure DefineBinaryProperty(const Name: string;
  923. AReadData, WriteData: TStreamProc;
  924. HasData: Boolean); override;
  925. function EndOfList: Boolean;
  926. procedure EndReferences;
  927. procedure FixupReferences;
  928. function NextValue: TValueType;
  929. //Please don't use read, better use ReadBinary whenever possible
  930. //uuups, ReadBinary is protected ..
  931. procedure Read(var Buffer : TBytes; Count: LongInt); virtual;
  932. function ReadBoolean: Boolean;
  933. function ReadChar: Char;
  934. function ReadWideChar: WideChar;
  935. function ReadUnicodeChar: UnicodeChar;
  936. procedure ReadCollection(Collection: TCollection);
  937. function ReadComponent(Component: TComponent): TComponent;
  938. procedure ReadComponents(AOwner, AParent: TComponent;
  939. Proc: TReadComponentsProc);
  940. function ReadFloat: Extended;
  941. function ReadCurrency: Currency;
  942. function ReadIdent: string;
  943. function ReadInteger: Longint;
  944. function ReadNativeInt: NativeInt;
  945. function ReadSet(EnumType: Pointer): Integer;
  946. procedure ReadListBegin;
  947. procedure ReadListEnd;
  948. function ReadRootComponent(ARoot: TComponent): TComponent;
  949. function ReadVariant: JSValue;
  950. procedure ReadSignature;
  951. function ReadString: string;
  952. function ReadWideString: WideString;
  953. function ReadUnicodeString: UnicodeString;
  954. function ReadValue: TValueType;
  955. procedure CopyValue(Writer: TWriter);
  956. property Driver: TAbstractObjectReader read FDriver;
  957. property Owner: TComponent read FOwner write FOwner;
  958. property Parent: TComponent read FParent write FParent;
  959. property OnError: TReaderError read FOnError write FOnError;
  960. property OnPropertyNotFound: TPropertyNotFoundEvent read FOnPropertyNotFound write FOnPropertyNotFound;
  961. property OnFindMethod: TFindMethodEvent read FOnFindMethod write FOnFindMethod;
  962. property OnSetMethodProperty: TSetMethodPropertyEvent read FOnSetMethodProperty write FOnSetMethodProperty;
  963. property OnSetName: TSetNameEvent read FOnSetName write FOnSetName;
  964. property OnReferenceName: TReferenceNameEvent read FOnReferenceName write FOnReferenceName;
  965. property OnAncestorNotFound: TAncestorNotFoundEvent read FOnAncestorNotFound write FOnAncestorNotFound;
  966. property OnCreateComponent: TCreateComponentEvent read FOnCreateComponent write FOnCreateComponent;
  967. property OnFindComponentClass: TFindComponentClassEvent read FOnFindComponentClass write FOnFindComponentClass;
  968. property OnReadStringProperty: TReadWriteStringPropertyEvent read FOnReadStringProperty write FOnReadStringProperty;
  969. end;
  970. { TAbstractObjectWriter }
  971. TAbstractObjectWriter = class
  972. public
  973. { Begin/End markers. Those ones who don't have an end indicator, use
  974. "EndList", after the occurrence named in the comment. Note that this
  975. only counts for "EndList" calls on the same level; each BeginXXX call
  976. increases the current level. }
  977. procedure BeginCollection; virtual; abstract; { Ends with the next "EndList" }
  978. procedure BeginComponent(Component: TComponent; Flags: TFilerFlags;
  979. ChildPos: Integer); virtual; abstract; { Ends after the second "EndList" }
  980. procedure WriteSignature; virtual; abstract;
  981. procedure BeginList; virtual; abstract;
  982. procedure EndList; virtual; abstract;
  983. procedure BeginProperty(const PropName: String); virtual; abstract;
  984. procedure EndProperty; virtual; abstract;
  985. //Please don't use write, better use WriteBinary whenever possible
  986. procedure Write(const Buffer : TBytes; Count: Longint); virtual;abstract;
  987. Procedure FlushBuffer; virtual; abstract;
  988. procedure WriteBinary(const Buffer : TBytes; Count: Longint); virtual; abstract;
  989. procedure WriteBoolean(Value: Boolean); virtual; abstract;
  990. // procedure WriteChar(Value: Char);
  991. procedure WriteFloat(const Value: Extended); virtual; abstract;
  992. procedure WriteCurrency(const Value: Currency); virtual; abstract;
  993. procedure WriteIdent(const Ident: string); virtual; abstract;
  994. procedure WriteInteger(Value: NativeInt); virtual; abstract;
  995. procedure WriteNativeInt(Value: NativeInt); virtual; abstract;
  996. procedure WriteVariant(const Value: JSValue); virtual; abstract;
  997. procedure WriteMethodName(const Name: String); virtual; abstract;
  998. procedure WriteSet(Value: LongInt; SetType: Pointer); virtual; abstract;
  999. procedure WriteString(const Value: String); virtual; abstract;
  1000. procedure WriteWideString(const Value: WideString);virtual;abstract;
  1001. procedure WriteUnicodeString(const Value: UnicodeString);virtual;abstract;
  1002. end;
  1003. { TBinaryObjectWriter }
  1004. TBinaryObjectWriter = class(TAbstractObjectWriter)
  1005. protected
  1006. FStream: TStream;
  1007. FBuffer: Pointer;
  1008. FBufSize: Integer;
  1009. FBufPos: Integer;
  1010. FBufEnd: Integer;
  1011. procedure WriteWord(w : word);
  1012. procedure WriteDWord(lw : longword);
  1013. procedure WriteValue(Value: TValueType);
  1014. public
  1015. constructor Create(Stream: TStream);
  1016. procedure WriteSignature; override;
  1017. procedure BeginCollection; override;
  1018. procedure BeginComponent(Component: TComponent; Flags: TFilerFlags;
  1019. ChildPos: Integer); override;
  1020. procedure BeginList; override;
  1021. procedure EndList; override;
  1022. procedure BeginProperty(const PropName: String); override;
  1023. procedure EndProperty; override;
  1024. Procedure FlushBuffer; override;
  1025. //Please don't use write, better use WriteBinary whenever possible
  1026. procedure Write(const Buffer : TBytes; Count: Longint); override;
  1027. procedure WriteBinary(const Buffer : TBytes; Count: LongInt); override;
  1028. procedure WriteBoolean(Value: Boolean); override;
  1029. procedure WriteFloat(const Value: Extended); override;
  1030. procedure WriteCurrency(const Value: Currency); override;
  1031. procedure WriteIdent(const Ident: string); override;
  1032. procedure WriteInteger(Value: NativeInt); override;
  1033. procedure WriteNativeInt(Value: NativeInt); override;
  1034. procedure WriteMethodName(const Name: String); override;
  1035. procedure WriteSet(Value: LongInt; SetType: Pointer); override;
  1036. procedure WriteStr(const Value: String);
  1037. procedure WriteString(const Value: String); override;
  1038. procedure WriteWideString(const Value: WideString); override;
  1039. procedure WriteUnicodeString(const Value: UnicodeString); override;
  1040. procedure WriteVariant(const VarValue: JSValue);override;
  1041. end;
  1042. TFindAncestorEvent = procedure (Writer: TWriter; Component: TComponent;
  1043. const Name: string; var Ancestor, RootAncestor: TComponent) of object;
  1044. TWriteMethodPropertyEvent = procedure (Writer: TWriter; Instance: TPersistent;
  1045. PropInfo: TTypeMemberProperty;
  1046. const MethodValue, DefMethodValue: TMethod;
  1047. var Handled: boolean) of object;
  1048. { TWriter }
  1049. TWriter = class(TFiler)
  1050. private
  1051. FDriver: TAbstractObjectWriter;
  1052. FDestroyDriver: Boolean;
  1053. FRootAncestor: TComponent;
  1054. FPropPath: String;
  1055. FAncestors: TStringList;
  1056. FAncestorPos: Integer;
  1057. FCurrentPos: Integer;
  1058. FOnFindAncestor: TFindAncestorEvent;
  1059. FOnWriteMethodProperty: TWriteMethodPropertyEvent;
  1060. FOnWriteStringProperty:TReadWriteStringPropertyEvent;
  1061. procedure AddToAncestorList(Component: TComponent);
  1062. procedure WriteComponentData(Instance: TComponent);
  1063. Procedure DetermineAncestor(Component: TComponent);
  1064. procedure DoFindAncestor(Component : TComponent);
  1065. protected
  1066. procedure SetRoot(ARoot: TComponent); override;
  1067. procedure WriteBinary(AWriteData: TStreamProc);
  1068. procedure WriteProperty(Instance: TPersistent; PropInfo: TTypeMemberProperty);
  1069. procedure WriteProperties(Instance: TPersistent);
  1070. procedure WriteChildren(Component: TComponent);
  1071. function CreateDriver(Stream: TStream): TAbstractObjectWriter; virtual;
  1072. public
  1073. constructor Create(ADriver: TAbstractObjectWriter);
  1074. constructor Create(Stream: TStream);
  1075. destructor Destroy; override;
  1076. procedure DefineProperty(const Name: string;
  1077. ReadData: TReaderProc; AWriteData: TWriterProc;
  1078. HasData: Boolean); override;
  1079. procedure DefineBinaryProperty(const Name: string;
  1080. ReadData, AWriteData: TStreamProc;
  1081. HasData: Boolean); override;
  1082. Procedure FlushBuffer; override;
  1083. procedure Write(const Buffer : TBytes; Count: Longint); virtual;
  1084. procedure WriteBoolean(Value: Boolean);
  1085. procedure WriteCollection(Value: TCollection);
  1086. procedure WriteComponent(Component: TComponent);
  1087. procedure WriteChar(Value: Char);
  1088. procedure WriteWideChar(Value: WideChar);
  1089. procedure WriteDescendent(ARoot: TComponent; AAncestor: TComponent);
  1090. procedure WriteFloat(const Value: Extended);
  1091. procedure WriteCurrency(const Value: Currency);
  1092. procedure WriteIdent(const Ident: string);
  1093. procedure WriteInteger(Value: Longint); overload;
  1094. procedure WriteInteger(Value: NativeInt); overload;
  1095. procedure WriteSet(Value: LongInt; SetType: Pointer);
  1096. procedure WriteListBegin;
  1097. procedure WriteListEnd;
  1098. Procedure WriteSignature;
  1099. procedure WriteRootComponent(ARoot: TComponent);
  1100. procedure WriteString(const Value: string);
  1101. procedure WriteWideString(const Value: WideString);
  1102. procedure WriteUnicodeString(const Value: UnicodeString);
  1103. procedure WriteVariant(const VarValue: JSValue);
  1104. property RootAncestor: TComponent read FRootAncestor write FRootAncestor;
  1105. property OnFindAncestor: TFindAncestorEvent read FOnFindAncestor write FOnFindAncestor;
  1106. property OnWriteMethodProperty: TWriteMethodPropertyEvent read FOnWriteMethodProperty write FOnWriteMethodProperty;
  1107. property OnWriteStringProperty: TReadWriteStringPropertyEvent read FOnWriteStringProperty write FOnWriteStringProperty;
  1108. property Driver: TAbstractObjectWriter read FDriver;
  1109. property PropertyPath: string read FPropPath;
  1110. end;
  1111. type
  1112. TIdentMapEntry = record
  1113. Value: Integer;
  1114. Name: String;
  1115. end;
  1116. TIdentToInt = function(const Ident: string; var Int: Longint): Boolean;
  1117. TIntToIdent = function(Int: Longint; var Ident: string): Boolean;
  1118. TFindGlobalComponent = function(const Name: string): TComponent;
  1119. TInitComponentHandler = function(Instance: TComponent; RootAncestor : TClass): boolean;
  1120. procedure RegisterInitComponentHandler(ComponentClass: TComponentClass; Handler: TInitComponentHandler);
  1121. Procedure RegisterClass(AClass : TPersistentClass);
  1122. Function GetClass(AClassName : string) : TPersistentClass;
  1123. procedure RegisterFindGlobalComponentProc(AFindGlobalComponent: TFindGlobalComponent);
  1124. procedure UnregisterFindGlobalComponentProc(AFindGlobalComponent: TFindGlobalComponent);
  1125. function FindGlobalComponent(const Name: string): TComponent;
  1126. Function FindNestedComponent(Root : TComponent; APath : String; CStyle : Boolean = True) : TComponent;
  1127. procedure RedirectFixupReferences(Root: TComponent; const OldRootName, NewRootName: string);
  1128. procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
  1129. procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToIntFn: TIdentToInt; IntToIdentFn: TIntToIdent);
  1130. function IdentToInt(const Ident: string; out Int: Longint; const Map: array of TIdentMapEntry): Boolean;
  1131. function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean;
  1132. function FindIntToIdent(AIntegerType: Pointer): TIntToIdent;
  1133. function FindIdentToInt(AIntegerType: Pointer): TIdentToInt;
  1134. function FindClass(const AClassName: string): TPersistentClass;
  1135. function CollectionsEqual(C1, C2: TCollection): Boolean;
  1136. function CollectionsEqual(C1, C2: TCollection; Owner1, Owner2: TComponent): Boolean;
  1137. procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
  1138. procedure GetFixupInstanceNames(Root: TComponent; const ReferenceRootName: string; Names: TStrings);
  1139. Const
  1140. vaSingle = vaDouble;
  1141. vaExtended = vaDouble;
  1142. vaLString = vaString;
  1143. vaUTF8String = vaString;
  1144. vaUString = vaString;
  1145. vaWString = vaString;
  1146. vaQWord = vaNativeInt;
  1147. vaInt64 = vaNativeInt;
  1148. implementation
  1149. uses simplelinkedlist;
  1150. var
  1151. GlobalLoaded,
  1152. IntConstList: TFPList;
  1153. type
  1154. TIntConst = class
  1155. Private
  1156. IntegerType: PTypeInfo; // The integer type RTTI pointer
  1157. IdentToIntFn: TIdentToInt; // Identifier to Integer conversion
  1158. IntToIdentFn: TIntToIdent; // Integer to Identifier conversion
  1159. Public
  1160. constructor Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
  1161. AIntToIdent: TIntToIdent);
  1162. end;
  1163. constructor TIntConst.Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
  1164. AIntToIdent: TIntToIdent);
  1165. begin
  1166. IntegerType := AIntegerType;
  1167. IdentToIntFn := AIdentToInt;
  1168. IntToIdentFn := AIntToIdent;
  1169. end;
  1170. procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToIntFn: TIdentToInt;
  1171. IntToIdentFn: TIntToIdent);
  1172. begin
  1173. if Not Assigned(IntConstList) then
  1174. IntConstList:=TFPList.Create;
  1175. IntConstList.Add(TIntConst.Create(IntegerType, IdentToIntFn, IntToIdentFn));
  1176. end;
  1177. function FindIntToIdent(AIntegerType: Pointer): TIntToIdent;
  1178. var
  1179. i: Integer;
  1180. begin
  1181. Result := nil;
  1182. if Not Assigned(IntConstList) then
  1183. exit;
  1184. with IntConstList do
  1185. for i := 0 to Count - 1 do
  1186. if TIntConst(Items[i]).IntegerType = AIntegerType then
  1187. exit(TIntConst(Items[i]).IntToIdentFn);
  1188. end;
  1189. function FindIdentToInt(AIntegerType: Pointer): TIdentToInt;
  1190. var
  1191. i: Integer;
  1192. begin
  1193. Result := nil;
  1194. if Not Assigned(IntConstList) then
  1195. exit;
  1196. with IntConstList do
  1197. for i := 0 to Count - 1 do
  1198. with TIntConst(Items[I]) do
  1199. if TIntConst(Items[I]).IntegerType = AIntegerType then
  1200. exit(IdentToIntFn);
  1201. end;
  1202. function IdentToInt(const Ident: String; out Int: LongInt;
  1203. const Map: array of TIdentMapEntry): Boolean;
  1204. var
  1205. i: Integer;
  1206. begin
  1207. for i := Low(Map) to High(Map) do
  1208. if CompareText(Map[i].Name, Ident) = 0 then
  1209. begin
  1210. Int := Map[i].Value;
  1211. exit(True);
  1212. end;
  1213. Result := False;
  1214. end;
  1215. function IntToIdent(Int: LongInt; var Ident: String;
  1216. const Map: array of TIdentMapEntry): Boolean;
  1217. var
  1218. i: Integer;
  1219. begin
  1220. for i := Low(Map) to High(Map) do
  1221. if Map[i].Value = Int then
  1222. begin
  1223. Ident := Map[i].Name;
  1224. exit(True);
  1225. end;
  1226. Result := False;
  1227. end;
  1228. function GlobalIdentToInt(const Ident: String; var Int: LongInt):boolean;
  1229. var
  1230. i : Integer;
  1231. begin
  1232. Result := false;
  1233. if Not Assigned(IntConstList) then
  1234. exit;
  1235. with IntConstList do
  1236. for i := 0 to Count - 1 do
  1237. if TIntConst(Items[I]).IdentToIntFn(Ident, Int) then
  1238. Exit(True);
  1239. end;
  1240. function FindClass(const AClassName: string): TPersistentClass;
  1241. begin
  1242. Result := GetClass(AClassName);
  1243. if not Assigned(Result) then
  1244. raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
  1245. end;
  1246. function CollectionsEqual(C1, C2: TCollection): Boolean;
  1247. Var
  1248. Comp1,Comp2 : TComponent;
  1249. begin
  1250. Comp2:=Nil;
  1251. Comp1:=TComponent.Create;
  1252. try
  1253. Result:=CollectionsEqual(C1,C2,Comp1,Comp2);
  1254. finally
  1255. Comp1.Free;
  1256. Comp2.Free;
  1257. end;
  1258. end;
  1259. function CollectionsEqual(C1, C2: TCollection; Owner1, Owner2: TComponent): Boolean;
  1260. procedure stream_collection(s : tstream;c : tcollection;o : tcomponent);
  1261. var
  1262. w : twriter;
  1263. begin
  1264. w:=twriter.create(s);
  1265. try
  1266. w.root:=o;
  1267. w.flookuproot:=o;
  1268. w.writecollection(c);
  1269. finally
  1270. w.free;
  1271. end;
  1272. end;
  1273. var
  1274. s1,s2 : tbytesstream;
  1275. b1,b2 : TBytes;
  1276. I,Len : Integer;
  1277. begin
  1278. result:=false;
  1279. if (c1.classtype<>c2.classtype) or
  1280. (c1.count<>c2.count) then
  1281. exit;
  1282. if c1.count = 0 then
  1283. begin
  1284. result:= true;
  1285. exit;
  1286. end;
  1287. s2:=Nil;
  1288. s1:=tbytesstream.create;
  1289. try
  1290. s2:=tbytesstream.create;
  1291. stream_collection(s1,c1,owner1);
  1292. stream_collection(s2,c2,owner2);
  1293. result:=(s1.size=s2.size);
  1294. if Result then
  1295. begin
  1296. b1:=S1.Bytes;
  1297. b2:=S2.Bytes;
  1298. I:=0;
  1299. Len:=S1.Size; // Not length of B
  1300. While Result and (I<Len) do
  1301. begin
  1302. Result:=b1[I]=b2[i];
  1303. Inc(i);
  1304. end;
  1305. end;
  1306. finally
  1307. s2.free;
  1308. s1.free;
  1309. end;
  1310. end;
  1311. { TInterfacedPersistent }
  1312. function TInterfacedPersistent._AddRef: Integer;
  1313. begin
  1314. Result:=-1;
  1315. if Assigned(FOwnerInterface) then
  1316. Result:=FOwnerInterface._AddRef;
  1317. end;
  1318. function TInterfacedPersistent._Release: Integer;
  1319. begin
  1320. Result:=-1;
  1321. if Assigned(FOwnerInterface) then
  1322. Result:=FOwnerInterface._Release;
  1323. end;
  1324. function TInterfacedPersistent.QueryInterface(const IID: TGUID; out Obj): integer;
  1325. begin
  1326. Result:=E_NOINTERFACE;
  1327. if GetInterface(IID, Obj) then
  1328. Result:=0;
  1329. end;
  1330. procedure TInterfacedPersistent.AfterConstruction;
  1331. begin
  1332. inherited AfterConstruction;
  1333. if (GetOwner<>nil) then
  1334. GetOwner.GetInterface(IInterface, FOwnerInterface);
  1335. end;
  1336. { TComponentEnumerator }
  1337. constructor TComponentEnumerator.Create(AComponent: TComponent);
  1338. begin
  1339. inherited Create;
  1340. FComponent := AComponent;
  1341. FPosition := -1;
  1342. end;
  1343. function TComponentEnumerator.GetCurrent: TComponent;
  1344. begin
  1345. Result := FComponent.Components[FPosition];
  1346. end;
  1347. function TComponentEnumerator.MoveNext: Boolean;
  1348. begin
  1349. Inc(FPosition);
  1350. Result := FPosition < FComponent.ComponentCount;
  1351. end;
  1352. { TListEnumerator }
  1353. constructor TListEnumerator.Create(AList: TList);
  1354. begin
  1355. inherited Create;
  1356. FList := AList;
  1357. FPosition := -1;
  1358. end;
  1359. function TListEnumerator.GetCurrent: JSValue;
  1360. begin
  1361. Result := FList[FPosition];
  1362. end;
  1363. function TListEnumerator.MoveNext: Boolean;
  1364. begin
  1365. Inc(FPosition);
  1366. Result := FPosition < FList.Count;
  1367. end;
  1368. { TFPListEnumerator }
  1369. constructor TFPListEnumerator.Create(AList: TFPList);
  1370. begin
  1371. inherited Create;
  1372. FList := AList;
  1373. FPosition := -1;
  1374. end;
  1375. function TFPListEnumerator.GetCurrent: JSValue;
  1376. begin
  1377. Result := FList[FPosition];
  1378. end;
  1379. function TFPListEnumerator.MoveNext: Boolean;
  1380. begin
  1381. Inc(FPosition);
  1382. Result := FPosition < FList.Count;
  1383. end;
  1384. { TFPList }
  1385. procedure TFPList.CopyMove(aList: TFPList);
  1386. var r : integer;
  1387. begin
  1388. Clear;
  1389. for r := 0 to aList.count-1 do
  1390. Add(aList[r]);
  1391. end;
  1392. procedure TFPList.MergeMove(aList: TFPList);
  1393. var r : integer;
  1394. begin
  1395. For r := 0 to aList.count-1 do
  1396. if IndexOf(aList[r]) < 0 then
  1397. Add(aList[r]);
  1398. end;
  1399. procedure TFPList.DoCopy(ListA, ListB: TFPList);
  1400. begin
  1401. if Assigned(ListB) then
  1402. CopyMove(ListB)
  1403. else
  1404. CopyMove(ListA);
  1405. end;
  1406. procedure TFPList.DoSrcUnique(ListA, ListB: TFPList);
  1407. var r : integer;
  1408. begin
  1409. if Assigned(ListB) then
  1410. begin
  1411. Clear;
  1412. for r := 0 to ListA.Count-1 do
  1413. if ListB.IndexOf(ListA[r]) < 0 then
  1414. Add(ListA[r]);
  1415. end
  1416. else
  1417. begin
  1418. for r := Count-1 downto 0 do
  1419. if ListA.IndexOf(Self[r]) >= 0 then
  1420. Delete(r);
  1421. end;
  1422. end;
  1423. procedure TFPList.DoAnd(ListA, ListB: TFPList);
  1424. var r : integer;
  1425. begin
  1426. if Assigned(ListB) then
  1427. begin
  1428. Clear;
  1429. for r := 0 to ListA.count-1 do
  1430. if ListB.IndexOf(ListA[r]) >= 0 then
  1431. Add(ListA[r]);
  1432. end
  1433. else
  1434. begin
  1435. for r := Count-1 downto 0 do
  1436. if ListA.IndexOf(Self[r]) < 0 then
  1437. Delete(r);
  1438. end;
  1439. end;
  1440. procedure TFPList.DoDestUnique(ListA, ListB: TFPList);
  1441. procedure MoveElements(Src, Dest: TFPList);
  1442. var r : integer;
  1443. begin
  1444. Clear;
  1445. for r := 0 to Src.count-1 do
  1446. if Dest.IndexOf(Src[r]) < 0 then
  1447. self.Add(Src[r]);
  1448. end;
  1449. var Dest : TFPList;
  1450. begin
  1451. if Assigned(ListB) then
  1452. MoveElements(ListB, ListA)
  1453. else
  1454. Dest := TFPList.Create;
  1455. try
  1456. Dest.CopyMove(Self);
  1457. MoveElements(ListA, Dest)
  1458. finally
  1459. Dest.Destroy;
  1460. end;
  1461. end;
  1462. procedure TFPList.DoOr(ListA, ListB: TFPList);
  1463. begin
  1464. if Assigned(ListB) then
  1465. begin
  1466. CopyMove(ListA);
  1467. MergeMove(ListB);
  1468. end
  1469. else
  1470. MergeMove(ListA);
  1471. end;
  1472. procedure TFPList.DoXOr(ListA, ListB: TFPList);
  1473. var
  1474. r : integer;
  1475. l : TFPList;
  1476. begin
  1477. if Assigned(ListB) then
  1478. begin
  1479. Clear;
  1480. for r := 0 to ListA.Count-1 do
  1481. if ListB.IndexOf(ListA[r]) < 0 then
  1482. Add(ListA[r]);
  1483. for r := 0 to ListB.Count-1 do
  1484. if ListA.IndexOf(ListB[r]) < 0 then
  1485. Add(ListB[r]);
  1486. end
  1487. else
  1488. begin
  1489. l := TFPList.Create;
  1490. try
  1491. l.CopyMove(Self);
  1492. for r := Count-1 downto 0 do
  1493. if listA.IndexOf(Self[r]) >= 0 then
  1494. Delete(r);
  1495. for r := 0 to ListA.Count-1 do
  1496. if l.IndexOf(ListA[r]) < 0 then
  1497. Add(ListA[r]);
  1498. finally
  1499. l.Destroy;
  1500. end;
  1501. end;
  1502. end;
  1503. function TFPList.Get(Index: Integer): JSValue;
  1504. begin
  1505. If (Index < 0) or (Index >= FCount) then
  1506. RaiseIndexError(Index);
  1507. Result:=FList[Index];
  1508. end;
  1509. procedure TFPList.Put(Index: Integer; Item: JSValue);
  1510. begin
  1511. if (Index < 0) or (Index >= FCount) then
  1512. RaiseIndexError(Index);
  1513. FList[Index] := Item;
  1514. end;
  1515. procedure TFPList.SetCapacity(NewCapacity: Integer);
  1516. begin
  1517. If (NewCapacity < FCount) then
  1518. Error (SListCapacityError, str(NewCapacity));
  1519. if NewCapacity = FCapacity then
  1520. exit;
  1521. SetLength(FList,NewCapacity);
  1522. FCapacity := NewCapacity;
  1523. end;
  1524. procedure TFPList.SetCount(NewCount: Integer);
  1525. begin
  1526. if (NewCount < 0) then
  1527. Error(SListCountError, str(NewCount));
  1528. If NewCount > FCount then
  1529. begin
  1530. If NewCount > FCapacity then
  1531. SetCapacity(NewCount);
  1532. end;
  1533. FCount := NewCount;
  1534. end;
  1535. procedure TFPList.RaiseIndexError(Index: Integer);
  1536. begin
  1537. Error(SListIndexError, str(Index));
  1538. end;
  1539. destructor TFPList.Destroy;
  1540. begin
  1541. Clear;
  1542. inherited Destroy;
  1543. end;
  1544. procedure TFPList.AddList(AList: TFPList);
  1545. Var
  1546. I : Integer;
  1547. begin
  1548. If (Capacity<Count+AList.Count) then
  1549. Capacity:=Count+AList.Count;
  1550. For I:=0 to AList.Count-1 do
  1551. Add(AList[i]);
  1552. end;
  1553. function TFPList.Add(Item: JSValue): Integer;
  1554. begin
  1555. if FCount = FCapacity then
  1556. Expand;
  1557. FList[FCount] := Item;
  1558. Result := FCount;
  1559. Inc(FCount);
  1560. end;
  1561. procedure TFPList.Clear;
  1562. begin
  1563. if Assigned(FList) then
  1564. begin
  1565. SetCount(0);
  1566. SetCapacity(0);
  1567. end;
  1568. end;
  1569. procedure TFPList.Delete(Index: Integer);
  1570. begin
  1571. If (Index<0) or (Index>=FCount) then
  1572. Error (SListIndexError, str(Index));
  1573. FCount := FCount-1;
  1574. System.Delete(FList,Index,1);
  1575. Dec(FCapacity);
  1576. end;
  1577. class procedure TFPList.Error(const Msg: string; const Data: String);
  1578. begin
  1579. Raise EListError.CreateFmt(Msg,[Data]);
  1580. end;
  1581. procedure TFPList.Exchange(Index1, Index2: Integer);
  1582. var
  1583. Temp : JSValue;
  1584. begin
  1585. If (Index1 >= FCount) or (Index1 < 0) then
  1586. Error(SListIndexError, str(Index1));
  1587. If (Index2 >= FCount) or (Index2 < 0) then
  1588. Error(SListIndexError, str(Index2));
  1589. Temp := FList[Index1];
  1590. FList[Index1] := FList[Index2];
  1591. FList[Index2] := Temp;
  1592. end;
  1593. function TFPList.Expand: TFPList;
  1594. var
  1595. IncSize : Integer;
  1596. begin
  1597. if FCount < FCapacity then exit(self);
  1598. IncSize := 4;
  1599. if FCapacity > 3 then IncSize := IncSize + 4;
  1600. if FCapacity > 8 then IncSize := IncSize+8;
  1601. if FCapacity > 127 then Inc(IncSize, FCapacity shr 2);
  1602. SetCapacity(FCapacity + IncSize);
  1603. Result := Self;
  1604. end;
  1605. function TFPList.Extract(Item: JSValue): JSValue;
  1606. var
  1607. i : Integer;
  1608. begin
  1609. i := IndexOf(Item);
  1610. if i >= 0 then
  1611. begin
  1612. Result := Item;
  1613. Delete(i);
  1614. end
  1615. else
  1616. Result := nil;
  1617. end;
  1618. function TFPList.First: JSValue;
  1619. begin
  1620. If FCount = 0 then
  1621. Result := Nil
  1622. else
  1623. Result := Items[0];
  1624. end;
  1625. function TFPList.GetEnumerator: TFPListEnumerator;
  1626. begin
  1627. Result:=TFPListEnumerator.Create(Self);
  1628. end;
  1629. function TFPList.IndexOf(Item: JSValue): Integer;
  1630. Var
  1631. C : Integer;
  1632. begin
  1633. Result:=0;
  1634. C:=Count;
  1635. while (Result<C) and (FList[Result]<>Item) do
  1636. Inc(Result);
  1637. If Result>=C then
  1638. Result:=-1;
  1639. end;
  1640. function TFPList.IndexOfItem(Item: JSValue; Direction: TDirection): Integer;
  1641. begin
  1642. if Direction=fromBeginning then
  1643. Result:=IndexOf(Item)
  1644. else
  1645. begin
  1646. Result:=Count-1;
  1647. while (Result >=0) and (Flist[Result]<>Item) do
  1648. Result:=Result - 1;
  1649. end;
  1650. end;
  1651. procedure TFPList.Insert(Index: Integer; Item: JSValue);
  1652. begin
  1653. if (Index < 0) or (Index > FCount )then
  1654. Error(SlistIndexError, str(Index));
  1655. TJSArray(FList).splice(Index, 0, Item);
  1656. inc(FCapacity);
  1657. inc(FCount);
  1658. end;
  1659. function TFPList.Last: JSValue;
  1660. begin
  1661. If FCount = 0 then
  1662. Result := nil
  1663. else
  1664. Result := Items[FCount - 1];
  1665. end;
  1666. procedure TFPList.Move(CurIndex, NewIndex: Integer);
  1667. var
  1668. Temp: JSValue;
  1669. begin
  1670. if (CurIndex < 0) or (CurIndex > Count - 1) then
  1671. Error(SListIndexError, str(CurIndex));
  1672. if (NewIndex < 0) or (NewIndex > Count -1) then
  1673. Error(SlistIndexError, str(NewIndex));
  1674. if CurIndex=NewIndex then exit;
  1675. Temp:=FList[CurIndex];
  1676. // ToDo: use TJSArray.copyWithin if available
  1677. TJSArray(FList).splice(CurIndex,1);
  1678. TJSArray(FList).splice(NewIndex,0,Temp);
  1679. end;
  1680. procedure TFPList.Assign(ListA: TFPList; AOperator: TListAssignOp;
  1681. ListB: TFPList);
  1682. begin
  1683. case AOperator of
  1684. laCopy : DoCopy (ListA, ListB); // replace dest with src
  1685. laSrcUnique : DoSrcUnique (ListA, ListB); // replace dest with src that are not in dest
  1686. laAnd : DoAnd (ListA, ListB); // remove from dest that are not in src
  1687. laDestUnique: DoDestUnique (ListA, ListB);// remove from dest that are in src
  1688. laOr : DoOr (ListA, ListB); // add to dest from src and not in dest
  1689. laXOr : DoXOr (ListA, ListB); // add to dest from src and not in dest, remove from dest that are in src
  1690. end;
  1691. end;
  1692. function TFPList.Remove(Item: JSValue): Integer;
  1693. begin
  1694. Result := IndexOf(Item);
  1695. If Result <> -1 then
  1696. Delete(Result);
  1697. end;
  1698. procedure TFPList.Pack;
  1699. var
  1700. Dst, i: Integer;
  1701. V: JSValue;
  1702. begin
  1703. Dst:=0;
  1704. for i:=0 to Count-1 do
  1705. begin
  1706. V:=FList[i];
  1707. if not Assigned(V) then continue;
  1708. FList[Dst]:=V;
  1709. inc(Dst);
  1710. end;
  1711. end;
  1712. // Needed by Sort method.
  1713. Procedure QuickSort(aList: TJSValueDynArray; L, R : Longint;
  1714. const Compare: TListSortCompare);
  1715. var
  1716. I, J : Longint;
  1717. P, Q : JSValue;
  1718. begin
  1719. repeat
  1720. I := L;
  1721. J := R;
  1722. P := aList[ (L + R) div 2 ];
  1723. repeat
  1724. while Compare(P, aList[i]) > 0 do
  1725. I := I + 1;
  1726. while Compare(P, aList[J]) < 0 do
  1727. J := J - 1;
  1728. If I <= J then
  1729. begin
  1730. Q := aList[I];
  1731. aList[I] := aList[J];
  1732. aList[J] := Q;
  1733. I := I + 1;
  1734. J := J - 1;
  1735. end;
  1736. until I > J;
  1737. // sort the smaller range recursively
  1738. // sort the bigger range via the loop
  1739. // Reasons: memory usage is O(log(n)) instead of O(n) and loop is faster than recursion
  1740. if J - L < R - I then
  1741. begin
  1742. if L < J then
  1743. QuickSort(aList, L, J, Compare);
  1744. L := I;
  1745. end
  1746. else
  1747. begin
  1748. if I < R then
  1749. QuickSort(aList, I, R, Compare);
  1750. R := J;
  1751. end;
  1752. until L >= R;
  1753. end;
  1754. procedure TFPList.Sort(const Compare: TListSortCompare);
  1755. begin
  1756. if Not Assigned(FList) or (FCount < 2) then exit;
  1757. QuickSort(Flist, 0, FCount-1, Compare);
  1758. end;
  1759. procedure TFPList.ForEachCall(const proc2call: TListCallback; const arg: JSValue
  1760. );
  1761. var
  1762. i : integer;
  1763. v : JSValue;
  1764. begin
  1765. For I:=0 To Count-1 Do
  1766. begin
  1767. v:=FList[i];
  1768. if Assigned(v) then
  1769. proc2call(v,arg);
  1770. end;
  1771. end;
  1772. procedure TFPList.ForEachCall(const proc2call: TListStaticCallback;
  1773. const arg: JSValue);
  1774. var
  1775. i : integer;
  1776. v : JSValue;
  1777. begin
  1778. For I:=0 To Count-1 Do
  1779. begin
  1780. v:=FList[i];
  1781. if Assigned(v) then
  1782. proc2call(v,arg);
  1783. end;
  1784. end;
  1785. { TList }
  1786. procedure TList.CopyMove(aList: TList);
  1787. var
  1788. r : integer;
  1789. begin
  1790. Clear;
  1791. for r := 0 to aList.count-1 do
  1792. Add(aList[r]);
  1793. end;
  1794. procedure TList.MergeMove(aList: TList);
  1795. var r : integer;
  1796. begin
  1797. For r := 0 to aList.count-1 do
  1798. if IndexOf(aList[r]) < 0 then
  1799. Add(aList[r]);
  1800. end;
  1801. procedure TList.DoCopy(ListA, ListB: TList);
  1802. begin
  1803. if Assigned(ListB) then
  1804. CopyMove(ListB)
  1805. else
  1806. CopyMove(ListA);
  1807. end;
  1808. procedure TList.DoSrcUnique(ListA, ListB: TList);
  1809. var r : integer;
  1810. begin
  1811. if Assigned(ListB) then
  1812. begin
  1813. Clear;
  1814. for r := 0 to ListA.Count-1 do
  1815. if ListB.IndexOf(ListA[r]) < 0 then
  1816. Add(ListA[r]);
  1817. end
  1818. else
  1819. begin
  1820. for r := Count-1 downto 0 do
  1821. if ListA.IndexOf(Self[r]) >= 0 then
  1822. Delete(r);
  1823. end;
  1824. end;
  1825. procedure TList.DoAnd(ListA, ListB: TList);
  1826. var r : integer;
  1827. begin
  1828. if Assigned(ListB) then
  1829. begin
  1830. Clear;
  1831. for r := 0 to ListA.Count-1 do
  1832. if ListB.IndexOf(ListA[r]) >= 0 then
  1833. Add(ListA[r]);
  1834. end
  1835. else
  1836. begin
  1837. for r := Count-1 downto 0 do
  1838. if ListA.IndexOf(Self[r]) < 0 then
  1839. Delete(r);
  1840. end;
  1841. end;
  1842. procedure TList.DoDestUnique(ListA, ListB: TList);
  1843. procedure MoveElements(Src, Dest : TList);
  1844. var r : integer;
  1845. begin
  1846. Clear;
  1847. for r := 0 to Src.Count-1 do
  1848. if Dest.IndexOf(Src[r]) < 0 then
  1849. Add(Src[r]);
  1850. end;
  1851. var Dest : TList;
  1852. begin
  1853. if Assigned(ListB) then
  1854. MoveElements(ListB, ListA)
  1855. else
  1856. try
  1857. Dest := TList.Create;
  1858. Dest.CopyMove(Self);
  1859. MoveElements(ListA, Dest)
  1860. finally
  1861. Dest.Destroy;
  1862. end;
  1863. end;
  1864. procedure TList.DoOr(ListA, ListB: TList);
  1865. begin
  1866. if Assigned(ListB) then
  1867. begin
  1868. CopyMove(ListA);
  1869. MergeMove(ListB);
  1870. end
  1871. else
  1872. MergeMove(ListA);
  1873. end;
  1874. procedure TList.DoXOr(ListA, ListB: TList);
  1875. var
  1876. r : integer;
  1877. l : TList;
  1878. begin
  1879. if Assigned(ListB) then
  1880. begin
  1881. Clear;
  1882. for r := 0 to ListA.Count-1 do
  1883. if ListB.IndexOf(ListA[r]) < 0 then
  1884. Add(ListA[r]);
  1885. for r := 0 to ListB.Count-1 do
  1886. if ListA.IndexOf(ListB[r]) < 0 then
  1887. Add(ListB[r]);
  1888. end
  1889. else
  1890. try
  1891. l := TList.Create;
  1892. l.CopyMove (Self);
  1893. for r := Count-1 downto 0 do
  1894. if listA.IndexOf(Self[r]) >= 0 then
  1895. Delete(r);
  1896. for r := 0 to ListA.Count-1 do
  1897. if l.IndexOf(ListA[r]) < 0 then
  1898. Add(ListA[r]);
  1899. finally
  1900. l.Destroy;
  1901. end;
  1902. end;
  1903. function TList.Get(Index: Integer): JSValue;
  1904. begin
  1905. Result := FList.Get(Index);
  1906. end;
  1907. procedure TList.Put(Index: Integer; Item: JSValue);
  1908. var V : JSValue;
  1909. begin
  1910. V := Get(Index);
  1911. FList.Put(Index, Item);
  1912. if Assigned(V) then
  1913. Notify(V, lnDeleted);
  1914. if Assigned(Item) then
  1915. Notify(Item, lnAdded);
  1916. end;
  1917. procedure TList.Notify(aValue: JSValue; Action: TListNotification);
  1918. begin
  1919. if Assigned(aValue) then ;
  1920. if Action=lnExtracted then ;
  1921. end;
  1922. procedure TList.SetCapacity(NewCapacity: Integer);
  1923. begin
  1924. FList.SetCapacity(NewCapacity);
  1925. end;
  1926. function TList.GetCapacity: integer;
  1927. begin
  1928. Result := FList.Capacity;
  1929. end;
  1930. procedure TList.SetCount(NewCount: Integer);
  1931. begin
  1932. if NewCount < FList.Count then
  1933. while FList.Count > NewCount do
  1934. Delete(FList.Count - 1)
  1935. else
  1936. FList.SetCount(NewCount);
  1937. end;
  1938. function TList.GetCount: integer;
  1939. begin
  1940. Result := FList.Count;
  1941. end;
  1942. function TList.GetList: TJSValueDynArray;
  1943. begin
  1944. Result := FList.List;
  1945. end;
  1946. constructor TList.Create;
  1947. begin
  1948. inherited Create;
  1949. FList := TFPList.Create;
  1950. end;
  1951. destructor TList.Destroy;
  1952. begin
  1953. if Assigned(FList) then
  1954. Clear;
  1955. FreeAndNil(FList);
  1956. end;
  1957. procedure TList.AddList(AList: TList);
  1958. var
  1959. I: Integer;
  1960. begin
  1961. { this only does FList.AddList(AList.FList), avoiding notifications }
  1962. FList.AddList(AList.FList);
  1963. { make lnAdded notifications }
  1964. for I := 0 to AList.Count - 1 do
  1965. if Assigned(AList[I]) then
  1966. Notify(AList[I], lnAdded);
  1967. end;
  1968. function TList.Add(Item: JSValue): Integer;
  1969. begin
  1970. Result := FList.Add(Item);
  1971. if Assigned(Item) then
  1972. Notify(Item, lnAdded);
  1973. end;
  1974. procedure TList.Clear;
  1975. begin
  1976. While (FList.Count>0) do
  1977. Delete(Count-1);
  1978. end;
  1979. procedure TList.Delete(Index: Integer);
  1980. var V : JSValue;
  1981. begin
  1982. V:=FList.Get(Index);
  1983. FList.Delete(Index);
  1984. if assigned(V) then
  1985. Notify(V, lnDeleted);
  1986. end;
  1987. class procedure TList.Error(const Msg: string; Data: String);
  1988. begin
  1989. Raise EListError.CreateFmt(Msg,[Data]);
  1990. end;
  1991. procedure TList.Exchange(Index1, Index2: Integer);
  1992. begin
  1993. FList.Exchange(Index1, Index2);
  1994. end;
  1995. function TList.Expand: TList;
  1996. begin
  1997. FList.Expand;
  1998. Result:=Self;
  1999. end;
  2000. function TList.Extract(Item: JSValue): JSValue;
  2001. var c : integer;
  2002. begin
  2003. c := FList.Count;
  2004. Result := FList.Extract(Item);
  2005. if c <> FList.Count then
  2006. Notify (Result, lnExtracted);
  2007. end;
  2008. function TList.First: JSValue;
  2009. begin
  2010. Result := FList.First;
  2011. end;
  2012. function TList.GetEnumerator: TListEnumerator;
  2013. begin
  2014. Result:=TListEnumerator.Create(Self);
  2015. end;
  2016. function TList.IndexOf(Item: JSValue): Integer;
  2017. begin
  2018. Result := FList.IndexOf(Item);
  2019. end;
  2020. procedure TList.Insert(Index: Integer; Item: JSValue);
  2021. begin
  2022. FList.Insert(Index, Item);
  2023. if Assigned(Item) then
  2024. Notify(Item,lnAdded);
  2025. end;
  2026. function TList.Last: JSValue;
  2027. begin
  2028. Result := FList.Last;
  2029. end;
  2030. procedure TList.Move(CurIndex, NewIndex: Integer);
  2031. begin
  2032. FList.Move(CurIndex, NewIndex);
  2033. end;
  2034. procedure TList.Assign(ListA: TList; AOperator: TListAssignOp; ListB: TList);
  2035. begin
  2036. case AOperator of
  2037. laCopy : DoCopy (ListA, ListB); // replace dest with src
  2038. laSrcUnique : DoSrcUnique (ListA, ListB); // replace dest with src that are not in dest
  2039. laAnd : DoAnd (ListA, ListB); // remove from dest that are not in src
  2040. laDestUnique: DoDestUnique (ListA, ListB);// remove from dest that are in src
  2041. laOr : DoOr (ListA, ListB); // add to dest from src and not in dest
  2042. laXOr : DoXOr (ListA, ListB); // add to dest from src and not in dest, remove from dest that are in src
  2043. end;
  2044. end;
  2045. function TList.Remove(Item: JSValue): Integer;
  2046. begin
  2047. Result := IndexOf(Item);
  2048. if Result <> -1 then
  2049. Self.Delete(Result);
  2050. end;
  2051. procedure TList.Pack;
  2052. begin
  2053. FList.Pack;
  2054. end;
  2055. procedure TList.Sort(const Compare: TListSortCompare);
  2056. begin
  2057. FList.Sort(Compare);
  2058. end;
  2059. { TPersistent }
  2060. procedure TPersistent.AssignError(Source: TPersistent);
  2061. var
  2062. SourceName: String;
  2063. begin
  2064. if Source<>Nil then
  2065. SourceName:=Source.ClassName
  2066. else
  2067. SourceName:='Nil';
  2068. raise EConvertError.Create('Cannot assign a '+SourceName+' to a '+ClassName+'.');
  2069. end;
  2070. procedure TPersistent.DefineProperties(Filer: TFiler);
  2071. begin
  2072. if Filer=Nil then exit;
  2073. // Do nothing
  2074. end;
  2075. procedure TPersistent.AssignTo(Dest: TPersistent);
  2076. begin
  2077. Dest.AssignError(Self);
  2078. end;
  2079. function TPersistent.GetOwner: TPersistent;
  2080. begin
  2081. Result:=nil;
  2082. end;
  2083. procedure TPersistent.Assign(Source: TPersistent);
  2084. begin
  2085. If Source<>Nil then
  2086. Source.AssignTo(Self)
  2087. else
  2088. AssignError(Nil);
  2089. end;
  2090. function TPersistent.GetNamePath: string;
  2091. var
  2092. OwnerName: String;
  2093. TheOwner: TPersistent;
  2094. begin
  2095. Result:=ClassName;
  2096. TheOwner:=GetOwner;
  2097. if TheOwner<>Nil then
  2098. begin
  2099. OwnerName:=TheOwner.GetNamePath;
  2100. if OwnerName<>'' then Result:=OwnerName+'.'+Result;
  2101. end;
  2102. end;
  2103. {
  2104. This file is part of the Free Component Library (FCL)
  2105. Copyright (c) 1999-2000 by the Free Pascal development team
  2106. See the file COPYING.FPC, included in this distribution,
  2107. for details about the copyright.
  2108. This program is distributed in the hope that it will be useful,
  2109. but WITHOUT ANY WARRANTY; without even the implied warranty of
  2110. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  2111. **********************************************************************}
  2112. {****************************************************************************}
  2113. {* TStringsEnumerator *}
  2114. {****************************************************************************}
  2115. constructor TStringsEnumerator.Create(AStrings: TStrings);
  2116. begin
  2117. inherited Create;
  2118. FStrings := AStrings;
  2119. FPosition := -1;
  2120. end;
  2121. function TStringsEnumerator.GetCurrent: String;
  2122. begin
  2123. Result := FStrings[FPosition];
  2124. end;
  2125. function TStringsEnumerator.MoveNext: Boolean;
  2126. begin
  2127. Inc(FPosition);
  2128. Result := FPosition < FStrings.Count;
  2129. end;
  2130. {****************************************************************************}
  2131. {* TStrings *}
  2132. {****************************************************************************}
  2133. // Function to quote text. Should move maybe to sysutils !!
  2134. // Also, it is not clear at this point what exactly should be done.
  2135. { //!! is used to mark unsupported things. }
  2136. {
  2137. For compatibility we can't add a Constructor to TSTrings to initialize
  2138. the special characters. Therefore we add a routine which is called whenever
  2139. the special chars are needed.
  2140. }
  2141. Procedure Tstrings.CheckSpecialChars;
  2142. begin
  2143. If Not FSpecialCharsInited then
  2144. begin
  2145. FQuoteChar:='"';
  2146. FDelimiter:=',';
  2147. FNameValueSeparator:='=';
  2148. FLBS:=DefaultTextLineBreakStyle;
  2149. FSpecialCharsInited:=true;
  2150. FLineBreak:=sLineBreak;
  2151. end;
  2152. end;
  2153. Function TStrings.GetSkipLastLineBreak : Boolean;
  2154. begin
  2155. CheckSpecialChars;
  2156. Result:=FSkipLastLineBreak;
  2157. end;
  2158. procedure TStrings.SetSkipLastLineBreak(const AValue : Boolean);
  2159. begin
  2160. CheckSpecialChars;
  2161. FSkipLastLineBreak:=AValue;
  2162. end;
  2163. Function TStrings.GetLBS : TTextLineBreakStyle;
  2164. begin
  2165. CheckSpecialChars;
  2166. Result:=FLBS;
  2167. end;
  2168. Procedure TStrings.SetLBS (AValue : TTextLineBreakStyle);
  2169. begin
  2170. CheckSpecialChars;
  2171. FLBS:=AValue;
  2172. end;
  2173. procedure TStrings.SetDelimiter(c:Char);
  2174. begin
  2175. CheckSpecialChars;
  2176. FDelimiter:=c;
  2177. end;
  2178. Function TStrings.GetDelimiter : Char;
  2179. begin
  2180. CheckSpecialChars;
  2181. Result:=FDelimiter;
  2182. end;
  2183. procedure TStrings.SetLineBreak(Const S : String);
  2184. begin
  2185. CheckSpecialChars;
  2186. FLineBreak:=S;
  2187. end;
  2188. Function TStrings.GetLineBreak : String;
  2189. begin
  2190. CheckSpecialChars;
  2191. Result:=FLineBreak;
  2192. end;
  2193. procedure TStrings.SetQuoteChar(c:Char);
  2194. begin
  2195. CheckSpecialChars;
  2196. FQuoteChar:=c;
  2197. end;
  2198. Function TStrings.GetQuoteChar :Char;
  2199. begin
  2200. CheckSpecialChars;
  2201. Result:=FQuoteChar;
  2202. end;
  2203. procedure TStrings.SetNameValueSeparator(c:Char);
  2204. begin
  2205. CheckSpecialChars;
  2206. FNameValueSeparator:=c;
  2207. end;
  2208. Function TStrings.GetNameValueSeparator :Char;
  2209. begin
  2210. CheckSpecialChars;
  2211. Result:=FNameValueSeparator;
  2212. end;
  2213. function TStrings.GetCommaText: string;
  2214. Var
  2215. C1,C2 : Char;
  2216. FSD : Boolean;
  2217. begin
  2218. CheckSpecialChars;
  2219. FSD:=StrictDelimiter;
  2220. C1:=Delimiter;
  2221. C2:=QuoteChar;
  2222. Delimiter:=',';
  2223. QuoteChar:='"';
  2224. StrictDelimiter:=False;
  2225. Try
  2226. Result:=GetDelimitedText;
  2227. Finally
  2228. Delimiter:=C1;
  2229. QuoteChar:=C2;
  2230. StrictDelimiter:=FSD;
  2231. end;
  2232. end;
  2233. Function TStrings.GetDelimitedText: string;
  2234. Var
  2235. I: integer;
  2236. RE : string;
  2237. S : String;
  2238. doQuote : Boolean;
  2239. begin
  2240. CheckSpecialChars;
  2241. result:='';
  2242. RE:=QuoteChar+'|'+Delimiter;
  2243. if not StrictDelimiter then
  2244. RE:=' |'+RE;
  2245. RE:='/'+RE+'/';
  2246. // Check for break characters and quote if required.
  2247. For i:=0 to count-1 do
  2248. begin
  2249. S:=Strings[i];
  2250. doQuote:=FAlwaysQuote or (TJSString(s).search(RE)<>-1);
  2251. if DoQuote then
  2252. Result:=Result+QuoteString(S,QuoteChar)
  2253. else
  2254. Result:=Result+S;
  2255. if I<Count-1 then
  2256. Result:=Result+Delimiter;
  2257. end;
  2258. // Quote empty string:
  2259. If (Length(Result)=0) and (Count=1) then
  2260. Result:=QuoteChar+QuoteChar;
  2261. end;
  2262. procedure TStrings.GetNameValue(Index : Integer; Out AName,AValue : String);
  2263. Var L : longint;
  2264. begin
  2265. CheckSpecialChars;
  2266. AValue:=Strings[Index];
  2267. L:=Pos(FNameValueSeparator,AValue);
  2268. If L<>0 then
  2269. begin
  2270. AName:=Copy(AValue,1,L-1);
  2271. // System.Delete(AValue,1,L);
  2272. AValue:=Copy(AValue,L+1,length(AValue)-L);
  2273. end
  2274. else
  2275. AName:='';
  2276. end;
  2277. function TStrings.ExtractName(const s:String):String;
  2278. var
  2279. L: Longint;
  2280. begin
  2281. CheckSpecialChars;
  2282. L:=Pos(FNameValueSeparator,S);
  2283. If L<>0 then
  2284. Result:=Copy(S,1,L-1)
  2285. else
  2286. Result:='';
  2287. end;
  2288. function TStrings.GetName(Index: Integer): string;
  2289. Var
  2290. V : String;
  2291. begin
  2292. GetNameValue(Index,Result,V);
  2293. end;
  2294. Function TStrings.GetValue(const Name: string): string;
  2295. Var
  2296. L : longint;
  2297. N : String;
  2298. begin
  2299. Result:='';
  2300. L:=IndexOfName(Name);
  2301. If L<>-1 then
  2302. GetNameValue(L,N,Result);
  2303. end;
  2304. Function TStrings.GetValueFromIndex(Index: Integer): string;
  2305. Var
  2306. N : String;
  2307. begin
  2308. GetNameValue(Index,N,Result);
  2309. end;
  2310. Procedure TStrings.SetValueFromIndex(Index: Integer; const Value: string);
  2311. begin
  2312. If (Value='') then
  2313. Delete(Index)
  2314. else
  2315. begin
  2316. If (Index<0) then
  2317. Index:=Add('');
  2318. CheckSpecialChars;
  2319. Strings[Index]:=GetName(Index)+FNameValueSeparator+Value;
  2320. end;
  2321. end;
  2322. Procedure TStrings.SetDelimitedText(const AValue: string);
  2323. var i,j:integer;
  2324. aNotFirst:boolean;
  2325. begin
  2326. CheckSpecialChars;
  2327. BeginUpdate;
  2328. i:=1;
  2329. j:=1;
  2330. aNotFirst:=false;
  2331. { Paraphrased from Delphi XE2 help:
  2332. Strings must be separated by Delimiter characters or spaces.
  2333. They may be enclosed in QuoteChars.
  2334. QuoteChars in the string must be repeated to distinguish them from the QuoteChars enclosing the string.
  2335. }
  2336. try
  2337. Clear;
  2338. If StrictDelimiter then
  2339. begin
  2340. while i<=length(AValue) do begin
  2341. // skip delimiter
  2342. if aNotFirst and (i<=length(AValue)) and (AValue[i]=FDelimiter) then inc(i);
  2343. // read next string
  2344. if i<=length(AValue) then begin
  2345. if AValue[i]=FQuoteChar then begin
  2346. // next string is quoted
  2347. j:=i+1;
  2348. while (j<=length(AValue)) and
  2349. ( (AValue[j]<>FQuoteChar) or
  2350. ( (j+1<=length(AValue)) and (AValue[j+1]=FQuoteChar) ) ) do begin
  2351. if (j<=length(AValue)) and (AValue[j]=FQuoteChar) then inc(j,2)
  2352. else inc(j);
  2353. end;
  2354. // j is position of closing quote
  2355. Add( StringReplace (Copy(AValue,i+1,j-i-1),
  2356. FQuoteChar+FQuoteChar,FQuoteChar, [rfReplaceAll]));
  2357. i:=j+1;
  2358. end else begin
  2359. // next string is not quoted; read until delimiter
  2360. j:=i;
  2361. while (j<=length(AValue)) and
  2362. (AValue[j]<>FDelimiter) do inc(j);
  2363. Add( Copy(AValue,i,j-i));
  2364. i:=j;
  2365. end;
  2366. end else begin
  2367. if aNotFirst then Add('');
  2368. end;
  2369. aNotFirst:=true;
  2370. end;
  2371. end
  2372. else
  2373. begin
  2374. while i<=length(AValue) do begin
  2375. // skip delimiter
  2376. if aNotFirst and (i<=length(AValue)) and (AValue[i]=FDelimiter) then inc(i);
  2377. // skip spaces
  2378. while (i<=length(AValue)) and (Ord(AValue[i])<=Ord(' ')) do inc(i);
  2379. // read next string
  2380. if i<=length(AValue) then begin
  2381. if AValue[i]=FQuoteChar then begin
  2382. // next string is quoted
  2383. j:=i+1;
  2384. while (j<=length(AValue)) and
  2385. ( (AValue[j]<>FQuoteChar) or
  2386. ( (j+1<=length(AValue)) and (AValue[j+1]=FQuoteChar) ) ) do begin
  2387. if (j<=length(AValue)) and (AValue[j]=FQuoteChar) then inc(j,2)
  2388. else inc(j);
  2389. end;
  2390. // j is position of closing quote
  2391. Add( StringReplace (Copy(AValue,i+1,j-i-1),
  2392. FQuoteChar+FQuoteChar,FQuoteChar, [rfReplaceAll]));
  2393. i:=j+1;
  2394. end else begin
  2395. // next string is not quoted; read until control character/space/delimiter
  2396. j:=i;
  2397. while (j<=length(AValue)) and
  2398. (Ord(AValue[j])>Ord(' ')) and
  2399. (AValue[j]<>FDelimiter) do inc(j);
  2400. Add( Copy(AValue,i,j-i));
  2401. i:=j;
  2402. end;
  2403. end else begin
  2404. if aNotFirst then Add('');
  2405. end;
  2406. // skip spaces
  2407. while (i<=length(AValue)) and (Ord(AValue[i])<=Ord(' ')) do inc(i);
  2408. aNotFirst:=true;
  2409. end;
  2410. end;
  2411. finally
  2412. EndUpdate;
  2413. end;
  2414. end;
  2415. Procedure TStrings.SetCommaText(const Value: string);
  2416. Var
  2417. C1,C2 : Char;
  2418. begin
  2419. CheckSpecialChars;
  2420. C1:=Delimiter;
  2421. C2:=QuoteChar;
  2422. Delimiter:=',';
  2423. QuoteChar:='"';
  2424. Try
  2425. SetDelimitedText(Value);
  2426. Finally
  2427. Delimiter:=C1;
  2428. QuoteChar:=C2;
  2429. end;
  2430. end;
  2431. Procedure TStrings.SetValue(const Name, Value: string);
  2432. Var L : longint;
  2433. begin
  2434. CheckSpecialChars;
  2435. L:=IndexOfName(Name);
  2436. if L=-1 then
  2437. Add (Name+FNameValueSeparator+Value)
  2438. else
  2439. Strings[L]:=Name+FNameValueSeparator+value;
  2440. end;
  2441. Procedure TStrings.Error(const Msg: string; Data: Integer);
  2442. begin
  2443. Raise EStringListError.CreateFmt(Msg,[IntToStr(Data)]);
  2444. end;
  2445. Function TStrings.GetCapacity: Integer;
  2446. begin
  2447. Result:=Count;
  2448. end;
  2449. Function TStrings.GetObject(Index: Integer): TObject;
  2450. begin
  2451. if Index=0 then ;
  2452. Result:=Nil;
  2453. end;
  2454. Function TStrings.GetTextStr: string;
  2455. Var
  2456. I : Longint;
  2457. S,NL : String;
  2458. begin
  2459. CheckSpecialChars;
  2460. // Determine needed place
  2461. if FLineBreak<>sLineBreak then
  2462. NL:=FLineBreak
  2463. else
  2464. Case FLBS of
  2465. tlbsLF : NL:=#10;
  2466. tlbsCRLF : NL:=#13#10;
  2467. tlbsCR : NL:=#13;
  2468. end;
  2469. Result:='';
  2470. For i:=0 To count-1 do
  2471. begin
  2472. S:=Strings[I];
  2473. Result:=Result+S;
  2474. if (I<Count-1) or Not SkipLastLineBreak then
  2475. Result:=Result+NL;
  2476. end;
  2477. end;
  2478. Procedure TStrings.Put(Index: Integer; const S: string);
  2479. Var Obj : TObject;
  2480. begin
  2481. Obj:=Objects[Index];
  2482. Delete(Index);
  2483. InsertObject(Index,S,Obj);
  2484. end;
  2485. Procedure TStrings.PutObject(Index: Integer; AObject: TObject);
  2486. begin
  2487. // Empty.
  2488. if Index=0 then exit;
  2489. if AObject=nil then exit;
  2490. end;
  2491. Procedure TStrings.SetCapacity(NewCapacity: Integer);
  2492. begin
  2493. // Empty.
  2494. if NewCapacity=0 then ;
  2495. end;
  2496. Function TStrings.GetNextLineBreak (Const Value : String; Out S : String; Var P : Integer) : Boolean;
  2497. Var
  2498. PP : Integer;
  2499. begin
  2500. S:='';
  2501. Result:=False;
  2502. If ((Length(Value)-P)<0) then
  2503. exit;
  2504. PP:=TJSString(Value).IndexOf(LineBreak,P-1)+1;
  2505. if (PP<1) then
  2506. PP:=Length(Value)+1;
  2507. S:=Copy(Value,P,PP-P);
  2508. P:=PP+length(LineBreak);
  2509. Result:=True;
  2510. end;
  2511. Procedure TStrings.DoSetTextStr(const Value: string; DoClear : Boolean);
  2512. Var
  2513. S : String;
  2514. P : Integer;
  2515. begin
  2516. Try
  2517. BeginUpdate;
  2518. if DoClear then
  2519. Clear;
  2520. P:=1;
  2521. While GetNextLineBreak (Value,S,P) do
  2522. Add(S);
  2523. finally
  2524. EndUpdate;
  2525. end;
  2526. end;
  2527. Procedure TStrings.SetTextStr(const Value: string);
  2528. begin
  2529. CheckSpecialChars;
  2530. DoSetTextStr(Value,True);
  2531. end;
  2532. Procedure TStrings.AddText(const S: string);
  2533. begin
  2534. CheckSpecialChars;
  2535. DoSetTextStr(S,False);
  2536. end;
  2537. Procedure TStrings.SetUpdateState(Updating: Boolean);
  2538. begin
  2539. // FPONotifyObservers(Self,ooChange,Nil);
  2540. if Updating then ;
  2541. end;
  2542. destructor TSTrings.Destroy;
  2543. begin
  2544. inherited destroy;
  2545. end;
  2546. constructor TStrings.Create;
  2547. begin
  2548. inherited Create;
  2549. FAlwaysQuote:=False;
  2550. end;
  2551. Function TStrings.Add(const S: string): Integer;
  2552. begin
  2553. Result:=Count;
  2554. Insert (Count,S);
  2555. end;
  2556. (*
  2557. function TStrings.AddFmt(const Fmt : string; const Args : Array of const): Integer;
  2558. begin
  2559. Result:=Add(Format(Fmt,Args));
  2560. end;
  2561. *)
  2562. Function TStrings.AddObject(const S: string; AObject: TObject): Integer;
  2563. begin
  2564. Result:=Add(S);
  2565. Objects[result]:=AObject;
  2566. end;
  2567. (*
  2568. function TStrings.AddObject(const Fmt: string; Args : Array of const; AObject: TObject): Integer;
  2569. begin
  2570. Result:=AddObject(Format(Fmt,Args),AObject);
  2571. end;
  2572. *)
  2573. Procedure TStrings.Append(const S: string);
  2574. begin
  2575. Add (S);
  2576. end;
  2577. Procedure TStrings.AddStrings(TheStrings: TStrings; ClearFirst : Boolean);
  2578. begin
  2579. beginupdate;
  2580. try
  2581. if ClearFirst then
  2582. Clear;
  2583. AddStrings(TheStrings);
  2584. finally
  2585. EndUpdate;
  2586. end;
  2587. end;
  2588. Procedure TStrings.AddStrings(TheStrings: TStrings);
  2589. Var Runner : longint;
  2590. begin
  2591. For Runner:=0 to TheStrings.Count-1 do
  2592. self.AddObject (Thestrings[Runner],TheStrings.Objects[Runner]);
  2593. end;
  2594. Procedure TStrings.AddStrings(const TheStrings: array of string);
  2595. Var Runner : longint;
  2596. begin
  2597. if Count + High(TheStrings)+1 > Capacity then
  2598. Capacity := Count + High(TheStrings)+1;
  2599. For Runner:=Low(TheStrings) to High(TheStrings) do
  2600. self.Add(Thestrings[Runner]);
  2601. end;
  2602. Procedure TStrings.AddStrings(const TheStrings: array of string; ClearFirst : Boolean);
  2603. begin
  2604. beginupdate;
  2605. try
  2606. if ClearFirst then
  2607. Clear;
  2608. AddStrings(TheStrings);
  2609. finally
  2610. EndUpdate;
  2611. end;
  2612. end;
  2613. function TStrings.AddPair(const AName, AValue: string): TStrings;
  2614. begin
  2615. Result:=AddPair(AName,AValue,Nil);
  2616. end;
  2617. function TStrings.AddPair(const AName, AValue: string; AObject: TObject): TStrings;
  2618. begin
  2619. Result := Self;
  2620. AddObject(AName+NameValueSeparator+AValue, AObject);
  2621. end;
  2622. Procedure TStrings.Assign(Source: TPersistent);
  2623. Var
  2624. S : TStrings;
  2625. begin
  2626. If Source is TStrings then
  2627. begin
  2628. S:=TStrings(Source);
  2629. BeginUpdate;
  2630. Try
  2631. clear;
  2632. FSpecialCharsInited:=S.FSpecialCharsInited;
  2633. FQuoteChar:=S.FQuoteChar;
  2634. FDelimiter:=S.FDelimiter;
  2635. FNameValueSeparator:=S.FNameValueSeparator;
  2636. FLBS:=S.FLBS;
  2637. FLineBreak:=S.FLineBreak;
  2638. AddStrings(S);
  2639. finally
  2640. EndUpdate;
  2641. end;
  2642. end
  2643. else
  2644. Inherited Assign(Source);
  2645. end;
  2646. Procedure TStrings.BeginUpdate;
  2647. begin
  2648. if FUpdateCount = 0 then SetUpdateState(true);
  2649. inc(FUpdateCount);
  2650. end;
  2651. Procedure TStrings.EndUpdate;
  2652. begin
  2653. If FUpdateCount>0 then
  2654. Dec(FUpdateCount);
  2655. if FUpdateCount=0 then
  2656. SetUpdateState(False);
  2657. end;
  2658. Function TStrings.Equals(Obj: TObject): Boolean;
  2659. begin
  2660. if Obj is TStrings then
  2661. Result := Equals(TStrings(Obj))
  2662. else
  2663. Result := inherited Equals(Obj);
  2664. end;
  2665. Function TStrings.Equals(TheStrings: TStrings): Boolean;
  2666. Var Runner,Nr : Longint;
  2667. begin
  2668. Result:=False;
  2669. Nr:=Self.Count;
  2670. if Nr<>TheStrings.Count then exit;
  2671. For Runner:=0 to Nr-1 do
  2672. If Strings[Runner]<>TheStrings[Runner] then exit;
  2673. Result:=True;
  2674. end;
  2675. Procedure TStrings.Exchange(Index1, Index2: Integer);
  2676. Var
  2677. Obj : TObject;
  2678. Str : String;
  2679. begin
  2680. beginUpdate;
  2681. Try
  2682. Obj:=Objects[Index1];
  2683. Str:=Strings[Index1];
  2684. Objects[Index1]:=Objects[Index2];
  2685. Strings[Index1]:=Strings[Index2];
  2686. Objects[Index2]:=Obj;
  2687. Strings[Index2]:=Str;
  2688. finally
  2689. EndUpdate;
  2690. end;
  2691. end;
  2692. function TStrings.GetEnumerator: TStringsEnumerator;
  2693. begin
  2694. Result:=TStringsEnumerator.Create(Self);
  2695. end;
  2696. Function TStrings.DoCompareText(const s1,s2 : string) : PtrInt;
  2697. begin
  2698. result:=CompareText(s1,s2);
  2699. end;
  2700. Function TStrings.IndexOf(const S: string): Integer;
  2701. begin
  2702. Result:=0;
  2703. While (Result<Count) and (DoCompareText(Strings[Result],S)<>0) do Result:=Result+1;
  2704. if Result=Count then Result:=-1;
  2705. end;
  2706. Function TStrings.IndexOfName(const Name: string): Integer;
  2707. Var
  2708. len : longint;
  2709. S : String;
  2710. begin
  2711. CheckSpecialChars;
  2712. Result:=0;
  2713. while (Result<Count) do
  2714. begin
  2715. S:=Strings[Result];
  2716. len:=pos(FNameValueSeparator,S)-1;
  2717. if (len>=0) and (DoCompareText(Name,Copy(S,1,Len))=0) then
  2718. exit;
  2719. inc(result);
  2720. end;
  2721. result:=-1;
  2722. end;
  2723. Function TStrings.IndexOfObject(AObject: TObject): Integer;
  2724. begin
  2725. Result:=0;
  2726. While (Result<count) and (Objects[Result]<>AObject) do Result:=Result+1;
  2727. If Result=Count then Result:=-1;
  2728. end;
  2729. Procedure TStrings.InsertObject(Index: Integer; const S: string;
  2730. AObject: TObject);
  2731. begin
  2732. Insert (Index,S);
  2733. Objects[Index]:=AObject;
  2734. end;
  2735. Procedure TStrings.Move(CurIndex, NewIndex: Integer);
  2736. Var
  2737. Obj : TObject;
  2738. Str : String;
  2739. begin
  2740. BeginUpdate;
  2741. Try
  2742. Obj:=Objects[CurIndex];
  2743. Str:=Strings[CurIndex];
  2744. Objects[CurIndex]:=Nil; // Prevent Delete from freeing.
  2745. Delete(Curindex);
  2746. InsertObject(NewIndex,Str,Obj);
  2747. finally
  2748. EndUpdate;
  2749. end;
  2750. end;
  2751. {****************************************************************************}
  2752. {* TStringList *}
  2753. {****************************************************************************}
  2754. procedure TStringList.ExchangeItemsInt(Index1, Index2: Integer);
  2755. Var
  2756. S : String;
  2757. O : TObject;
  2758. begin
  2759. S:=Flist[Index1].FString;
  2760. O:=Flist[Index1].FObject;
  2761. Flist[Index1].Fstring:=Flist[Index2].Fstring;
  2762. Flist[Index1].FObject:=Flist[Index2].FObject;
  2763. Flist[Index2].Fstring:=S;
  2764. Flist[Index2].FObject:=O;
  2765. end;
  2766. function TStringList.GetSorted: Boolean;
  2767. begin
  2768. Result:=FSortStyle in [sslUser,sslAuto];
  2769. end;
  2770. procedure TStringList.ExchangeItems(Index1, Index2: Integer);
  2771. begin
  2772. ExchangeItemsInt(Index1, Index2);
  2773. end;
  2774. procedure TStringList.Grow;
  2775. Var
  2776. NC : Integer;
  2777. begin
  2778. NC:=Capacity;
  2779. If NC>=256 then
  2780. NC:=NC+(NC Div 4)
  2781. else if NC=0 then
  2782. NC:=4
  2783. else
  2784. NC:=NC*4;
  2785. SetCapacity(NC);
  2786. end;
  2787. procedure TStringList.InternalClear(FromIndex: Integer; ClearOnly: Boolean);
  2788. Var
  2789. I: Integer;
  2790. begin
  2791. if FromIndex < FCount then
  2792. begin
  2793. if FOwnsObjects then
  2794. begin
  2795. For I:=FromIndex to FCount-1 do
  2796. begin
  2797. Flist[I].FString:='';
  2798. freeandnil(Flist[i].FObject);
  2799. end;
  2800. end
  2801. else
  2802. begin
  2803. For I:=FromIndex to FCount-1 do
  2804. Flist[I].FString:='';
  2805. end;
  2806. FCount:=FromIndex;
  2807. end;
  2808. if Not ClearOnly then
  2809. SetCapacity(0);
  2810. end;
  2811. procedure TStringList.QuickSort(L, R: Integer; CompareFn: TStringListSortCompare
  2812. );
  2813. var
  2814. Pivot, vL, vR: Integer;
  2815. begin
  2816. //if ExchangeItems is override call that, else call (faster) ExchangeItemsInt
  2817. if R - L <= 1 then begin // a little bit of time saver
  2818. if L < R then
  2819. if CompareFn(Self, L, R) > 0 then
  2820. ExchangeItems(L, R);
  2821. Exit;
  2822. end;
  2823. vL := L;
  2824. vR := R;
  2825. Pivot := L + Random(R - L); // they say random is best
  2826. while vL < vR do begin
  2827. while (vL < Pivot) and (CompareFn(Self, vL, Pivot) <= 0) do
  2828. Inc(vL);
  2829. while (vR > Pivot) and (CompareFn(Self, vR, Pivot) > 0) do
  2830. Dec(vR);
  2831. ExchangeItems(vL, vR);
  2832. if Pivot = vL then // swap pivot if we just hit it from one side
  2833. Pivot := vR
  2834. else if Pivot = vR then
  2835. Pivot := vL;
  2836. end;
  2837. if Pivot - 1 >= L then
  2838. QuickSort(L, Pivot - 1, CompareFn);
  2839. if Pivot + 1 <= R then
  2840. QuickSort(Pivot + 1, R, CompareFn);
  2841. end;
  2842. procedure TStringList.InsertItem(Index: Integer; const S: string);
  2843. begin
  2844. InsertItem(Index, S, nil);
  2845. end;
  2846. procedure TStringList.InsertItem(Index: Integer; const S: string; O: TObject);
  2847. Var
  2848. It : TStringItem;
  2849. begin
  2850. Changing;
  2851. If FCount=Capacity then Grow;
  2852. it.FString:=S;
  2853. it.FObject:=O;
  2854. TJSArray(FList).Splice(Index,0,It);
  2855. Inc(FCount);
  2856. Changed;
  2857. end;
  2858. procedure TStringList.SetSorted(Value: Boolean);
  2859. begin
  2860. If Value then
  2861. SortStyle:=sslAuto
  2862. else
  2863. SortStyle:=sslNone
  2864. end;
  2865. procedure TStringList.Changed;
  2866. begin
  2867. If (FUpdateCount=0) Then
  2868. begin
  2869. If Assigned(FOnChange) then
  2870. FOnchange(Self);
  2871. end;
  2872. end;
  2873. procedure TStringList.Changing;
  2874. begin
  2875. If FUpdateCount=0 then
  2876. if Assigned(FOnChanging) then
  2877. FOnchanging(Self);
  2878. end;
  2879. function TStringList.Get(Index: Integer): string;
  2880. begin
  2881. CheckIndex(Index);
  2882. Result:=Flist[Index].FString;
  2883. end;
  2884. function TStringList.GetCapacity: Integer;
  2885. begin
  2886. Result:=Length(FList);
  2887. end;
  2888. function TStringList.GetCount: Integer;
  2889. begin
  2890. Result:=FCount;
  2891. end;
  2892. function TStringList.GetObject(Index: Integer): TObject;
  2893. begin
  2894. CheckIndex(Index);
  2895. Result:=Flist[Index].FObject;
  2896. end;
  2897. procedure TStringList.Put(Index: Integer; const S: string);
  2898. begin
  2899. If Sorted then
  2900. Error(SSortedListError,0);
  2901. CheckIndex(Index);
  2902. Changing;
  2903. Flist[Index].FString:=S;
  2904. Changed;
  2905. end;
  2906. procedure TStringList.PutObject(Index: Integer; AObject: TObject);
  2907. begin
  2908. CheckIndex(Index);
  2909. Changing;
  2910. Flist[Index].FObject:=AObject;
  2911. Changed;
  2912. end;
  2913. procedure TStringList.SetCapacity(NewCapacity: Integer);
  2914. begin
  2915. If (NewCapacity<0) then
  2916. Error (SListCapacityError,NewCapacity);
  2917. If NewCapacity<>Capacity then
  2918. SetLength(FList,NewCapacity)
  2919. end;
  2920. procedure TStringList.SetUpdateState(Updating: Boolean);
  2921. begin
  2922. If Updating then
  2923. Changing
  2924. else
  2925. Changed
  2926. end;
  2927. destructor TStringList.Destroy;
  2928. begin
  2929. InternalClear;
  2930. Inherited destroy;
  2931. end;
  2932. function TStringList.Add(const S: string): Integer;
  2933. begin
  2934. If Not (SortStyle=sslAuto) then
  2935. Result:=FCount
  2936. else
  2937. If Find (S,Result) then
  2938. Case DUplicates of
  2939. DupIgnore : Exit;
  2940. DupError : Error(SDuplicateString,0)
  2941. end;
  2942. InsertItem (Result,S);
  2943. end;
  2944. procedure TStringList.Clear;
  2945. begin
  2946. if FCount = 0 then Exit;
  2947. Changing;
  2948. InternalClear;
  2949. Changed;
  2950. end;
  2951. procedure TStringList.Delete(Index: Integer);
  2952. begin
  2953. CheckIndex(Index);
  2954. Changing;
  2955. if FOwnsObjects then
  2956. FreeAndNil(Flist[Index].FObject);
  2957. TJSArray(FList).splice(Index,1);
  2958. FList[Count-1].FString:='';
  2959. Flist[Count-1].FObject:=Nil;
  2960. Dec(FCount);
  2961. Changed;
  2962. end;
  2963. procedure TStringList.Exchange(Index1, Index2: Integer);
  2964. begin
  2965. CheckIndex(Index1);
  2966. CheckIndex(Index2);
  2967. Changing;
  2968. ExchangeItemsInt(Index1,Index2);
  2969. changed;
  2970. end;
  2971. procedure TStringList.SetCaseSensitive(b : boolean);
  2972. begin
  2973. if b=FCaseSensitive then
  2974. Exit;
  2975. FCaseSensitive:=b;
  2976. if FSortStyle=sslAuto then
  2977. begin
  2978. FForceSort:=True;
  2979. try
  2980. Sort;
  2981. finally
  2982. FForceSort:=False;
  2983. end;
  2984. end;
  2985. end;
  2986. procedure TStringList.SetSortStyle(AValue: TStringsSortStyle);
  2987. begin
  2988. if FSortStyle=AValue then Exit;
  2989. if (AValue=sslAuto) then
  2990. Sort;
  2991. FSortStyle:=AValue;
  2992. end;
  2993. procedure TStringList.CheckIndex(AIndex: Integer);
  2994. begin
  2995. If (AIndex<0) or (AIndex>=FCount) then
  2996. Error(SListIndexError,AIndex);
  2997. end;
  2998. function TStringList.DoCompareText(const s1, s2: string): PtrInt;
  2999. begin
  3000. if FCaseSensitive then
  3001. result:=CompareStr(s1,s2)
  3002. else
  3003. result:=CompareText(s1,s2);
  3004. end;
  3005. function TStringList.CompareStrings(const s1,s2 : string) : Integer;
  3006. begin
  3007. Result := DoCompareText(s1, s2);
  3008. end;
  3009. function TStringList.Find(const S: string; out Index: Integer): Boolean;
  3010. var
  3011. L, R, I: Integer;
  3012. CompareRes: PtrInt;
  3013. begin
  3014. Result := false;
  3015. Index:=-1;
  3016. if Not Sorted then
  3017. Raise EListError.Create(SErrFindNeedsSortedList);
  3018. // Use binary search.
  3019. L := 0;
  3020. R := Count - 1;
  3021. while (L<=R) do
  3022. begin
  3023. I := L + (R - L) div 2;
  3024. CompareRes := DoCompareText(S, Flist[I].FString);
  3025. if (CompareRes>0) then
  3026. L := I+1
  3027. else begin
  3028. R := I-1;
  3029. if (CompareRes=0) then begin
  3030. Result := true;
  3031. if (Duplicates<>dupAccept) then
  3032. L := I; // forces end of while loop
  3033. end;
  3034. end;
  3035. end;
  3036. Index := L;
  3037. end;
  3038. function TStringList.IndexOf(const S: string): Integer;
  3039. begin
  3040. If Not Sorted then
  3041. Result:=Inherited indexOf(S)
  3042. else
  3043. // faster using binary search...
  3044. If Not Find (S,Result) then
  3045. Result:=-1;
  3046. end;
  3047. procedure TStringList.Insert(Index: Integer; const S: string);
  3048. begin
  3049. If SortStyle=sslAuto then
  3050. Error (SSortedListError,0)
  3051. else
  3052. begin
  3053. If (Index<0) or (Index>FCount) then
  3054. Error(SListIndexError,Index); // Cannot use CheckIndex, because there >= FCount...
  3055. InsertItem (Index,S);
  3056. end;
  3057. end;
  3058. procedure TStringList.CustomSort(CompareFn: TStringListSortCompare);
  3059. begin
  3060. If (FForceSort or (Not (FSortStyle=sslAuto))) and (FCount>1) then
  3061. begin
  3062. Changing;
  3063. QuickSort(0,FCount-1, CompareFn);
  3064. Changed;
  3065. end;
  3066. end;
  3067. function StringListAnsiCompare(List: TStringList; Index1, Index: Integer): Integer;
  3068. begin
  3069. Result := List.DoCompareText(List.FList[Index1].FString,
  3070. List.FList[Index].FString);
  3071. end;
  3072. procedure TStringList.Sort;
  3073. begin
  3074. CustomSort(@StringListAnsiCompare);
  3075. end;
  3076. {****************************************************************************}
  3077. {* TCollectionItem *}
  3078. {****************************************************************************}
  3079. function TCollectionItem.GetIndex: Integer;
  3080. begin
  3081. if FCollection<>nil then
  3082. Result:=FCollection.FItems.IndexOf(Self)
  3083. else
  3084. Result:=-1;
  3085. end;
  3086. procedure TCollectionItem.SetCollection(Value: TCollection);
  3087. begin
  3088. IF Value<>FCollection then
  3089. begin
  3090. If FCollection<>Nil then FCollection.RemoveItem(Self);
  3091. if Value<>Nil then Value.InsertItem(Self);
  3092. end;
  3093. end;
  3094. procedure TCollectionItem.Changed(AllItems: Boolean);
  3095. begin
  3096. If (FCollection<>Nil) and (FCollection.UpdateCount=0) then
  3097. begin
  3098. If AllItems then
  3099. FCollection.Update(Nil)
  3100. else
  3101. FCollection.Update(Self);
  3102. end;
  3103. end;
  3104. function TCollectionItem.GetNamePath: string;
  3105. begin
  3106. If FCollection<>Nil then
  3107. Result:=FCollection.GetNamePath+'['+IntToStr(Index)+']'
  3108. else
  3109. Result:=ClassName;
  3110. end;
  3111. function TCollectionItem.GetOwner: TPersistent;
  3112. begin
  3113. Result:=FCollection;
  3114. end;
  3115. function TCollectionItem.GetDisplayName: string;
  3116. begin
  3117. Result:=ClassName;
  3118. end;
  3119. procedure TCollectionItem.SetIndex(Value: Integer);
  3120. Var Temp : Longint;
  3121. begin
  3122. Temp:=GetIndex;
  3123. If (Temp>-1) and (Temp<>Value) then
  3124. begin
  3125. FCollection.FItems.Move(Temp,Value);
  3126. Changed(True);
  3127. end;
  3128. end;
  3129. procedure TCollectionItem.SetDisplayName(const Value: string);
  3130. begin
  3131. Changed(False);
  3132. if Value='' then ;
  3133. end;
  3134. constructor TCollectionItem.Create(ACollection: TCollection);
  3135. begin
  3136. Inherited Create;
  3137. SetCollection(ACollection);
  3138. end;
  3139. destructor TCollectionItem.Destroy;
  3140. begin
  3141. SetCollection(Nil);
  3142. Inherited Destroy;
  3143. end;
  3144. {****************************************************************************}
  3145. {* TCollectionEnumerator *}
  3146. {****************************************************************************}
  3147. constructor TCollectionEnumerator.Create(ACollection: TCollection);
  3148. begin
  3149. inherited Create;
  3150. FCollection := ACollection;
  3151. FPosition := -1;
  3152. end;
  3153. function TCollectionEnumerator.GetCurrent: TCollectionItem;
  3154. begin
  3155. Result := FCollection.Items[FPosition];
  3156. end;
  3157. function TCollectionEnumerator.MoveNext: Boolean;
  3158. begin
  3159. Inc(FPosition);
  3160. Result := FPosition < FCollection.Count;
  3161. end;
  3162. {****************************************************************************}
  3163. {* TCollection *}
  3164. {****************************************************************************}
  3165. function TCollection.Owner: TPersistent;
  3166. begin
  3167. result:=getowner;
  3168. end;
  3169. function TCollection.GetCount: Integer;
  3170. begin
  3171. Result:=FItems.Count;
  3172. end;
  3173. Procedure TCollection.SetPropName;
  3174. {
  3175. Var
  3176. TheOwner : TPersistent;
  3177. PropList : PPropList;
  3178. I, PropCount : Integer;
  3179. }
  3180. begin
  3181. FPropName:='';
  3182. {
  3183. TheOwner:=GetOwner;
  3184. // TODO: This needs to wait till Mattias finishes typeinfo.
  3185. // It's normally only used in the designer so should not be a problem currently.
  3186. if (TheOwner=Nil) Or (TheOwner.Classinfo=Nil) Then Exit;
  3187. // get information from the owner RTTI
  3188. PropCount:=GetPropList(TheOwner, PropList);
  3189. Try
  3190. For I:=0 To PropCount-1 Do
  3191. If (PropList^[i]^.PropType^.Kind=tkClass) And
  3192. (GetObjectProp(TheOwner, PropList^[i], ClassType)=Self) Then
  3193. Begin
  3194. FPropName:=PropList^[i]^.Name;
  3195. Exit;
  3196. End;
  3197. Finally
  3198. FreeMem(PropList);
  3199. End;
  3200. }
  3201. end;
  3202. function TCollection.GetPropName: string;
  3203. {Var
  3204. TheOwner : TPersistent;}
  3205. begin
  3206. Result:=FPropNAme;
  3207. // TheOwner:=GetOwner;
  3208. // If (Result<>'') or (TheOwner=Nil) Or (TheOwner.Classinfo=Nil) then exit;
  3209. SetPropName;
  3210. Result:=FPropName;
  3211. end;
  3212. procedure TCollection.InsertItem(Item: TCollectionItem);
  3213. begin
  3214. If Not(Item Is FitemClass) then
  3215. exit;
  3216. FItems.add(Item);
  3217. Item.FCollection:=Self;
  3218. Item.FID:=FNextID;
  3219. inc(FNextID);
  3220. SetItemName(Item);
  3221. Notify(Item,cnAdded);
  3222. Changed;
  3223. end;
  3224. procedure TCollection.RemoveItem(Item: TCollectionItem);
  3225. Var
  3226. I : Integer;
  3227. begin
  3228. Notify(Item,cnExtracting);
  3229. I:=FItems.IndexOfItem(Item,fromEnd);
  3230. If (I<>-1) then
  3231. FItems.Delete(I);
  3232. Item.FCollection:=Nil;
  3233. Changed;
  3234. end;
  3235. function TCollection.GetAttrCount: Integer;
  3236. begin
  3237. Result:=0;
  3238. end;
  3239. function TCollection.GetAttr(Index: Integer): string;
  3240. begin
  3241. Result:='';
  3242. if Index=0 then ;
  3243. end;
  3244. function TCollection.GetItemAttr(Index, ItemIndex: Integer): string;
  3245. begin
  3246. Result:=TCollectionItem(FItems.Items[ItemIndex]).DisplayName;
  3247. if Index=0 then ;
  3248. end;
  3249. function TCollection.GetEnumerator: TCollectionEnumerator;
  3250. begin
  3251. Result := TCollectionEnumerator.Create(Self);
  3252. end;
  3253. function TCollection.GetNamePath: string;
  3254. var o : TPersistent;
  3255. begin
  3256. o:=getowner;
  3257. if assigned(o) and (propname<>'') then
  3258. result:=o.getnamepath+'.'+propname
  3259. else
  3260. result:=classname;
  3261. end;
  3262. procedure TCollection.Changed;
  3263. begin
  3264. if FUpdateCount=0 then
  3265. Update(Nil);
  3266. end;
  3267. function TCollection.GetItem(Index: Integer): TCollectionItem;
  3268. begin
  3269. Result:=TCollectionItem(FItems.Items[Index]);
  3270. end;
  3271. procedure TCollection.SetItem(Index: Integer; Value: TCollectionItem);
  3272. begin
  3273. TCollectionItem(FItems.items[Index]).Assign(Value);
  3274. end;
  3275. procedure TCollection.SetItemName(Item: TCollectionItem);
  3276. begin
  3277. if Item=nil then ;
  3278. end;
  3279. procedure TCollection.Update(Item: TCollectionItem);
  3280. begin
  3281. if Item=nil then ;
  3282. end;
  3283. constructor TCollection.Create(AItemClass: TCollectionItemClass);
  3284. begin
  3285. inherited create;
  3286. FItemClass:=AItemClass;
  3287. FItems:=TFpList.Create;
  3288. end;
  3289. destructor TCollection.Destroy;
  3290. begin
  3291. FUpdateCount:=1; // Prevent OnChange
  3292. try
  3293. DoClear;
  3294. Finally
  3295. FUpdateCount:=0;
  3296. end;
  3297. if assigned(FItems) then
  3298. FItems.Destroy;
  3299. Inherited Destroy;
  3300. end;
  3301. function TCollection.Add: TCollectionItem;
  3302. begin
  3303. Result:=FItemClass.Create(Self);
  3304. end;
  3305. procedure TCollection.Assign(Source: TPersistent);
  3306. Var I : Longint;
  3307. begin
  3308. If Source is TCollection then
  3309. begin
  3310. Clear;
  3311. For I:=0 To TCollection(Source).Count-1 do
  3312. Add.Assign(TCollection(Source).Items[I]);
  3313. exit;
  3314. end
  3315. else
  3316. Inherited Assign(Source);
  3317. end;
  3318. procedure TCollection.BeginUpdate;
  3319. begin
  3320. inc(FUpdateCount);
  3321. end;
  3322. procedure TCollection.Clear;
  3323. begin
  3324. if FItems.Count=0 then
  3325. exit; // Prevent Changed
  3326. BeginUpdate;
  3327. try
  3328. DoClear;
  3329. finally
  3330. EndUpdate;
  3331. end;
  3332. end;
  3333. procedure TCollection.DoClear;
  3334. var
  3335. Item: TCollectionItem;
  3336. begin
  3337. While FItems.Count>0 do
  3338. begin
  3339. Item:=TCollectionItem(FItems.Last);
  3340. if Assigned(Item) then
  3341. Item.Destroy;
  3342. end;
  3343. end;
  3344. procedure TCollection.EndUpdate;
  3345. begin
  3346. if FUpdateCount>0 then
  3347. dec(FUpdateCount);
  3348. if FUpdateCount=0 then
  3349. Changed;
  3350. end;
  3351. function TCollection.FindItemID(ID: Integer): TCollectionItem;
  3352. Var
  3353. I : Longint;
  3354. begin
  3355. For I:=0 to Fitems.Count-1 do
  3356. begin
  3357. Result:=TCollectionItem(FItems.items[I]);
  3358. If Result.Id=Id then
  3359. exit;
  3360. end;
  3361. Result:=Nil;
  3362. end;
  3363. procedure TCollection.Delete(Index: Integer);
  3364. Var
  3365. Item : TCollectionItem;
  3366. begin
  3367. Item:=TCollectionItem(FItems[Index]);
  3368. Notify(Item,cnDeleting);
  3369. If assigned(Item) then
  3370. Item.Destroy;
  3371. end;
  3372. function TCollection.Insert(Index: Integer): TCollectionItem;
  3373. begin
  3374. Result:=Add;
  3375. Result.Index:=Index;
  3376. end;
  3377. procedure TCollection.Notify(Item: TCollectionItem;Action: TCollectionNotification);
  3378. begin
  3379. if Item=nil then ;
  3380. if Action=cnAdded then ;
  3381. end;
  3382. procedure TCollection.Sort(Const Compare : TCollectionSortCompare);
  3383. begin
  3384. BeginUpdate;
  3385. try
  3386. FItems.Sort(TListSortCompare(Compare));
  3387. Finally
  3388. EndUpdate;
  3389. end;
  3390. end;
  3391. procedure TCollection.Exchange(Const Index1, index2: integer);
  3392. begin
  3393. FItems.Exchange(Index1,Index2);
  3394. end;
  3395. {****************************************************************************}
  3396. {* TOwnedCollection *}
  3397. {****************************************************************************}
  3398. Constructor TOwnedCollection.Create(AOwner: TPersistent; AItemClass: TCollectionItemClass);
  3399. Begin
  3400. FOwner := AOwner;
  3401. inherited Create(AItemClass);
  3402. end;
  3403. Function TOwnedCollection.GetOwner: TPersistent;
  3404. begin
  3405. Result:=FOwner;
  3406. end;
  3407. {****************************************************************************}
  3408. {* TComponent *}
  3409. {****************************************************************************}
  3410. function TComponent.GetComponent(AIndex: Integer): TComponent;
  3411. begin
  3412. If not assigned(FComponents) then
  3413. Result:=Nil
  3414. else
  3415. Result:=TComponent(FComponents.Items[Aindex]);
  3416. end;
  3417. function TComponent.GetComponentCount: Integer;
  3418. begin
  3419. If not assigned(FComponents) then
  3420. result:=0
  3421. else
  3422. Result:=FComponents.Count;
  3423. end;
  3424. function TComponent.GetComponentIndex: Integer;
  3425. begin
  3426. If Assigned(FOwner) and Assigned(FOwner.FComponents) then
  3427. Result:=FOWner.FComponents.IndexOf(Self)
  3428. else
  3429. Result:=-1;
  3430. end;
  3431. procedure TComponent.Insert(AComponent: TComponent);
  3432. begin
  3433. If not assigned(FComponents) then
  3434. FComponents:=TFpList.Create;
  3435. FComponents.Add(AComponent);
  3436. AComponent.FOwner:=Self;
  3437. end;
  3438. procedure TComponent.Remove(AComponent: TComponent);
  3439. begin
  3440. AComponent.FOwner:=Nil;
  3441. If assigned(FCOmponents) then
  3442. begin
  3443. FComponents.Remove(AComponent);
  3444. IF FComponents.Count=0 then
  3445. begin
  3446. FComponents.Destroy;
  3447. FComponents:=Nil;
  3448. end;
  3449. end;
  3450. end;
  3451. procedure TComponent.RemoveNotification(AComponent: TComponent);
  3452. begin
  3453. if FFreeNotifies<>nil then
  3454. begin
  3455. FFreeNotifies.Remove(AComponent);
  3456. if FFreeNotifies.Count=0 then
  3457. begin
  3458. FFreeNotifies.Destroy;
  3459. FFreeNotifies:=nil;
  3460. Exclude(FComponentState,csFreeNotification);
  3461. end;
  3462. end;
  3463. end;
  3464. procedure TComponent.SetComponentIndex(Value: Integer);
  3465. Var Temp,Count : longint;
  3466. begin
  3467. If Not assigned(Fowner) then exit;
  3468. Temp:=getcomponentindex;
  3469. If temp<0 then exit;
  3470. If value<0 then value:=0;
  3471. Count:=Fowner.FComponents.Count;
  3472. If Value>=Count then value:=count-1;
  3473. If Value<>Temp then
  3474. begin
  3475. FOWner.FComponents.Delete(Temp);
  3476. FOwner.FComponents.Insert(Value,Self);
  3477. end;
  3478. end;
  3479. procedure TComponent.ChangeName(const NewName: TComponentName);
  3480. begin
  3481. FName:=NewName;
  3482. end;
  3483. procedure TComponent.GetChildren(Proc: TGetChildProc; Root: TComponent);
  3484. begin
  3485. // Does nothing.
  3486. if Proc=nil then ;
  3487. if Root=nil then ;
  3488. end;
  3489. function TComponent.GetChildOwner: TComponent;
  3490. begin
  3491. Result:=Nil;
  3492. end;
  3493. function TComponent.GetChildParent: TComponent;
  3494. begin
  3495. Result:=Self;
  3496. end;
  3497. function TComponent.GetNamePath: string;
  3498. begin
  3499. Result:=FName;
  3500. end;
  3501. function TComponent.GetOwner: TPersistent;
  3502. begin
  3503. Result:=FOwner;
  3504. end;
  3505. procedure TComponent.Loaded;
  3506. begin
  3507. Exclude(FComponentState,csLoading);
  3508. end;
  3509. procedure TComponent.Loading;
  3510. begin
  3511. Include(FComponentState,csLoading);
  3512. end;
  3513. procedure TComponent.SetWriting(Value: Boolean);
  3514. begin
  3515. If Value then
  3516. Include(FComponentState,csWriting)
  3517. else
  3518. Exclude(FComponentState,csWriting);
  3519. end;
  3520. procedure TComponent.SetReading(Value: Boolean);
  3521. begin
  3522. If Value then
  3523. Include(FComponentState,csReading)
  3524. else
  3525. Exclude(FComponentState,csReading);
  3526. end;
  3527. procedure TComponent.Notification(AComponent: TComponent; Operation: TOperation);
  3528. Var
  3529. C : Longint;
  3530. begin
  3531. If (Operation=opRemove) then
  3532. RemoveFreeNotification(AComponent);
  3533. If Not assigned(FComponents) then
  3534. exit;
  3535. C:=FComponents.Count-1;
  3536. While (C>=0) do
  3537. begin
  3538. TComponent(FComponents.Items[C]).Notification(AComponent,Operation);
  3539. Dec(C);
  3540. if C>=FComponents.Count then
  3541. C:=FComponents.Count-1;
  3542. end;
  3543. end;
  3544. procedure TComponent.PaletteCreated;
  3545. begin
  3546. end;
  3547. procedure TComponent.ReadState(Reader: TReader);
  3548. begin
  3549. Reader.ReadData(Self);
  3550. end;
  3551. procedure TComponent.SetAncestor(Value: Boolean);
  3552. Var Runner : Longint;
  3553. begin
  3554. If Value then
  3555. Include(FComponentState,csAncestor)
  3556. else
  3557. Exclude(FCOmponentState,csAncestor);
  3558. if Assigned(FComponents) then
  3559. For Runner:=0 To FComponents.Count-1 do
  3560. TComponent(FComponents.Items[Runner]).SetAncestor(Value);
  3561. end;
  3562. procedure TComponent.SetDesigning(Value: Boolean; SetChildren: Boolean);
  3563. Var Runner : Longint;
  3564. begin
  3565. If Value then
  3566. Include(FComponentState,csDesigning)
  3567. else
  3568. Exclude(FComponentState,csDesigning);
  3569. if Assigned(FComponents) and SetChildren then
  3570. For Runner:=0 To FComponents.Count - 1 do
  3571. TComponent(FComponents.items[Runner]).SetDesigning(Value);
  3572. end;
  3573. procedure TComponent.SetDesignInstance(Value: Boolean);
  3574. begin
  3575. If Value then
  3576. Include(FComponentState,csDesignInstance)
  3577. else
  3578. Exclude(FComponentState,csDesignInstance);
  3579. end;
  3580. procedure TComponent.SetInline(Value: Boolean);
  3581. begin
  3582. If Value then
  3583. Include(FComponentState,csInline)
  3584. else
  3585. Exclude(FComponentState,csInline);
  3586. end;
  3587. procedure TComponent.SetName(const NewName: TComponentName);
  3588. begin
  3589. If FName=NewName then exit;
  3590. If (NewName<>'') and not IsValidIdent(NewName) then
  3591. Raise EComponentError.CreateFmt(SInvalidName,[NewName]);
  3592. If Assigned(FOwner) Then
  3593. FOwner.ValidateRename(Self,FName,NewName)
  3594. else
  3595. ValidateRename(Nil,FName,NewName);
  3596. SetReference(False);
  3597. ChangeName(NewName);
  3598. SetReference(True);
  3599. end;
  3600. procedure TComponent.SetChildOrder(Child: TComponent; Order: Integer);
  3601. begin
  3602. // does nothing
  3603. if Child=nil then ;
  3604. if Order=0 then ;
  3605. end;
  3606. procedure TComponent.SetParentComponent(Value: TComponent);
  3607. begin
  3608. // Does nothing
  3609. if Value=nil then ;
  3610. end;
  3611. procedure TComponent.Updating;
  3612. begin
  3613. Include (FComponentState,csUpdating);
  3614. end;
  3615. procedure TComponent.Updated;
  3616. begin
  3617. Exclude(FComponentState,csUpdating);
  3618. end;
  3619. procedure TComponent.ValidateRename(AComponent: TComponent; const CurName, NewName: string);
  3620. begin
  3621. //!! This contradicts the Delphi manual.
  3622. If (AComponent<>Nil) and (CompareText(CurName,NewName)<>0) and (AComponent.Owner = Self) and
  3623. (FindComponent(NewName)<>Nil) then
  3624. raise EComponentError.Createfmt(SDuplicateName,[newname]);
  3625. If (csDesigning in FComponentState) and (FOwner<>Nil) then
  3626. FOwner.ValidateRename(AComponent,Curname,Newname);
  3627. end;
  3628. Procedure TComponent.SetReference(Enable: Boolean);
  3629. var
  3630. aField, aValue, aOwner : Pointer;
  3631. begin
  3632. if Name='' then
  3633. exit;
  3634. if Assigned(Owner) then
  3635. begin
  3636. aOwner:=Owner; // so as not to depend on low-level names
  3637. aField := Owner.FieldAddress(Name);
  3638. if Assigned(aField) then
  3639. begin
  3640. if Enable then
  3641. aValue:= Self
  3642. else
  3643. aValue := nil;
  3644. TJSObject(aOwner)[String(TJSObject(aField)['name'])]:=aValue;
  3645. end;
  3646. end;
  3647. end;
  3648. procedure TComponent.ValidateContainer(AComponent: TComponent);
  3649. begin
  3650. AComponent.ValidateInsert(Self);
  3651. end;
  3652. procedure TComponent.ValidateInsert(AComponent: TComponent);
  3653. begin
  3654. // Does nothing.
  3655. if AComponent=nil then ;
  3656. end;
  3657. function TComponent._AddRef: Integer;
  3658. begin
  3659. Result:=-1;
  3660. end;
  3661. function TComponent._Release: Integer;
  3662. begin
  3663. Result:=-1;
  3664. end;
  3665. constructor TComponent.Create(AOwner: TComponent);
  3666. begin
  3667. FComponentStyle:=[csInheritable];
  3668. If Assigned(AOwner) then AOwner.InsertComponent(Self);
  3669. end;
  3670. destructor TComponent.Destroy;
  3671. Var
  3672. I : Integer;
  3673. C : TComponent;
  3674. begin
  3675. Destroying;
  3676. If Assigned(FFreeNotifies) then
  3677. begin
  3678. I:=FFreeNotifies.Count-1;
  3679. While (I>=0) do
  3680. begin
  3681. C:=TComponent(FFreeNotifies.Items[I]);
  3682. // Delete, so one component is not notified twice, if it is owned.
  3683. FFreeNotifies.Delete(I);
  3684. C.Notification (self,opRemove);
  3685. If (FFreeNotifies=Nil) then
  3686. I:=0
  3687. else if (I>FFreeNotifies.Count) then
  3688. I:=FFreeNotifies.Count;
  3689. dec(i);
  3690. end;
  3691. FreeAndNil(FFreeNotifies);
  3692. end;
  3693. DestroyComponents;
  3694. If FOwner<>Nil Then FOwner.RemoveComponent(Self);
  3695. inherited destroy;
  3696. end;
  3697. procedure TComponent.BeforeDestruction;
  3698. begin
  3699. if not(csDestroying in FComponentstate) then
  3700. Destroying;
  3701. end;
  3702. procedure TComponent.DestroyComponents;
  3703. Var acomponent: TComponent;
  3704. begin
  3705. While assigned(FComponents) do
  3706. begin
  3707. aComponent:=TComponent(FComponents.Last);
  3708. Remove(aComponent);
  3709. Acomponent.Destroy;
  3710. end;
  3711. end;
  3712. procedure TComponent.Destroying;
  3713. Var Runner : longint;
  3714. begin
  3715. If csDestroying in FComponentstate Then Exit;
  3716. include (FComponentState,csDestroying);
  3717. If Assigned(FComponents) then
  3718. for Runner:=0 to FComponents.Count-1 do
  3719. TComponent(FComponents.Items[Runner]).Destroying;
  3720. end;
  3721. function TComponent.QueryInterface(const IID: TGUID; out Obj): integer;
  3722. begin
  3723. if GetInterface(IID, Obj) then
  3724. Result := S_OK
  3725. else
  3726. Result := E_NOINTERFACE;
  3727. end;
  3728. procedure TComponent.WriteState(Writer: TWriter);
  3729. begin
  3730. Writer.WriteComponentData(Self);
  3731. end;
  3732. function TComponent.FindComponent(const AName: string): TComponent;
  3733. Var I : longint;
  3734. begin
  3735. Result:=Nil;
  3736. If (AName='') or Not assigned(FComponents) then exit;
  3737. For i:=0 to FComponents.Count-1 do
  3738. if (CompareText(TComponent(FComponents[I]).Name,AName)=0) then
  3739. begin
  3740. Result:=TComponent(FComponents.Items[I]);
  3741. exit;
  3742. end;
  3743. end;
  3744. procedure TComponent.FreeNotification(AComponent: TComponent);
  3745. begin
  3746. If (Owner<>Nil) and (AComponent=Owner) then exit;
  3747. If not (Assigned(FFreeNotifies)) then
  3748. FFreeNotifies:=TFpList.Create;
  3749. If FFreeNotifies.IndexOf(AComponent)=-1 then
  3750. begin
  3751. FFreeNotifies.Add(AComponent);
  3752. AComponent.FreeNotification (self);
  3753. end;
  3754. end;
  3755. procedure TComponent.RemoveFreeNotification(AComponent: TComponent);
  3756. begin
  3757. RemoveNotification(AComponent);
  3758. AComponent.RemoveNotification (self);
  3759. end;
  3760. function TComponent.GetParentComponent: TComponent;
  3761. begin
  3762. Result:=Nil;
  3763. end;
  3764. function TComponent.HasParent: Boolean;
  3765. begin
  3766. Result:=False;
  3767. end;
  3768. procedure TComponent.InsertComponent(AComponent: TComponent);
  3769. begin
  3770. AComponent.ValidateContainer(Self);
  3771. ValidateRename(AComponent,'',AComponent.FName);
  3772. Insert(AComponent);
  3773. If csDesigning in FComponentState then
  3774. AComponent.SetDesigning(true);
  3775. Notification(AComponent,opInsert);
  3776. end;
  3777. procedure TComponent.RemoveComponent(AComponent: TComponent);
  3778. begin
  3779. Notification(AComponent,opRemove);
  3780. Remove(AComponent);
  3781. Acomponent.Setdesigning(False);
  3782. ValidateRename(AComponent,AComponent.FName,'');
  3783. end;
  3784. procedure TComponent.SetSubComponent(ASubComponent: Boolean);
  3785. begin
  3786. if ASubComponent then
  3787. Include(FComponentStyle, csSubComponent)
  3788. else
  3789. Exclude(FComponentStyle, csSubComponent);
  3790. end;
  3791. function TComponent.GetEnumerator: TComponentEnumerator;
  3792. begin
  3793. Result:=TComponentEnumerator.Create(Self);
  3794. end;
  3795. { ---------------------------------------------------------------------
  3796. TStream
  3797. ---------------------------------------------------------------------}
  3798. Resourcestring
  3799. SStreamInvalidSeek = 'Seek is not implemented for class %s';
  3800. SStreamNoReading = 'Stream reading is not implemented for class %s';
  3801. SStreamNoWriting = 'Stream writing is not implemented for class %s';
  3802. SReadError = 'Could not read data from stream';
  3803. SWriteError = 'Could not write data to stream';
  3804. SMemoryStreamError = 'Could not allocate memory';
  3805. SerrInvalidStreamSize = 'Invalid Stream size';
  3806. procedure TStream.ReadNotImplemented;
  3807. begin
  3808. raise EStreamError.CreateFmt(SStreamNoReading, [ClassName]);
  3809. end;
  3810. procedure TStream.WriteNotImplemented;
  3811. begin
  3812. raise EStreamError.CreateFmt(SStreamNoWriting, [ClassName]);
  3813. end;
  3814. function TStream.Read(var Buffer: TBytes; Count: Longint): Longint;
  3815. begin
  3816. Result:=Read(Buffer,0,Count);
  3817. end;
  3818. function TStream.Write(const Buffer: TBytes; Count: Longint): Longint;
  3819. begin
  3820. Result:=Self.Write(Buffer,0,Count);
  3821. end;
  3822. function TStream.GetPosition: NativeInt;
  3823. begin
  3824. Result:=Seek(0,soCurrent);
  3825. end;
  3826. procedure TStream.SetPosition(const Pos: NativeInt);
  3827. begin
  3828. Seek(pos,soBeginning);
  3829. end;
  3830. procedure TStream.SetSize64(const NewSize: NativeInt);
  3831. begin
  3832. // Required because can't use overloaded functions in properties
  3833. SetSize(NewSize);
  3834. end;
  3835. function TStream.GetSize: NativeInt;
  3836. var
  3837. p : NativeInt;
  3838. begin
  3839. p:=Seek(0,soCurrent);
  3840. GetSize:=Seek(0,soEnd);
  3841. Seek(p,soBeginning);
  3842. end;
  3843. procedure TStream.SetSize(const NewSize: NativeInt);
  3844. begin
  3845. if NewSize<0 then
  3846. Raise EStreamError.Create(SerrInvalidStreamSize);
  3847. end;
  3848. procedure TStream.Discard(const Count: NativeInt);
  3849. const
  3850. CSmallSize =255;
  3851. CLargeMaxBuffer =32*1024; // 32 KiB
  3852. var
  3853. Buffer: TBytes;
  3854. begin
  3855. if Count=0 then
  3856. Exit;
  3857. if (Count<=CSmallSize) then
  3858. begin
  3859. SetLength(Buffer,CSmallSize);
  3860. ReadBuffer(Buffer,Count)
  3861. end
  3862. else
  3863. DiscardLarge(Count,CLargeMaxBuffer);
  3864. end;
  3865. procedure TStream.DiscardLarge(Count: NativeInt; const MaxBufferSize: Longint);
  3866. var
  3867. Buffer: TBytes;
  3868. begin
  3869. if Count=0 then
  3870. Exit;
  3871. if Count>MaxBufferSize then
  3872. SetLength(Buffer,MaxBufferSize)
  3873. else
  3874. SetLength(Buffer,Count);
  3875. while (Count>=Length(Buffer)) do
  3876. begin
  3877. ReadBuffer(Buffer,Length(Buffer));
  3878. Dec(Count,Length(Buffer));
  3879. end;
  3880. if Count>0 then
  3881. ReadBuffer(Buffer,Count);
  3882. end;
  3883. procedure TStream.InvalidSeek;
  3884. begin
  3885. raise EStreamError.CreateFmt(SStreamInvalidSeek, [ClassName]);
  3886. end;
  3887. procedure TStream.FakeSeekForward(Offset: NativeInt; const Origin: TSeekOrigin; const Pos: NativeInt);
  3888. begin
  3889. if Origin=soBeginning then
  3890. Dec(Offset,Pos);
  3891. if (Offset<0) or (Origin=soEnd) then
  3892. InvalidSeek;
  3893. if Offset>0 then
  3894. Discard(Offset);
  3895. end;
  3896. function TStream.ReadData({var} Buffer: TBytes; Count: NativeInt): NativeInt;
  3897. begin
  3898. Result:=Read(Buffer,0,Count);
  3899. end;
  3900. function TStream.ReadMaxSizeData(Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
  3901. Var
  3902. CP : NativeInt;
  3903. begin
  3904. if aCount<=aSize then
  3905. Result:=read(Buffer,aCount)
  3906. else
  3907. begin
  3908. Result:=Read(Buffer,aSize);
  3909. CP:=Position;
  3910. Result:=Result+Seek(aCount-aSize,soCurrent)-CP;
  3911. end
  3912. end;
  3913. function TStream.WriteMaxSizeData(const Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
  3914. Var
  3915. CP : NativeInt;
  3916. begin
  3917. if aCount<=aSize then
  3918. Result:=Self.Write(Buffer,aCount)
  3919. else
  3920. begin
  3921. Result:=Self.Write(Buffer,aSize);
  3922. CP:=Position;
  3923. Result:=Result+Seek(aCount-aSize,soCurrent)-CP;
  3924. end
  3925. end;
  3926. procedure TStream.WriteExactSizeData(const Buffer : TBytes; aSize, aCount: NativeInt);
  3927. begin
  3928. // Embarcadero docs mentions no exception. Does not seem very logical
  3929. WriteMaxSizeData(Buffer,aSize,ACount);
  3930. end;
  3931. procedure TStream.ReadExactSizeData(Buffer : TBytes; aSize, aCount: NativeInt);
  3932. begin
  3933. if ReadMaxSizeData(Buffer,aSize,ACount)<>aCount then
  3934. Raise EReadError.Create(SReadError);
  3935. end;
  3936. function TStream.ReadData(var Buffer: Boolean): NativeInt;
  3937. Var
  3938. B : Byte;
  3939. begin
  3940. Result:=ReadData(B,1);
  3941. if Result=1 then
  3942. Buffer:=B<>0;
  3943. end;
  3944. function TStream.ReadData(var Buffer: Boolean; Count: NativeInt): NativeInt;
  3945. Var
  3946. B : TBytes;
  3947. begin
  3948. SetLength(B,Count);
  3949. Result:=ReadMaxSizeData(B,1,Count);
  3950. if Result>0 then
  3951. Buffer:=B[0]<>0
  3952. end;
  3953. function TStream.ReadData(var Buffer: WideChar): NativeInt;
  3954. begin
  3955. Result:=ReadData(Buffer,2);
  3956. end;
  3957. function TStream.ReadData(var Buffer: WideChar; Count: NativeInt): NativeInt;
  3958. Var
  3959. W : Word;
  3960. begin
  3961. Result:=ReadData(W,Count);
  3962. if Result=2 then
  3963. Buffer:=WideChar(W);
  3964. end;
  3965. function TStream.ReadData(var Buffer: Int8): NativeInt;
  3966. begin
  3967. Result:=ReadData(Buffer,1);
  3968. end;
  3969. Function TStream.MakeInt(B : TBytes; aSize : Integer; Signed : Boolean) : NativeInt;
  3970. Var
  3971. Mem : TJSArrayBuffer;
  3972. A : TJSUInt8Array;
  3973. D : TJSDataView;
  3974. isLittle : Boolean;
  3975. begin
  3976. IsLittle:=(Endian=TEndian.Little);
  3977. Mem:=TJSArrayBuffer.New(Length(B));
  3978. A:=TJSUInt8Array.new(Mem);
  3979. A._set(B);
  3980. D:=TJSDataView.New(Mem);
  3981. if Signed then
  3982. case aSize of
  3983. 1 : Result:=D.getInt8(0);
  3984. 2 : Result:=D.getInt16(0,IsLittle);
  3985. 4 : Result:=D.getInt32(0,IsLittle);
  3986. // Todo : fix sign
  3987. 8 : Result:=Round(D.getFloat64(0,IsLittle));
  3988. end
  3989. else
  3990. case aSize of
  3991. 1 : Result:=D.getUInt8(0);
  3992. 2 : Result:=D.getUInt16(0,IsLittle);
  3993. 4 : Result:=D.getUInt32(0,IsLittle);
  3994. 8 : Result:=Round(D.getFloat64(0,IsLittle));
  3995. end
  3996. end;
  3997. function TStream.MakeBytes(B: NativeInt; aSize: Integer; Signed: Boolean): TBytes;
  3998. Var
  3999. Mem : TJSArrayBuffer;
  4000. A : TJSUInt8Array;
  4001. D : TJSDataView;
  4002. isLittle : Boolean;
  4003. begin
  4004. IsLittle:=(Endian=TEndian.Little);
  4005. Mem:=TJSArrayBuffer.New(aSize);
  4006. D:=TJSDataView.New(Mem);
  4007. if Signed then
  4008. case aSize of
  4009. 1 : D.setInt8(0,B);
  4010. 2 : D.setInt16(0,B,IsLittle);
  4011. 4 : D.setInt32(0,B,IsLittle);
  4012. 8 : D.setFloat64(0,B,IsLittle);
  4013. end
  4014. else
  4015. case aSize of
  4016. 1 : D.SetUInt8(0,B);
  4017. 2 : D.SetUInt16(0,B,IsLittle);
  4018. 4 : D.SetUInt32(0,B,IsLittle);
  4019. 8 : D.setFloat64(0,B,IsLittle);
  4020. end;
  4021. SetLength(Result,aSize);
  4022. A:=TJSUInt8Array.new(Mem);
  4023. Result:=TMemoryStream.MemoryToBytes(A);
  4024. end;
  4025. function TStream.ReadData(var Buffer: Int8; Count: NativeInt): NativeInt;
  4026. Var
  4027. B : TBytes;
  4028. begin
  4029. SetLength(B,Count);
  4030. Result:=ReadMaxSizeData(B,1,Count);
  4031. if Result>=1 then
  4032. Buffer:=MakeInt(B,1,True);
  4033. end;
  4034. function TStream.ReadData(var Buffer: UInt8): NativeInt;
  4035. begin
  4036. Result:=ReadData(Buffer,1);
  4037. end;
  4038. function TStream.ReadData(var Buffer: UInt8; Count: NativeInt): NativeInt;
  4039. Var
  4040. B : TBytes;
  4041. begin
  4042. SetLength(B,Count);
  4043. Result:=ReadMaxSizeData(B,1,Count);
  4044. if Result>=1 then
  4045. Buffer:=MakeInt(B,1,False);
  4046. end;
  4047. function TStream.ReadData(var Buffer: Int16): NativeInt;
  4048. begin
  4049. Result:=ReadData(Buffer,2);
  4050. end;
  4051. function TStream.ReadData(var Buffer: Int16; Count: NativeInt): NativeInt;
  4052. Var
  4053. B : TBytes;
  4054. begin
  4055. SetLength(B,Count);
  4056. Result:=ReadMaxSizeData(B,2,Count);
  4057. if Result>=2 then
  4058. Buffer:=MakeInt(B,2,True);
  4059. end;
  4060. function TStream.ReadData(var Buffer: UInt16): NativeInt;
  4061. begin
  4062. Result:=ReadData(Buffer,2);
  4063. end;
  4064. function TStream.ReadData(var Buffer: UInt16; Count: NativeInt): NativeInt;
  4065. Var
  4066. B : TBytes;
  4067. begin
  4068. SetLength(B,Count);
  4069. Result:=ReadMaxSizeData(B,2,Count);
  4070. if Result>=2 then
  4071. Buffer:=MakeInt(B,2,False);
  4072. end;
  4073. function TStream.ReadData(var Buffer: Int32): NativeInt;
  4074. begin
  4075. Result:=ReadData(Buffer,4);
  4076. end;
  4077. function TStream.ReadData(var Buffer: Int32; Count: NativeInt): NativeInt;
  4078. Var
  4079. B : TBytes;
  4080. begin
  4081. SetLength(B,Count);
  4082. Result:=ReadMaxSizeData(B,4,Count);
  4083. if Result>=4 then
  4084. Buffer:=MakeInt(B,4,True);
  4085. end;
  4086. function TStream.ReadData(var Buffer: UInt32): NativeInt;
  4087. begin
  4088. Result:=ReadData(Buffer,4);
  4089. end;
  4090. function TStream.ReadData(var Buffer: UInt32; Count: NativeInt): NativeInt;
  4091. Var
  4092. B : TBytes;
  4093. begin
  4094. SetLength(B,Count);
  4095. Result:=ReadMaxSizeData(B,4,Count);
  4096. if Result>=4 then
  4097. Buffer:=MakeInt(B,4,False);
  4098. end;
  4099. function TStream.ReadData(var Buffer: NativeInt): NativeInt;
  4100. begin
  4101. Result:=ReadData(Buffer,8);
  4102. end;
  4103. function TStream.ReadData(var Buffer: NativeInt; Count: NativeInt): NativeInt;
  4104. Var
  4105. B : TBytes;
  4106. begin
  4107. SetLength(B,Count);
  4108. Result:=ReadMaxSizeData(B,8,8);
  4109. if Result>=8 then
  4110. Buffer:=MakeInt(B,8,True);
  4111. end;
  4112. function TStream.ReadData(var Buffer: NativeLargeUInt): NativeInt;
  4113. begin
  4114. Result:=ReadData(Buffer,8);
  4115. end;
  4116. function TStream.ReadData(var Buffer: NativeLargeUInt; Count: NativeInt): NativeInt;
  4117. Var
  4118. B : TBytes;
  4119. B1 : Integer;
  4120. begin
  4121. SetLength(B,Count);
  4122. Result:=ReadMaxSizeData(B,4,4);
  4123. if Result>=4 then
  4124. begin
  4125. B1:=MakeInt(B,4,False);
  4126. Result:=Result+ReadMaxSizeData(B,4,4);
  4127. Buffer:=MakeInt(B,4,False);
  4128. Buffer:=(Buffer shl 32) or B1;
  4129. end;
  4130. end;
  4131. function TStream.ReadData(var Buffer: Double): NativeInt;
  4132. begin
  4133. Result:=ReadData(Buffer,8);
  4134. end;
  4135. function TStream.ReadData(var Buffer: Double; Count: NativeInt): NativeInt;
  4136. Var
  4137. B : TBytes;
  4138. Mem : TJSArrayBuffer;
  4139. A : TJSUInt8Array;
  4140. D : TJSDataView;
  4141. begin
  4142. SetLength(B,Count);
  4143. Result:=ReadMaxSizeData(B,8,Count);
  4144. if Result>=8 then
  4145. begin
  4146. Mem:=TJSArrayBuffer.New(8);
  4147. A:=TJSUInt8Array.new(Mem);
  4148. A._set(B);
  4149. D:=TJSDataView.New(Mem);
  4150. Buffer:=D.getFloat64(0);
  4151. end;
  4152. end;
  4153. procedure TStream.ReadBuffer(var Buffer: TBytes; Count: NativeInt);
  4154. begin
  4155. ReadBuffer(Buffer,0,Count);
  4156. end;
  4157. procedure TStream.ReadBuffer(var Buffer: TBytes; Offset, Count: NativeInt);
  4158. begin
  4159. if Read(Buffer,OffSet,Count)<>Count then
  4160. Raise EStreamError.Create(SReadError);
  4161. end;
  4162. procedure TStream.ReadBufferData(var Buffer: Boolean);
  4163. begin
  4164. ReadBufferData(Buffer,1);
  4165. end;
  4166. procedure TStream.ReadBufferData(var Buffer: Boolean; Count: NativeInt);
  4167. begin
  4168. if (ReadData(Buffer,Count)<>Count) then
  4169. Raise EStreamError.Create(SReadError);
  4170. end;
  4171. procedure TStream.ReadBufferData(var Buffer: WideChar);
  4172. begin
  4173. ReadBufferData(Buffer,2);
  4174. end;
  4175. procedure TStream.ReadBufferData(var Buffer: WideChar; Count: NativeInt);
  4176. begin
  4177. if (ReadData(Buffer,Count)<>Count) then
  4178. Raise EStreamError.Create(SReadError);
  4179. end;
  4180. procedure TStream.ReadBufferData(var Buffer: Int8);
  4181. begin
  4182. ReadBufferData(Buffer,1);
  4183. end;
  4184. procedure TStream.ReadBufferData(var Buffer: Int8; Count: NativeInt);
  4185. begin
  4186. if (ReadData(Buffer,Count)<>Count) then
  4187. Raise EStreamError.Create(SReadError);
  4188. end;
  4189. procedure TStream.ReadBufferData(var Buffer: UInt8);
  4190. begin
  4191. ReadBufferData(Buffer,1);
  4192. end;
  4193. procedure TStream.ReadBufferData(var Buffer: UInt8; Count: NativeInt);
  4194. begin
  4195. if (ReadData(Buffer,Count)<>Count) then
  4196. Raise EStreamError.Create(SReadError);
  4197. end;
  4198. procedure TStream.ReadBufferData(var Buffer: Int16);
  4199. begin
  4200. ReadBufferData(Buffer,2);
  4201. end;
  4202. procedure TStream.ReadBufferData(var Buffer: Int16; Count: NativeInt);
  4203. begin
  4204. if (ReadData(Buffer,Count)<>Count) then
  4205. Raise EStreamError.Create(SReadError);
  4206. end;
  4207. procedure TStream.ReadBufferData(var Buffer: UInt16);
  4208. begin
  4209. ReadBufferData(Buffer,2);
  4210. end;
  4211. procedure TStream.ReadBufferData(var Buffer: UInt16; Count: NativeInt);
  4212. begin
  4213. if (ReadData(Buffer,Count)<>Count) then
  4214. Raise EStreamError.Create(SReadError);
  4215. end;
  4216. procedure TStream.ReadBufferData(var Buffer: Int32);
  4217. begin
  4218. ReadBufferData(Buffer,4);
  4219. end;
  4220. procedure TStream.ReadBufferData(var Buffer: Int32; Count: NativeInt);
  4221. begin
  4222. if (ReadData(Buffer,Count)<>Count) then
  4223. Raise EStreamError.Create(SReadError);
  4224. end;
  4225. procedure TStream.ReadBufferData(var Buffer: UInt32);
  4226. begin
  4227. ReadBufferData(Buffer,4);
  4228. end;
  4229. procedure TStream.ReadBufferData(var Buffer: UInt32; Count: NativeInt);
  4230. begin
  4231. if (ReadData(Buffer,Count)<>Count) then
  4232. Raise EStreamError.Create(SReadError);
  4233. end;
  4234. procedure TStream.ReadBufferData(var Buffer: NativeLargeInt);
  4235. begin
  4236. ReadBufferData(Buffer,8)
  4237. end;
  4238. procedure TStream.ReadBufferData(var Buffer: NativeLargeInt; Count: NativeInt);
  4239. begin
  4240. if (ReadData(Buffer,Count)<>Count) then
  4241. Raise EStreamError.Create(SReadError);
  4242. end;
  4243. procedure TStream.ReadBufferData(var Buffer: NativeLargeUInt);
  4244. begin
  4245. ReadBufferData(Buffer,8);
  4246. end;
  4247. procedure TStream.ReadBufferData(var Buffer: NativeLargeUInt; Count: NativeInt);
  4248. begin
  4249. if (ReadData(Buffer,Count)<>Count) then
  4250. Raise EStreamError.Create(SReadError);
  4251. end;
  4252. procedure TStream.ReadBufferData(var Buffer: Double);
  4253. begin
  4254. ReadBufferData(Buffer,8);
  4255. end;
  4256. procedure TStream.ReadBufferData(var Buffer: Double; Count: NativeInt);
  4257. begin
  4258. if (ReadData(Buffer,Count)<>Count) then
  4259. Raise EStreamError.Create(SReadError);
  4260. end;
  4261. procedure TStream.WriteBuffer(const Buffer: TBytes; Count: NativeInt);
  4262. begin
  4263. WriteBuffer(Buffer,0,Count);
  4264. end;
  4265. procedure TStream.WriteBuffer(const Buffer: TBytes; Offset, Count: NativeInt);
  4266. begin
  4267. if Self.Write(Buffer,Offset,Count)<>Count then
  4268. Raise EStreamError.Create(SWriteError);
  4269. end;
  4270. function TStream.WriteData(const Buffer: TBytes; Count: NativeInt): NativeInt;
  4271. begin
  4272. Result:=Self.Write(Buffer, 0, Count);
  4273. end;
  4274. function TStream.WriteData(const Buffer: Boolean): NativeInt;
  4275. begin
  4276. Result:=WriteData(Buffer,1);
  4277. end;
  4278. function TStream.WriteData(const Buffer: Boolean; Count: NativeInt): NativeInt;
  4279. Var
  4280. B : Int8;
  4281. begin
  4282. B:=Ord(Buffer);
  4283. Result:=WriteData(B,Count);
  4284. end;
  4285. function TStream.WriteData(const Buffer: WideChar): NativeInt;
  4286. begin
  4287. Result:=WriteData(Buffer,2);
  4288. end;
  4289. function TStream.WriteData(const Buffer: WideChar; Count: NativeInt): NativeInt;
  4290. Var
  4291. U : UInt16;
  4292. begin
  4293. U:=Ord(Buffer);
  4294. Result:=WriteData(U,Count);
  4295. end;
  4296. function TStream.WriteData(const Buffer: Int8): NativeInt;
  4297. begin
  4298. Result:=WriteData(Buffer,1);
  4299. end;
  4300. function TStream.WriteData(const Buffer: Int8; Count: NativeInt): NativeInt;
  4301. begin
  4302. Result:=WriteMaxSizeData(MakeBytes(Buffer,1,True),1,Count);
  4303. end;
  4304. function TStream.WriteData(const Buffer: UInt8): NativeInt;
  4305. begin
  4306. Result:=WriteData(Buffer,1);
  4307. end;
  4308. function TStream.WriteData(const Buffer: UInt8; Count: NativeInt): NativeInt;
  4309. begin
  4310. Result:=WriteMaxSizeData(MakeBytes(Buffer,1,False),1,Count);
  4311. end;
  4312. function TStream.WriteData(const Buffer: Int16): NativeInt;
  4313. begin
  4314. Result:=WriteData(Buffer,2);
  4315. end;
  4316. function TStream.WriteData(const Buffer: Int16; Count: NativeInt): NativeInt;
  4317. begin
  4318. Result:=WriteMaxSizeData(MakeBytes(Buffer,2,True),2,Count);
  4319. end;
  4320. function TStream.WriteData(const Buffer: UInt16): NativeInt;
  4321. begin
  4322. Result:=WriteData(Buffer,2);
  4323. end;
  4324. function TStream.WriteData(const Buffer: UInt16; Count: NativeInt): NativeInt;
  4325. begin
  4326. Result:=WriteMaxSizeData(MakeBytes(Buffer,2,True),2,Count);
  4327. end;
  4328. function TStream.WriteData(const Buffer: Int32): NativeInt;
  4329. begin
  4330. Result:=WriteData(Buffer,4);
  4331. end;
  4332. function TStream.WriteData(const Buffer: Int32; Count: NativeInt): NativeInt;
  4333. begin
  4334. Result:=WriteMaxSizeData(MakeBytes(Buffer,4,True),4,Count);
  4335. end;
  4336. function TStream.WriteData(const Buffer: UInt32): NativeInt;
  4337. begin
  4338. Result:=WriteData(Buffer,4);
  4339. end;
  4340. function TStream.WriteData(const Buffer: UInt32; Count: NativeInt): NativeInt;
  4341. begin
  4342. Result:=WriteMaxSizeData(MakeBytes(Buffer,4,False),4,Count);
  4343. end;
  4344. function TStream.WriteData(const Buffer: NativeLargeInt): NativeInt;
  4345. begin
  4346. Result:=WriteData(Buffer,8);
  4347. end;
  4348. function TStream.WriteData(const Buffer: NativeLargeInt; Count: NativeInt): NativeInt;
  4349. begin
  4350. Result:=WriteMaxSizeData(MakeBytes(Buffer,8,True),8,Count);
  4351. end;
  4352. function TStream.WriteData(const Buffer: NativeLargeUInt): NativeInt;
  4353. begin
  4354. Result:=WriteData(Buffer,8);
  4355. end;
  4356. function TStream.WriteData(const Buffer: NativeLargeUInt; Count: NativeInt): NativeInt;
  4357. begin
  4358. Result:=WriteMaxSizeData(MakeBytes(Buffer,8,False),8,Count);
  4359. end;
  4360. function TStream.WriteData(const Buffer: Double): NativeInt;
  4361. begin
  4362. Result:=WriteData(Buffer,8);
  4363. end;
  4364. function TStream.WriteData(const Buffer: Double; Count: NativeInt): NativeInt;
  4365. Var
  4366. Mem : TJSArrayBuffer;
  4367. A : TJSUint8array;
  4368. D : TJSDataview;
  4369. B : TBytes;
  4370. I : Integer;
  4371. begin
  4372. Mem:=TJSArrayBuffer.New(8);
  4373. D:=TJSDataView.new(Mem);
  4374. D.setFloat64(0,Buffer);
  4375. SetLength(B,8);
  4376. A:=TJSUint8array.New(Mem);
  4377. For I:=0 to 7 do
  4378. B[i]:=A[i];
  4379. Result:=WriteMaxSizeData(B,8,Count);
  4380. end;
  4381. procedure TStream.WriteBufferData(Buffer: Int32);
  4382. begin
  4383. WriteBufferData(Buffer,4);
  4384. end;
  4385. procedure TStream.WriteBufferData(Buffer: Int32; Count: NativeInt);
  4386. begin
  4387. if (WriteData(Buffer,Count)<>Count) then
  4388. Raise EStreamError.Create(SWriteError);
  4389. end;
  4390. procedure TStream.WriteBufferData(Buffer: Boolean);
  4391. begin
  4392. WriteBufferData(Buffer,1);
  4393. end;
  4394. procedure TStream.WriteBufferData(Buffer: Boolean; Count: NativeInt);
  4395. begin
  4396. if (WriteData(Buffer,Count)<>Count) then
  4397. Raise EStreamError.Create(SWriteError);
  4398. end;
  4399. procedure TStream.WriteBufferData(Buffer: WideChar);
  4400. begin
  4401. WriteBufferData(Buffer,2);
  4402. end;
  4403. procedure TStream.WriteBufferData(Buffer: WideChar; Count: NativeInt);
  4404. begin
  4405. if (WriteData(Buffer,Count)<>Count) then
  4406. Raise EStreamError.Create(SWriteError);
  4407. end;
  4408. procedure TStream.WriteBufferData(Buffer: Int8);
  4409. begin
  4410. WriteBufferData(Buffer,1);
  4411. end;
  4412. procedure TStream.WriteBufferData(Buffer: Int8; Count: NativeInt);
  4413. begin
  4414. if (WriteData(Buffer,Count)<>Count) then
  4415. Raise EStreamError.Create(SWriteError);
  4416. end;
  4417. procedure TStream.WriteBufferData(Buffer: UInt8);
  4418. begin
  4419. WriteBufferData(Buffer,1);
  4420. end;
  4421. procedure TStream.WriteBufferData(Buffer: UInt8; Count: NativeInt);
  4422. begin
  4423. if (WriteData(Buffer,Count)<>Count) then
  4424. Raise EStreamError.Create(SWriteError);
  4425. end;
  4426. procedure TStream.WriteBufferData(Buffer: Int16);
  4427. begin
  4428. WriteBufferData(Buffer,2);
  4429. end;
  4430. procedure TStream.WriteBufferData(Buffer: Int16; Count: NativeInt);
  4431. begin
  4432. if (WriteData(Buffer,Count)<>Count) then
  4433. Raise EStreamError.Create(SWriteError);
  4434. end;
  4435. procedure TStream.WriteBufferData(Buffer: UInt16);
  4436. begin
  4437. WriteBufferData(Buffer,2);
  4438. end;
  4439. procedure TStream.WriteBufferData(Buffer: UInt16; Count: NativeInt);
  4440. begin
  4441. if (WriteData(Buffer,Count)<>Count) then
  4442. Raise EStreamError.Create(SWriteError);
  4443. end;
  4444. procedure TStream.WriteBufferData(Buffer: UInt32);
  4445. begin
  4446. WriteBufferData(Buffer,4);
  4447. end;
  4448. procedure TStream.WriteBufferData(Buffer: UInt32; Count: NativeInt);
  4449. begin
  4450. if (WriteData(Buffer,Count)<>Count) then
  4451. Raise EStreamError.Create(SWriteError);
  4452. end;
  4453. procedure TStream.WriteBufferData(Buffer: NativeInt);
  4454. begin
  4455. WriteBufferData(Buffer,8);
  4456. end;
  4457. procedure TStream.WriteBufferData(Buffer: NativeInt; Count: NativeInt);
  4458. begin
  4459. if (WriteData(Buffer,Count)<>Count) then
  4460. Raise EStreamError.Create(SWriteError);
  4461. end;
  4462. procedure TStream.WriteBufferData(Buffer: NativeLargeUInt);
  4463. begin
  4464. WriteBufferData(Buffer,8);
  4465. end;
  4466. procedure TStream.WriteBufferData(Buffer: NativeLargeUInt; Count: NativeInt);
  4467. begin
  4468. if (WriteData(Buffer,Count)<>Count) then
  4469. Raise EStreamError.Create(SWriteError);
  4470. end;
  4471. procedure TStream.WriteBufferData(Buffer: Double);
  4472. begin
  4473. WriteBufferData(Buffer,8);
  4474. end;
  4475. procedure TStream.WriteBufferData(Buffer: Double; Count: NativeInt);
  4476. begin
  4477. if (WriteData(Buffer,Count)<>Count) then
  4478. Raise EStreamError.Create(SWriteError);
  4479. end;
  4480. function TStream.CopyFrom(Source: TStream; Count: NativeInt): NativeInt;
  4481. var
  4482. Buffer: TBytes;
  4483. BufferSize, i: LongInt;
  4484. const
  4485. MaxSize = $20000;
  4486. begin
  4487. Result:=0;
  4488. if Count=0 then
  4489. Source.Position:=0; // This WILL fail for non-seekable streams...
  4490. BufferSize:=MaxSize;
  4491. if (Count>0) and (Count<BufferSize) then
  4492. BufferSize:=Count; // do not allocate more than needed
  4493. SetLength(Buffer,BufferSize);
  4494. if Count=0 then
  4495. repeat
  4496. i:=Source.Read(Buffer,BufferSize);
  4497. if i>0 then
  4498. WriteBuffer(Buffer,i);
  4499. Inc(Result,i);
  4500. until i<BufferSize
  4501. else
  4502. while Count>0 do
  4503. begin
  4504. if Count>BufferSize then
  4505. i:=BufferSize
  4506. else
  4507. i:=Count;
  4508. Source.ReadBuffer(Buffer,i);
  4509. WriteBuffer(Buffer,i);
  4510. Dec(count,i);
  4511. Inc(Result,i);
  4512. end;
  4513. end;
  4514. function TStream.ReadComponent(Instance: TComponent): TComponent;
  4515. var
  4516. Reader: TReader;
  4517. begin
  4518. Reader := TReader.Create(Self);
  4519. try
  4520. Result := Reader.ReadRootComponent(Instance);
  4521. finally
  4522. Reader.Free;
  4523. end;
  4524. end;
  4525. function TStream.ReadComponentRes(Instance: TComponent): TComponent;
  4526. begin
  4527. ReadResHeader;
  4528. Result := ReadComponent(Instance);
  4529. end;
  4530. procedure TStream.WriteComponent(Instance: TComponent);
  4531. begin
  4532. WriteDescendent(Instance, nil);
  4533. end;
  4534. procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
  4535. begin
  4536. WriteDescendentRes(ResName, Instance, nil);
  4537. end;
  4538. procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
  4539. var
  4540. Driver : TAbstractObjectWriter;
  4541. Writer : TWriter;
  4542. begin
  4543. Driver := TBinaryObjectWriter.Create(Self);
  4544. Try
  4545. Writer := TWriter.Create(Driver);
  4546. Try
  4547. Writer.WriteDescendent(Instance, Ancestor);
  4548. Finally
  4549. Writer.Destroy;
  4550. end;
  4551. Finally
  4552. Driver.Free;
  4553. end;
  4554. end;
  4555. procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
  4556. var
  4557. FixupInfo: Longint;
  4558. begin
  4559. { Write a resource header }
  4560. WriteResourceHeader(ResName, FixupInfo);
  4561. { Write the instance itself }
  4562. WriteDescendent(Instance, Ancestor);
  4563. { Insert the correct resource size into the resource header }
  4564. FixupResourceHeader(FixupInfo);
  4565. end;
  4566. procedure TStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Longint);
  4567. var
  4568. ResType, Flags : word;
  4569. B : Byte;
  4570. I : Integer;
  4571. begin
  4572. ResType:=Word($000A);
  4573. Flags:=Word($1030);
  4574. { Note: This is a Windows 16 bit resource }
  4575. { Numeric resource type }
  4576. WriteByte($ff);
  4577. { Application defined data }
  4578. WriteWord(ResType);
  4579. { write the name as asciiz }
  4580. For I:=1 to Length(ResName) do
  4581. begin
  4582. B:=Ord(ResName[i]);
  4583. WriteByte(B);
  4584. end;
  4585. WriteByte(0);
  4586. { Movable, Pure and Discardable }
  4587. WriteWord(Flags);
  4588. { Placeholder for the resource size }
  4589. WriteDWord(0);
  4590. { Return current stream position so that the resource size can be
  4591. inserted later }
  4592. FixupInfo := Position;
  4593. end;
  4594. procedure TStream.FixupResourceHeader(FixupInfo: Longint);
  4595. var
  4596. ResSize,TmpResSize : Longint;
  4597. begin
  4598. ResSize := Position - FixupInfo;
  4599. TmpResSize := longword(ResSize);
  4600. { Insert the correct resource size into the placeholder written by
  4601. WriteResourceHeader }
  4602. Position := FixupInfo - 4;
  4603. WriteDWord(TmpResSize);
  4604. { Seek back to the end of the resource }
  4605. Position := FixupInfo + ResSize;
  4606. end;
  4607. procedure TStream.ReadResHeader;
  4608. var
  4609. ResType, Flags : word;
  4610. begin
  4611. try
  4612. { Note: This is a Windows 16 bit resource }
  4613. { application specific resource ? }
  4614. if ReadByte<>$ff then
  4615. raise EInvalidImage.Create(SInvalidImage);
  4616. ResType:=ReadWord;
  4617. if ResType<>$000a then
  4618. raise EInvalidImage.Create(SInvalidImage);
  4619. { read name }
  4620. while ReadByte<>0 do
  4621. ;
  4622. { check the access specifier }
  4623. Flags:=ReadWord;
  4624. if Flags<>$1030 then
  4625. raise EInvalidImage.Create(SInvalidImage);
  4626. { ignore the size }
  4627. ReadDWord;
  4628. except
  4629. on EInvalidImage do
  4630. raise;
  4631. else
  4632. raise EInvalidImage.create(SInvalidImage);
  4633. end;
  4634. end;
  4635. function TStream.ReadByte : Byte;
  4636. begin
  4637. ReadBufferData(Result,1);
  4638. end;
  4639. function TStream.ReadWord : Word;
  4640. begin
  4641. ReadBufferData(Result,2);
  4642. end;
  4643. function TStream.ReadDWord : Cardinal;
  4644. begin
  4645. ReadBufferData(Result,4);
  4646. end;
  4647. function TStream.ReadQWord: NativeLargeUInt;
  4648. begin
  4649. ReadBufferData(Result,8);
  4650. end;
  4651. procedure TStream.WriteByte(b : Byte);
  4652. begin
  4653. WriteBufferData(b,1);
  4654. end;
  4655. procedure TStream.WriteWord(w : Word);
  4656. begin
  4657. WriteBufferData(W,2);
  4658. end;
  4659. procedure TStream.WriteDWord(d : Cardinal);
  4660. begin
  4661. WriteBufferData(d,4);
  4662. end;
  4663. procedure TStream.WriteQWord(q: NativeLargeUInt);
  4664. begin
  4665. WriteBufferData(q,8);
  4666. end;
  4667. {****************************************************************************}
  4668. {* TCustomMemoryStream *}
  4669. {****************************************************************************}
  4670. procedure TCustomMemoryStream.SetPointer(Ptr: TJSArrayBuffer; ASize: PtrInt);
  4671. begin
  4672. FMemory:=Ptr;
  4673. FSize:=ASize;
  4674. FDataView:=Nil;
  4675. FDataArray:=Nil;
  4676. end;
  4677. Class Function TCustomMemoryStream.MemoryToBytes(Mem : TJSArrayBuffer) : TBytes; overload;
  4678. begin
  4679. Result:=MemoryToBytes(TJSUint8Array.New(Mem));
  4680. end;
  4681. class function TCustomMemoryStream.MemoryToBytes(Mem: TJSUint8Array): TBytes;
  4682. Var
  4683. I : Integer;
  4684. begin
  4685. // This must be improved, but needs some asm or TJSFunction.call() to implement answers in
  4686. // https://stackoverflow.com/questions/29676635/convert-uint8array-to-array-in-javascript
  4687. for i:=0 to mem.length-1 do
  4688. Result[i]:=Mem[i];
  4689. end;
  4690. class function TCustomMemoryStream.BytesToMemory(aBytes: TBytes): TJSArrayBuffer;
  4691. Var
  4692. a : TJSUint8Array;
  4693. begin
  4694. Result:=TJSArrayBuffer.new(Length(aBytes));
  4695. A:=TJSUint8Array.New(Result);
  4696. A._set(aBytes);
  4697. end;
  4698. function TCustomMemoryStream.GetDataArray: TJSUint8Array;
  4699. begin
  4700. if FDataArray=Nil then
  4701. FDataArray:=TJSUint8Array.new(Memory);
  4702. Result:=FDataArray;
  4703. end;
  4704. function TCustomMemoryStream.GetDataView: TJSDataview;
  4705. begin
  4706. if FDataView=Nil then
  4707. FDataView:=TJSDataView.New(Memory);
  4708. Result:=FDataView;
  4709. end;
  4710. function TCustomMemoryStream.GetSize: NativeInt;
  4711. begin
  4712. Result:=FSize;
  4713. end;
  4714. function TCustomMemoryStream.GetPosition: NativeInt;
  4715. begin
  4716. Result:=FPosition;
  4717. end;
  4718. function TCustomMemoryStream.Read(Buffer : TBytes; offset, Count: LongInt): LongInt;
  4719. Var
  4720. I,Src,Dest : Integer;
  4721. begin
  4722. Result:=0;
  4723. If (FSize>0) and (FPosition<Fsize) and (FPosition>=0) then
  4724. begin
  4725. Result:=Count;
  4726. If (Result>(FSize-FPosition)) then
  4727. Result:=(FSize-FPosition);
  4728. Src:=FPosition;
  4729. Dest:=Offset;
  4730. I:=0;
  4731. While I<Result do
  4732. begin
  4733. Buffer[Dest]:=DataView.getUint8(Src);
  4734. inc(Src);
  4735. inc(Dest);
  4736. inc(I);
  4737. end;
  4738. FPosition:=Fposition+Result;
  4739. end;
  4740. end;
  4741. function TCustomMemoryStream.Seek(const Offset: NativeInt; Origin: TSeekOrigin): NativeInt;
  4742. begin
  4743. Case Origin of
  4744. soBeginning : FPosition:=Offset;
  4745. soEnd : FPosition:=FSize+Offset;
  4746. soCurrent : FPosition:=FPosition+Offset;
  4747. end;
  4748. if SizeBoundsSeek and (FPosition>FSize) then
  4749. FPosition:=FSize;
  4750. Result:=FPosition;
  4751. {$IFDEF DEBUG}
  4752. if Result < 0 then
  4753. raise Exception.Create('TCustomMemoryStream');
  4754. {$ENDIF}
  4755. end;
  4756. procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
  4757. begin
  4758. if FSize>0 then
  4759. Stream.WriteBuffer(TMemoryStream.MemoryToBytes(Memory),FSize);
  4760. end;
  4761. {****************************************************************************}
  4762. {* TMemoryStream *}
  4763. {****************************************************************************}
  4764. Const TMSGrow = 4096; { Use 4k blocks. }
  4765. procedure TMemoryStream.SetCapacity(NewCapacity: PtrInt);
  4766. begin
  4767. SetPointer (Realloc(NewCapacity),Fsize);
  4768. FCapacity:=NewCapacity;
  4769. end;
  4770. function TMemoryStream.Realloc(var NewCapacity: PtrInt): TJSArrayBuffer;
  4771. Var
  4772. GC : PtrInt;
  4773. DestView : TJSUInt8array;
  4774. begin
  4775. If NewCapacity<0 Then
  4776. NewCapacity:=0
  4777. else
  4778. begin
  4779. GC:=FCapacity + (FCapacity div 4);
  4780. // if growing, grow at least a quarter
  4781. if (NewCapacity>FCapacity) and (NewCapacity < GC) then
  4782. NewCapacity := GC;
  4783. // round off to block size.
  4784. NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
  4785. end;
  4786. // Only now check !
  4787. If NewCapacity=FCapacity then
  4788. Result:=FMemory
  4789. else if NewCapacity=0 then
  4790. Result:=Nil
  4791. else
  4792. begin
  4793. // New buffer
  4794. Result:=TJSArrayBuffer.New(NewCapacity);
  4795. If (Result=Nil) then
  4796. Raise EStreamError.Create(SMemoryStreamError);
  4797. // Transfer
  4798. DestView:=TJSUInt8array.New(Result);
  4799. Destview._Set(Self.DataArray);
  4800. end;
  4801. end;
  4802. destructor TMemoryStream.Destroy;
  4803. begin
  4804. Clear;
  4805. Inherited Destroy;
  4806. end;
  4807. procedure TMemoryStream.Clear;
  4808. begin
  4809. FSize:=0;
  4810. FPosition:=0;
  4811. SetCapacity (0);
  4812. end;
  4813. procedure TMemoryStream.LoadFromStream(Stream: TStream);
  4814. begin
  4815. Stream.Position:=0;
  4816. SetSize(Stream.Size);
  4817. If FSize>0 then Stream.ReadBuffer(MemoryToBytes(FMemory),FSize);
  4818. end;
  4819. procedure TMemoryStream.SetSize(const NewSize: NativeInt);
  4820. begin
  4821. SetCapacity (NewSize);
  4822. FSize:=NewSize;
  4823. IF FPosition>FSize then
  4824. FPosition:=FSize;
  4825. end;
  4826. function TMemoryStream.Write(Const Buffer : TBytes; OffSet, Count: LongInt): LongInt;
  4827. Var NewPos : PtrInt;
  4828. begin
  4829. If (Count=0) or (FPosition<0) then
  4830. exit(0);
  4831. NewPos:=FPosition+Count;
  4832. If NewPos>Fsize then
  4833. begin
  4834. IF NewPos>FCapacity then
  4835. SetCapacity (NewPos);
  4836. FSize:=Newpos;
  4837. end;
  4838. DataArray._set(Copy(Buffer,Offset,Count),FPosition);
  4839. FPosition:=NewPos;
  4840. Result:=Count;
  4841. end;
  4842. {****************************************************************************}
  4843. {* TBytesStream *}
  4844. {****************************************************************************}
  4845. constructor TBytesStream.Create(const ABytes: TBytes);
  4846. begin
  4847. inherited Create;
  4848. SetPointer(TMemoryStream.BytesToMemory(aBytes),Length(ABytes));
  4849. FCapacity:=Length(ABytes);
  4850. end;
  4851. function TBytesStream.GetBytes: TBytes;
  4852. begin
  4853. Result:=TMemoryStream.MemoryToBytes(Memory);
  4854. end;
  4855. { *********************************************************************
  4856. * TFiler *
  4857. *********************************************************************}
  4858. procedure TFiler.SetRoot(ARoot: TComponent);
  4859. begin
  4860. FRoot := ARoot;
  4861. end;
  4862. {
  4863. This file is part of the Free Component Library (FCL)
  4864. Copyright (c) 1999-2000 by the Free Pascal development team
  4865. See the file COPYING.FPC, included in this distribution,
  4866. for details about the copyright.
  4867. This program is distributed in the hope that it will be useful,
  4868. but WITHOUT ANY WARRANTY; without even the implied warranty of
  4869. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  4870. **********************************************************************}
  4871. {****************************************************************************}
  4872. {* TBinaryObjectReader *}
  4873. {****************************************************************************}
  4874. function TBinaryObjectReader.ReadWord : word;
  4875. begin
  4876. FStream.ReadBufferData(Result);
  4877. end;
  4878. function TBinaryObjectReader.ReadDWord : longword;
  4879. begin
  4880. FStream.ReadBufferData(Result);
  4881. end;
  4882. constructor TBinaryObjectReader.Create(Stream: TStream);
  4883. begin
  4884. inherited Create;
  4885. If (Stream=Nil) then
  4886. Raise EReadError.Create(SEmptyStreamIllegalReader);
  4887. FStream := Stream;
  4888. end;
  4889. function TBinaryObjectReader.ReadValue: TValueType;
  4890. var
  4891. b: byte;
  4892. begin
  4893. FStream.ReadBufferData(b);
  4894. Result := TValueType(b);
  4895. end;
  4896. function TBinaryObjectReader.NextValue: TValueType;
  4897. begin
  4898. Result := ReadValue;
  4899. { We only 'peek' at the next value, so seek back to unget the read value: }
  4900. FStream.Seek(-1,soCurrent);
  4901. end;
  4902. procedure TBinaryObjectReader.BeginRootComponent;
  4903. begin
  4904. { Read filer signature }
  4905. ReadSignature;
  4906. end;
  4907. procedure TBinaryObjectReader.BeginComponent(var Flags: TFilerFlags;
  4908. var AChildPos: Integer; var CompClassName, CompName: String);
  4909. var
  4910. Prefix: Byte;
  4911. ValueType: TValueType;
  4912. begin
  4913. { Every component can start with a special prefix: }
  4914. Flags := [];
  4915. if (Byte(NextValue) and $f0) = $f0 then
  4916. begin
  4917. Prefix := Byte(ReadValue);
  4918. Flags:=[];
  4919. if (Prefix and $01)<>0 then
  4920. Include(Flags,ffInherited);
  4921. if (Prefix and $02)<>0 then
  4922. Include(Flags,ffChildPos);
  4923. if (Prefix and $04)<>0 then
  4924. Include(Flags,ffInline);
  4925. if ffChildPos in Flags then
  4926. begin
  4927. ValueType := ReadValue;
  4928. case ValueType of
  4929. vaInt8:
  4930. AChildPos := ReadInt8;
  4931. vaInt16:
  4932. AChildPos := ReadInt16;
  4933. vaInt32:
  4934. AChildPos := ReadInt32;
  4935. vaNativeInt:
  4936. AChildPos := ReadNativeInt;
  4937. else
  4938. raise EReadError.Create(SInvalidPropertyValue);
  4939. end;
  4940. end;
  4941. end;
  4942. CompClassName := ReadStr;
  4943. CompName := ReadStr;
  4944. end;
  4945. function TBinaryObjectReader.BeginProperty: String;
  4946. begin
  4947. Result := ReadStr;
  4948. end;
  4949. procedure TBinaryObjectReader.Read(var Buffer: TBytes; Count: Longint);
  4950. begin
  4951. FStream.Read(Buffer,Count);
  4952. end;
  4953. procedure TBinaryObjectReader.ReadBinary(const DestData: TMemoryStream);
  4954. var
  4955. BinSize: LongInt;
  4956. begin
  4957. BinSize:=LongInt(ReadDWord);
  4958. DestData.Size := BinSize;
  4959. DestData.CopyFrom(FStream,BinSize);
  4960. end;
  4961. function TBinaryObjectReader.ReadFloat: Extended;
  4962. begin
  4963. FStream.ReadBufferData(Result);
  4964. end;
  4965. function TBinaryObjectReader.ReadCurrency: Currency;
  4966. begin
  4967. Result:=ReadFloat;
  4968. end;
  4969. function TBinaryObjectReader.ReadIdent(ValueType: TValueType): String;
  4970. var
  4971. i: Byte;
  4972. c : Char;
  4973. begin
  4974. case ValueType of
  4975. vaIdent:
  4976. begin
  4977. FStream.ReadBufferData(i);
  4978. SetLength(Result,i);
  4979. For I:=1 to Length(Result) do
  4980. begin
  4981. FStream.ReadBufferData(C);
  4982. Result[I]:=C;
  4983. end;
  4984. end;
  4985. vaNil:
  4986. Result := 'nil';
  4987. vaFalse:
  4988. Result := 'False';
  4989. vaTrue:
  4990. Result := 'True';
  4991. vaNull:
  4992. Result := 'Null';
  4993. end;
  4994. end;
  4995. function TBinaryObjectReader.ReadInt8: ShortInt;
  4996. begin
  4997. FStream.ReadBufferData(Result);
  4998. end;
  4999. function TBinaryObjectReader.ReadInt16: SmallInt;
  5000. begin
  5001. FStream.ReadBufferData(Result);
  5002. end;
  5003. function TBinaryObjectReader.ReadInt32: LongInt;
  5004. begin
  5005. FStream.ReadBufferData(Result);
  5006. end;
  5007. function TBinaryObjectReader.ReadNativeInt : NativeInt;
  5008. begin
  5009. FStream.ReadBufferData(Result);
  5010. end;
  5011. function TBinaryObjectReader.ReadSet(EnumType: TTypeInfoEnum): Integer;
  5012. var
  5013. Name: String;
  5014. Value: Integer;
  5015. begin
  5016. try
  5017. Result := 0;
  5018. while True do
  5019. begin
  5020. Name := ReadStr;
  5021. if Length(Name) = 0 then
  5022. break;
  5023. Value:=EnumType.EnumType.NameToInt[Name];
  5024. if Value=-1 then
  5025. raise EReadError.Create(SInvalidPropertyValue);
  5026. Result:=Result or (1 shl Value);
  5027. end;
  5028. except
  5029. SkipSetBody;
  5030. raise;
  5031. end;
  5032. end;
  5033. Const
  5034. // Integer version of 4 chars 'TPF0'
  5035. FilerSignatureInt = 809914452;
  5036. procedure TBinaryObjectReader.ReadSignature;
  5037. var
  5038. Signature: LongInt;
  5039. begin
  5040. FStream.ReadBufferData(Signature);
  5041. if Signature <> FilerSignatureInt then
  5042. raise EReadError.Create(SInvalidImage);
  5043. end;
  5044. function TBinaryObjectReader.ReadStr: String;
  5045. var
  5046. l,i: Byte;
  5047. c : Char;
  5048. begin
  5049. FStream.ReadBufferData(L);
  5050. SetLength(Result,L);
  5051. For I:=1 to L do
  5052. begin
  5053. FStream.ReadBufferData(C);
  5054. Result[i]:=C;
  5055. end;
  5056. end;
  5057. function TBinaryObjectReader.ReadString(StringType: TValueType): String;
  5058. var
  5059. i: Integer;
  5060. C : Char;
  5061. begin
  5062. Result:='';
  5063. if StringType<>vaString then
  5064. Raise EFilerError.Create('Invalid string type passed to ReadString');
  5065. i:=ReadDWord;
  5066. SetLength(Result, i);
  5067. for I:=1 to Length(Result) do
  5068. begin
  5069. FStream.ReadbufferData(C);
  5070. Result[i]:=C;
  5071. end;
  5072. end;
  5073. function TBinaryObjectReader.ReadWideString: WideString;
  5074. begin
  5075. Result:=ReadString(vaWString);
  5076. end;
  5077. function TBinaryObjectReader.ReadUnicodeString: UnicodeString;
  5078. begin
  5079. Result:=ReadString(vaWString);
  5080. end;
  5081. procedure TBinaryObjectReader.SkipComponent(SkipComponentInfos: Boolean);
  5082. var
  5083. Flags: TFilerFlags;
  5084. Dummy: Integer;
  5085. CompClassName, CompName: String;
  5086. begin
  5087. if SkipComponentInfos then
  5088. { Skip prefix, component class name and component object name }
  5089. BeginComponent(Flags, Dummy, CompClassName, CompName);
  5090. { Skip properties }
  5091. while NextValue <> vaNull do
  5092. SkipProperty;
  5093. ReadValue;
  5094. { Skip children }
  5095. while NextValue <> vaNull do
  5096. SkipComponent(True);
  5097. ReadValue;
  5098. end;
  5099. procedure TBinaryObjectReader.SkipValue;
  5100. procedure SkipBytes(Count: LongInt);
  5101. var
  5102. Dummy: TBytes;
  5103. SkipNow: Integer;
  5104. begin
  5105. while Count > 0 do
  5106. begin
  5107. if Count > 1024 then
  5108. SkipNow := 1024
  5109. else
  5110. SkipNow := Count;
  5111. SetLength(Dummy,SkipNow);
  5112. Read(Dummy, SkipNow);
  5113. Dec(Count, SkipNow);
  5114. end;
  5115. end;
  5116. var
  5117. Count: LongInt;
  5118. begin
  5119. case ReadValue of
  5120. vaNull, vaFalse, vaTrue, vaNil: ;
  5121. vaList:
  5122. begin
  5123. while NextValue <> vaNull do
  5124. SkipValue;
  5125. ReadValue;
  5126. end;
  5127. vaInt8:
  5128. SkipBytes(1);
  5129. vaInt16:
  5130. SkipBytes(2);
  5131. vaInt32:
  5132. SkipBytes(4);
  5133. vaInt64,
  5134. vaDouble:
  5135. SkipBytes(8);
  5136. vaString, vaIdent:
  5137. ReadStr;
  5138. vaBinary:
  5139. begin
  5140. Count:=LongInt(ReadDWord);
  5141. SkipBytes(Count);
  5142. end;
  5143. vaSet:
  5144. SkipSetBody;
  5145. vaCollection:
  5146. begin
  5147. while NextValue <> vaNull do
  5148. begin
  5149. { Skip the order value if present }
  5150. if NextValue in [vaInt8, vaInt16, vaInt32] then
  5151. SkipValue;
  5152. SkipBytes(1);
  5153. while NextValue <> vaNull do
  5154. SkipProperty;
  5155. ReadValue;
  5156. end;
  5157. ReadValue;
  5158. end;
  5159. end;
  5160. end;
  5161. { private methods }
  5162. procedure TBinaryObjectReader.SkipProperty;
  5163. begin
  5164. { Skip property name, then the property value }
  5165. ReadStr;
  5166. SkipValue;
  5167. end;
  5168. procedure TBinaryObjectReader.SkipSetBody;
  5169. begin
  5170. while Length(ReadStr) > 0 do;
  5171. end;
  5172. // Quadruple representing an unresolved component property.
  5173. Type
  5174. { TUnresolvedReference }
  5175. TUnresolvedReference = class(TlinkedListItem)
  5176. Private
  5177. FRoot: TComponent; // Root component when streaming
  5178. FPropInfo: TTypeMemberProperty; // Property to set.
  5179. FGlobal, // Global component.
  5180. FRelative : string; // Path relative to global component.
  5181. Function Resolve(Instance : TPersistent) : Boolean; // Resolve this reference
  5182. Function RootMatches(ARoot : TComponent) : Boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE} // True if Froot matches or ARoot is nil.
  5183. Function NextRef : TUnresolvedReference; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  5184. end;
  5185. TLocalUnResolvedReference = class(TUnresolvedReference)
  5186. Finstance : TPersistent;
  5187. end;
  5188. // Linked list of TPersistent items that have unresolved properties.
  5189. { TUnResolvedInstance }
  5190. TUnResolvedInstance = Class(TLinkedListItem)
  5191. Public
  5192. Instance : TPersistent; // Instance we're handling unresolveds for
  5193. FUnresolved : TLinkedList; // The list
  5194. Destructor Destroy; override;
  5195. Function AddReference(ARoot : TComponent; APropInfo : TTypeMemberProperty; AGlobal,ARelative : String) : TUnresolvedReference;
  5196. Function RootUnresolved : TUnresolvedReference; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE} // Return root element in list.
  5197. Function ResolveReferences : Boolean; // Return true if all unresolveds were resolved.
  5198. end;
  5199. // Builds a list of TUnResolvedInstances, removes them from global list on free.
  5200. TBuildListVisitor = Class(TLinkedListVisitor)
  5201. Private
  5202. List : TFPList;
  5203. Public
  5204. Procedure Add(Item : TlinkedListItem); // Add TUnResolvedInstance item to list. Create list if needed
  5205. Destructor Destroy; override; // All elements in list (if any) are removed from the global list.
  5206. end;
  5207. // Visitor used to try and resolve instances in the global list
  5208. TResolveReferenceVisitor = Class(TBuildListVisitor)
  5209. Function Visit(Item : TLinkedListItem) : Boolean; override;
  5210. end;
  5211. // Visitor used to remove all references to a certain component.
  5212. TRemoveReferenceVisitor = Class(TBuildListVisitor)
  5213. Private
  5214. FRef : String;
  5215. FRoot : TComponent;
  5216. Public
  5217. Constructor Create(ARoot : TComponent;Const ARef : String);
  5218. Function Visit(Item : TLinkedListItem) : Boolean; override;
  5219. end;
  5220. // Visitor used to collect reference names.
  5221. TReferenceNamesVisitor = Class(TLinkedListVisitor)
  5222. Private
  5223. FList : TStrings;
  5224. FRoot : TComponent;
  5225. Public
  5226. Function Visit(Item : TLinkedListItem) : Boolean; override;
  5227. Constructor Create(ARoot : TComponent;AList : TStrings);
  5228. end;
  5229. // Visitor used to collect instance names.
  5230. TReferenceInstancesVisitor = Class(TLinkedListVisitor)
  5231. Private
  5232. FList : TStrings;
  5233. FRef : String;
  5234. FRoot : TComponent;
  5235. Public
  5236. Function Visit(Item : TLinkedListItem) : Boolean; override;
  5237. Constructor Create(ARoot : TComponent;Const ARef : String; AList : TStrings);
  5238. end;
  5239. // Visitor used to redirect links to another root component.
  5240. TRedirectReferenceVisitor = Class(TLinkedListVisitor)
  5241. Private
  5242. FOld,
  5243. FNew : String;
  5244. FRoot : TComponent;
  5245. Public
  5246. Function Visit(Item : TLinkedListItem) : Boolean; override;
  5247. Constructor Create(ARoot : TComponent;Const AOld,ANew : String);
  5248. end;
  5249. var
  5250. NeedResolving : TLinkedList;
  5251. // Add an instance to the global list of instances which need resolving.
  5252. Function FindUnresolvedInstance(AInstance: TPersistent) : TUnResolvedInstance;
  5253. begin
  5254. Result:=Nil;
  5255. {$ifdef FPC_HAS_FEATURE_THREADING}
  5256. EnterCriticalSection(ResolveSection);
  5257. Try
  5258. {$endif}
  5259. If Assigned(NeedResolving) then
  5260. begin
  5261. Result:=TUnResolvedInstance(NeedResolving.Root);
  5262. While (Result<>Nil) and (Result.Instance<>AInstance) do
  5263. Result:=TUnResolvedInstance(Result.Next);
  5264. end;
  5265. {$ifdef FPC_HAS_FEATURE_THREADING}
  5266. finally
  5267. LeaveCriticalSection(ResolveSection);
  5268. end;
  5269. {$endif}
  5270. end;
  5271. Function AddtoResolveList(AInstance: TPersistent) : TUnResolvedInstance;
  5272. begin
  5273. Result:=FindUnresolvedInstance(AInstance);
  5274. If (Result=Nil) then
  5275. begin
  5276. {$ifdef FPC_HAS_FEATURE_THREADING}
  5277. EnterCriticalSection(ResolveSection);
  5278. Try
  5279. {$endif}
  5280. If not Assigned(NeedResolving) then
  5281. NeedResolving:=TLinkedList.Create(TUnResolvedInstance);
  5282. Result:=NeedResolving.Add as TUnResolvedInstance;
  5283. Result.Instance:=AInstance;
  5284. {$ifdef FPC_HAS_FEATURE_THREADING}
  5285. finally
  5286. LeaveCriticalSection(ResolveSection);
  5287. end;
  5288. {$endif}
  5289. end;
  5290. end;
  5291. // Walk through the global list of instances to be resolved.
  5292. Procedure VisitResolveList(V : TLinkedListVisitor);
  5293. begin
  5294. {$ifdef FPC_HAS_FEATURE_THREADING}
  5295. EnterCriticalSection(ResolveSection);
  5296. Try
  5297. {$endif}
  5298. try
  5299. NeedResolving.Foreach(V);
  5300. Finally
  5301. FreeAndNil(V);
  5302. end;
  5303. {$ifdef FPC_HAS_FEATURE_THREADING}
  5304. Finally
  5305. LeaveCriticalSection(ResolveSection);
  5306. end;
  5307. {$endif}
  5308. end;
  5309. procedure GlobalFixupReferences;
  5310. begin
  5311. If (NeedResolving=Nil) then
  5312. Exit;
  5313. {$ifdef FPC_HAS_FEATURE_THREADING}
  5314. GlobalNameSpace.BeginWrite;
  5315. try
  5316. {$endif}
  5317. VisitResolveList(TResolveReferenceVisitor.Create);
  5318. {$ifdef FPC_HAS_FEATURE_THREADING}
  5319. finally
  5320. GlobalNameSpace.EndWrite;
  5321. end;
  5322. {$endif}
  5323. end;
  5324. procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
  5325. begin
  5326. If (NeedResolving=Nil) then
  5327. Exit;
  5328. VisitResolveList(TReferenceNamesVisitor.Create(Root,Names));
  5329. end;
  5330. procedure GetFixupInstanceNames(Root: TComponent; const ReferenceRootName: string; Names: TStrings);
  5331. begin
  5332. If (NeedResolving=Nil) then
  5333. Exit;
  5334. VisitResolveList(TReferenceInstancesVisitor.Create(Root,ReferenceRootName,Names));
  5335. end;
  5336. procedure RedirectFixupReferences(Root: TComponent; const OldRootName, NewRootName: string);
  5337. begin
  5338. If (NeedResolving=Nil) then
  5339. Exit;
  5340. VisitResolveList(TRedirectReferenceVisitor.Create(Root,OldRootName,NewRootName));
  5341. end;
  5342. procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
  5343. begin
  5344. If (NeedResolving=Nil) then
  5345. Exit;
  5346. VisitResolveList(TRemoveReferenceVisitor.Create(Root,RootName));
  5347. end;
  5348. { TUnresolvedReference }
  5349. Function TUnresolvedReference.Resolve(Instance : TPersistent) : Boolean;
  5350. Var
  5351. C : TComponent;
  5352. begin
  5353. C:=FindGlobalComponent(FGlobal);
  5354. Result:=(C<>Nil);
  5355. If Result then
  5356. begin
  5357. C:=FindNestedComponent(C,FRelative);
  5358. Result:=C<>Nil;
  5359. If Result then
  5360. SetObjectProp(Instance, FPropInfo,C);
  5361. end;
  5362. end;
  5363. Function TUnresolvedReference.RootMatches(ARoot : TComponent) : Boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  5364. begin
  5365. Result:=(ARoot=Nil) or (ARoot=FRoot);
  5366. end;
  5367. Function TUnResolvedReference.NextRef : TUnresolvedReference;
  5368. begin
  5369. Result:=TUnresolvedReference(Next);
  5370. end;
  5371. { TUnResolvedInstance }
  5372. destructor TUnResolvedInstance.Destroy;
  5373. begin
  5374. FUnresolved.Free;
  5375. inherited Destroy;
  5376. end;
  5377. function TUnResolvedInstance.AddReference(ARoot: TComponent; APropInfo : TTypeMemberProperty; AGlobal, ARelative: String): TUnresolvedReference;
  5378. begin
  5379. If (FUnResolved=Nil) then
  5380. FUnResolved:=TLinkedList.Create(TUnresolvedReference);
  5381. Result:=FUnResolved.Add as TUnresolvedReference;
  5382. Result.FGlobal:=AGLobal;
  5383. Result.FRelative:=ARelative;
  5384. Result.FPropInfo:=APropInfo;
  5385. Result.FRoot:=ARoot;
  5386. end;
  5387. Function TUnResolvedInstance.RootUnresolved : TUnresolvedReference;
  5388. begin
  5389. Result:=Nil;
  5390. If Assigned(FUnResolved) then
  5391. Result:=TUnresolvedReference(FUnResolved.Root);
  5392. end;
  5393. Function TUnResolvedInstance.ResolveReferences:Boolean;
  5394. Var
  5395. R,RN : TUnresolvedReference;
  5396. begin
  5397. R:=RootUnResolved;
  5398. While (R<>Nil) do
  5399. begin
  5400. RN:=R.NextRef;
  5401. If R.Resolve(Self.Instance) then
  5402. FUnresolved.RemoveItem(R,True);
  5403. R:=RN;
  5404. end;
  5405. Result:=RootUnResolved=Nil;
  5406. end;
  5407. { TReferenceNamesVisitor }
  5408. Constructor TReferenceNamesVisitor.Create(ARoot : TComponent;AList : TStrings);
  5409. begin
  5410. FRoot:=ARoot;
  5411. FList:=AList;
  5412. end;
  5413. Function TReferenceNamesVisitor.Visit(Item : TLinkedListItem) : Boolean;
  5414. Var
  5415. R : TUnresolvedReference;
  5416. begin
  5417. R:=TUnResolvedInstance(Item).RootUnresolved;
  5418. While (R<>Nil) do
  5419. begin
  5420. If R.RootMatches(FRoot) then
  5421. If (FList.IndexOf(R.FGlobal)=-1) then
  5422. FList.Add(R.FGlobal);
  5423. R:=R.NextRef;
  5424. end;
  5425. Result:=True;
  5426. end;
  5427. { TReferenceInstancesVisitor }
  5428. Constructor TReferenceInstancesVisitor.Create(ARoot : TComponent; Const ARef : String;AList : TStrings);
  5429. begin
  5430. FRoot:=ARoot;
  5431. FRef:=UpperCase(ARef);
  5432. FList:=AList;
  5433. end;
  5434. Function TReferenceInstancesVisitor.Visit(Item : TLinkedListItem) : Boolean;
  5435. Var
  5436. R : TUnresolvedReference;
  5437. begin
  5438. R:=TUnResolvedInstance(Item).RootUnresolved;
  5439. While (R<>Nil) do
  5440. begin
  5441. If (FRoot=R.FRoot) and (FRef=UpperCase(R.FGLobal)) Then
  5442. If Flist.IndexOf(R.FRelative)=-1 then
  5443. Flist.Add(R.FRelative);
  5444. R:=R.NextRef;
  5445. end;
  5446. Result:=True;
  5447. end;
  5448. { TRedirectReferenceVisitor }
  5449. Constructor TRedirectReferenceVisitor.Create(ARoot : TComponent; Const AOld,ANew : String);
  5450. begin
  5451. FRoot:=ARoot;
  5452. FOld:=UpperCase(AOld);
  5453. FNew:=ANew;
  5454. end;
  5455. Function TRedirectReferenceVisitor.Visit(Item : TLinkedListItem) : Boolean;
  5456. Var
  5457. R : TUnresolvedReference;
  5458. begin
  5459. R:=TUnResolvedInstance(Item).RootUnresolved;
  5460. While (R<>Nil) do
  5461. begin
  5462. If R.RootMatches(FRoot) and (FOld=UpperCase(R.FGLobal)) Then
  5463. R.FGlobal:=FNew;
  5464. R:=R.NextRef;
  5465. end;
  5466. Result:=True;
  5467. end;
  5468. { TRemoveReferenceVisitor }
  5469. Constructor TRemoveReferenceVisitor.Create(ARoot : TComponent; Const ARef : String);
  5470. begin
  5471. FRoot:=ARoot;
  5472. FRef:=UpperCase(ARef);
  5473. end;
  5474. Function TRemoveReferenceVisitor.Visit(Item : TLinkedListItem) : Boolean;
  5475. Var
  5476. I : Integer;
  5477. UI : TUnResolvedInstance;
  5478. R : TUnresolvedReference;
  5479. L : TFPList;
  5480. begin
  5481. UI:=TUnResolvedInstance(Item);
  5482. R:=UI.RootUnresolved;
  5483. L:=Nil;
  5484. Try
  5485. // Collect all matches.
  5486. While (R<>Nil) do
  5487. begin
  5488. If R.RootMatches(FRoot) and ((FRef = '') or (FRef=UpperCase(R.FGLobal))) Then
  5489. begin
  5490. If Not Assigned(L) then
  5491. L:=TFPList.Create;
  5492. L.Add(R);
  5493. end;
  5494. R:=R.NextRef;
  5495. end;
  5496. // Remove all matches.
  5497. IF Assigned(L) then
  5498. begin
  5499. For I:=0 to L.Count-1 do
  5500. UI.FUnresolved.RemoveItem(TLinkedListitem(L[i]),True);
  5501. end;
  5502. // If any references are left, leave them.
  5503. If UI.FUnResolved.Root=Nil then
  5504. begin
  5505. If List=Nil then
  5506. List:=TFPList.Create;
  5507. List.Add(UI);
  5508. end;
  5509. Finally
  5510. L.Free;
  5511. end;
  5512. Result:=True;
  5513. end;
  5514. { TBuildListVisitor }
  5515. Procedure TBuildListVisitor.Add(Item : TlinkedListItem);
  5516. begin
  5517. If (List=Nil) then
  5518. List:=TFPList.Create;
  5519. List.Add(Item);
  5520. end;
  5521. Destructor TBuildListVisitor.Destroy;
  5522. Var
  5523. I : Integer;
  5524. begin
  5525. If Assigned(List) then
  5526. For I:=0 to List.Count-1 do
  5527. NeedResolving.RemoveItem(TLinkedListItem(List[I]),True);
  5528. FreeAndNil(List);
  5529. Inherited;
  5530. end;
  5531. { TResolveReferenceVisitor }
  5532. Function TResolveReferenceVisitor.Visit(Item : TLinkedListItem) : Boolean;
  5533. begin
  5534. If TUnResolvedInstance(Item).ResolveReferences then
  5535. Add(Item);
  5536. Result:=True;
  5537. end;
  5538. {****************************************************************************}
  5539. {* TREADER *}
  5540. {****************************************************************************}
  5541. constructor TReader.Create(Stream: TStream);
  5542. begin
  5543. inherited Create;
  5544. If (Stream=Nil) then
  5545. Raise EReadError.Create(SEmptyStreamIllegalReader);
  5546. FDriver := CreateDriver(Stream);
  5547. end;
  5548. destructor TReader.Destroy;
  5549. begin
  5550. FDriver.Free;
  5551. inherited Destroy;
  5552. end;
  5553. procedure TReader.FlushBuffer;
  5554. begin
  5555. Driver.FlushBuffer;
  5556. end;
  5557. function TReader.CreateDriver(Stream: TStream): TAbstractObjectReader;
  5558. begin
  5559. Result := TBinaryObjectReader.Create(Stream);
  5560. end;
  5561. procedure TReader.BeginReferences;
  5562. begin
  5563. FLoaded := TFpList.Create;
  5564. end;
  5565. procedure TReader.CheckValue(Value: TValueType);
  5566. begin
  5567. if FDriver.NextValue <> Value then
  5568. raise EReadError.Create(SInvalidPropertyValue)
  5569. else
  5570. FDriver.ReadValue;
  5571. end;
  5572. procedure TReader.DefineProperty(const Name: String; AReadData: TReaderProc;
  5573. WriteData: TWriterProc; HasData: Boolean);
  5574. begin
  5575. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  5576. begin
  5577. AReadData(Self);
  5578. SetLength(FPropName, 0);
  5579. end;
  5580. end;
  5581. procedure TReader.DefineBinaryProperty(const Name: String;
  5582. AReadData, WriteData: TStreamProc; HasData: Boolean);
  5583. var
  5584. MemBuffer: TMemoryStream;
  5585. begin
  5586. if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
  5587. begin
  5588. { Check if the next property really is a binary property}
  5589. if FDriver.NextValue <> vaBinary then
  5590. begin
  5591. FDriver.SkipValue;
  5592. FCanHandleExcepts := True;
  5593. raise EReadError.Create(SInvalidPropertyValue);
  5594. end else
  5595. FDriver.ReadValue;
  5596. MemBuffer := TMemoryStream.Create;
  5597. try
  5598. FDriver.ReadBinary(MemBuffer);
  5599. FCanHandleExcepts := True;
  5600. AReadData(MemBuffer);
  5601. finally
  5602. MemBuffer.Free;
  5603. end;
  5604. SetLength(FPropName, 0);
  5605. end;
  5606. end;
  5607. function TReader.EndOfList: Boolean;
  5608. begin
  5609. Result := FDriver.NextValue = vaNull;
  5610. end;
  5611. procedure TReader.EndReferences;
  5612. begin
  5613. FLoaded.Free;
  5614. FLoaded := nil;
  5615. end;
  5616. function TReader.Error(const Message: String): Boolean;
  5617. begin
  5618. Result := False;
  5619. if Assigned(FOnError) then
  5620. FOnError(Self, Message, Result);
  5621. end;
  5622. function TReader.FindMethod(ARoot: TComponent; const AMethodName: String): CodePointer;
  5623. var
  5624. ErrorResult: Boolean;
  5625. begin
  5626. Result:=nil;
  5627. if (ARoot=Nil) or (aMethodName='') then
  5628. exit;
  5629. Result := ARoot.MethodAddress(AMethodName);
  5630. ErrorResult := Result = nil;
  5631. { always give the OnFindMethod callback a chance to locate the method }
  5632. if Assigned(FOnFindMethod) then
  5633. FOnFindMethod(Self, AMethodName, Result, ErrorResult);
  5634. if ErrorResult then
  5635. raise EReadError.Create(SInvalidPropertyValue);
  5636. end;
  5637. procedure TReader.DoFixupReferences;
  5638. Var
  5639. R,RN : TLocalUnresolvedReference;
  5640. G : TUnresolvedInstance;
  5641. Ref : String;
  5642. C : TComponent;
  5643. P : integer;
  5644. L : TLinkedList;
  5645. begin
  5646. If Assigned(FFixups) then
  5647. begin
  5648. L:=TLinkedList(FFixups);
  5649. R:=TLocalUnresolvedReference(L.Root);
  5650. While (R<>Nil) do
  5651. begin
  5652. RN:=TLocalUnresolvedReference(R.Next);
  5653. Ref:=R.FRelative;
  5654. If Assigned(FOnReferenceName) then
  5655. FOnReferenceName(Self,Ref);
  5656. C:=FindNestedComponent(R.FRoot,Ref);
  5657. If Assigned(C) then
  5658. if R.FPropInfo.TypeInfo.Kind = tkInterface then
  5659. SetInterfaceProp(R.FInstance,R.FPropInfo,C)
  5660. else
  5661. SetObjectProp(R.FInstance,R.FPropInfo,C)
  5662. else
  5663. begin
  5664. P:=Pos('.',R.FRelative);
  5665. If (P<>0) then
  5666. begin
  5667. G:=AddToResolveList(R.FInstance);
  5668. G.Addreference(R.FRoot,R.FPropInfo,Copy(R.FRelative,1,P-1),Copy(R.FRelative,P+1,Length(R.FRelative)-P));
  5669. end;
  5670. end;
  5671. L.RemoveItem(R,True);
  5672. R:=RN;
  5673. end;
  5674. FreeAndNil(FFixups);
  5675. end;
  5676. end;
  5677. procedure TReader.FixupReferences;
  5678. var
  5679. i: Integer;
  5680. begin
  5681. DoFixupReferences;
  5682. GlobalFixupReferences;
  5683. for i := 0 to FLoaded.Count - 1 do
  5684. TComponent(FLoaded[I]).Loaded;
  5685. end;
  5686. function TReader.NextValue: TValueType;
  5687. begin
  5688. Result := FDriver.NextValue;
  5689. end;
  5690. procedure TReader.Read(var Buffer : TBytes; Count: LongInt);
  5691. begin
  5692. //This should give an exception if read is not implemented (i.e. TTextObjectReader)
  5693. //but should work with TBinaryObjectReader.
  5694. Driver.Read(Buffer, Count);
  5695. end;
  5696. procedure TReader.PropertyError;
  5697. begin
  5698. FDriver.SkipValue;
  5699. raise EReadError.CreateFmt(SUnknownProperty,[FPropName]);
  5700. end;
  5701. function TReader.ReadBoolean: Boolean;
  5702. var
  5703. ValueType: TValueType;
  5704. begin
  5705. ValueType := FDriver.ReadValue;
  5706. if ValueType = vaTrue then
  5707. Result := True
  5708. else if ValueType = vaFalse then
  5709. Result := False
  5710. else
  5711. raise EReadError.Create(SInvalidPropertyValue);
  5712. end;
  5713. function TReader.ReadChar: Char;
  5714. var
  5715. s: String;
  5716. begin
  5717. s := ReadString;
  5718. if Length(s) = 1 then
  5719. Result := s[1]
  5720. else
  5721. raise EReadError.Create(SInvalidPropertyValue);
  5722. end;
  5723. function TReader.ReadWideChar: WideChar;
  5724. var
  5725. W: WideString;
  5726. begin
  5727. W := ReadWideString;
  5728. if Length(W) = 1 then
  5729. Result := W[1]
  5730. else
  5731. raise EReadError.Create(SInvalidPropertyValue);
  5732. end;
  5733. function TReader.ReadUnicodeChar: UnicodeChar;
  5734. var
  5735. U: UnicodeString;
  5736. begin
  5737. U := ReadUnicodeString;
  5738. if Length(U) = 1 then
  5739. Result := U[1]
  5740. else
  5741. raise EReadError.Create(SInvalidPropertyValue);
  5742. end;
  5743. procedure TReader.ReadCollection(Collection: TCollection);
  5744. var
  5745. Item: TCollectionItem;
  5746. begin
  5747. Collection.BeginUpdate;
  5748. if not EndOfList then
  5749. Collection.Clear;
  5750. while not EndOfList do begin
  5751. ReadListBegin;
  5752. Item := Collection.Add;
  5753. while NextValue<>vaNull do
  5754. ReadProperty(Item);
  5755. ReadListEnd;
  5756. end;
  5757. Collection.EndUpdate;
  5758. ReadListEnd;
  5759. end;
  5760. function TReader.ReadComponent(Component: TComponent): TComponent;
  5761. var
  5762. Flags: TFilerFlags;
  5763. function Recover(E : Exception; var aComponent: TComponent): Boolean;
  5764. begin
  5765. Result := False;
  5766. if not ((ffInherited in Flags) or Assigned(Component)) then
  5767. aComponent.Free;
  5768. aComponent := nil;
  5769. FDriver.SkipComponent(False);
  5770. Result := Error(E.Message);
  5771. end;
  5772. var
  5773. CompClassName, Name: String;
  5774. n, ChildPos: Integer;
  5775. SavedParent, SavedLookupRoot: TComponent;
  5776. ComponentClass: TComponentClass;
  5777. C, NewComponent: TComponent;
  5778. SubComponents: TList;
  5779. begin
  5780. FDriver.BeginComponent(Flags, ChildPos, CompClassName, Name);
  5781. SavedParent := Parent;
  5782. SavedLookupRoot := FLookupRoot;
  5783. SubComponents := nil;
  5784. try
  5785. Result := Component;
  5786. if not Assigned(Result) then
  5787. try
  5788. if ffInherited in Flags then
  5789. begin
  5790. { Try to locate the existing ancestor component }
  5791. if Assigned(FLookupRoot) then
  5792. Result := FLookupRoot.FindComponent(Name)
  5793. else
  5794. Result := nil;
  5795. if not Assigned(Result) then
  5796. begin
  5797. if Assigned(FOnAncestorNotFound) then
  5798. FOnAncestorNotFound(Self, Name,
  5799. FindComponentClass(CompClassName), Result);
  5800. if not Assigned(Result) then
  5801. raise EReadError.CreateFmt(SAncestorNotFound, [Name]);
  5802. end;
  5803. Parent := Result.GetParentComponent;
  5804. if not Assigned(Parent) then
  5805. Parent := Root;
  5806. end else
  5807. begin
  5808. Result := nil;
  5809. ComponentClass := FindComponentClass(CompClassName);
  5810. if Assigned(FOnCreateComponent) then
  5811. FOnCreateComponent(Self, ComponentClass, Result);
  5812. if not Assigned(Result) then
  5813. begin
  5814. asm
  5815. NewComponent = Object.create(ComponentClass);
  5816. NewComponent.$init();
  5817. end;
  5818. if ffInline in Flags then
  5819. NewComponent.FComponentState :=
  5820. NewComponent.FComponentState + [csLoading, csInline];
  5821. NewComponent.Create(Owner);
  5822. NewComponent.AfterConstruction;
  5823. { Don't set Result earlier because else we would come in trouble
  5824. with the exception recover mechanism! (Result should be NIL if
  5825. an error occurred) }
  5826. Result := NewComponent;
  5827. end;
  5828. Include(Result.FComponentState, csLoading);
  5829. end;
  5830. except
  5831. On E: Exception do
  5832. if not Recover(E,Result) then
  5833. raise;
  5834. end;
  5835. if Assigned(Result) then
  5836. try
  5837. Include(Result.FComponentState, csLoading);
  5838. { create list of subcomponents and set loading}
  5839. SubComponents := TList.Create;
  5840. for n := 0 to Result.ComponentCount - 1 do
  5841. begin
  5842. C := Result.Components[n];
  5843. if csSubcomponent in C.ComponentStyle
  5844. then begin
  5845. SubComponents.Add(C);
  5846. Include(C.FComponentState, csLoading);
  5847. end;
  5848. end;
  5849. if not (ffInherited in Flags) then
  5850. try
  5851. Result.SetParentComponent(Parent);
  5852. if Assigned(FOnSetName) then
  5853. FOnSetName(Self, Result, Name);
  5854. Result.Name := Name;
  5855. if FindGlobalComponent(Name) = Result then
  5856. Include(Result.FComponentState, csInline);
  5857. except
  5858. On E : Exception do
  5859. if not Recover(E,Result) then
  5860. raise;
  5861. end;
  5862. if not Assigned(Result) then
  5863. exit;
  5864. if csInline in Result.ComponentState then
  5865. FLookupRoot := Result;
  5866. { Read the component state }
  5867. Include(Result.FComponentState, csReading);
  5868. for n := 0 to Subcomponents.Count - 1 do
  5869. Include(TComponent(Subcomponents[n]).FComponentState, csReading);
  5870. Result.ReadState(Self);
  5871. Exclude(Result.FComponentState, csReading);
  5872. for n := 0 to Subcomponents.Count - 1 do
  5873. Exclude(TComponent(Subcomponents[n]).FComponentState, csReading);
  5874. if ffChildPos in Flags then
  5875. Parent.SetChildOrder(Result, ChildPos);
  5876. { Add component to list of loaded components, if necessary }
  5877. if (not ((ffInherited in Flags) or (csInline in Result.ComponentState))) or
  5878. (FLoaded.IndexOf(Result) < 0)
  5879. then begin
  5880. for n := 0 to Subcomponents.Count - 1 do
  5881. FLoaded.Add(Subcomponents[n]);
  5882. FLoaded.Add(Result);
  5883. end;
  5884. except
  5885. if ((ffInherited in Flags) or Assigned(Component)) then
  5886. Result.Free;
  5887. raise;
  5888. end;
  5889. finally
  5890. Parent := SavedParent;
  5891. FLookupRoot := SavedLookupRoot;
  5892. Subcomponents.Free;
  5893. end;
  5894. end;
  5895. procedure TReader.ReadData(Instance: TComponent);
  5896. var
  5897. SavedOwner, SavedParent: TComponent;
  5898. begin
  5899. { Read properties }
  5900. while not EndOfList do
  5901. ReadProperty(Instance);
  5902. ReadListEnd;
  5903. { Read children }
  5904. SavedOwner := Owner;
  5905. SavedParent := Parent;
  5906. try
  5907. Owner := Instance.GetChildOwner;
  5908. if not Assigned(Owner) then
  5909. Owner := Root;
  5910. Parent := Instance.GetChildParent;
  5911. while not EndOfList do
  5912. ReadComponent(nil);
  5913. ReadListEnd;
  5914. finally
  5915. Owner := SavedOwner;
  5916. Parent := SavedParent;
  5917. end;
  5918. { Fixup references if necessary (normally only if this is the root) }
  5919. If (Instance=FRoot) then
  5920. DoFixupReferences;
  5921. end;
  5922. function TReader.ReadFloat: Extended;
  5923. begin
  5924. if FDriver.NextValue = vaExtended then
  5925. begin
  5926. ReadValue;
  5927. Result := FDriver.ReadFloat
  5928. end else
  5929. Result := ReadNativeInt;
  5930. end;
  5931. procedure TReader.ReadSignature;
  5932. begin
  5933. FDriver.ReadSignature;
  5934. end;
  5935. function TReader.ReadCurrency: Currency;
  5936. begin
  5937. if FDriver.NextValue = vaCurrency then
  5938. begin
  5939. FDriver.ReadValue;
  5940. Result := FDriver.ReadCurrency;
  5941. end else
  5942. Result := ReadInteger;
  5943. end;
  5944. function TReader.ReadIdent: String;
  5945. var
  5946. ValueType: TValueType;
  5947. begin
  5948. ValueType := FDriver.ReadValue;
  5949. if ValueType in [vaIdent, vaNil, vaFalse, vaTrue, vaNull] then
  5950. Result := FDriver.ReadIdent(ValueType)
  5951. else
  5952. raise EReadError.Create(SInvalidPropertyValue);
  5953. end;
  5954. function TReader.ReadInteger: LongInt;
  5955. begin
  5956. case FDriver.ReadValue of
  5957. vaInt8:
  5958. Result := FDriver.ReadInt8;
  5959. vaInt16:
  5960. Result := FDriver.ReadInt16;
  5961. vaInt32:
  5962. Result := FDriver.ReadInt32;
  5963. else
  5964. raise EReadError.Create(SInvalidPropertyValue);
  5965. end;
  5966. end;
  5967. function TReader.ReadNativeInt: NativeInt;
  5968. begin
  5969. if FDriver.NextValue = vaInt64 then
  5970. begin
  5971. FDriver.ReadValue;
  5972. Result := FDriver.ReadNativeInt;
  5973. end else
  5974. Result := ReadInteger;
  5975. end;
  5976. function TReader.ReadSet(EnumType: Pointer): Integer;
  5977. begin
  5978. if FDriver.NextValue = vaSet then
  5979. begin
  5980. FDriver.ReadValue;
  5981. Result := FDriver.ReadSet(enumtype);
  5982. end
  5983. else
  5984. Result := ReadInteger;
  5985. end;
  5986. procedure TReader.ReadListBegin;
  5987. begin
  5988. CheckValue(vaList);
  5989. end;
  5990. procedure TReader.ReadListEnd;
  5991. begin
  5992. CheckValue(vaNull);
  5993. end;
  5994. function TReader.ReadVariant: JSValue;
  5995. var
  5996. nv: TValueType;
  5997. begin
  5998. nv:=NextValue;
  5999. case nv of
  6000. vaNil:
  6001. begin
  6002. Result:=Undefined;
  6003. readvalue;
  6004. end;
  6005. vaNull:
  6006. begin
  6007. Result:=Nil;
  6008. readvalue;
  6009. end;
  6010. { all integer sizes must be split for big endian systems }
  6011. vaInt8,vaInt16,vaInt32:
  6012. begin
  6013. Result:=ReadInteger;
  6014. end;
  6015. vaInt64:
  6016. begin
  6017. Result:=ReadNativeInt;
  6018. end;
  6019. {
  6020. vaQWord:
  6021. begin
  6022. Result:=QWord(ReadInt64);
  6023. end;
  6024. } vaFalse,vaTrue:
  6025. begin
  6026. Result:=(nv<>vaFalse);
  6027. readValue;
  6028. end;
  6029. vaCurrency:
  6030. begin
  6031. Result:=ReadCurrency;
  6032. end;
  6033. vaDouble:
  6034. begin
  6035. Result:=ReadFloat;
  6036. end;
  6037. vaString:
  6038. begin
  6039. Result:=ReadString;
  6040. end;
  6041. else
  6042. raise EReadError.CreateFmt(SUnsupportedPropertyVariantType, [Ord(nv)]);
  6043. end;
  6044. end;
  6045. procedure TReader.ReadProperty(AInstance: TPersistent);
  6046. var
  6047. Path: String;
  6048. Instance: TPersistent;
  6049. PropInfo: TTypeMemberProperty;
  6050. Obj: TObject;
  6051. Name: String;
  6052. Skip: Boolean;
  6053. Handled: Boolean;
  6054. OldPropName: String;
  6055. DotPos : String;
  6056. NextPos: Integer;
  6057. function HandleMissingProperty(IsPath: Boolean): boolean;
  6058. begin
  6059. Result:=true;
  6060. if Assigned(OnPropertyNotFound) then begin
  6061. // user defined property error handling
  6062. OldPropName:=FPropName;
  6063. Handled:=false;
  6064. Skip:=false;
  6065. OnPropertyNotFound(Self,Instance,FPropName,IsPath,Handled,Skip);
  6066. if Handled and (not Skip) and (OldPropName<>FPropName) then
  6067. // try alias property
  6068. PropInfo := GetPropInfo(Instance.ClassType, FPropName);
  6069. if Skip then begin
  6070. FDriver.SkipValue;
  6071. Result:=false;
  6072. exit;
  6073. end;
  6074. end;
  6075. end;
  6076. begin
  6077. try
  6078. Path := FDriver.BeginProperty;
  6079. try
  6080. Instance := AInstance;
  6081. FCanHandleExcepts := True;
  6082. DotPos := Path;
  6083. while True do
  6084. begin
  6085. NextPos := Pos('.',DotPos);
  6086. if NextPos>0 then
  6087. FPropName := Copy(DotPos, 1, NextPos-1)
  6088. else
  6089. begin
  6090. FPropName := DotPos;
  6091. break;
  6092. end;
  6093. Delete(DotPos,1,NextPos);
  6094. PropInfo := GetPropInfo(Instance.ClassType, FPropName);
  6095. if not Assigned(PropInfo) then begin
  6096. if not HandleMissingProperty(true) then exit;
  6097. if not Assigned(PropInfo) then
  6098. PropertyError;
  6099. end;
  6100. if PropInfo.TypeInfo.Kind = tkClass then
  6101. Obj := TObject(GetObjectProp(Instance, PropInfo))
  6102. //else if PropInfo^.PropType^.Kind = tkInterface then
  6103. // Obj := TObject(GetInterfaceProp(Instance, PropInfo))
  6104. else
  6105. Obj := nil;
  6106. if not (Obj is TPersistent) then
  6107. begin
  6108. { All path elements must be persistent objects! }
  6109. FDriver.SkipValue;
  6110. raise EReadError.Create(SInvalidPropertyPath);
  6111. end;
  6112. Instance := TPersistent(Obj);
  6113. end;
  6114. PropInfo := GetPropInfo(Instance.ClassType, FPropName);
  6115. if Assigned(PropInfo) then
  6116. ReadPropValue(Instance, PropInfo)
  6117. else
  6118. begin
  6119. FCanHandleExcepts := False;
  6120. Instance.DefineProperties(Self);
  6121. FCanHandleExcepts := True;
  6122. if Length(FPropName) > 0 then begin
  6123. if not HandleMissingProperty(false) then exit;
  6124. if not Assigned(PropInfo) then
  6125. PropertyError;
  6126. end;
  6127. end;
  6128. except
  6129. on e: Exception do
  6130. begin
  6131. SetLength(Name, 0);
  6132. if AInstance.InheritsFrom(TComponent) then
  6133. Name := TComponent(AInstance).Name;
  6134. if Length(Name) = 0 then
  6135. Name := AInstance.ClassName;
  6136. raise EReadError.CreateFmt(SPropertyException, [Name, '.', Path, e.Message]);
  6137. end;
  6138. end;
  6139. except
  6140. on e: Exception do
  6141. if not FCanHandleExcepts or not Error(E.Message) then
  6142. raise;
  6143. end;
  6144. end;
  6145. procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: TTypeMemberProperty);
  6146. const
  6147. NullMethod: TMethod = (Code: nil; Data: nil);
  6148. var
  6149. PropType: TTypeInfo;
  6150. Value: LongInt;
  6151. { IdentToIntFn: TIdentToInt; }
  6152. Ident: String;
  6153. Method: TMethod;
  6154. Handled: Boolean;
  6155. TmpStr: String;
  6156. begin
  6157. if (PropInfo.Setter='') then
  6158. raise EReadError.Create(SReadOnlyProperty);
  6159. PropType := PropInfo.TypeInfo;
  6160. case PropType.Kind of
  6161. tkInteger:
  6162. case FDriver.NextValue of
  6163. vaIdent :
  6164. begin
  6165. Ident := ReadIdent;
  6166. if GlobalIdentToInt(Ident,Value) then
  6167. SetOrdProp(Instance, PropInfo, Value)
  6168. else
  6169. raise EReadError.Create(SInvalidPropertyValue);
  6170. end;
  6171. vaNativeInt :
  6172. SetOrdProp(Instance, PropInfo, ReadNativeInt);
  6173. vaCurrency:
  6174. SetFloatProp(Instance, PropInfo, ReadCurrency);
  6175. else
  6176. SetOrdProp(Instance, PropInfo, ReadInteger);
  6177. end;
  6178. tkBool:
  6179. SetOrdProp(Instance, PropInfo, Ord(ReadBoolean));
  6180. tkChar:
  6181. SetOrdProp(Instance, PropInfo, Ord(ReadChar));
  6182. tkEnumeration:
  6183. begin
  6184. Value := GetEnumValue(TTypeInfoEnum(PropType), ReadIdent);
  6185. if Value = -1 then
  6186. raise EReadError.Create(SInvalidPropertyValue);
  6187. SetOrdProp(Instance, PropInfo, Value);
  6188. end;
  6189. {$ifndef FPUNONE}
  6190. tkFloat:
  6191. SetFloatProp(Instance, PropInfo, ReadFloat);
  6192. {$endif}
  6193. tkSet:
  6194. begin
  6195. CheckValue(vaSet);
  6196. if TTypeInfoSet(PropType).CompType.Kind=tkEnumeration then
  6197. SetOrdProp(Instance, PropInfo, FDriver.ReadSet(TTypeInfoEnum(TTypeInfoSet(PropType).CompType)));
  6198. end;
  6199. tkMethod:
  6200. if FDriver.NextValue = vaNil then
  6201. begin
  6202. FDriver.ReadValue;
  6203. SetMethodProp(Instance, PropInfo, NullMethod);
  6204. end else
  6205. begin
  6206. Handled:=false;
  6207. Ident:=ReadIdent;
  6208. if Assigned(OnSetMethodProperty) then
  6209. OnSetMethodProperty(Self,Instance,PropInfo,Ident,Handled);
  6210. if not Handled then begin
  6211. Method.Code := FindMethod(Root, Ident);
  6212. Method.Data := Root;
  6213. if Assigned(Method.Code) then
  6214. SetMethodProp(Instance, PropInfo, Method);
  6215. end;
  6216. end;
  6217. tkString:
  6218. begin
  6219. TmpStr:=ReadString;
  6220. if Assigned(FOnReadStringProperty) then
  6221. FOnReadStringProperty(Self,Instance,PropInfo,TmpStr);
  6222. SetStrProp(Instance, PropInfo, TmpStr);
  6223. end;
  6224. tkJSValue:
  6225. begin
  6226. SetJSValueProp(Instance,PropInfo,ReadVariant);
  6227. end;
  6228. tkClass, tkInterface:
  6229. case FDriver.NextValue of
  6230. vaNil:
  6231. begin
  6232. FDriver.ReadValue;
  6233. SetOrdProp(Instance, PropInfo, 0)
  6234. end;
  6235. vaCollection:
  6236. begin
  6237. FDriver.ReadValue;
  6238. ReadCollection(TCollection(GetObjectProp(Instance, PropInfo)));
  6239. end
  6240. else
  6241. begin
  6242. If Not Assigned(FFixups) then
  6243. FFixups:=TLinkedList.Create(TLocalUnresolvedReference);
  6244. With TLocalUnresolvedReference(TLinkedList(FFixups).Add) do
  6245. begin
  6246. FInstance:=Instance;
  6247. FRoot:=Root;
  6248. FPropInfo:=PropInfo;
  6249. FRelative:=ReadIdent;
  6250. end;
  6251. end;
  6252. end;
  6253. {tkint64:
  6254. SetInt64Prop(Instance, PropInfo, ReadInt64);}
  6255. else
  6256. raise EReadError.CreateFmt(SUnknownPropertyType, [Ord(PropType.Kind)]);
  6257. end;
  6258. end;
  6259. function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
  6260. var
  6261. Dummy, i: Integer;
  6262. Flags: TFilerFlags;
  6263. CompClassName, CompName, ResultName: String;
  6264. begin
  6265. FDriver.BeginRootComponent;
  6266. Result := nil;
  6267. {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
  6268. try}
  6269. try
  6270. FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
  6271. if not Assigned(ARoot) then
  6272. begin
  6273. { Read the class name and the object name and create a new object: }
  6274. Result := TComponentClass(FindClass(CompClassName)).Create(nil);
  6275. Result.Name := CompName;
  6276. end else
  6277. begin
  6278. Result := ARoot;
  6279. if not (csDesigning in Result.ComponentState) then
  6280. begin
  6281. Result.FComponentState :=
  6282. Result.FComponentState + [csLoading, csReading];
  6283. { We need an unique name }
  6284. i := 0;
  6285. { Don't use Result.Name directly, as this would influence
  6286. FindGlobalComponent in successive loop runs }
  6287. ResultName := CompName;
  6288. while Assigned(FindGlobalComponent(ResultName)) do
  6289. begin
  6290. Inc(i);
  6291. ResultName := CompName + '_' + IntToStr(i);
  6292. end;
  6293. Result.Name := ResultName;
  6294. end;
  6295. end;
  6296. FRoot := Result;
  6297. FLookupRoot := Result;
  6298. if Assigned(GlobalLoaded) then
  6299. FLoaded := GlobalLoaded
  6300. else
  6301. FLoaded := TFpList.Create;
  6302. try
  6303. if FLoaded.IndexOf(FRoot) < 0 then
  6304. FLoaded.Add(FRoot);
  6305. FOwner := FRoot;
  6306. FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
  6307. FRoot.ReadState(Self);
  6308. Exclude(FRoot.FComponentState, csReading);
  6309. if not Assigned(GlobalLoaded) then
  6310. for i := 0 to FLoaded.Count - 1 do
  6311. TComponent(FLoaded[i]).Loaded;
  6312. finally
  6313. if not Assigned(GlobalLoaded) then
  6314. FLoaded.Free;
  6315. FLoaded := nil;
  6316. end;
  6317. GlobalFixupReferences;
  6318. except
  6319. RemoveFixupReferences(ARoot, '');
  6320. if not Assigned(ARoot) then
  6321. Result.Free;
  6322. raise;
  6323. end;
  6324. {finally
  6325. GlobalNameSpace.EndWrite;
  6326. end;}
  6327. end;
  6328. procedure TReader.ReadComponents(AOwner, AParent: TComponent;
  6329. Proc: TReadComponentsProc);
  6330. var
  6331. Component: TComponent;
  6332. begin
  6333. Root := AOwner;
  6334. Owner := AOwner;
  6335. Parent := AParent;
  6336. BeginReferences;
  6337. try
  6338. while not EndOfList do
  6339. begin
  6340. FDriver.BeginRootComponent;
  6341. Component := ReadComponent(nil);
  6342. if Assigned(Proc) then
  6343. Proc(Component);
  6344. end;
  6345. ReadListEnd;
  6346. FixupReferences;
  6347. finally
  6348. EndReferences;
  6349. end;
  6350. end;
  6351. function TReader.ReadString: String;
  6352. var
  6353. StringType: TValueType;
  6354. begin
  6355. StringType := FDriver.ReadValue;
  6356. if StringType=vaString then
  6357. Result := FDriver.ReadString(StringType)
  6358. else
  6359. raise EReadError.Create(SInvalidPropertyValue);
  6360. end;
  6361. function TReader.ReadWideString: WideString;
  6362. begin
  6363. Result:=ReadString;
  6364. end;
  6365. function TReader.ReadUnicodeString: UnicodeString;
  6366. begin
  6367. Result:=ReadString;
  6368. end;
  6369. function TReader.ReadValue: TValueType;
  6370. begin
  6371. Result := FDriver.ReadValue;
  6372. end;
  6373. procedure TReader.CopyValue(Writer: TWriter);
  6374. (*
  6375. procedure CopyBytes(Count: Integer);
  6376. { var
  6377. Buffer: array[0..1023] of Byte; }
  6378. begin
  6379. {!!!: while Count > 1024 do
  6380. begin
  6381. FDriver.Read(Buffer, 1024);
  6382. Writer.Driver.Write(Buffer, 1024);
  6383. Dec(Count, 1024);
  6384. end;
  6385. if Count > 0 then
  6386. begin
  6387. FDriver.Read(Buffer, Count);
  6388. Writer.Driver.Write(Buffer, Count);
  6389. end;}
  6390. end;
  6391. *)
  6392. {var
  6393. s: String;
  6394. Count: LongInt; }
  6395. begin
  6396. case FDriver.NextValue of
  6397. vaNull:
  6398. Writer.WriteIdent('NULL');
  6399. vaFalse:
  6400. Writer.WriteIdent('FALSE');
  6401. vaTrue:
  6402. Writer.WriteIdent('TRUE');
  6403. vaNil:
  6404. Writer.WriteIdent('NIL');
  6405. {!!!: vaList, vaCollection:
  6406. begin
  6407. Writer.WriteValue(FDriver.ReadValue);
  6408. while not EndOfList do
  6409. CopyValue(Writer);
  6410. ReadListEnd;
  6411. Writer.WriteListEnd;
  6412. end;}
  6413. vaInt8, vaInt16, vaInt32:
  6414. Writer.WriteInteger(ReadInteger);
  6415. {$ifndef FPUNONE}
  6416. vaExtended:
  6417. Writer.WriteFloat(ReadFloat);
  6418. {$endif}
  6419. vaString:
  6420. Writer.WriteString(ReadString);
  6421. vaIdent:
  6422. Writer.WriteIdent(ReadIdent);
  6423. {!!!: vaBinary, vaLString, vaWString:
  6424. begin
  6425. Writer.WriteValue(FDriver.ReadValue);
  6426. FDriver.Read(Count, SizeOf(Count));
  6427. Writer.Driver.Write(Count, SizeOf(Count));
  6428. CopyBytes(Count);
  6429. end;}
  6430. {!!!: vaSet:
  6431. Writer.WriteSet(ReadSet);}
  6432. {!!!: vaCurrency:
  6433. Writer.WriteCurrency(ReadCurrency);}
  6434. vaInt64:
  6435. Writer.WriteInteger(ReadNativeInt);
  6436. end;
  6437. end;
  6438. function TReader.FindComponentClass(const AClassName: String): TComponentClass;
  6439. var
  6440. PersistentClass: TPersistentClass;
  6441. function FindClassInFieldTable(Instance: TComponent): TComponentClass;
  6442. var
  6443. aClass: TClass;
  6444. i: longint;
  6445. ClassTI, MemberClassTI: TTypeInfoClass;
  6446. MemberTI: TTypeInfo;
  6447. begin
  6448. aClass:=Instance.ClassType;
  6449. while aClass<>nil do
  6450. begin
  6451. ClassTI:=typeinfo(aClass);
  6452. for i:=0 to ClassTI.FieldCount-1 do
  6453. begin
  6454. MemberTI:=ClassTI.GetField(i).TypeInfo;
  6455. if MemberTI.Kind=tkClass then
  6456. begin
  6457. MemberClassTI:=TTypeInfoClass(MemberTI);
  6458. if SameText(MemberClassTI.Name,aClassName)
  6459. and (MemberClassTI.ClassType is TComponent) then
  6460. exit(TComponentClass(MemberClassTI.ClassType));
  6461. end;
  6462. end;
  6463. aClass:=aClass.ClassParent;
  6464. end;
  6465. end;
  6466. begin
  6467. Result := nil;
  6468. Result:=FindClassInFieldTable(Root);
  6469. if (Result=nil) and assigned(LookupRoot) and (LookupRoot<>Root) then
  6470. Result:=FindClassInFieldTable(LookupRoot);
  6471. if (Result=nil) then begin
  6472. PersistentClass := GetClass(AClassName);
  6473. if PersistentClass.InheritsFrom(TComponent) then
  6474. Result := TComponentClass(PersistentClass);
  6475. end;
  6476. if (Result=nil) and assigned(OnFindComponentClass) then
  6477. OnFindComponentClass(Self, AClassName, Result);
  6478. if (Result=nil) or (not Result.InheritsFrom(TComponent)) then
  6479. raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
  6480. end;
  6481. { TAbstractObjectReader }
  6482. procedure TAbstractObjectReader.FlushBuffer;
  6483. begin
  6484. // Do nothing
  6485. end;
  6486. {
  6487. This file is part of the Free Component Library (FCL)
  6488. Copyright (c) 1999-2000 by the Free Pascal development team
  6489. See the file COPYING.FPC, included in this distribution,
  6490. for details about the copyright.
  6491. This program is distributed in the hope that it will be useful,
  6492. but WITHOUT ANY WARRANTY; without even the implied warranty of
  6493. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  6494. **********************************************************************}
  6495. {****************************************************************************}
  6496. {* TBinaryObjectWriter *}
  6497. {****************************************************************************}
  6498. procedure TBinaryObjectWriter.WriteWord(w : word);
  6499. begin
  6500. FStream.WriteBufferData(w);
  6501. end;
  6502. procedure TBinaryObjectWriter.WriteDWord(lw : longword);
  6503. begin
  6504. FStream.WriteBufferData(lw);
  6505. end;
  6506. constructor TBinaryObjectWriter.Create(Stream: TStream);
  6507. begin
  6508. inherited Create;
  6509. If (Stream=Nil) then
  6510. Raise EWriteError.Create(SEmptyStreamIllegalWriter);
  6511. FStream := Stream;
  6512. end;
  6513. procedure TBinaryObjectWriter.BeginCollection;
  6514. begin
  6515. WriteValue(vaCollection);
  6516. end;
  6517. procedure TBinaryObjectWriter.WriteSignature;
  6518. begin
  6519. FStream.WriteBufferData(FilerSignatureInt);
  6520. end;
  6521. procedure TBinaryObjectWriter.BeginComponent(Component: TComponent;
  6522. Flags: TFilerFlags; ChildPos: Integer);
  6523. var
  6524. Prefix: Byte;
  6525. begin
  6526. { Only write the flags if they are needed! }
  6527. if Flags <> [] then
  6528. begin
  6529. Prefix:=0;
  6530. if ffInherited in Flags then
  6531. Prefix:=Prefix or $01;
  6532. if ffChildPos in Flags then
  6533. Prefix:=Prefix or $02;
  6534. if ffInline in Flags then
  6535. Prefix:=Prefix or $04;
  6536. Prefix := Prefix or $f0;
  6537. FStream.WriteBufferData(Prefix);
  6538. if ffChildPos in Flags then
  6539. WriteInteger(ChildPos);
  6540. end;
  6541. WriteStr(Component.ClassName);
  6542. WriteStr(Component.Name);
  6543. end;
  6544. procedure TBinaryObjectWriter.BeginList;
  6545. begin
  6546. WriteValue(vaList);
  6547. end;
  6548. procedure TBinaryObjectWriter.EndList;
  6549. begin
  6550. WriteValue(vaNull);
  6551. end;
  6552. procedure TBinaryObjectWriter.BeginProperty(const PropName: String);
  6553. begin
  6554. WriteStr(PropName);
  6555. end;
  6556. procedure TBinaryObjectWriter.EndProperty;
  6557. begin
  6558. end;
  6559. procedure TBinaryObjectWriter.FlushBuffer;
  6560. begin
  6561. // Do nothing;
  6562. end;
  6563. procedure TBinaryObjectWriter.WriteBinary(const Buffer : TBytes; Count: LongInt);
  6564. begin
  6565. WriteValue(vaBinary);
  6566. WriteDWord(longword(Count));
  6567. FStream.Write(Buffer, Count);
  6568. end;
  6569. procedure TBinaryObjectWriter.WriteBoolean(Value: Boolean);
  6570. begin
  6571. if Value then
  6572. WriteValue(vaTrue)
  6573. else
  6574. WriteValue(vaFalse);
  6575. end;
  6576. procedure TBinaryObjectWriter.WriteFloat(const Value: Extended);
  6577. begin
  6578. WriteValue(vaDouble);
  6579. FStream.WriteBufferData(Value);
  6580. end;
  6581. procedure TBinaryObjectWriter.WriteCurrency(const Value: Currency);
  6582. Var
  6583. F : Double;
  6584. begin
  6585. WriteValue(vaCurrency);
  6586. F:=Value;
  6587. FStream.WriteBufferData(F);
  6588. end;
  6589. procedure TBinaryObjectWriter.WriteIdent(const Ident: string);
  6590. begin
  6591. { Check if Ident is a special identifier before trying to just write
  6592. Ident directly }
  6593. if UpperCase(Ident) = 'NIL' then
  6594. WriteValue(vaNil)
  6595. else if UpperCase(Ident) = 'FALSE' then
  6596. WriteValue(vaFalse)
  6597. else if UpperCase(Ident) = 'TRUE' then
  6598. WriteValue(vaTrue)
  6599. else if UpperCase(Ident) = 'NULL' then
  6600. WriteValue(vaNull) else
  6601. begin
  6602. WriteValue(vaIdent);
  6603. WriteStr(Ident);
  6604. end;
  6605. end;
  6606. procedure TBinaryObjectWriter.WriteInteger(Value: NativeInt);
  6607. var
  6608. s: ShortInt;
  6609. i: SmallInt;
  6610. l: Longint;
  6611. begin
  6612. { Use the smallest possible integer type for the given value: }
  6613. if (Value >= -128) and (Value <= 127) then
  6614. begin
  6615. WriteValue(vaInt8);
  6616. s := Value;
  6617. FStream.WriteBufferData(s);
  6618. end else if (Value >= -32768) and (Value <= 32767) then
  6619. begin
  6620. WriteValue(vaInt16);
  6621. i := Value;
  6622. WriteWord(word(i));
  6623. end else if (Value >= -$80000000) and (Value <= $7fffffff) then
  6624. begin
  6625. WriteValue(vaInt32);
  6626. l := Value;
  6627. WriteDWord(longword(l));
  6628. end else
  6629. begin
  6630. WriteValue(vaInt64);
  6631. FStream.WriteBufferData(Value);
  6632. end;
  6633. end;
  6634. procedure TBinaryObjectWriter.WriteNativeInt(Value: NativeInt);
  6635. var
  6636. s: Int8;
  6637. i: Int16;
  6638. l: Int32;
  6639. begin
  6640. { Use the smallest possible integer type for the given value: }
  6641. if (Value <= 127) then
  6642. begin
  6643. WriteValue(vaInt8);
  6644. s := Value;
  6645. FStream.WriteBufferData(s);
  6646. end else if (Value <= 32767) then
  6647. begin
  6648. WriteValue(vaInt16);
  6649. i := Value;
  6650. WriteWord(word(i));
  6651. end else if (Value <= $7fffffff) then
  6652. begin
  6653. WriteValue(vaInt32);
  6654. l := Value;
  6655. WriteDWord(longword(l));
  6656. end else
  6657. begin
  6658. WriteValue(vaQWord);
  6659. FStream.WriteBufferData(Value);
  6660. end;
  6661. end;
  6662. procedure TBinaryObjectWriter.WriteMethodName(const Name: String);
  6663. begin
  6664. if Length(Name) > 0 then
  6665. begin
  6666. WriteValue(vaIdent);
  6667. WriteStr(Name);
  6668. end else
  6669. WriteValue(vaNil);
  6670. end;
  6671. procedure TBinaryObjectWriter.WriteSet(Value: LongInt; SetType: Pointer);
  6672. var
  6673. i: Integer;
  6674. b : Integer;
  6675. begin
  6676. WriteValue(vaSet);
  6677. B:=1;
  6678. for i:=0 to 31 do
  6679. begin
  6680. if (Value and b) <>0 then
  6681. begin
  6682. WriteStr(GetEnumName(PTypeInfo(SetType), i));
  6683. end;
  6684. b:=b shl 1;
  6685. end;
  6686. WriteStr('');
  6687. end;
  6688. procedure TBinaryObjectWriter.WriteString(const Value: String);
  6689. var
  6690. i, len: Integer;
  6691. begin
  6692. len := Length(Value);
  6693. WriteValue(vaString);
  6694. WriteDWord(len);
  6695. For I:=1 to len do
  6696. FStream.WriteBufferData(Value[i]);
  6697. end;
  6698. procedure TBinaryObjectWriter.WriteWideString(const Value: WideString);
  6699. begin
  6700. WriteString(Value);
  6701. end;
  6702. procedure TBinaryObjectWriter.WriteUnicodeString(const Value: UnicodeString);
  6703. begin
  6704. WriteString(Value);
  6705. end;
  6706. procedure TBinaryObjectWriter.WriteVariant(const VarValue: JSValue);
  6707. begin
  6708. if isUndefined(varValue) then
  6709. WriteValue(vaNil)
  6710. else if IsNull(VarValue) then
  6711. WriteValue(vaNull)
  6712. else if IsNumber(VarValue) then
  6713. begin
  6714. if Frac(Double(varValue))=0 then
  6715. WriteInteger(NativeInt(VarValue))
  6716. else
  6717. WriteFloat(Double(varValue))
  6718. end
  6719. else if isBoolean(varValue) then
  6720. WriteBoolean(Boolean(VarValue))
  6721. else if isString(varValue) then
  6722. WriteString(String(VarValue))
  6723. else
  6724. raise EWriteError.Create(SUnsupportedPropertyVariantType);
  6725. end;
  6726. procedure TBinaryObjectWriter.Write(const Buffer : TBytes; Count: LongInt);
  6727. begin
  6728. FStream.Write(Buffer,Count);
  6729. end;
  6730. procedure TBinaryObjectWriter.WriteValue(Value: TValueType);
  6731. var
  6732. b: uint8;
  6733. begin
  6734. b := uint8(Value);
  6735. FStream.WriteBufferData(b);
  6736. end;
  6737. procedure TBinaryObjectWriter.WriteStr(const Value: String);
  6738. var
  6739. len,i: integer;
  6740. b: uint8;
  6741. begin
  6742. len:= Length(Value);
  6743. if len > 255 then
  6744. len := 255;
  6745. b := len;
  6746. FStream.WriteBufferData(b);
  6747. For I:=1 to len do
  6748. FStream.WriteBufferData(Value[i]);
  6749. end;
  6750. {****************************************************************************}
  6751. {* TWriter *}
  6752. {****************************************************************************}
  6753. constructor TWriter.Create(ADriver: TAbstractObjectWriter);
  6754. begin
  6755. inherited Create;
  6756. FDriver := ADriver;
  6757. end;
  6758. constructor TWriter.Create(Stream: TStream);
  6759. begin
  6760. inherited Create;
  6761. If (Stream=Nil) then
  6762. Raise EWriteError.Create(SEmptyStreamIllegalWriter);
  6763. FDriver := CreateDriver(Stream);
  6764. FDestroyDriver := True;
  6765. end;
  6766. destructor TWriter.Destroy;
  6767. begin
  6768. if FDestroyDriver then
  6769. FDriver.Free;
  6770. inherited Destroy;
  6771. end;
  6772. function TWriter.CreateDriver(Stream: TStream): TAbstractObjectWriter;
  6773. begin
  6774. Result := TBinaryObjectWriter.Create(Stream);
  6775. end;
  6776. Type
  6777. TPosComponent = Class(TObject)
  6778. Private
  6779. FPos : Integer;
  6780. FComponent : TComponent;
  6781. Public
  6782. Constructor Create(APos : Integer; AComponent : TComponent);
  6783. end;
  6784. Constructor TPosComponent.Create(APos : Integer; AComponent : TComponent);
  6785. begin
  6786. FPos:=APos;
  6787. FComponent:=AComponent;
  6788. end;
  6789. // Used as argument for calls to TComponent.GetChildren:
  6790. procedure TWriter.AddToAncestorList(Component: TComponent);
  6791. begin
  6792. FAncestors.AddObject(Component.Name,TPosComponent.Create(FAncestors.Count,Component));
  6793. end;
  6794. procedure TWriter.DefineProperty(const Name: String;
  6795. ReadData: TReaderProc; AWriteData: TWriterProc; HasData: Boolean);
  6796. begin
  6797. if HasData and Assigned(AWriteData) then
  6798. begin
  6799. // Write the property name and then the data itself
  6800. Driver.BeginProperty(FPropPath + Name);
  6801. AWriteData(Self);
  6802. Driver.EndProperty;
  6803. end;
  6804. end;
  6805. procedure TWriter.DefineBinaryProperty(const Name: String;
  6806. ReadData, AWriteData: TStreamProc; HasData: Boolean);
  6807. begin
  6808. if HasData and Assigned(AWriteData) then
  6809. begin
  6810. // Write the property name and then the data itself
  6811. Driver.BeginProperty(FPropPath + Name);
  6812. WriteBinary(AWriteData);
  6813. Driver.EndProperty;
  6814. end;
  6815. end;
  6816. procedure TWriter.FlushBuffer;
  6817. begin
  6818. Driver.FlushBuffer;
  6819. end;
  6820. procedure TWriter.Write(const Buffer : TBytes; Count: Longint);
  6821. begin
  6822. //This should give an exception if write is not implemented (i.e. TTextObjectWriter)
  6823. //but should work with TBinaryObjectWriter.
  6824. Driver.Write(Buffer, Count);
  6825. end;
  6826. procedure TWriter.SetRoot(ARoot: TComponent);
  6827. begin
  6828. inherited SetRoot(ARoot);
  6829. // Use the new root as lookup root too
  6830. FLookupRoot := ARoot;
  6831. end;
  6832. procedure TWriter.WriteSignature;
  6833. begin
  6834. FDriver.WriteSignature;
  6835. end;
  6836. procedure TWriter.WriteBinary(AWriteData: TStreamProc);
  6837. var
  6838. MemBuffer: TBytesStream;
  6839. begin
  6840. { First write the binary data into a memory stream, then copy this buffered
  6841. stream into the writing destination. This is necessary as we have to know
  6842. the size of the binary data in advance (we're assuming that seeking within
  6843. the writer stream is not possible) }
  6844. MemBuffer := TBytesStream.Create;
  6845. try
  6846. AWriteData(MemBuffer);
  6847. Driver.WriteBinary(MemBuffer.Bytes, MemBuffer.Size);
  6848. finally
  6849. MemBuffer.Free;
  6850. end;
  6851. end;
  6852. procedure TWriter.WriteBoolean(Value: Boolean);
  6853. begin
  6854. Driver.WriteBoolean(Value);
  6855. end;
  6856. procedure TWriter.WriteChar(Value: Char);
  6857. begin
  6858. WriteString(Value);
  6859. end;
  6860. procedure TWriter.WriteWideChar(Value: WideChar);
  6861. begin
  6862. WriteWideString(Value);
  6863. end;
  6864. procedure TWriter.WriteCollection(Value: TCollection);
  6865. var
  6866. i: Integer;
  6867. begin
  6868. Driver.BeginCollection;
  6869. if Assigned(Value) then
  6870. for i := 0 to Value.Count - 1 do
  6871. begin
  6872. { Each collection item needs its own ListBegin/ListEnd tag, or else the
  6873. reader wouldn't be able to know where an item ends and where the next
  6874. one starts }
  6875. WriteListBegin;
  6876. WriteProperties(Value.Items[i]);
  6877. WriteListEnd;
  6878. end;
  6879. WriteListEnd;
  6880. end;
  6881. procedure TWriter.DetermineAncestor(Component : TComponent);
  6882. Var
  6883. I : Integer;
  6884. begin
  6885. // Should be set only when we write an inherited with children.
  6886. if Not Assigned(FAncestors) then
  6887. exit;
  6888. I:=FAncestors.IndexOf(Component.Name);
  6889. If (I=-1) then
  6890. begin
  6891. FAncestor:=Nil;
  6892. FAncestorPos:=-1;
  6893. end
  6894. else
  6895. With TPosComponent(FAncestors.Objects[i]) do
  6896. begin
  6897. FAncestor:=FComponent;
  6898. FAncestorPos:=FPos;
  6899. end;
  6900. end;
  6901. procedure TWriter.DoFindAncestor(Component : TComponent);
  6902. Var
  6903. C : TComponent;
  6904. begin
  6905. if Assigned(FOnFindAncestor) then
  6906. if (Ancestor=Nil) or (Ancestor is TComponent) then
  6907. begin
  6908. C:=TComponent(Ancestor);
  6909. FOnFindAncestor(Self,Component,Component.Name,C,FRootAncestor);
  6910. Ancestor:=C;
  6911. end;
  6912. end;
  6913. procedure TWriter.WriteComponent(Component: TComponent);
  6914. var
  6915. SA : TPersistent;
  6916. SR, SRA : TComponent;
  6917. begin
  6918. SR:=FRoot;
  6919. SA:=FAncestor;
  6920. SRA:=FRootAncestor;
  6921. Try
  6922. Component.FComponentState:=Component.FComponentState+[csWriting];
  6923. Try
  6924. // Possibly set ancestor.
  6925. DetermineAncestor(Component);
  6926. DoFindAncestor(Component); // Mainly for IDE when a parent form had an ancestor renamed...
  6927. // Will call WriteComponentData.
  6928. Component.WriteState(Self);
  6929. FDriver.EndList;
  6930. Finally
  6931. Component.FComponentState:=Component.FComponentState-[csWriting];
  6932. end;
  6933. Finally
  6934. FAncestor:=SA;
  6935. FRoot:=SR;
  6936. FRootAncestor:=SRA;
  6937. end;
  6938. end;
  6939. procedure TWriter.WriteChildren(Component : TComponent);
  6940. Var
  6941. SRoot, SRootA : TComponent;
  6942. SList : TStringList;
  6943. SPos, I , SAncestorPos: Integer;
  6944. O : TObject;
  6945. begin
  6946. // Write children list.
  6947. // While writing children, the ancestor environment must be saved
  6948. // This is recursive...
  6949. SRoot:=FRoot;
  6950. SRootA:=FRootAncestor;
  6951. SList:=FAncestors;
  6952. SPos:=FCurrentPos;
  6953. SAncestorPos:=FAncestorPos;
  6954. try
  6955. FAncestors:=Nil;
  6956. FCurrentPos:=0;
  6957. FAncestorPos:=-1;
  6958. if csInline in Component.ComponentState then
  6959. FRoot:=Component;
  6960. if (FAncestor is TComponent) then
  6961. begin
  6962. FAncestors:=TStringList.Create;
  6963. if csInline in TComponent(FAncestor).ComponentState then
  6964. FRootAncestor := TComponent(FAncestor);
  6965. TComponent(FAncestor).GetChildren(@AddToAncestorList,FRootAncestor);
  6966. FAncestors.Sorted:=True;
  6967. end;
  6968. try
  6969. Component.GetChildren(@WriteComponent, FRoot);
  6970. Finally
  6971. If Assigned(Fancestors) then
  6972. For I:=0 to FAncestors.Count-1 do
  6973. begin
  6974. O:=FAncestors.Objects[i];
  6975. FAncestors.Objects[i]:=Nil;
  6976. O.Free;
  6977. end;
  6978. FreeAndNil(FAncestors);
  6979. end;
  6980. finally
  6981. FAncestors:=Slist;
  6982. FRoot:=SRoot;
  6983. FRootAncestor:=SRootA;
  6984. FCurrentPos:=SPos;
  6985. FAncestorPos:=SAncestorPos;
  6986. end;
  6987. end;
  6988. procedure TWriter.WriteComponentData(Instance: TComponent);
  6989. var
  6990. Flags: TFilerFlags;
  6991. begin
  6992. Flags := [];
  6993. If (Assigned(FAncestor)) and //has ancestor
  6994. (not (csInline in Instance.ComponentState) or // no inline component
  6995. // .. or the inline component is inherited
  6996. (csAncestor in Instance.Componentstate) and (FAncestors <> nil)) then
  6997. Flags:=[ffInherited]
  6998. else If csInline in Instance.ComponentState then
  6999. Flags:=[ffInline];
  7000. If (FAncestors<>Nil) and ((FCurrentPos<>FAncestorPos) or (FAncestor=Nil)) then
  7001. Include(Flags,ffChildPos);
  7002. FDriver.BeginComponent(Instance,Flags,FCurrentPos);
  7003. If (FAncestors<>Nil) then
  7004. Inc(FCurrentPos);
  7005. WriteProperties(Instance);
  7006. WriteListEnd;
  7007. // Needs special handling of ancestor.
  7008. If not IgnoreChildren then
  7009. WriteChildren(Instance);
  7010. end;
  7011. procedure TWriter.WriteDescendent(ARoot: TComponent; AAncestor: TComponent);
  7012. begin
  7013. FRoot := ARoot;
  7014. FAncestor := AAncestor;
  7015. FRootAncestor := AAncestor;
  7016. FLookupRoot := ARoot;
  7017. WriteSignature;
  7018. WriteComponent(ARoot);
  7019. end;
  7020. procedure TWriter.WriteFloat(const Value: Extended);
  7021. begin
  7022. Driver.WriteFloat(Value);
  7023. end;
  7024. procedure TWriter.WriteCurrency(const Value: Currency);
  7025. begin
  7026. Driver.WriteCurrency(Value);
  7027. end;
  7028. procedure TWriter.WriteIdent(const Ident: string);
  7029. begin
  7030. Driver.WriteIdent(Ident);
  7031. end;
  7032. procedure TWriter.WriteInteger(Value: LongInt);
  7033. begin
  7034. Driver.WriteInteger(Value);
  7035. end;
  7036. procedure TWriter.WriteInteger(Value: NativeInt);
  7037. begin
  7038. Driver.WriteInteger(Value);
  7039. end;
  7040. procedure TWriter.WriteSet(Value: LongInt; SetType: Pointer);
  7041. begin
  7042. Driver.WriteSet(Value,SetType);
  7043. end;
  7044. procedure TWriter.WriteVariant(const VarValue: JSValue);
  7045. begin
  7046. Driver.WriteVariant(VarValue);
  7047. end;
  7048. procedure TWriter.WriteListBegin;
  7049. begin
  7050. Driver.BeginList;
  7051. end;
  7052. procedure TWriter.WriteListEnd;
  7053. begin
  7054. Driver.EndList;
  7055. end;
  7056. procedure TWriter.WriteProperties(Instance: TPersistent);
  7057. var
  7058. PropCount,i : integer;
  7059. PropList : TTypeMemberPropertyDynArray;
  7060. begin
  7061. PropList:=GetPropList(Instance);
  7062. PropCount:=Length(PropList);
  7063. if PropCount>0 then
  7064. for i := 0 to PropCount-1 do
  7065. if IsStoredProp(Instance,PropList[i]) then
  7066. WriteProperty(Instance,PropList[i]);
  7067. Instance.DefineProperties(Self);
  7068. end;
  7069. procedure TWriter.WriteProperty(Instance: TPersistent; PropInfo: TTypeMemberProperty);
  7070. var
  7071. HasAncestor: Boolean;
  7072. PropType: TTypeInfo;
  7073. N,Value, DefValue: LongInt;
  7074. Ident: String;
  7075. IntToIdentFn: TIntToIdent;
  7076. {$ifndef FPUNONE}
  7077. FloatValue, DefFloatValue: Extended;
  7078. {$endif}
  7079. MethodValue: TMethod;
  7080. DefMethodValue: TMethod;
  7081. StrValue, DefStrValue: String;
  7082. AncestorObj: TObject;
  7083. C,Component: TComponent;
  7084. ObjValue: TObject;
  7085. SavedAncestor: TPersistent;
  7086. Key, SavedPropPath, Name, lMethodName: String;
  7087. VarValue, DefVarValue : JSValue;
  7088. BoolValue, DefBoolValue: boolean;
  7089. Handled: Boolean;
  7090. O : TJSObject;
  7091. intfValue : IInterface;
  7092. begin
  7093. // do not stream properties without getter
  7094. if PropInfo.Getter='' then
  7095. exit;
  7096. // properties without setter are only allowed, if they are subcomponents
  7097. PropType := PropInfo.TypeInfo;
  7098. if (PropInfo.Setter='') then
  7099. begin
  7100. if PropType.Kind<>tkClass then
  7101. exit;
  7102. ObjValue := TObject(GetObjectProp(Instance, PropInfo));
  7103. if not ObjValue.InheritsFrom(TComponent) or
  7104. not (csSubComponent in TComponent(ObjValue).ComponentStyle) then
  7105. exit;
  7106. end;
  7107. { Check if the ancestor can be used }
  7108. HasAncestor := Assigned(Ancestor) and ((Instance = Root) or
  7109. (Instance.ClassType = Ancestor.ClassType));
  7110. //writeln('TWriter.WriteProperty Name=',PropType^.Name,' Kind=',GetEnumName(TypeInfo(TTypeKind),ord(PropType^.Kind)),' HasAncestor=',HasAncestor);
  7111. case PropType.Kind of
  7112. tkInteger, tkChar, tkEnumeration, tkSet:
  7113. begin
  7114. Value := GetOrdProp(Instance, PropInfo);
  7115. if HasAncestor then
  7116. DefValue := GetOrdProp(Ancestor, PropInfo)
  7117. else
  7118. begin
  7119. if PropType.Kind<>tkSet then
  7120. DefValue := Longint(PropInfo.Default)
  7121. else
  7122. begin
  7123. o:=TJSObject(PropInfo.Default);
  7124. DefValue:=0;
  7125. for Key in o do
  7126. begin
  7127. n:=parseInt(Key,10);
  7128. if n<32 then
  7129. DefValue:=DefValue+(1 shl n);
  7130. end;
  7131. end;
  7132. end;
  7133. // writeln(PPropInfo(PropInfo)^.Name, ', HasAncestor=', ord(HasAncestor), ', Value=', Value, ', Default=', DefValue);
  7134. if (Value <> DefValue) or (DefValue=longint($80000000)) then
  7135. begin
  7136. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7137. case PropType.Kind of
  7138. tkInteger:
  7139. begin
  7140. // Check if this integer has a string identifier
  7141. IntToIdentFn := FindIntToIdent(PropInfo.TypeInfo);
  7142. if Assigned(IntToIdentFn) and IntToIdentFn(Value, Ident) then
  7143. // Integer can be written a human-readable identifier
  7144. WriteIdent(Ident)
  7145. else
  7146. // Integer has to be written just as number
  7147. WriteInteger(Value);
  7148. end;
  7149. tkChar:
  7150. WriteChar(Chr(Value));
  7151. tkSet:
  7152. begin
  7153. Driver.WriteSet(Value, TTypeInfoSet(PropType).CompType);
  7154. end;
  7155. tkEnumeration:
  7156. WriteIdent(GetEnumName(TTypeInfoEnum(PropType), Value));
  7157. end;
  7158. Driver.EndProperty;
  7159. end;
  7160. end;
  7161. {$ifndef FPUNONE}
  7162. tkFloat:
  7163. begin
  7164. FloatValue := GetFloatProp(Instance, PropInfo);
  7165. if HasAncestor then
  7166. DefFloatValue := GetFloatProp(Ancestor, PropInfo)
  7167. else
  7168. begin
  7169. // This is really ugly..
  7170. DefFloatValue:=Double(PropInfo.Default);
  7171. end;
  7172. if (FloatValue<>DefFloatValue) or (not HasAncestor and (int(DefFloatValue)=longint($80000000))) then
  7173. begin
  7174. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7175. WriteFloat(FloatValue);
  7176. Driver.EndProperty;
  7177. end;
  7178. end;
  7179. {$endif}
  7180. tkMethod:
  7181. begin
  7182. MethodValue := GetMethodProp(Instance, PropInfo);
  7183. if HasAncestor then
  7184. DefMethodValue := GetMethodProp(Ancestor, PropInfo)
  7185. else begin
  7186. DefMethodValue.Data := nil;
  7187. DefMethodValue.Code := nil;
  7188. end;
  7189. Handled:=false;
  7190. if Assigned(OnWriteMethodProperty) then
  7191. OnWriteMethodProperty(Self,Instance,PropInfo,MethodValue,
  7192. DefMethodValue,Handled);
  7193. if isString(MethodValue.Code) then
  7194. lMethodName:=String(MethodValue.Code)
  7195. else
  7196. lMethodName:=FLookupRoot.MethodName(MethodValue.Code);
  7197. //Writeln('Writeln A: ',lMethodName);
  7198. if (not Handled) and
  7199. (MethodValue.Code <> DefMethodValue.Code) and
  7200. ((not Assigned(MethodValue.Code)) or
  7201. ((Length(lMethodName) > 0))) then
  7202. begin
  7203. //Writeln('Writeln B',FPropPath + PropInfo.Name);
  7204. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7205. if Assigned(MethodValue.Code) then
  7206. Driver.WriteMethodName(lMethodName)
  7207. else
  7208. Driver.WriteMethodName('');
  7209. Driver.EndProperty;
  7210. end;
  7211. end;
  7212. tkString: // tkSString, tkLString, tkAString are not supported
  7213. begin
  7214. StrValue := GetStrProp(Instance, PropInfo);
  7215. if HasAncestor then
  7216. DefStrValue := GetStrProp(Ancestor, PropInfo)
  7217. else
  7218. begin
  7219. DefValue :=Longint(PropInfo.Default);
  7220. SetLength(DefStrValue, 0);
  7221. end;
  7222. if (StrValue<>DefStrValue) or (not HasAncestor and (DefValue=longint($80000000))) then
  7223. begin
  7224. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7225. if Assigned(FOnWriteStringProperty) then
  7226. FOnWriteStringProperty(Self,Instance,PropInfo,StrValue);
  7227. WriteString(StrValue);
  7228. Driver.EndProperty;
  7229. end;
  7230. end;
  7231. tkJSValue:
  7232. begin
  7233. { Ensure that a Variant manager is installed }
  7234. VarValue := GetJSValueProp(Instance, PropInfo);
  7235. if HasAncestor then
  7236. DefVarValue := GetJSValueProp(Ancestor, PropInfo)
  7237. else
  7238. DefVarValue:=null;
  7239. if (VarValue<>DefVarValue) then
  7240. begin
  7241. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7242. { can't use variant() typecast, pulls in variants unit }
  7243. WriteVariant(VarValue);
  7244. Driver.EndProperty;
  7245. end;
  7246. end;
  7247. tkClass:
  7248. begin
  7249. ObjValue := TObject(GetObjectProp(Instance, PropInfo));
  7250. if HasAncestor then
  7251. begin
  7252. AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo));
  7253. if (AncestorObj is TComponent) and
  7254. (ObjValue is TComponent) then
  7255. begin
  7256. //writeln('TWriter.WriteProperty AncestorObj=',TComponent(AncestorObj).Name,' OwnerFit=',TComponent(AncestorObj).Owner = FRootAncestor,' ',TComponent(ObjValue).Name,' OwnerFit=',TComponent(ObjValue).Owner = Root);
  7257. if (AncestorObj<> ObjValue) and
  7258. (TComponent(AncestorObj).Owner = FRootAncestor) and
  7259. (TComponent(ObjValue).Owner = Root) and
  7260. (UpperCase(TComponent(AncestorObj).Name) = UpperCase(TComponent(ObjValue).Name)) then
  7261. begin
  7262. // different components, but with the same name
  7263. // treat it like an override
  7264. AncestorObj := ObjValue;
  7265. end;
  7266. end;
  7267. end else
  7268. AncestorObj := nil;
  7269. if not Assigned(ObjValue) then
  7270. begin
  7271. if ObjValue <> AncestorObj then
  7272. begin
  7273. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7274. Driver.WriteIdent('NIL');
  7275. Driver.EndProperty;
  7276. end
  7277. end
  7278. else if ObjValue.InheritsFrom(TPersistent) then
  7279. begin
  7280. { Subcomponents are streamed the same way as persistents }
  7281. if ObjValue.InheritsFrom(TComponent)
  7282. and ((not (csSubComponent in TComponent(ObjValue).ComponentStyle))
  7283. or ((TComponent(ObjValue).Owner<>Instance) and (TComponent(ObjValue).Owner<>Nil))) then
  7284. begin
  7285. Component := TComponent(ObjValue);
  7286. if (ObjValue <> AncestorObj)
  7287. and not (csTransient in Component.ComponentStyle) then
  7288. begin
  7289. Name:= '';
  7290. C:= Component;
  7291. While (C<>Nil) and (C.Name<>'') do
  7292. begin
  7293. If (Name<>'') Then
  7294. Name:='.'+Name;
  7295. if C.Owner = LookupRoot then
  7296. begin
  7297. Name := C.Name+Name;
  7298. break;
  7299. end
  7300. else if C = LookupRoot then
  7301. begin
  7302. Name := 'Owner' + Name;
  7303. break;
  7304. end;
  7305. Name:=C.Name + Name;
  7306. C:= C.Owner;
  7307. end;
  7308. if (C=nil) and (Component.Owner=nil) then
  7309. if (Name<>'') then //foreign root
  7310. Name:=Name+'.Owner';
  7311. if Length(Name) > 0 then
  7312. begin
  7313. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7314. WriteIdent(Name);
  7315. Driver.EndProperty;
  7316. end; // length Name>0
  7317. end; //(ObjValue <> AncestorObj)
  7318. end // ObjValue.InheritsFrom(TComponent)
  7319. else
  7320. begin
  7321. SavedAncestor := Ancestor;
  7322. SavedPropPath := FPropPath;
  7323. try
  7324. FPropPath := FPropPath + PropInfo.Name + '.';
  7325. if HasAncestor then
  7326. Ancestor := TPersistent(GetObjectProp(Ancestor, PropInfo));
  7327. WriteProperties(TPersistent(ObjValue));
  7328. finally
  7329. Ancestor := SavedAncestor;
  7330. FPropPath := SavedPropPath;
  7331. end;
  7332. if ObjValue.InheritsFrom(TCollection) then
  7333. begin
  7334. if (not HasAncestor) or (not CollectionsEqual(TCollection(ObjValue),
  7335. TCollection(GetObjectProp(Ancestor, PropInfo)),root,rootancestor)) then
  7336. begin
  7337. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7338. SavedPropPath := FPropPath;
  7339. try
  7340. SetLength(FPropPath, 0);
  7341. WriteCollection(TCollection(ObjValue));
  7342. finally
  7343. FPropPath := SavedPropPath;
  7344. Driver.EndProperty;
  7345. end;
  7346. end;
  7347. end // Tcollection
  7348. end;
  7349. end; // Inheritsfrom(TPersistent)
  7350. end;
  7351. { tkInt64, tkQWord:
  7352. begin
  7353. Int64Value := GetInt64Prop(Instance, PropInfo);
  7354. if HasAncestor then
  7355. DefInt64Value := GetInt64Prop(Ancestor, PropInfo)
  7356. else
  7357. DefInt64Value := 0;
  7358. if Int64Value <> DefInt64Value then
  7359. begin
  7360. Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
  7361. WriteInteger(Int64Value);
  7362. Driver.EndProperty;
  7363. end;
  7364. end;}
  7365. tkBool:
  7366. begin
  7367. BoolValue := GetOrdProp(Instance, PropInfo)<>0;
  7368. if HasAncestor then
  7369. DefBoolValue := GetOrdProp(Ancestor, PropInfo)<>0
  7370. else
  7371. begin
  7372. DefBoolValue := PropInfo.Default<>0;
  7373. DefValue:=Longint(PropInfo.Default);
  7374. end;
  7375. // writeln(PropInfo.Name, ', HasAncestor=', ord(HasAncestor), ', Value=', Value, ', Default=', DefBoolValue);
  7376. if (BoolValue<>DefBoolValue) or (DefValue=longint($80000000)) then
  7377. begin
  7378. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7379. WriteBoolean(BoolValue);
  7380. Driver.EndProperty;
  7381. end;
  7382. end;
  7383. tkInterface:
  7384. begin
  7385. IntfValue := GetInterfaceProp(Instance, PropInfo);
  7386. {
  7387. if Assigned(IntfValue) and Supports(IntfValue, IInterfaceComponentReference, CompRef) then
  7388. begin
  7389. Component := CompRef.GetComponent;
  7390. if HasAncestor then
  7391. begin
  7392. AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo));
  7393. if (AncestorObj is TComponent) then
  7394. begin
  7395. //writeln('TWriter.WriteProperty AncestorObj=',TComponent(AncestorObj).Name,' OwnerFit=',TComponent(AncestorObj).Owner = FRootAncestor,' ',TComponent(ObjValue).Name,' OwnerFit=',TComponent(ObjValue).Owner = Root);
  7396. if (AncestorObj<> Component) and
  7397. (TComponent(AncestorObj).Owner = FRootAncestor) and
  7398. (Component.Owner = Root) and
  7399. (UpperCase(TComponent(AncestorObj).Name) = UpperCase(Component.Name)) then
  7400. begin
  7401. // different components, but with the same name
  7402. // treat it like an override
  7403. AncestorObj := Component;
  7404. end;
  7405. end;
  7406. end else
  7407. AncestorObj := nil;
  7408. if not Assigned(Component) then
  7409. begin
  7410. if Component <> AncestorObj then
  7411. begin
  7412. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7413. Driver.WriteIdent('NIL');
  7414. Driver.EndProperty;
  7415. end
  7416. end
  7417. else if ((not (csSubComponent in Component.ComponentStyle))
  7418. or ((Component.Owner<>Instance) and (Component.Owner<>Nil))) then
  7419. begin
  7420. if (Component <> AncestorObj)
  7421. and not (csTransient in Component.ComponentStyle) then
  7422. begin
  7423. Name:= '';
  7424. C:= Component;
  7425. While (C<>Nil) and (C.Name<>'') do
  7426. begin
  7427. If (Name<>'') Then
  7428. Name:='.'+Name;
  7429. if C.Owner = LookupRoot then
  7430. begin
  7431. Name := C.Name+Name;
  7432. break;
  7433. end
  7434. else if C = LookupRoot then
  7435. begin
  7436. Name := 'Owner' + Name;
  7437. break;
  7438. end;
  7439. Name:=C.Name + Name;
  7440. C:= C.Owner;
  7441. end;
  7442. if (C=nil) and (Component.Owner=nil) then
  7443. if (Name<>'') then //foreign root
  7444. Name:=Name+'.Owner';
  7445. if Length(Name) > 0 then
  7446. begin
  7447. Driver.BeginProperty(FPropPath + PropInfo.Name);
  7448. WriteIdent(Name);
  7449. Driver.EndProperty;
  7450. end; // length Name>0
  7451. end; //(Component <> AncestorObj)
  7452. end;
  7453. end; //Assigned(IntfValue) and Supports(IntfValue,..
  7454. //else write NIL ?
  7455. } end;
  7456. end;
  7457. end;
  7458. procedure TWriter.WriteRootComponent(ARoot: TComponent);
  7459. begin
  7460. WriteDescendent(ARoot, nil);
  7461. end;
  7462. procedure TWriter.WriteString(const Value: String);
  7463. begin
  7464. Driver.WriteString(Value);
  7465. end;
  7466. procedure TWriter.WriteWideString(const Value: WideString);
  7467. begin
  7468. Driver.WriteWideString(Value);
  7469. end;
  7470. procedure TWriter.WriteUnicodeString(const Value: UnicodeString);
  7471. begin
  7472. Driver.WriteUnicodeString(Value);
  7473. end;
  7474. { TAbstractObjectWriter }
  7475. { ---------------------------------------------------------------------
  7476. Global routines
  7477. ---------------------------------------------------------------------}
  7478. var
  7479. ClassList : TJSObject;
  7480. InitHandlerList : TList;
  7481. FindGlobalComponentList : TFPList;
  7482. Procedure RegisterClass(AClass : TPersistentClass);
  7483. begin
  7484. ClassList[AClass.ClassName]:=AClass;
  7485. end;
  7486. Function GetClass(AClassName : string) : TPersistentClass;
  7487. begin
  7488. Result:=nil;
  7489. if AClassName='' then exit;
  7490. if not ClassList.hasOwnProperty(AClassName) then exit;
  7491. Result:=TPersistentClass(ClassList[AClassName]);
  7492. end;
  7493. procedure RegisterFindGlobalComponentProc(AFindGlobalComponent: TFindGlobalComponent);
  7494. begin
  7495. if not(assigned(FindGlobalComponentList)) then
  7496. FindGlobalComponentList:=TFPList.Create;
  7497. if FindGlobalComponentList.IndexOf(CodePointer(AFindGlobalComponent))<0 then
  7498. FindGlobalComponentList.Add(CodePointer(AFindGlobalComponent));
  7499. end;
  7500. procedure UnregisterFindGlobalComponentProc(AFindGlobalComponent: TFindGlobalComponent);
  7501. begin
  7502. if assigned(FindGlobalComponentList) then
  7503. FindGlobalComponentList.Remove(CodePointer(AFindGlobalComponent));
  7504. end;
  7505. function FindGlobalComponent(const Name: string): TComponent;
  7506. var
  7507. i : sizeint;
  7508. begin
  7509. Result:=nil;
  7510. if assigned(FindGlobalComponentList) then
  7511. begin
  7512. for i:=FindGlobalComponentList.Count-1 downto 0 do
  7513. begin
  7514. FindGlobalComponent:=TFindGlobalComponent(FindGlobalComponentList[i])(name);
  7515. if assigned(Result) then
  7516. break;
  7517. end;
  7518. end;
  7519. end;
  7520. Function FindNestedComponent(Root : TComponent; APath : String; CStyle : Boolean = True) : TComponent;
  7521. Function GetNextName : String; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  7522. Var
  7523. P : Integer;
  7524. CM : Boolean;
  7525. begin
  7526. P:=Pos('.',APath);
  7527. CM:=False;
  7528. If (P=0) then
  7529. begin
  7530. If CStyle then
  7531. begin
  7532. P:=Pos('->',APath);
  7533. CM:=P<>0;
  7534. end;
  7535. If (P=0) Then
  7536. P:=Length(APath)+1;
  7537. end;
  7538. Result:=Copy(APath,1,P-1);
  7539. Delete(APath,1,P+Ord(CM));
  7540. end;
  7541. Var
  7542. C : TComponent;
  7543. S : String;
  7544. begin
  7545. If (APath='') then
  7546. Result:=Nil
  7547. else
  7548. begin
  7549. Result:=Root;
  7550. While (APath<>'') And (Result<>Nil) do
  7551. begin
  7552. C:=Result;
  7553. S:=Uppercase(GetNextName);
  7554. Result:=C.FindComponent(S);
  7555. If (Result=Nil) And (S='OWNER') then
  7556. Result:=C;
  7557. end;
  7558. end;
  7559. end;
  7560. Type
  7561. TInitHandler = Class(TObject)
  7562. AHandler : TInitComponentHandler;
  7563. AClass : TComponentClass;
  7564. end;
  7565. procedure RegisterInitComponentHandler(ComponentClass: TComponentClass; Handler: TInitComponentHandler);
  7566. Var
  7567. I : Integer;
  7568. H: TInitHandler;
  7569. begin
  7570. If (InitHandlerList=Nil) then
  7571. InitHandlerList:=TList.Create;
  7572. H:=TInitHandler.Create;
  7573. H.Aclass:=ComponentClass;
  7574. H.AHandler:=Handler;
  7575. try
  7576. With InitHandlerList do
  7577. begin
  7578. I:=0;
  7579. While (I<Count) and not H.AClass.InheritsFrom(TInitHandler(Items[I]).AClass) do
  7580. Inc(I);
  7581. { override? }
  7582. if (I<Count) and (TInitHandler(Items[I]).AClass=H.AClass) then
  7583. begin
  7584. TInitHandler(Items[I]).AHandler:=Handler;
  7585. H.Free;
  7586. end
  7587. else
  7588. InitHandlerList.Insert(I,H);
  7589. end;
  7590. except
  7591. H.Free;
  7592. raise;
  7593. end;
  7594. end;
  7595. initialization
  7596. ClassList:=TJSObject.create(nil);
  7597. end.