classes.pas 281 KB

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