classes.pas 264 KB

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