classes.pas 270 KB

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