classes.pas 257 KB

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