classes.pas 281 KB

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