123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899 |
- {
- This file is part of the Pas2JS run time library.
- Copyright (c) 2017 by Mattias Gaertner
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit Classes;
- {$mode objfpc}
- interface
- uses
- RTLConsts, Types, SysUtils, JS, TypInfo;
- type
- TNotifyEvent = procedure(Sender: TObject) of object;
- TNotifyEventRef = reference to procedure(Sender: TObject);
- TStringNotifyEventRef = Reference to Procedure(Sender: TObject; Const aString : String);
- // Notification operations :
- // Observer has changed, is freed, item added to/deleted from list, custom event.
- TFPObservedOperation = (ooChange,ooFree,ooAddItem,ooDeleteItem,ooCustom);
- EStreamError = class(Exception);
- EFCreateError = class(EStreamError);
- EFOpenError = class(EStreamError);
- EFilerError = class(EStreamError);
- EReadError = class(EFilerError);
- EWriteError = class(EFilerError);
- EClassNotFound = class(EFilerError);
- EMethodNotFound = class(EFilerError);
- EInvalidImage = class(EFilerError);
- EResNotFound = class(Exception);
- EListError = class(Exception);
- EBitsError = class(Exception);
- EStringListError = class(EListError);
- EComponentError = class(Exception);
- EParserError = class(Exception);
- EOutOfResources = class(EOutOfMemory);
- EInvalidOperation = class(Exception);
- TListAssignOp = (laCopy, laAnd, laOr, laXor, laSrcUnique, laDestUnique);
- TListSortCompare = function(Item1, Item2: JSValue): Integer;
- TListSortCompareFunc = reference to function (Item1, Item2: JSValue): Integer;
- TListCallback = Types.TListCallback;
- TListStaticCallback = Types.TListStaticCallback;
- TAlignment = (taLeftJustify, taRightJustify, taCenter);
- // Forward class definitions
- TFPList = Class;
- TReader = Class;
- TWriter = Class;
- TFiler = Class;
- { TFPListEnumerator }
- TFPListEnumerator = class
- private
- FList: TFPList;
- FPosition: Integer;
- public
- constructor Create(AList: TFPList); reintroduce;
- function GetCurrent: JSValue;
- function MoveNext: Boolean;
- property Current: JSValue read GetCurrent;
- end;
- { TFPList }
- TFPList = class(TObject)
- private
- FList: TJSValueDynArray;
- FCount: Integer;
- FCapacity: Integer;
- procedure CopyMove(aList: TFPList);
- procedure MergeMove(aList: TFPList);
- procedure DoCopy(ListA, ListB: TFPList);
- procedure DoSrcUnique(ListA, ListB: TFPList);
- procedure DoAnd(ListA, ListB: TFPList);
- procedure DoDestUnique(ListA, ListB: TFPList);
- procedure DoOr(ListA, ListB: TFPList);
- procedure DoXOr(ListA, ListB: TFPList);
- protected
- function Get(Index: Integer): JSValue; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- procedure Put(Index: Integer; Item: JSValue); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- procedure SetCapacity(NewCapacity: Integer);
- procedure SetCount(NewCount: Integer);
- Procedure RaiseIndexError(Index: Integer);
- public
- //Type
- // TDirection = (FromBeginning, FromEnd);
- destructor Destroy; override;
- procedure AddList(AList: TFPList);
- function Add(Item: JSValue): Integer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- procedure Clear;
- procedure Delete(Index: Integer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- class procedure Error(const Msg: string; const Data: String);
- procedure Exchange(Index1, Index2: Integer);
- function Expand: TFPList; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- function Extract(Item: JSValue): JSValue;
- function First: JSValue;
- function GetEnumerator: TFPListEnumerator;
- function IndexOf(Item: JSValue): Integer;
- function IndexOfItem(Item: JSValue; Direction: TDirection): Integer;
- procedure Insert(Index: Integer; Item: JSValue); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- function Last: JSValue;
- procedure Move(CurIndex, NewIndex: Integer);
- procedure Assign (ListA: TFPList; AOperator: TListAssignOp=laCopy; ListB: TFPList=nil);
- function Remove(Item: JSValue): Integer;
- procedure Pack;
- procedure Sort(const Compare: TListSortCompare);
- procedure SortList(const Compare: TListSortCompareFunc);
- procedure ForEachCall(const proc2call: TListCallback; const arg: JSValue);
- procedure ForEachCall(const proc2call: TListStaticCallback; const arg: JSValue);
- property Capacity: Integer read FCapacity write SetCapacity;
- property Count: Integer read FCount write SetCount;
- property Items[Index: Integer]: JSValue read Get write Put; default;
- property List: TJSValueDynArray read FList;
- end;
- TListNotification = (lnAdded, lnExtracted, lnDeleted);
- TList = class;
- { TListEnumerator }
- TListEnumerator = class
- private
- FList: TList;
- FPosition: Integer;
- public
- constructor Create(AList: TList); reintroduce;
- function GetCurrent: JSValue;
- function MoveNext: Boolean;
- property Current: JSValue read GetCurrent;
- end;
- { TList }
- TList = class(TObject)
- private
- FList: TFPList;
- procedure CopyMove (aList : TList);
- procedure MergeMove (aList : TList);
- procedure DoCopy(ListA, ListB : TList);
- procedure DoSrcUnique(ListA, ListB : TList);
- procedure DoAnd(ListA, ListB : TList);
- procedure DoDestUnique(ListA, ListB : TList);
- procedure DoOr(ListA, ListB : TList);
- procedure DoXOr(ListA, ListB : TList);
- protected
- function Get(Index: Integer): JSValue;
- procedure Put(Index: Integer; Item: JSValue);
- procedure Notify(aValue: JSValue; Action: TListNotification); virtual;
- procedure SetCapacity(NewCapacity: Integer);
- function GetCapacity: integer;
- procedure SetCount(NewCount: Integer);
- function GetCount: integer;
- function GetList: TJSValueDynArray;
- property FPList : TFPList Read FList;
- public
- constructor Create; reintroduce;
- destructor Destroy; override;
- Procedure AddList(AList : TList);
- function Add(Item: JSValue): Integer;
- procedure Clear; virtual;
- procedure Delete(Index: Integer);
- class procedure Error(const Msg: string; Data: String); virtual;
- procedure Exchange(Index1, Index2: Integer);
- function Expand: TList;
- function Extract(Item: JSValue): JSValue;
- function First: JSValue;
- function GetEnumerator: TListEnumerator;
- function IndexOf(Item: JSValue): Integer;
- procedure Insert(Index: Integer; Item: JSValue);
- function Last: JSValue;
- procedure Move(CurIndex, NewIndex: Integer);
- procedure Assign (ListA: TList; AOperator: TListAssignOp=laCopy; ListB: TList=nil);
- function Remove(Item: JSValue): Integer;
- procedure Pack;
- procedure Sort(const Compare: TListSortCompare);
- procedure SortList(const Compare: TListSortCompareFunc);
- property Capacity: Integer read GetCapacity write SetCapacity;
- property Count: Integer read GetCount write SetCount;
- property Items[Index: Integer]: JSValue read Get write Put; default;
- property List: TJSValueDynArray read GetList;
- end;
- { TPersistent }
-
- {$M+}
- TPersistent = class(TObject)
- private
- //FObservers : TFPList;
- procedure AssignError(Source: TPersistent);
- protected
- procedure DefineProperties(Filer: TFiler); virtual;
- procedure AssignTo(Dest: TPersistent); virtual;
- function GetOwner: TPersistent; virtual;
- public
- procedure Assign(Source: TPersistent); virtual;
- //procedure FPOAttachObserver(AObserver : TObject);
- //procedure FPODetachObserver(AObserver : TObject);
- //procedure FPONotifyObservers(ASender : TObject; AOperation: TFPObservedOperation; Data: TObject);
- function GetNamePath: string; virtual;
- end;
- TPersistentClass = Class of TPersistent;
- { TInterfacedPersistent }
- TInterfacedPersistent = class(TPersistent, IInterface)
- private
- FOwnerInterface: IInterface;
- protected
- function _AddRef: Integer; {$IFDEF MAKESTUB}stdcall;{$ENDIF}
- function _Release: Integer; {$IFDEF MAKESTUB}stdcall;{$ENDIF}
- public
- function QueryInterface(const IID: TGUID; out Obj): HRESULT; virtual;{$IFDEF MAKESTUB} stdcall;{$ENDIF}
- procedure AfterConstruction; override;
- end;
- TStrings = Class;
- { TStringsEnumerator class }
- TStringsEnumerator = class
- private
- FStrings: TStrings;
- FPosition: Integer;
- public
- constructor Create(AStrings: TStrings); reintroduce;
- function GetCurrent: String;
- function MoveNext: Boolean;
- property Current: String read GetCurrent;
- end;
- { TStrings class }
- TStrings = class(TPersistent)
- private
- FSpecialCharsInited : boolean;
- FAlwaysQuote: Boolean;
- FQuoteChar : Char;
- FDelimiter : Char;
- FNameValueSeparator : Char;
- FUpdateCount: Integer;
- FLBS : TTextLineBreakStyle;
- FSkipLastLineBreak : Boolean;
- FStrictDelimiter : Boolean;
- FLineBreak : String;
- function GetCommaText: string;
- function GetName(Index: Integer): string;
- function GetValue(const Name: string): string;
- Function GetLBS : TTextLineBreakStyle;
- Procedure SetLBS (AValue : TTextLineBreakStyle);
- procedure SetCommaText(const Value: string);
- procedure SetValue(const Name : String; Const Value: string);
- procedure SetDelimiter(c:Char);
- procedure SetQuoteChar(c:Char);
- procedure SetNameValueSeparator(c:Char);
- procedure DoSetTextStr(const Value: string; DoClear : Boolean);
- Function GetDelimiter : Char;
- Function GetNameValueSeparator : Char;
- Function GetQuoteChar: Char;
- Function GetLineBreak : String;
- procedure SetLineBreak(const S : String);
- Function GetSkipLastLineBreak : Boolean;
- procedure SetSkipLastLineBreak(const AValue : Boolean);
- procedure ReadData(Reader: TReader);
- procedure WriteData(Writer: TWriter);
- protected
- procedure DefineProperties(Filer: TFiler); override;
- procedure Error(const Msg: string; Data: Integer);
- function Get(Index: Integer): string; virtual; abstract;
- function GetCapacity: Integer; virtual;
- function GetCount: Integer; virtual; abstract;
- function GetObject(Index: Integer): TObject; virtual;
- function GetTextStr: string; virtual;
- procedure Put(Index: Integer; const S: string); virtual;
- procedure PutObject(Index: Integer; AObject: TObject); virtual;
- procedure SetCapacity(NewCapacity: Integer); virtual;
- procedure SetTextStr(const Value: string); virtual;
- procedure SetUpdateState(Updating: Boolean); virtual;
- property UpdateCount: Integer read FUpdateCount;
- Function DoCompareText(const s1,s2 : string) : PtrInt; virtual;
- Function GetDelimitedText: string;
- Procedure SetDelimitedText(Const AValue: string);
- Function GetValueFromIndex(Index: Integer): string;
- Procedure SetValueFromIndex(Index: Integer; const Value: string);
- Procedure CheckSpecialChars;
- // Class Function GetNextLine (Const Value : String; Var S : String; Var P : Integer) : Boolean;
- Function GetNextLinebreak (Const Value : String; Out S : String; Var P : Integer) : Boolean;
- public
- constructor Create; reintroduce;
- destructor Destroy; override;
- function ToObjectArray: TObjectDynArray; overload;
- function ToObjectArray(aStart,aEnd : Integer): TObjectDynArray; overload;
- function ToStringArray: TStringDynArray; overload;
- function ToStringArray(aStart,aEnd : Integer): TStringDynArray; overload;
- function Add(const S: string): Integer; virtual; overload;
- function Add(const Fmt : string; const Args : Array of const): Integer; overload;
- function AddFmt(const Fmt : string; const Args : Array of const): Integer;
- function AddObject(const S: string; AObject: TObject): Integer; virtual; overload;
- function AddObject(const Fmt: string; Args : Array of const; AObject: TObject): Integer; overload;
- procedure Append(const S: string);
- procedure AddStrings(TheStrings: TStrings); overload; virtual;
- procedure AddStrings(TheStrings: TStrings; ClearFirst : Boolean); overload;
- procedure AddStrings(const TheStrings: array of string); overload; virtual;
- procedure AddStrings(const TheStrings: array of string; ClearFirst : Boolean); overload;
- function AddPair(const AName, AValue: string): TStrings; overload;
- function AddPair(const AName, AValue: string; AObject: TObject): TStrings; overload;
- Procedure AddText(Const S : String); virtual;
- procedure Assign(Source: TPersistent); override;
- procedure BeginUpdate;
- procedure Clear; virtual; abstract;
- procedure Delete(Index: Integer); virtual; abstract;
- procedure EndUpdate;
- function Equals(Obj: TObject): Boolean; override; overload;
- function Equals(TheStrings: TStrings): Boolean; overload;
- procedure Exchange(Index1, Index2: Integer); virtual;
- function GetEnumerator: TStringsEnumerator;
- function IndexOf(const S: string): Integer; virtual;
- function IndexOfName(const Name: string): Integer; virtual;
- function IndexOfObject(AObject: TObject): Integer; virtual;
- procedure Insert(Index: Integer; const S: string); virtual; abstract;
- procedure InsertObject(Index: Integer; const S: string; AObject: TObject);
- procedure Move(CurIndex, NewIndex: Integer); virtual;
- procedure GetNameValue(Index : Integer; Out AName,AValue : String);
- Procedure LoadFromURL(Const aURL : String; Async : Boolean = True; OnLoaded : TNotifyEventRef = Nil; OnError: TStringNotifyEventRef = Nil); virtual;
- // Delphi compatibility. Must be an URL
- Procedure LoadFromFile(Const aFileName : String; const OnLoaded : TProc = Nil; const AError: TProcString = Nil);
- function ExtractName(Const S:String):String;
- Property TextLineBreakStyle : TTextLineBreakStyle Read GetLBS Write SetLBS;
- property Delimiter: Char read GetDelimiter write SetDelimiter;
- property DelimitedText: string read GetDelimitedText write SetDelimitedText;
- property LineBreak : string Read GetLineBreak write SetLineBreak;
- Property StrictDelimiter : Boolean Read FStrictDelimiter Write FStrictDelimiter;
- property AlwaysQuote: Boolean read FAlwaysQuote write FAlwaysQuote;
- property QuoteChar: Char read GetQuoteChar write SetQuoteChar;
- Property NameValueSeparator : Char Read GetNameValueSeparator Write SetNameValueSeparator;
- property ValueFromIndex[Index: Integer]: string read GetValueFromIndex write SetValueFromIndex;
- property Capacity: Integer read GetCapacity write SetCapacity;
- property CommaText: string read GetCommaText write SetCommaText;
- property Count: Integer read GetCount;
- property Names[Index: Integer]: string read GetName;
- property Objects[Index: Integer]: TObject read GetObject write PutObject;
- property Values[const Name: string]: string read GetValue write SetValue;
- property Strings[Index: Integer]: string read Get write Put; default;
- property Text: string read GetTextStr write SetTextStr;
- Property SkipLastLineBreak : Boolean Read GetSkipLastLineBreak Write SetSkipLastLineBreak;
- end;
- { TStringList}
- TStringItem = record
- FString: string;
- FObject: TObject;
- end;
- TStringItemArray = Array of TStringItem;
- TStringList = class;
- TStringListSortCompare = function(List: TStringList; Index1, Index2: Integer): Integer;
- TStringsSortStyle = (sslNone,sslUser,sslAuto);
- TStringsSortStyles = Set of TStringsSortStyle;
- TStringList = class(TStrings)
- private
- FList: TStringItemArray;
- FCount: Integer;
- FOnChange: TNotifyEvent;
- FOnChanging: TNotifyEvent;
- FDuplicates: TDuplicates;
- FCaseSensitive : Boolean;
- FForceSort : Boolean;
- FOwnsObjects : Boolean;
- FSortStyle: TStringsSortStyle;
- procedure ExchangeItemsInt(Index1, Index2: Integer);
- function GetSorted: Boolean;
- procedure Grow;
- procedure InternalClear(FromIndex : Integer = 0; ClearOnly : Boolean = False);
- procedure QuickSort(L, R: Integer; CompareFn: TStringListSortCompare);
- procedure SetSorted(Value: Boolean);
- procedure SetCaseSensitive(b : boolean);
- procedure SetSortStyle(AValue: TStringsSortStyle);
- protected
- Procedure CheckIndex(AIndex : Integer);
- procedure ExchangeItems(Index1, Index2: Integer); virtual;
- procedure Changed; virtual;
- procedure Changing; virtual;
- function Get(Index: Integer): string; override;
- function GetCapacity: Integer; override;
- function GetCount: Integer; override;
- function GetObject(Index: Integer): TObject; override;
- procedure Put(Index: Integer; const S: string); override;
- procedure PutObject(Index: Integer; AObject: TObject); override;
- procedure SetCapacity(NewCapacity: Integer); override;
- procedure SetUpdateState(Updating: Boolean); override;
- procedure InsertItem(Index: Integer; const S: string); virtual;
- procedure InsertItem(Index: Integer; const S: string; O: TObject); virtual;
- Function DoCompareText(const s1,s2 : string) : PtrInt; override;
- function CompareStrings(const s1,s2 : string) : Integer; virtual;
- public
- destructor Destroy; override;
- function Add(const S: string): Integer; override;
- procedure Clear; override;
- procedure Delete(Index: Integer); override;
- procedure Exchange(Index1, Index2: Integer); override;
- function Find(const S: string; Out Index: Integer): Boolean; virtual;
- function IndexOf(const S: string): Integer; override;
- procedure Insert(Index: Integer; const S: string); override;
- procedure Sort; virtual;
- procedure CustomSort(CompareFn: TStringListSortCompare); virtual;
- property Duplicates: TDuplicates read FDuplicates write FDuplicates;
- property Sorted: Boolean read GetSorted write SetSorted;
- property CaseSensitive: Boolean read FCaseSensitive write SetCaseSensitive;
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
- property OwnsObjects : boolean read FOwnsObjects write FOwnsObjects;
- Property SortStyle : TStringsSortStyle Read FSortStyle Write SetSortStyle;
- end;
- TCollection = class;
- { TCollectionItem }
- TCollectionItem = class(TPersistent)
- private
- FCollection: TCollection;
- FID: Integer;
- FUpdateCount: Integer;
- function GetIndex: Integer;
- protected
- procedure SetCollection(Value: TCollection);virtual;
- procedure Changed(AllItems: Boolean);
- function GetOwner: TPersistent; override;
- function GetDisplayName: string; virtual;
- procedure SetIndex(Value: Integer); virtual;
- procedure SetDisplayName(const Value: string); virtual;
- property UpdateCount: Integer read FUpdateCount;
- public
- constructor Create(ACollection: TCollection); virtual; reintroduce;
- destructor Destroy; override;
- function GetNamePath: string; override;
- property Collection: TCollection read FCollection write SetCollection;
- property ID: Integer read FID;
- property Index: Integer read GetIndex write SetIndex;
- property DisplayName: string read GetDisplayName write SetDisplayName;
- end;
- TCollectionEnumerator = class
- private
- FCollection: TCollection;
- FPosition: Integer;
- public
- constructor Create(ACollection: TCollection); reintroduce;
- function GetCurrent: TCollectionItem;
- function MoveNext: Boolean;
- property Current: TCollectionItem read GetCurrent;
- end;
- TCollectionItemClass = class of TCollectionItem;
- TCollectionNotification = (cnAdded, cnExtracting, cnDeleting);
- TCollectionSortCompare = function (Item1, Item2: TCollectionItem): Integer;
- TCollectionSortCompareFunc = reference to function (Item1, Item2: TCollectionItem): Integer;
- TCollection = class(TPersistent)
- private
- FItemClass: TCollectionItemClass;
- FItems: TFpList;
- FUpdateCount: Integer;
- FNextID: Integer;
- FPropName: string;
- function GetCount: Integer;
- function GetPropName: string;
- procedure InsertItem(Item: TCollectionItem);
- procedure RemoveItem(Item: TCollectionItem);
- procedure DoClear;
- protected
- { Design-time editor support }
- function GetAttrCount: Integer; virtual;
- function GetAttr(Index: Integer): string; virtual;
- function GetItemAttr(Index, ItemIndex: Integer): string; virtual;
- procedure Changed;
- function GetItem(Index: Integer): TCollectionItem;
- procedure SetItem(Index: Integer; Value: TCollectionItem);
- procedure SetItemName(Item: TCollectionItem); virtual;
- procedure SetPropName; virtual;
- procedure Update(Item: TCollectionItem); virtual;
- procedure Notify(Item: TCollectionItem;Action: TCollectionNotification); virtual;
- property PropName: string read GetPropName write FPropName;
- property UpdateCount: Integer read FUpdateCount;
- public
- constructor Create(AItemClass: TCollectionItemClass); reintroduce;
- destructor Destroy; override;
- function Owner: TPersistent;
- function Add: TCollectionItem;
- procedure Assign(Source: TPersistent); override;
- procedure BeginUpdate; virtual;
- procedure Clear;
- procedure EndUpdate; virtual;
- procedure Delete(Index: Integer);
- function GetEnumerator: TCollectionEnumerator;
- function GetNamePath: string; override;
- function Insert(Index: Integer): TCollectionItem;
- function FindItemID(ID: Integer): TCollectionItem;
- procedure Exchange(Const Index1, index2: integer);
- procedure Sort(Const Compare : TCollectionSortCompare);
- procedure SortList(Const Compare : TCollectionSortCompareFunc);
- property Count: Integer read GetCount;
- property ItemClass: TCollectionItemClass read FItemClass;
- property Items[Index: Integer]: TCollectionItem read GetItem write SetItem;
- end;
- TOwnedCollection = class(TCollection)
- private
- FOwner: TPersistent;
- protected
- Function GetOwner: TPersistent; override;
- public
- Constructor Create(AOwner: TPersistent; AItemClass: TCollectionItemClass); reintroduce;
- end;
- TComponent = Class;
- TOperation = (opInsert, opRemove);
- TComponentStateItem = ( csLoading, csReading, csWriting, csDestroying,
- csDesigning, csAncestor, csUpdating, csFixups, csFreeNotification,
- csInline, csDesignInstance);
- TComponentState = set of TComponentStateItem;
- TComponentStyleItem = (csInheritable, csCheckPropAvail, csSubComponent, csTransient);
- TComponentStyle = set of TComponentStyleItem;
- TGetChildProc = procedure (Child: TComponent) of object;
- TComponentName = string;
- { TComponentEnumerator }
- TComponentEnumerator = class
- private
- FComponent: TComponent;
- FPosition: Integer;
- public
- constructor Create(AComponent: TComponent); reintroduce;
- function GetCurrent: TComponent;
- function MoveNext: Boolean;
- property Current: TComponent read GetCurrent;
- end;
- TComponent = class(TPersistent, IInterface)
- private
- FOwner: TComponent;
- FName: TComponentName;
- FTag: Ptrint;
- FComponents: TFpList;
- FFreeNotifies: TFpList;
- FDesignInfo: Longint;
- FComponentState: TComponentState;
- function GetComponent(AIndex: Integer): TComponent;
- function GetComponentCount: Integer;
- function GetComponentIndex: Integer;
- procedure Insert(AComponent: TComponent);
- procedure ReadLeft(AReader: TReader);
- procedure ReadTop(AReader: TReader);
- procedure Remove(AComponent: TComponent);
- procedure RemoveNotification(AComponent: TComponent);
- procedure SetComponentIndex(Value: Integer);
- procedure SetReference(Enable: Boolean);
- procedure WriteLeft(AWriter: TWriter);
- procedure WriteTop(AWriter: TWriter);
- protected
- FComponentStyle: TComponentStyle;
- procedure ChangeName(const NewName: TComponentName);
- procedure DefineProperties(Filer: TFiler); override;
- procedure GetChildren(Proc: TGetChildProc; Root: TComponent); virtual;
- function GetChildOwner: TComponent; virtual;
- function GetChildParent: TComponent; virtual;
- function GetOwner: TPersistent; override;
- procedure Loaded; virtual;
- procedure Loading; virtual;
- procedure SetWriting(Value: Boolean); virtual;
- procedure SetReading(Value: Boolean); virtual;
- procedure Notification(AComponent: TComponent; Operation: TOperation); virtual;
- procedure PaletteCreated; virtual;
- procedure ReadState(Reader: TReader); virtual;
- procedure SetAncestor(Value: Boolean);
- procedure SetDesigning(Value: Boolean; SetChildren : Boolean = True);
- procedure SetDesignInstance(Value: Boolean);
- procedure SetInline(Value: Boolean);
- procedure SetName(const NewName: TComponentName); virtual;
- procedure SetChildOrder(Child: TComponent; Order: Integer); virtual;
- procedure SetParentComponent(Value: TComponent); virtual;
- procedure Updating; virtual;
- procedure Updated; virtual;
- procedure ValidateRename(AComponent: TComponent; const CurName, NewName: string); virtual;
- procedure ValidateContainer(AComponent: TComponent); virtual;
- procedure ValidateInsert(AComponent: TComponent); virtual;
- protected
- function _AddRef: Integer; {$IFDEF MAKESTUB}stdcall;{$ENDIF}
- function _Release: Integer; {$IFDEF MAKESTUB}stdcall;{$ENDIF}
- public
- constructor Create(AOwner: TComponent); virtual; reintroduce;
- destructor Destroy; override;
- procedure BeforeDestruction; override;
- procedure DestroyComponents;
- procedure Destroying;
- function QueryInterface(const IID: TGUID; out Obj): HRESULT; virtual; {$IFDEF MAKESTUB} stdcall;{$ENDIF}
- procedure WriteState(Writer: TWriter); virtual;
- // function ExecuteAction(Action: TBasicAction): Boolean; virtual;
- function FindComponent(const AName: string): TComponent;
- procedure FreeNotification(AComponent: TComponent);
- procedure RemoveFreeNotification(AComponent: TComponent);
- function GetNamePath: string; override;
- function GetParentComponent: TComponent; virtual;
- function HasParent: Boolean; virtual;
- procedure InsertComponent(AComponent: TComponent);
- procedure RemoveComponent(AComponent: TComponent);
- procedure SetSubComponent(ASubComponent: Boolean);
- function GetEnumerator: TComponentEnumerator;
- // function UpdateAction(Action: TBasicAction): Boolean; dynamic;
- property Components[Index: Integer]: TComponent read GetComponent;
- property ComponentCount: Integer read GetComponentCount;
- property ComponentIndex: Integer read GetComponentIndex write SetComponentIndex;
- property ComponentState: TComponentState read FComponentState;
- property ComponentStyle: TComponentStyle read FComponentStyle;
- property DesignInfo: Longint read FDesignInfo write FDesignInfo;
- property Owner: TComponent read FOwner;
- published
- property Name: TComponentName read FName write SetName stored False;
- property Tag: PtrInt read FTag write FTag default 0;
- end;
- TComponentClass = Class of TComponent;
- TSeekOrigin = (soBeginning, soCurrent, soEnd);
- { TStream }
- TStream = class(TObject)
- private
- FEndian: TEndian;
- function MakeInt(B: TBytes; aSize: Integer; Signed: Boolean): NativeInt;
- function MakeBytes(B: NativeInt; aSize: Integer; Signed: Boolean): TBytes;
- protected
- procedure InvalidSeek; virtual;
- procedure Discard(const Count: NativeInt);
- procedure DiscardLarge(Count: NativeInt; const MaxBufferSize: Longint);
- procedure FakeSeekForward(Offset: NativeInt; const Origin: TSeekOrigin; const Pos: NativeInt);
- function GetPosition: NativeInt; virtual;
- procedure SetPosition(const Pos: NativeInt); virtual;
- function GetSize: NativeInt; virtual;
- procedure SetSize(const NewSize: NativeInt); virtual;
- procedure SetSize64(const NewSize: NativeInt); virtual;
- procedure ReadNotImplemented;
- procedure WriteNotImplemented;
- function ReadMaxSizeData(Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
- Procedure ReadExactSizeData(Buffer : TBytes; aSize,aCount : NativeInt);
- function WriteMaxSizeData(Const Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
- Procedure WriteExactSizeData(Const Buffer : TBytes; aSize,aCount : NativeInt);
- public
- function Read(var Buffer: TBytes; Count: Longint): Longint; overload;
- function Read(Buffer : TBytes; aOffset, Count: Longint): Longint; virtual; abstract; overload;
- function Write(const Buffer: TBytes; Count: Longint): Longint; virtual; overload;
- function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; virtual; abstract; overload;
- function Seek(const Offset: NativeInt; Origin: TSeekOrigin): NativeInt; virtual; abstract; overload;
- function ReadData(Buffer: TBytes; Count: NativeInt): NativeInt; overload;
- function ReadData(var Buffer: Boolean): NativeInt; overload;
- function ReadData(var Buffer: Boolean; Count: NativeInt): NativeInt; overload;
- function ReadData(var Buffer: WideChar): NativeInt; overload;
- function ReadData(var Buffer: WideChar; Count: NativeInt): NativeInt; overload;
- function ReadData(var Buffer: Int8): NativeInt; overload;
- function ReadData(var Buffer: Int8; Count: NativeInt): NativeInt; overload;
- function ReadData(var Buffer: UInt8): NativeInt; overload;
- function ReadData(var Buffer: UInt8; Count: NativeInt): NativeInt; overload;
- function ReadData(var Buffer: Int16): NativeInt; overload;
- function ReadData(var Buffer: Int16; Count: NativeInt): NativeInt; overload;
- function ReadData(var Buffer: UInt16): NativeInt; overload;
- function ReadData(var Buffer: UInt16; Count: NativeInt): NativeInt; overload;
- function ReadData(var Buffer: Int32): NativeInt; overload;
- function ReadData(var Buffer: Int32; Count: NativeInt): NativeInt; overload;
- function ReadData(var Buffer: UInt32): NativeInt; overload;
- function ReadData(var Buffer: UInt32; Count: NativeInt): NativeInt; overload;
- // NativeLargeint. Stored as a float64, Read as float64.
- function ReadData(var Buffer: NativeLargeInt): NativeInt; overload;
- function ReadData(var Buffer: NativeLargeInt; Count: NativeInt): NativeInt; overload;
- function ReadData(var Buffer: NativeLargeUInt): NativeInt; overload;
- function ReadData(var Buffer: NativeLargeUInt; Count: NativeInt): NativeInt; overload;
- // Note: a ReadData with Int64 would be Delphi/FPC incompatible
- function ReadData(var Buffer: Double): NativeInt; overload;
- function ReadData(var Buffer: Double; Count: NativeInt): NativeInt; overload;
- procedure ReadBuffer(var Buffer: TBytes; Count: NativeInt); overload;
- procedure ReadBuffer(var Buffer: TBytes; Offset, Count: NativeInt); overload;
- procedure ReadBufferData(var Buffer: Boolean); overload;
- procedure ReadBufferData(var Buffer: Boolean; Count: NativeInt); overload;
- procedure ReadBufferData(var Buffer: WideChar); overload;
- procedure ReadBufferData(var Buffer: WideChar; Count: NativeInt); overload;
- procedure ReadBufferData(var Buffer: Int8); overload;
- procedure ReadBufferData(var Buffer: Int8; Count: NativeInt); overload;
- procedure ReadBufferData(var Buffer: UInt8); overload;
- procedure ReadBufferData(var Buffer: UInt8; Count: NativeInt); overload;
- procedure ReadBufferData(var Buffer: Int16); overload;
- procedure ReadBufferData(var Buffer: Int16; Count: NativeInt); overload;
- procedure ReadBufferData(var Buffer: UInt16); overload;
- procedure ReadBufferData(var Buffer: UInt16; Count: NativeInt); overload;
- procedure ReadBufferData(var Buffer: Int32); overload;
- procedure ReadBufferData(var Buffer: Int32; Count: NativeInt); overload;
- procedure ReadBufferData(var Buffer: UInt32); overload;
- procedure ReadBufferData(var Buffer: UInt32; Count: NativeInt); overload;
- // NativeLargeint. Stored as a float64, Read as float64.
- procedure ReadBufferData(var Buffer: NativeLargeInt); overload;
- procedure ReadBufferData(var Buffer: NativeLargeInt; Count: NativeInt); overload;
- procedure ReadBufferData(var Buffer: NativeLargeUInt); overload;
- procedure ReadBufferData(var Buffer: NativeLargeUInt; Count: NativeInt); overload;
- procedure ReadBufferData(var Buffer: Double); overload;
- procedure ReadBufferData(var Buffer: Double; Count: NativeInt); overload;
- procedure WriteBuffer(const Buffer: TBytes; Count: NativeInt); overload;
- procedure WriteBuffer(const Buffer: TBytes; Offset, Count: NativeInt); overload;
- function WriteData(const Buffer: TBytes; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: Boolean): NativeInt; overload;
- function WriteData(const Buffer: Boolean; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: WideChar): NativeInt; overload;
- function WriteData(const Buffer: WideChar; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: Int8): NativeInt; overload;
- function WriteData(const Buffer: Int8; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: UInt8): NativeInt; overload;
- function WriteData(const Buffer: UInt8; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: Int16): NativeInt; overload;
- function WriteData(const Buffer: Int16; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: UInt16): NativeInt; overload;
- function WriteData(const Buffer: UInt16; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: Int32): NativeInt; overload;
- function WriteData(const Buffer: Int32; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: UInt32): NativeInt; overload;
- function WriteData(const Buffer: UInt32; Count: NativeInt): NativeInt; overload;
- // NativeLargeint. Stored as a float64, Read as float64.
- function WriteData(const Buffer: NativeLargeInt): NativeInt; overload;
- function WriteData(const Buffer: NativeLargeInt; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: NativeLargeUInt): NativeInt; overload;
- function WriteData(const Buffer: NativeLargeUInt; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: Double): NativeInt; overload;
- function WriteData(const Buffer: Double; Count: NativeInt): NativeInt; overload;
- {$IFDEF FPC_HAS_TYPE_EXTENDED}
- function WriteData(const Buffer: Extended): NativeInt; overload;
- function WriteData(const Buffer: Extended; Count: NativeInt): NativeInt; overload;
- function WriteData(const Buffer: TExtended80Rec): NativeInt; overload;
- function WriteData(const Buffer: TExtended80Rec; Count: NativeInt): NativeInt; overload;
- {$ENDIF}
- procedure WriteBufferData(Buffer: Int32); overload;
- procedure WriteBufferData(Buffer: Int32; Count: NativeInt); overload;
- procedure WriteBufferData(Buffer: Boolean); overload;
- procedure WriteBufferData(Buffer: Boolean; Count: NativeInt); overload;
- procedure WriteBufferData(Buffer: WideChar); overload;
- procedure WriteBufferData(Buffer: WideChar; Count: NativeInt); overload;
- procedure WriteBufferData(Buffer: Int8); overload;
- procedure WriteBufferData(Buffer: Int8; Count: NativeInt); overload;
- procedure WriteBufferData(Buffer: UInt8); overload;
- procedure WriteBufferData(Buffer: UInt8; Count: NativeInt); overload;
- procedure WriteBufferData(Buffer: Int16); overload;
- procedure WriteBufferData(Buffer: Int16; Count: NativeInt); overload;
- procedure WriteBufferData(Buffer: UInt16); overload;
- procedure WriteBufferData(Buffer: UInt16; Count: NativeInt); overload;
- procedure WriteBufferData(Buffer: UInt32); overload;
- procedure WriteBufferData(Buffer: UInt32; Count: NativeInt); overload;
- // NativeLargeint. Stored as a float64, Read as float64.
- procedure WriteBufferData(Buffer: NativeLargeInt); overload;
- procedure WriteBufferData(Buffer: NativeLargeInt; Count: NativeInt); overload;
- procedure WriteBufferData(Buffer: NativeLargeUInt); overload;
- procedure WriteBufferData(Buffer: NativeLargeUInt; Count: NativeInt); overload;
- procedure WriteBufferData(Buffer: Double); overload;
- procedure WriteBufferData(Buffer: Double; Count: NativeInt); overload;
- function CopyFrom(Source: TStream; Count: NativeInt): NativeInt;
- function ReadComponent(Instance: TComponent): TComponent;
- function ReadComponentRes(Instance: TComponent): TComponent;
- procedure WriteComponent(Instance: TComponent);
- procedure WriteComponentRes(const ResName: string; Instance: TComponent);
- procedure WriteDescendent(Instance, Ancestor: TComponent);
- procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
- procedure WriteResourceHeader(const ResName: string; {!!!:out} var FixupInfo: Longint);
- procedure FixupResourceHeader(FixupInfo: Longint);
- procedure ReadResHeader;
- function ReadByte : Byte;
- function ReadWord : Word;
- function ReadDWord : Cardinal;
- function ReadQWord : NativeLargeUInt;
- procedure WriteByte(b : Byte);
- procedure WriteWord(w : Word);
- procedure WriteDWord(d : Cardinal);
- procedure WriteQWord(q : NativeLargeUInt);
- property Position: NativeInt read GetPosition write SetPosition;
- property Size: NativeInt read GetSize write SetSize64;
- Property Endian: TEndian Read FEndian Write FEndian;
- end;
- { TCustomMemoryStream abstract class }
- TCustomMemoryStream = class(TStream)
- private
- FMemory: TJSArrayBuffer;
- FDataView : TJSDataView;
- FDataArray : TJSUint8Array;
- FSize, FPosition: PtrInt;
- FSizeBoundsSeek : Boolean;
- function GetDataArray: TJSUint8Array;
- function GetDataView: TJSDataview;
- protected
- Function GetSize : NativeInt; Override;
- function GetPosition: NativeInt; Override;
- procedure SetPointer(Ptr: TJSArrayBuffer; ASize: PtrInt);
- Property DataView : TJSDataview Read GetDataView;
- Property DataArray : TJSUint8Array Read GetDataArray;
- public
- Class Function MemoryToBytes(Mem : TJSArrayBuffer) : TBytes; overload;
- Class Function MemoryToBytes(Mem : TJSUint8Array) : TBytes; overload;
- Class Function BytesToMemory(aBytes : TBytes) : TJSArrayBuffer;
- function Read(Buffer : TBytes; Offset, Count: LongInt): LongInt; override;
- function Seek(const Offset: NativeInt; Origin: TSeekOrigin): NativeInt; override;
- procedure SaveToStream(Stream: TStream);
- Procedure LoadFromURL(Const aURL : String; Async : Boolean = True; OnLoaded : TNotifyEventRef = Nil; OnError: TStringNotifyEventRef = Nil); virtual;
- // Delphi compatibility. Must be an URL
- Procedure LoadFromFile(Const aFileName : String; const OnLoaded : TProc = Nil; const AError: TProcString = Nil);
- property Memory: TJSArrayBuffer read FMemory;
- Property SizeBoundsSeek : Boolean Read FSizeBoundsSeek Write FSizeBoundsSeek;
- end;
- { TMemoryStream }
- TMemoryStream = class(TCustomMemoryStream)
- private
- FCapacity: PtrInt;
- procedure SetCapacity(NewCapacity: PtrInt);
- protected
- function Realloc(var NewCapacity: PtrInt): TJSArrayBuffer; virtual;
- property Capacity: PtrInt read FCapacity write SetCapacity;
- public
- destructor Destroy; override;
- procedure Clear;
- procedure LoadFromStream(Stream: TStream);
- procedure SetSize(const NewSize: NativeInt); override;
- function Write(const Buffer: TBytes; Offset, Count: LongInt): LongInt; override;
- end;
- { TBytesStream }
- TBytesStream = class(TMemoryStream)
- private
- function GetBytes: TBytes;
- public
- constructor Create(const ABytes: TBytes); virtual; overload;
- property Bytes: TBytes read GetBytes;
- end;
- { TStringStream }
- TStringStream = class(TMemoryStream)
- private
- function GetDataString : String;
- public
- constructor Create; reintroduce; overload;
- constructor Create(const aString: String); virtual; overload;
- function ReadString(Count: Integer): string;
- procedure WriteString(const AString: string);
- property DataString: String read GetDataString;
- end;
- TFilerFlag = (ffInherited, ffChildPos, ffInline);
- TFilerFlags = set of TFilerFlag;
- TReaderProc = procedure(Reader: TReader) of object;
- TWriterProc = procedure(Writer: TWriter) of object;
- TStreamProc = procedure(Stream: TStream) of object;
- TFiler = class(TObject)
- private
- FRoot: TComponent;
- FLookupRoot: TComponent;
- FAncestor: TPersistent;
- FIgnoreChildren: Boolean;
- protected
- procedure SetRoot(ARoot: TComponent); virtual;
- public
- procedure DefineProperty(const Name: string;
- ReadData: TReaderProc; WriteData: TWriterProc;
- HasData: Boolean); virtual; abstract;
- procedure DefineBinaryProperty(const Name: string;
- ReadData, WriteData: TStreamProc;
- HasData: Boolean); virtual; abstract;
- Procedure FlushBuffer; virtual; abstract;
- property Root: TComponent read FRoot write SetRoot;
- property LookupRoot: TComponent read FLookupRoot;
- property Ancestor: TPersistent read FAncestor write FAncestor;
- property IgnoreChildren: Boolean read FIgnoreChildren write FIgnoreChildren;
- end;
- TValueType = (
- vaNull, vaList, vaInt8, vaInt16, vaInt32, vaDouble,
- vaString, vaIdent, vaFalse, vaTrue, vaBinary, vaSet,
- vaNil, vaCollection, vaCurrency, vaDate, vaNativeInt
- );
- { TAbstractObjectReader }
- TAbstractObjectReader = class
- public
- Procedure FlushBuffer; virtual;
- function NextValue: TValueType; virtual; abstract;
- function ReadValue: TValueType; virtual; abstract;
- procedure BeginRootComponent; virtual; abstract;
- procedure BeginComponent(var Flags: TFilerFlags; var AChildPos: Integer;
- var CompClassName, CompName: String); virtual; abstract;
- function BeginProperty: String; virtual; abstract;
- //Please don't use read, better use ReadBinary whenever possible
- procedure Read(var Buffer : TBytes; Count: Longint); virtual;abstract;
- { All ReadXXX methods are called _after_ the value type has been read! }
- procedure ReadBinary(const DestData: TMemoryStream); virtual; abstract;
- function ReadFloat: Extended; virtual; abstract;
- function ReadCurrency: Currency; virtual; abstract;
- function ReadIdent(ValueType: TValueType): String; virtual; abstract;
- function ReadInt8: ShortInt; virtual; abstract;
- function ReadInt16: SmallInt; virtual; abstract;
- function ReadInt32: LongInt; virtual; abstract;
- function ReadNativeInt: NativeInt; virtual; abstract;
- function ReadSet(EnumType: TTypeInfoEnum): Integer; virtual; abstract;
- procedure ReadSignature; virtual; abstract;
- function ReadStr: String; virtual; abstract;
- function ReadString(StringType: TValueType): String; virtual; abstract;
- function ReadWideString: WideString;virtual;abstract;
- function ReadUnicodeString: UnicodeString;virtual;abstract;
- procedure SkipComponent(SkipComponentInfos: Boolean); virtual; abstract;
- procedure SkipValue; virtual; abstract;
- end;
- { TBinaryObjectReader }
- TBinaryObjectReader = class(TAbstractObjectReader)
- protected
- FStream: TStream;
- function ReadWord : word;
- function ReadDWord : longword;
- procedure SkipProperty;
- procedure SkipSetBody;
- public
- constructor Create(Stream: TStream);
- function NextValue: TValueType; override;
- function ReadValue: TValueType; override;
- procedure BeginRootComponent; override;
- procedure BeginComponent(var Flags: TFilerFlags; var AChildPos: Integer;
- var CompClassName, CompName: String); override;
- function BeginProperty: String; override;
- //Please don't use read, better use ReadBinary whenever possible
- procedure Read(var Buffer : TBytes; Count: Longint); override;
- procedure ReadBinary(const DestData: TMemoryStream); override;
- function ReadFloat: Extended; override;
- function ReadCurrency: Currency; override;
- function ReadIdent(ValueType: TValueType): String; override;
- function ReadInt8: ShortInt; override;
- function ReadInt16: SmallInt; override;
- function ReadInt32: LongInt; override;
- function ReadNativeInt: NativeInt; override;
- function ReadSet(EnumType: TTypeInfoEnum): Integer; override;
- procedure ReadSignature; override;
- function ReadStr: String; override;
- function ReadString(StringType: TValueType): String; override;
- function ReadWideString: WideString;override;
- function ReadUnicodeString: UnicodeString;override;
- procedure SkipComponent(SkipComponentInfos: Boolean); override;
- procedure SkipValue; override;
- end;
- TFindMethodEvent = procedure(Reader: TReader; const MethodName: string; var Address: CodePointer; var Error: Boolean) of object;
- TSetNameEvent = procedure(Reader: TReader; Component: TComponent; var Name: string) of object;
- TReferenceNameEvent = procedure(Reader: TReader; var Name: string) of object;
- TAncestorNotFoundEvent = procedure(Reader: TReader; const ComponentName: string; ComponentClass: TPersistentClass; var Component: TComponent) of object;
- TReadComponentsProc = procedure(Component: TComponent) of object;
- TReaderError = procedure(Reader: TReader; const Message: string; var Handled: Boolean) of object;
- TPropertyNotFoundEvent = procedure(Reader: TReader; Instance: TPersistent; var PropName: string; IsPath: boolean; var Handled, Skip: Boolean) of object;
- TFindComponentClassEvent = procedure(Reader: TReader; const ClassName: string; var ComponentClass: TComponentClass) of object;
- TCreateComponentEvent = procedure(Reader: TReader; ComponentClass: TComponentClass; var Component: TComponent) of object;
- TSetMethodPropertyEvent = procedure(Reader: TReader; Instance: TPersistent; PropInfo: TTypeMemberProperty; const TheMethodName: string;
- var Handled: boolean) of object;
- TReadWriteStringPropertyEvent = procedure(Sender:TObject; const Instance: TPersistent; PropInfo: TTypeMemberProperty; var Content:string) of object;
- { TReader }
- TReader = class(TFiler)
- private
- FDriver: TAbstractObjectReader;
- FOwner: TComponent;
- FParent: TComponent;
- FFixups: TObject;
- FLoaded: TFpList;
- FOnFindMethod: TFindMethodEvent;
- FOnSetMethodProperty: TSetMethodPropertyEvent;
- FOnSetName: TSetNameEvent;
- FOnReferenceName: TReferenceNameEvent;
- FOnAncestorNotFound: TAncestorNotFoundEvent;
- FOnError: TReaderError;
- FOnPropertyNotFound: TPropertyNotFoundEvent;
- FOnFindComponentClass: TFindComponentClassEvent;
- FOnCreateComponent: TCreateComponentEvent;
- FPropName: string;
- FCanHandleExcepts: Boolean;
- FOnReadStringProperty:TReadWriteStringPropertyEvent;
- procedure DoFixupReferences;
- function FindComponentClass(const AClassName: string): TComponentClass;
- protected
- function Error(const Message: string): Boolean; virtual;
- function FindMethod(ARoot: TComponent; const AMethodName: string): CodePointer; virtual;
- procedure ReadProperty(AInstance: TPersistent);
- procedure ReadPropValue(Instance: TPersistent; PropInfo: TTypeMemberProperty);
- procedure PropertyError;
- procedure ReadData(Instance: TComponent);
- property PropName: string read FPropName;
- property CanHandleExceptions: Boolean read FCanHandleExcepts;
- function CreateDriver(Stream: TStream): TAbstractObjectReader; virtual;
- public
- constructor Create(Stream: TStream);
- destructor Destroy; override;
- Procedure FlushBuffer; override;
- procedure BeginReferences;
- procedure CheckValue(Value: TValueType);
- procedure DefineProperty(const Name: string;
- AReadData: TReaderProc; WriteData: TWriterProc;
- HasData: Boolean); override;
- procedure DefineBinaryProperty(const Name: string;
- AReadData, WriteData: TStreamProc;
- HasData: Boolean); override;
- function EndOfList: Boolean;
- procedure EndReferences;
- procedure FixupReferences;
- function NextValue: TValueType;
- //Please don't use read, better use ReadBinary whenever possible
- //uuups, ReadBinary is protected ..
- procedure Read(var Buffer : TBytes; Count: LongInt); virtual;
- function ReadBoolean: Boolean;
- function ReadChar: Char;
- function ReadWideChar: WideChar;
- function ReadUnicodeChar: UnicodeChar;
- procedure ReadCollection(Collection: TCollection);
- function ReadComponent(Component: TComponent): TComponent;
- procedure ReadComponents(AOwner, AParent: TComponent;
- Proc: TReadComponentsProc);
- function ReadFloat: Extended;
- function ReadCurrency: Currency;
- function ReadIdent: string;
- function ReadInteger: Longint;
- function ReadNativeInt: NativeInt;
- function ReadSet(EnumType: Pointer): Integer;
- procedure ReadListBegin;
- procedure ReadListEnd;
- function ReadRootComponent(ARoot: TComponent): TComponent;
- function ReadVariant: JSValue;
- procedure ReadSignature;
- function ReadString: string;
- function ReadWideString: WideString;
- function ReadUnicodeString: UnicodeString;
- function ReadValue: TValueType;
- procedure CopyValue(Writer: TWriter);
- property Driver: TAbstractObjectReader read FDriver;
- property Owner: TComponent read FOwner write FOwner;
- property Parent: TComponent read FParent write FParent;
- property OnError: TReaderError read FOnError write FOnError;
- property OnPropertyNotFound: TPropertyNotFoundEvent read FOnPropertyNotFound write FOnPropertyNotFound;
- property OnFindMethod: TFindMethodEvent read FOnFindMethod write FOnFindMethod;
- property OnSetMethodProperty: TSetMethodPropertyEvent read FOnSetMethodProperty write FOnSetMethodProperty;
- property OnSetName: TSetNameEvent read FOnSetName write FOnSetName;
- property OnReferenceName: TReferenceNameEvent read FOnReferenceName write FOnReferenceName;
- property OnAncestorNotFound: TAncestorNotFoundEvent read FOnAncestorNotFound write FOnAncestorNotFound;
- property OnCreateComponent: TCreateComponentEvent read FOnCreateComponent write FOnCreateComponent;
- property OnFindComponentClass: TFindComponentClassEvent read FOnFindComponentClass write FOnFindComponentClass;
- property OnReadStringProperty: TReadWriteStringPropertyEvent read FOnReadStringProperty write FOnReadStringProperty;
- end;
- { TAbstractObjectWriter }
- TAbstractObjectWriter = class
- public
- { Begin/End markers. Those ones who don't have an end indicator, use
- "EndList", after the occurrence named in the comment. Note that this
- only counts for "EndList" calls on the same level; each BeginXXX call
- increases the current level. }
- procedure BeginCollection; virtual; abstract; { Ends with the next "EndList" }
- procedure BeginComponent(Component: TComponent; Flags: TFilerFlags;
- ChildPos: Integer); virtual; abstract; { Ends after the second "EndList" }
- procedure WriteSignature; virtual; abstract;
- procedure BeginList; virtual; abstract;
- procedure EndList; virtual; abstract;
- procedure BeginProperty(const PropName: String); virtual; abstract;
- procedure EndProperty; virtual; abstract;
- //Please don't use write, better use WriteBinary whenever possible
- procedure Write(const Buffer : TBytes; Count: Longint); virtual;abstract;
- Procedure FlushBuffer; virtual; abstract;
- procedure WriteBinary(const Buffer : TBytes; Count: Longint); virtual; abstract;
- procedure WriteBoolean(Value: Boolean); virtual; abstract;
- // procedure WriteChar(Value: Char);
- procedure WriteFloat(const Value: Extended); virtual; abstract;
- procedure WriteCurrency(const Value: Currency); virtual; abstract;
- procedure WriteIdent(const Ident: string); virtual; abstract;
- procedure WriteInteger(Value: NativeInt); virtual; abstract;
- procedure WriteNativeInt(Value: NativeInt); virtual; abstract;
- procedure WriteVariant(const Value: JSValue); virtual; abstract;
- procedure WriteMethodName(const Name: String); virtual; abstract;
- procedure WriteSet(Value: LongInt; SetType: Pointer); virtual; abstract;
- procedure WriteString(const Value: String); virtual; abstract;
- procedure WriteWideString(const Value: WideString);virtual;abstract;
- procedure WriteUnicodeString(const Value: UnicodeString);virtual;abstract;
- end;
- { TBinaryObjectWriter }
- TBinaryObjectWriter = class(TAbstractObjectWriter)
- protected
- FStream: TStream;
- FBuffer: Pointer;
- FBufSize: Integer;
- FBufPos: Integer;
- FBufEnd: Integer;
- procedure WriteWord(w : word);
- procedure WriteDWord(lw : longword);
- procedure WriteValue(Value: TValueType);
- public
- constructor Create(Stream: TStream);
- procedure WriteSignature; override;
- procedure BeginCollection; override;
- procedure BeginComponent(Component: TComponent; Flags: TFilerFlags;
- ChildPos: Integer); override;
- procedure BeginList; override;
- procedure EndList; override;
- procedure BeginProperty(const PropName: String); override;
- procedure EndProperty; override;
- Procedure FlushBuffer; override;
- //Please don't use write, better use WriteBinary whenever possible
- procedure Write(const Buffer : TBytes; Count: Longint); override;
- procedure WriteBinary(const Buffer : TBytes; Count: LongInt); override;
- procedure WriteBoolean(Value: Boolean); override;
- procedure WriteFloat(const Value: Extended); override;
- procedure WriteCurrency(const Value: Currency); override;
- procedure WriteIdent(const Ident: string); override;
- procedure WriteInteger(Value: NativeInt); override;
- procedure WriteNativeInt(Value: NativeInt); override;
- procedure WriteMethodName(const Name: String); override;
- procedure WriteSet(Value: LongInt; SetType: Pointer); override;
- procedure WriteStr(const Value: String);
- procedure WriteString(const Value: String); override;
- procedure WriteWideString(const Value: WideString); override;
- procedure WriteUnicodeString(const Value: UnicodeString); override;
- procedure WriteVariant(const VarValue: JSValue);override;
- end;
- TFindAncestorEvent = procedure (Writer: TWriter; Component: TComponent;
- const Name: string; var Ancestor, RootAncestor: TComponent) of object;
- TWriteMethodPropertyEvent = procedure (Writer: TWriter; Instance: TPersistent;
- PropInfo: TTypeMemberProperty;
- const MethodValue, DefMethodValue: TMethod;
- var Handled: boolean) of object;
- { TWriter }
- TWriter = class(TFiler)
- private
- FDriver: TAbstractObjectWriter;
- FDestroyDriver: Boolean;
- FRootAncestor: TComponent;
- FPropPath: String;
- FAncestors: TStringList;
- FAncestorPos: Integer;
- FCurrentPos: Integer;
- FOnFindAncestor: TFindAncestorEvent;
- FOnWriteMethodProperty: TWriteMethodPropertyEvent;
- FOnWriteStringProperty:TReadWriteStringPropertyEvent;
- procedure AddToAncestorList(Component: TComponent);
- procedure WriteComponentData(Instance: TComponent);
- Procedure DetermineAncestor(Component: TComponent);
- procedure DoFindAncestor(Component : TComponent);
- protected
- procedure SetRoot(ARoot: TComponent); override;
- procedure WriteBinary(AWriteData: TStreamProc);
- procedure WriteProperty(Instance: TPersistent; PropInfo: TTypeMemberProperty);
- procedure WriteProperties(Instance: TPersistent);
- procedure WriteChildren(Component: TComponent);
- function CreateDriver(Stream: TStream): TAbstractObjectWriter; virtual;
- public
- constructor Create(ADriver: TAbstractObjectWriter);
- constructor Create(Stream: TStream);
- destructor Destroy; override;
- procedure DefineProperty(const Name: string;
- ReadData: TReaderProc; AWriteData: TWriterProc;
- HasData: Boolean); override;
- procedure DefineBinaryProperty(const Name: string;
- ReadData, AWriteData: TStreamProc;
- HasData: Boolean); override;
- Procedure FlushBuffer; override;
- procedure Write(const Buffer : TBytes; Count: Longint); virtual;
- procedure WriteBoolean(Value: Boolean);
- procedure WriteCollection(Value: TCollection);
- procedure WriteComponent(Component: TComponent);
- procedure WriteChar(Value: Char);
- procedure WriteWideChar(Value: WideChar);
- procedure WriteDescendent(ARoot: TComponent; AAncestor: TComponent);
- procedure WriteFloat(const Value: Extended);
- procedure WriteCurrency(const Value: Currency);
- procedure WriteIdent(const Ident: string);
- procedure WriteInteger(Value: Longint); overload;
- procedure WriteInteger(Value: NativeInt); overload;
- procedure WriteSet(Value: LongInt; SetType: Pointer);
- procedure WriteListBegin;
- procedure WriteListEnd;
- Procedure WriteSignature;
- procedure WriteRootComponent(ARoot: TComponent);
- procedure WriteString(const Value: string);
- procedure WriteWideString(const Value: WideString);
- procedure WriteUnicodeString(const Value: UnicodeString);
- procedure WriteVariant(const VarValue: JSValue);
- property RootAncestor: TComponent read FRootAncestor write FRootAncestor;
- property OnFindAncestor: TFindAncestorEvent read FOnFindAncestor write FOnFindAncestor;
- property OnWriteMethodProperty: TWriteMethodPropertyEvent read FOnWriteMethodProperty write FOnWriteMethodProperty;
- property OnWriteStringProperty: TReadWriteStringPropertyEvent read FOnWriteStringProperty write FOnWriteStringProperty;
- property Driver: TAbstractObjectWriter read FDriver;
- property PropertyPath: string read FPropPath;
- end;
- TParserToken = (toUnknown, // everything else
- toEOF, // EOF
- toSymbol, // Symbol (identifier)
- toString, // ''string''
- toInteger, // 123
- toFloat, // 12.3
- toMinus, // -
- toSetStart, // [
- toListStart, // (
- toCollectionStart, // <
- toBinaryStart, // {
- toSetEnd, // ]
- toListEnd, // )
- toCollectionEnd, // >
- toBinaryEnd, // }
- toComma, // ,
- toDot, // .
- toEqual, // =
- toColon, // :
- toPlus // +
- );
- TParser = class(TObject)
- private
- fStream : TStream;
- fBuf : Array of Char;
- FBufLen : integer;
- fPos : integer;
- fDeltaPos : integer;
- fFloatType : char;
- fSourceLine : integer;
- fToken : TParserToken;
- fEofReached : boolean;
- fLastTokenStr : string;
- function GetTokenName(aTok : TParserToken) : string;
- procedure LoadBuffer;
- procedure CheckLoadBuffer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- procedure ProcessChar; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- function IsNumber : boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- function IsHexNum : boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- function IsAlpha : boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- function IsAlphaNum : boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- function GetHexValue(c : char) : byte; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- function GetAlphaNum : string;
- procedure HandleNewLine;
- procedure SkipBOM;
- procedure SkipSpaces;
- procedure SkipWhitespace;
- procedure HandleEof;
- procedure HandleAlphaNum;
- procedure HandleNumber;
- procedure HandleHexNumber;
- function HandleQuotedString : string;
- Function HandleDecimalCharacter: char;
- procedure HandleString;
- procedure HandleMinus;
- procedure HandleUnknown;
- procedure GotoToNextChar;
- public
- // Input stream is expected to be UTF16 !
- constructor Create(Stream: TStream);
- destructor Destroy; override;
- procedure CheckToken(T: TParserToken);
- procedure CheckTokenSymbol(const S: string);
- procedure Error(const Ident: string);
- procedure ErrorFmt(const Ident: string; const Args: array of const);
- procedure ErrorStr(const Message: string);
- procedure HexToBinary(Stream: TStream);
- function NextToken: TParserToken;
- function SourcePos: Longint;
- function TokenComponentIdent: string;
- function TokenFloat: Double;
- function TokenInt: NativeInt;
- function TokenString: string;
- function TokenSymbolIs(const S: string): Boolean;
- property FloatType: Char read fFloatType;
- property SourceLine: Integer read fSourceLine;
- property Token: TParserToken read fToken;
- end;
- { TObjectStreamConverter }
- TObjectTextEncoding = (oteDFM,oteLFM);
- TObjectStreamConverter = Class
- private
- FIndent: String;
- FInput : TStream;
- FOutput : TStream;
- FEncoding : TObjectTextEncoding;
- Private
- // Low level writing
- procedure OutLn(s: String); virtual;
- procedure OutStr(s: String); virtual;
- procedure OutString(s: String); virtual;
- // Low level reading
- function ReadWord: word;
- function ReadDWord: longword;
- function ReadDouble: Double;
- function ReadInt(ValueType: TValueType): NativeInt;
- function ReadInt: NativeInt;
- function ReadNativeInt: NativeInt;
- function ReadStr: String;
- function ReadString(StringType: TValueType): String; virtual;
- // High-level
- procedure ProcessBinary; virtual;
- procedure ProcessValue(ValueType: TValueType; Indent: String); virtual;
- procedure ReadObject(indent: String); virtual;
- procedure ReadPropList(indent: String); virtual;
- Public
- procedure ObjectBinaryToText(aInput, aOutput: TStream);
- procedure ObjectBinaryToText(aInput, aOutput: TStream; aEncoding: TObjectTextEncoding);
- Procedure Execute;
- Property Input : TStream Read FInput Write FInput;
- Property Output : TStream Read Foutput Write FOutput;
- Property Encoding : TObjectTextEncoding Read FEncoding Write FEncoding;
- Property Indent : String Read FIndent Write Findent;
- end;
- { TObjectTextConverter }
- TObjectTextConverter = Class
- private
- FParser: TParser;
- private
- FInput: TStream;
- Foutput: TStream;
- procedure WriteDouble(e: double);
- procedure WriteDWord(lw: longword);
- procedure WriteInteger(value: nativeInt);
- //procedure WriteLString(const s: String);
- procedure WriteQWord(q: nativeint);
- procedure WriteString(s: String);
- procedure WriteWord(w: word);
- procedure WriteWString(const s: WideString);
- procedure ProcessObject; virtual;
- procedure ProcessProperty; virtual;
- procedure ProcessValue; virtual;
- procedure ProcessWideString(const left: string);
- Property Parser : TParser Read FParser;
- Public
- // Input stream must be UTF16 !
- procedure ObjectTextToBinary(aInput, aOutput: TStream);
- Procedure Execute; virtual;
- Property Input : TStream Read FInput Write FInput;
- Property Output: TStream Read Foutput Write Foutput;
- end;
- TLoadHelper = Class (TObject)
- Public
- Type
- TTextLoadedCallBack = reference to procedure (const aText : String);
- TBytesLoadedCallBack = reference to procedure (const aBuffer : TJSArrayBuffer);
- TErrorCallBack = reference to procedure (const aError : String);
- Class Procedure LoadText(aURL : String; aSync : Boolean; OnLoaded : TTextLoadedCallBack; OnError : TErrorCallBack); virtual; abstract;
- Class Procedure LoadBytes(aURL : String; aSync : Boolean; OnLoaded : TBytesLoadedCallBack; OnError : TErrorCallBack); virtual; abstract;
- end;
- TLoadHelperClass = Class of TLoadHelper;
- type
- TIdentMapEntry = record
- Value: Integer;
- Name: String;
- end;
- TIdentToInt = function(const Ident: string; var Int: Longint): Boolean;
- TIntToIdent = function(Int: Longint; var Ident: string): Boolean;
- TFindGlobalComponent = function(const Name: string): TComponent;
- TInitComponentHandler = function(Instance: TComponent; RootAncestor : TClass): boolean;
- procedure RegisterInitComponentHandler(ComponentClass: TComponentClass; Handler: TInitComponentHandler);
- Procedure RegisterClass(AClass : TPersistentClass);
- Procedure RegisterClasses(AClasses : specialize TArray<TPersistentClass>);
- Function GetClass(AClassName : string) : TPersistentClass;
- procedure RegisterFindGlobalComponentProc(AFindGlobalComponent: TFindGlobalComponent);
- procedure UnregisterFindGlobalComponentProc(AFindGlobalComponent: TFindGlobalComponent);
- function FindGlobalComponent(const Name: string): TComponent;
- Function FindNestedComponent(Root : TComponent; APath : String; CStyle : Boolean = True) : TComponent;
- procedure RedirectFixupReferences(Root: TComponent; const OldRootName, NewRootName: string);
- procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
- procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToIntFn: TIdentToInt; IntToIdentFn: TIntToIdent);
- function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: String; Strings: TStrings; AddEmptyStrings : Boolean = False): Integer;
- function IdentToInt(const Ident: string; out Int: Longint; const Map: array of TIdentMapEntry): Boolean;
- function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean;
- function FindIntToIdent(AIntegerType: Pointer): TIntToIdent;
- function FindIdentToInt(AIntegerType: Pointer): TIdentToInt;
- function FindClass(const AClassName: string): TPersistentClass;
- function CollectionsEqual(C1, C2: TCollection): Boolean;
- function CollectionsEqual(C1, C2: TCollection; Owner1, Owner2: TComponent): Boolean;
- procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
- procedure GetFixupInstanceNames(Root: TComponent; const ReferenceRootName: string; Names: TStrings);
- procedure ObjectBinaryToText(aInput, aOutput: TStream);
- procedure ObjectBinaryToText(aInput, aOutput: TStream; aEncoding: TObjectTextEncoding);
- procedure ObjectTextToBinary(aInput, aOutput: TStream);
- Function SetLoadHelperClass(aClass : TLoadHelperClass) : TLoadHelperClass;
- // Create buffer from string. aLen in bytes, not in characters
- Function StringToBuffer(aString : String; aLen : Integer) : TJSArrayBuffer;
- // Create buffer from string. aPos,aLen are in bytes, not in characters.
- Function BufferToString(aBuffer : TJSArrayBuffer; aPos,aLen : Integer) : String;
- Const
- // Some aliases
- vaSingle = vaDouble;
- vaExtended = vaDouble;
- vaLString = vaString;
- vaUTF8String = vaString;
- vaUString = vaString;
- vaWString = vaString;
- vaQWord = vaNativeInt;
- vaInt64 = vaNativeInt;
- toWString = toString;
- implementation
- uses simplelinkedlist;
- var
- GlobalLoaded,
- IntConstList: TFPList;
- GlobalLoadHelper : TLoadHelperClass;
- Function SetLoadHelperClass(aClass : TLoadHelperClass) : TLoadHelperClass;
- begin
- Result:=GlobalLoadHelper;
- GlobalLoadHelper:=aClass;
- end;
- Procedure CheckLoadHelper;
- begin
- If (GlobalLoadHelper=Nil) then
- Raise EInOutError.Create('No support for loading URLS. Include Rtl.BrowserLoadHelper in your project uses clause');
- end;
- Function StringToBuffer(aString : String; aLen : Integer) : TJSArrayBuffer;
- var
- I : Integer;
- begin
- Result:=TJSArrayBuffer.new(aLen*2);// 2 bytes for each char
- With TJSUint16Array.new(Result) do
- for i:=0 to aLen-1 do
- values[i] := TJSString(aString).charCodeAt(i);
- end;
- function BufferToString(aBuffer: TJSArrayBuffer; aPos, aLen: Integer): String;
- var
- a : TJSUint16Array;
- begin
- Result:=''; // Silence warning
- a:=TJSUint16Array.New(aBuffer.slice(aPos,aLen));
- if a<>nil then
- Result:=String(TJSFunction(@TJSString.fromCharCode).apply(nil,TJSValueDynArray(JSValue(a))));
- end;
- type
- TIntConst = class
- Private
- IntegerType: PTypeInfo; // The integer type RTTI pointer
- IdentToIntFn: TIdentToInt; // Identifier to Integer conversion
- IntToIdentFn: TIntToIdent; // Integer to Identifier conversion
- Public
- constructor Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
- AIntToIdent: TIntToIdent);
- end;
- { TStringStream }
- function TStringStream.GetDataString: String;
- var
- a : TJSUint16Array;
- begin
- Result:=''; // Silence warning
- a:=TJSUint16Array.New(Memory.slice(0,Size));
- if a<>nil then
- asm
- // Result=String.fromCharCode.apply(null, new Uint16Array(a));
- Result=String.fromCharCode.apply(null, a);
- end;
- end;
- constructor TStringStream.Create;
- begin
- Create('');
- end;
- constructor TStringStream.Create(const aString: String);
- var
- Len : Integer;
- begin
- inherited Create;
- Len:=Length(aString);
- SetPointer(StringToBuffer(aString,Len),Len*2);
- FCapacity:=Len*2;
- end;
- function TStringStream.ReadString(Count: Integer): string;
- Var
- B : TBytes;
- Buf : TJSArrayBuffer;
- BytesLeft : Integer;
- begin
- // Top off
- BytesLeft:=(Size-Position);
- if BytesLeft<Count then
- Count:=BytesLeft;
- SetLength(B,Count);
- ReadBuffer(B,0,Count);
- Buf:=BytesToMemory(B);
- Result:=BufferToString(Buf,0,Count);
- end;
- procedure TStringStream.WriteString(const AString: string);
- Var
- Buf : TJSArrayBuffer;
- B : TBytes;
- begin
- Buf:=StringToBuffer(aString,Length(aString));
- B:=MemoryToBytes(Buf);
- WriteBuffer(B,Length(B));
- end;
- constructor TIntConst.Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
- AIntToIdent: TIntToIdent);
- begin
- IntegerType := AIntegerType;
- IdentToIntFn := AIdentToInt;
- IntToIdentFn := AIntToIdent;
- end;
- procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToIntFn: TIdentToInt;
- IntToIdentFn: TIntToIdent);
- begin
- if Not Assigned(IntConstList) then
- IntConstList:=TFPList.Create;
- IntConstList.Add(TIntConst.Create(IntegerType, IdentToIntFn, IntToIdentFn));
- end;
- function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: String; Strings: TStrings; AddEmptyStrings : Boolean = False): Integer;
- var
- b,c : integer;
- procedure SkipWhitespace;
- begin
- while (Content[c] in Whitespace) do
- inc (C);
- end;
- procedure AddString;
- var
- l : integer;
- begin
- l := c-b;
- if (l > 0) or AddEmptyStrings then
- begin
- if assigned(Strings) then
- begin
- if l>0 then
- Strings.Add (Copy(Content,B,L))
- else
- Strings.Add('');
- end;
- inc (result);
- end;
- end;
- var
- cc,quoted : char;
- aLen : Integer;
- begin
- result := 0;
- c := 1;
- Quoted := #0;
- Separators := Separators + [#13, #10] - ['''','"'];
- SkipWhitespace;
- b := c;
- aLen:=Length(Content);
- while C<=aLen do
- begin
- CC:=Content[c];
- if (CC = Quoted) then
- begin
- if (C<aLen) and (Content[C+1] = Quoted) then
- inc (c)
- else
- Quoted := #0
- end
- else if (Quoted = #0) and (CC in ['''','"']) then
- Quoted := CC;
- if (Quoted = #0) and (CC in Separators) then
- begin
- AddString;
- inc (c);
- SkipWhitespace;
- b := c;
- end
- else
- inc (c);
- end;
- if (c <> b) then
- AddString;
- end;
- function FindIntToIdent(AIntegerType: Pointer): TIntToIdent;
- var
- i: Integer;
- begin
- Result := nil;
- if Not Assigned(IntConstList) then
- exit;
- with IntConstList do
- for i := 0 to Count - 1 do
- if TIntConst(Items[i]).IntegerType = AIntegerType then
- exit(TIntConst(Items[i]).IntToIdentFn);
- end;
- function FindIdentToInt(AIntegerType: Pointer): TIdentToInt;
- var
- i: Integer;
- begin
- Result := nil;
- if Not Assigned(IntConstList) then
- exit;
- with IntConstList do
- for i := 0 to Count - 1 do
- with TIntConst(Items[I]) do
- if TIntConst(Items[I]).IntegerType = AIntegerType then
- exit(IdentToIntFn);
- end;
- function IdentToInt(const Ident: String; out Int: LongInt;
- const Map: array of TIdentMapEntry): Boolean;
- var
- i: Integer;
- begin
- for i := Low(Map) to High(Map) do
- if CompareText(Map[i].Name, Ident) = 0 then
- begin
- Int := Map[i].Value;
- exit(True);
- end;
- Result := False;
- end;
- function IntToIdent(Int: LongInt; var Ident: String;
- const Map: array of TIdentMapEntry): Boolean;
- var
- i: Integer;
- begin
- for i := Low(Map) to High(Map) do
- if Map[i].Value = Int then
- begin
- Ident := Map[i].Name;
- exit(True);
- end;
- Result := False;
- end;
- function GlobalIdentToInt(const Ident: String; var Int: LongInt):boolean;
- var
- i : Integer;
- begin
- Result := false;
- if Not Assigned(IntConstList) then
- exit;
- with IntConstList do
- for i := 0 to Count - 1 do
- if TIntConst(Items[I]).IdentToIntFn(Ident, Int) then
- Exit(True);
- end;
- function FindClass(const AClassName: string): TPersistentClass;
- begin
- Result := GetClass(AClassName);
- if not Assigned(Result) then
- raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
- end;
- function CollectionsEqual(C1, C2: TCollection): Boolean;
- Var
- Comp1,Comp2 : TComponent;
- begin
- Comp2:=Nil;
- Comp1:=TComponent.Create;
- try
- Result:=CollectionsEqual(C1,C2,Comp1,Comp2);
- finally
- Comp1.Free;
- Comp2.Free;
- end;
- end;
- function CollectionsEqual(C1, C2: TCollection; Owner1, Owner2: TComponent): Boolean;
- procedure stream_collection(s : tstream;c : tcollection;o : tcomponent);
- var
- w : twriter;
- begin
- w:=twriter.create(s);
- try
- w.root:=o;
- w.flookuproot:=o;
- w.writecollection(c);
- finally
- w.free;
- end;
- end;
- var
- s1,s2 : tbytesstream;
- b1,b2 : TBytes;
- I,Len : Integer;
- begin
- result:=false;
- if (c1.classtype<>c2.classtype) or
- (c1.count<>c2.count) then
- exit;
- if c1.count = 0 then
- begin
- result:= true;
- exit;
- end;
- s2:=Nil;
- s1:=tbytesstream.create;
- try
- s2:=tbytesstream.create;
- stream_collection(s1,c1,owner1);
- stream_collection(s2,c2,owner2);
- result:=(s1.size=s2.size);
- if Result then
- begin
- b1:=S1.Bytes;
- b2:=S2.Bytes;
- I:=0;
- Len:=S1.Size; // Not length of B
- While Result and (I<Len) do
- begin
- Result:=b1[I]=b2[i];
- Inc(i);
- end;
- end;
- finally
- s2.free;
- s1.free;
- end;
- end;
- { TInterfacedPersistent }
- function TInterfacedPersistent._AddRef: Integer;
- begin
- Result:=-1;
- if Assigned(FOwnerInterface) then
- Result:=FOwnerInterface._AddRef;
- end;
- function TInterfacedPersistent._Release: Integer;
- begin
- Result:=-1;
- if Assigned(FOwnerInterface) then
- Result:=FOwnerInterface._Release;
- end;
- function TInterfacedPersistent.QueryInterface(const IID: TGUID; out Obj): HRESULT;
- begin
- Result:=E_NOINTERFACE;
- if GetInterface(IID, Obj) then
- Result:=0;
- end;
- procedure TInterfacedPersistent.AfterConstruction;
- begin
- inherited AfterConstruction;
- if (GetOwner<>nil) then
- GetOwner.GetInterface(IInterface, FOwnerInterface);
- end;
- { TComponentEnumerator }
- constructor TComponentEnumerator.Create(AComponent: TComponent);
- begin
- inherited Create;
- FComponent := AComponent;
- FPosition := -1;
- end;
- function TComponentEnumerator.GetCurrent: TComponent;
- begin
- Result := FComponent.Components[FPosition];
- end;
- function TComponentEnumerator.MoveNext: Boolean;
- begin
- Inc(FPosition);
- Result := FPosition < FComponent.ComponentCount;
- end;
- { TListEnumerator }
- constructor TListEnumerator.Create(AList: TList);
- begin
- inherited Create;
- FList := AList;
- FPosition := -1;
- end;
- function TListEnumerator.GetCurrent: JSValue;
- begin
- Result := FList[FPosition];
- end;
- function TListEnumerator.MoveNext: Boolean;
- begin
- Inc(FPosition);
- Result := FPosition < FList.Count;
- end;
- { TFPListEnumerator }
- constructor TFPListEnumerator.Create(AList: TFPList);
- begin
- inherited Create;
- FList := AList;
- FPosition := -1;
- end;
- function TFPListEnumerator.GetCurrent: JSValue;
- begin
- Result := FList[FPosition];
- end;
- function TFPListEnumerator.MoveNext: Boolean;
- begin
- Inc(FPosition);
- Result := FPosition < FList.Count;
- end;
- { TFPList }
- procedure TFPList.CopyMove(aList: TFPList);
- var r : integer;
- begin
- Clear;
- for r := 0 to aList.count-1 do
- Add(aList[r]);
- end;
- procedure TFPList.MergeMove(aList: TFPList);
- var r : integer;
- begin
- For r := 0 to aList.count-1 do
- if IndexOf(aList[r]) < 0 then
- Add(aList[r]);
- end;
- procedure TFPList.DoCopy(ListA, ListB: TFPList);
- begin
- if Assigned(ListB) then
- CopyMove(ListB)
- else
- CopyMove(ListA);
- end;
- procedure TFPList.DoSrcUnique(ListA, ListB: TFPList);
- var r : integer;
- begin
- if Assigned(ListB) then
- begin
- Clear;
- for r := 0 to ListA.Count-1 do
- if ListB.IndexOf(ListA[r]) < 0 then
- Add(ListA[r]);
- end
- else
- begin
- for r := Count-1 downto 0 do
- if ListA.IndexOf(Self[r]) >= 0 then
- Delete(r);
- end;
- end;
- procedure TFPList.DoAnd(ListA, ListB: TFPList);
- var r : integer;
- begin
- if Assigned(ListB) then
- begin
- Clear;
- for r := 0 to ListA.count-1 do
- if ListB.IndexOf(ListA[r]) >= 0 then
- Add(ListA[r]);
- end
- else
- begin
- for r := Count-1 downto 0 do
- if ListA.IndexOf(Self[r]) < 0 then
- Delete(r);
- end;
- end;
- procedure TFPList.DoDestUnique(ListA, ListB: TFPList);
- procedure MoveElements(Src, Dest: TFPList);
- var r : integer;
- begin
- Clear;
- for r := 0 to Src.count-1 do
- if Dest.IndexOf(Src[r]) < 0 then
- self.Add(Src[r]);
- end;
- var Dest : TFPList;
- begin
- if Assigned(ListB) then
- MoveElements(ListB, ListA)
- else
- Dest := TFPList.Create;
- try
- Dest.CopyMove(Self);
- MoveElements(ListA, Dest)
- finally
- Dest.Destroy;
- end;
- end;
- procedure TFPList.DoOr(ListA, ListB: TFPList);
- begin
- if Assigned(ListB) then
- begin
- CopyMove(ListA);
- MergeMove(ListB);
- end
- else
- MergeMove(ListA);
- end;
- procedure TFPList.DoXOr(ListA, ListB: TFPList);
- var
- r : integer;
- l : TFPList;
- begin
- if Assigned(ListB) then
- begin
- Clear;
- for r := 0 to ListA.Count-1 do
- if ListB.IndexOf(ListA[r]) < 0 then
- Add(ListA[r]);
- for r := 0 to ListB.Count-1 do
- if ListA.IndexOf(ListB[r]) < 0 then
- Add(ListB[r]);
- end
- else
- begin
- l := TFPList.Create;
- try
- l.CopyMove(Self);
- for r := Count-1 downto 0 do
- if listA.IndexOf(Self[r]) >= 0 then
- Delete(r);
- for r := 0 to ListA.Count-1 do
- if l.IndexOf(ListA[r]) < 0 then
- Add(ListA[r]);
- finally
- l.Destroy;
- end;
- end;
- end;
- function TFPList.Get(Index: Integer): JSValue;
- begin
- If (Index < 0) or (Index >= FCount) then
- RaiseIndexError(Index);
- Result:=FList[Index];
- end;
- procedure TFPList.Put(Index: Integer; Item: JSValue);
- begin
- if (Index < 0) or (Index >= FCount) then
- RaiseIndexError(Index);
- FList[Index] := Item;
- end;
- procedure TFPList.SetCapacity(NewCapacity: Integer);
- begin
- If (NewCapacity < FCount) then
- Error (SListCapacityError, str(NewCapacity));
- if NewCapacity = FCapacity then
- exit;
- SetLength(FList,NewCapacity);
- FCapacity := NewCapacity;
- end;
- procedure TFPList.SetCount(NewCount: Integer);
- begin
- if (NewCount < 0) then
- Error(SListCountError, str(NewCount));
- If NewCount > FCount then
- begin
- If NewCount > FCapacity then
- SetCapacity(NewCount);
- end;
- FCount := NewCount;
- end;
- procedure TFPList.RaiseIndexError(Index: Integer);
- begin
- Error(SListIndexError, str(Index));
- end;
- destructor TFPList.Destroy;
- begin
- Clear;
- inherited Destroy;
- end;
- procedure TFPList.AddList(AList: TFPList);
- Var
- I : Integer;
- begin
- If (Capacity<Count+AList.Count) then
- Capacity:=Count+AList.Count;
- For I:=0 to AList.Count-1 do
- Add(AList[i]);
- end;
- function TFPList.Add(Item: JSValue): Integer;
- begin
- if FCount = FCapacity then
- Expand;
- FList[FCount] := Item;
- Result := FCount;
- Inc(FCount);
- end;
- procedure TFPList.Clear;
- begin
- if Assigned(FList) then
- begin
- SetCount(0);
- SetCapacity(0);
- end;
- end;
- procedure TFPList.Delete(Index: Integer);
- begin
- If (Index<0) or (Index>=FCount) then
- Error (SListIndexError, str(Index));
- FCount := FCount-1;
- System.Delete(FList,Index,1);
- Dec(FCapacity);
- end;
- class procedure TFPList.Error(const Msg: string; const Data: String);
- begin
- Raise EListError.CreateFmt(Msg,[Data]);
- end;
- procedure TFPList.Exchange(Index1, Index2: Integer);
- var
- Temp : JSValue;
- begin
- If (Index1 >= FCount) or (Index1 < 0) then
- Error(SListIndexError, str(Index1));
- If (Index2 >= FCount) or (Index2 < 0) then
- Error(SListIndexError, str(Index2));
- Temp := FList[Index1];
- FList[Index1] := FList[Index2];
- FList[Index2] := Temp;
- end;
- function TFPList.Expand: TFPList;
- var
- IncSize : Integer;
- begin
- if FCount < FCapacity then exit(self);
- IncSize := 4;
- if FCapacity > 3 then IncSize := IncSize + 4;
- if FCapacity > 8 then IncSize := IncSize+8;
- if FCapacity > 127 then Inc(IncSize, FCapacity shr 2);
- SetCapacity(FCapacity + IncSize);
- Result := Self;
- end;
- function TFPList.Extract(Item: JSValue): JSValue;
- var
- i : Integer;
- begin
- i := IndexOf(Item);
- if i >= 0 then
- begin
- Result := Item;
- Delete(i);
- end
- else
- Result := nil;
- end;
- function TFPList.First: JSValue;
- begin
- If FCount = 0 then
- Result := Nil
- else
- Result := Items[0];
- end;
- function TFPList.GetEnumerator: TFPListEnumerator;
- begin
- Result:=TFPListEnumerator.Create(Self);
- end;
- function TFPList.IndexOf(Item: JSValue): Integer;
- Var
- C : Integer;
- begin
- Result:=0;
- C:=Count;
- while (Result<C) and (FList[Result]<>Item) do
- Inc(Result);
- If Result>=C then
- Result:=-1;
- end;
- function TFPList.IndexOfItem(Item: JSValue; Direction: TDirection): Integer;
- begin
- if Direction=fromBeginning then
- Result:=IndexOf(Item)
- else
- begin
- Result:=Count-1;
- while (Result >=0) and (Flist[Result]<>Item) do
- Result:=Result - 1;
- end;
- end;
- procedure TFPList.Insert(Index: Integer; Item: JSValue);
- begin
- if (Index < 0) or (Index > FCount )then
- Error(SlistIndexError, str(Index));
- TJSArray(FList).splice(Index, 0, Item);
- inc(FCapacity);
- inc(FCount);
- end;
- function TFPList.Last: JSValue;
- begin
- If FCount = 0 then
- Result := nil
- else
- Result := Items[FCount - 1];
- end;
- procedure TFPList.Move(CurIndex, NewIndex: Integer);
- var
- Temp: JSValue;
- begin
- if (CurIndex < 0) or (CurIndex > Count - 1) then
- Error(SListIndexError, str(CurIndex));
- if (NewIndex < 0) or (NewIndex > Count -1) then
- Error(SlistIndexError, str(NewIndex));
- if CurIndex=NewIndex then exit;
- Temp:=FList[CurIndex];
- // ToDo: use TJSArray.copyWithin if available
- TJSArray(FList).splice(CurIndex,1);
- TJSArray(FList).splice(NewIndex,0,Temp);
- end;
- procedure TFPList.Assign(ListA: TFPList; AOperator: TListAssignOp;
- ListB: TFPList);
- begin
- case AOperator of
- laCopy : DoCopy (ListA, ListB); // replace dest with src
- laSrcUnique : DoSrcUnique (ListA, ListB); // replace dest with src that are not in dest
- laAnd : DoAnd (ListA, ListB); // remove from dest that are not in src
- laDestUnique: DoDestUnique (ListA, ListB);// remove from dest that are in src
- laOr : DoOr (ListA, ListB); // add to dest from src and not in dest
- laXOr : DoXOr (ListA, ListB); // add to dest from src and not in dest, remove from dest that are in src
- end;
- end;
- function TFPList.Remove(Item: JSValue): Integer;
- begin
- Result := IndexOf(Item);
- If Result <> -1 then
- Delete(Result);
- end;
- procedure TFPList.Pack;
- var
- Dst, i: Integer;
- V: JSValue;
- begin
- Dst:=0;
- for i:=0 to Count-1 do
- begin
- V:=FList[i];
- if not Assigned(V) then continue;
- FList[Dst]:=V;
- inc(Dst);
- end;
- end;
- // Needed by Sort method.
- Procedure QuickSort(aList: TJSValueDynArray; L, R : Longint;
- const Compare: TListSortCompareFunc
- );
- var
- I, J, PivotIdx : SizeUInt;
- P, Q : JSValue;
- begin
- repeat
- I := L;
- J := R;
- PivotIdx := L + ((R - L) shr 1); { same as ((L + R) div 2), but without the possibility of overflow }
- P := aList[PivotIdx];
- repeat
- while (I < PivotIdx) and (Compare(P, aList[i]) > 0) do
- Inc(I);
- while (J > PivotIdx) and (Compare(P, aList[J]) < 0) do
- Dec(J);
- if I < J then
- begin
- Q := aList[I];
- aList[I] := aList[J];
- aList[J] := Q;
- if PivotIdx = I then
- begin
- PivotIdx := J;
- Inc(I);
- end
- else if PivotIdx = J then
- begin
- PivotIdx := I;
- Dec(J);
- end
- else
- begin
- Inc(I);
- Dec(J);
- end;
- end;
- until I >= J;
- // sort the smaller range recursively
- // sort the bigger range via the loop
- // Reasons: memory usage is O(log(n)) instead of O(n) and loop is faster than recursion
- if (PivotIdx - L) < (R - PivotIdx) then
- begin
- if (L + 1) < PivotIdx then
- QuickSort(aList, L, PivotIdx - 1, Compare);
- L := PivotIdx + 1;
- end
- else
- begin
- if (PivotIdx + 1) < R then
- QuickSort(aList, PivotIdx + 1, R, Compare);
- if (L + 1) < PivotIdx then
- R := PivotIdx - 1
- else
- exit;
- end;
- until L >= R;
- end;
- (*
- Procedure QuickSort(aList: TJSValueDynArray; L, R : Longint;
- const Compare: TListSortCompareFunc);
- var
- I, J : Longint;
- P, Q : JSValue;
- begin
- repeat
- I := L;
- J := R;
- P := aList[ (L + R) div 2 ];
- repeat
- while Compare(P, aList[i]) > 0 do
- I := I + 1;
- while Compare(P, aList[J]) < 0 do
- J := J - 1;
- If I <= J then
- begin
- Q := aList[I];
- aList[I] := aList[J];
- aList[J] := Q;
- I := I + 1;
- J := J - 1;
- end;
- until I > J;
- // sort the smaller range recursively
- // sort the bigger range via the loop
- // Reasons: memory usage is O(log(n)) instead of O(n) and loop is faster than recursion
- if J - L < R - I then
- begin
- if L < J then
- QuickSort(aList, L, J, Compare);
- L := I;
- end
- else
- begin
- if I < R then
- QuickSort(aList, I, R, Compare);
- R := J;
- end;
- until L >= R;
- end;
- *)
- procedure TFPList.Sort(const Compare: TListSortCompare);
- begin
- if Not Assigned(FList) or (FCount < 2) then exit;
- QuickSort(Flist, 0, FCount-1,
- function(Item1, Item2: JSValue): Integer
- begin
- Result := Compare(Item1, Item2);
- end);
- end;
- procedure TFPList.SortList(const Compare: TListSortCompareFunc);
- begin
- if Not Assigned(FList) or (FCount < 2) then exit;
- QuickSort(Flist, 0, FCount-1, Compare);
- end;
- procedure TFPList.ForEachCall(const proc2call: TListCallback; const arg: JSValue
- );
- var
- i : integer;
- v : JSValue;
- begin
- For I:=0 To Count-1 Do
- begin
- v:=FList[i];
- if Assigned(v) then
- proc2call(v,arg);
- end;
- end;
- procedure TFPList.ForEachCall(const proc2call: TListStaticCallback;
- const arg: JSValue);
- var
- i : integer;
- v : JSValue;
- begin
- For I:=0 To Count-1 Do
- begin
- v:=FList[i];
- if Assigned(v) then
- proc2call(v,arg);
- end;
- end;
- { TList }
- procedure TList.CopyMove(aList: TList);
- var
- r : integer;
- begin
- Clear;
- for r := 0 to aList.count-1 do
- Add(aList[r]);
- end;
- procedure TList.MergeMove(aList: TList);
- var r : integer;
- begin
- For r := 0 to aList.count-1 do
- if IndexOf(aList[r]) < 0 then
- Add(aList[r]);
- end;
- procedure TList.DoCopy(ListA, ListB: TList);
- begin
- if Assigned(ListB) then
- CopyMove(ListB)
- else
- CopyMove(ListA);
- end;
- procedure TList.DoSrcUnique(ListA, ListB: TList);
- var r : integer;
- begin
- if Assigned(ListB) then
- begin
- Clear;
- for r := 0 to ListA.Count-1 do
- if ListB.IndexOf(ListA[r]) < 0 then
- Add(ListA[r]);
- end
- else
- begin
- for r := Count-1 downto 0 do
- if ListA.IndexOf(Self[r]) >= 0 then
- Delete(r);
- end;
- end;
- procedure TList.DoAnd(ListA, ListB: TList);
- var r : integer;
- begin
- if Assigned(ListB) then
- begin
- Clear;
- for r := 0 to ListA.Count-1 do
- if ListB.IndexOf(ListA[r]) >= 0 then
- Add(ListA[r]);
- end
- else
- begin
- for r := Count-1 downto 0 do
- if ListA.IndexOf(Self[r]) < 0 then
- Delete(r);
- end;
- end;
- procedure TList.DoDestUnique(ListA, ListB: TList);
- procedure MoveElements(Src, Dest : TList);
- var r : integer;
- begin
- Clear;
- for r := 0 to Src.Count-1 do
- if Dest.IndexOf(Src[r]) < 0 then
- Add(Src[r]);
- end;
- var Dest : TList;
- begin
- if Assigned(ListB) then
- MoveElements(ListB, ListA)
- else
- try
- Dest := TList.Create;
- Dest.CopyMove(Self);
- MoveElements(ListA, Dest)
- finally
- Dest.Destroy;
- end;
- end;
- procedure TList.DoOr(ListA, ListB: TList);
- begin
- if Assigned(ListB) then
- begin
- CopyMove(ListA);
- MergeMove(ListB);
- end
- else
- MergeMove(ListA);
- end;
- procedure TList.DoXOr(ListA, ListB: TList);
- var
- r : integer;
- l : TList;
- begin
- if Assigned(ListB) then
- begin
- Clear;
- for r := 0 to ListA.Count-1 do
- if ListB.IndexOf(ListA[r]) < 0 then
- Add(ListA[r]);
- for r := 0 to ListB.Count-1 do
- if ListA.IndexOf(ListB[r]) < 0 then
- Add(ListB[r]);
- end
- else
- try
- l := TList.Create;
- l.CopyMove (Self);
- for r := Count-1 downto 0 do
- if listA.IndexOf(Self[r]) >= 0 then
- Delete(r);
- for r := 0 to ListA.Count-1 do
- if l.IndexOf(ListA[r]) < 0 then
- Add(ListA[r]);
- finally
- l.Destroy;
- end;
- end;
- function TList.Get(Index: Integer): JSValue;
- begin
- Result := FList.Get(Index);
- end;
- procedure TList.Put(Index: Integer; Item: JSValue);
- var V : JSValue;
- begin
- V := Get(Index);
- FList.Put(Index, Item);
- if Assigned(V) then
- Notify(V, lnDeleted);
- if Assigned(Item) then
- Notify(Item, lnAdded);
- end;
- procedure TList.Notify(aValue: JSValue; Action: TListNotification);
- begin
- if Assigned(aValue) then ;
- if Action=lnExtracted then ;
- end;
- procedure TList.SetCapacity(NewCapacity: Integer);
- begin
- FList.SetCapacity(NewCapacity);
- end;
- function TList.GetCapacity: integer;
- begin
- Result := FList.Capacity;
- end;
- procedure TList.SetCount(NewCount: Integer);
- begin
- if NewCount < FList.Count then
- while FList.Count > NewCount do
- Delete(FList.Count - 1)
- else
- FList.SetCount(NewCount);
- end;
- function TList.GetCount: integer;
- begin
- Result := FList.Count;
- end;
- function TList.GetList: TJSValueDynArray;
- begin
- Result := FList.List;
- end;
- constructor TList.Create;
- begin
- inherited Create;
- FList := TFPList.Create;
- end;
- destructor TList.Destroy;
- begin
- if Assigned(FList) then
- Clear;
- FreeAndNil(FList);
- end;
- procedure TList.AddList(AList: TList);
- var
- I: Integer;
- begin
- { this only does FList.AddList(AList.FList), avoiding notifications }
- FList.AddList(AList.FList);
- { make lnAdded notifications }
- for I := 0 to AList.Count - 1 do
- if Assigned(AList[I]) then
- Notify(AList[I], lnAdded);
- end;
- function TList.Add(Item: JSValue): Integer;
- begin
- Result := FList.Add(Item);
- if Assigned(Item) then
- Notify(Item, lnAdded);
- end;
- procedure TList.Clear;
- begin
- While (FList.Count>0) do
- Delete(Count-1);
- end;
- procedure TList.Delete(Index: Integer);
- var V : JSValue;
- begin
- V:=FList.Get(Index);
- FList.Delete(Index);
- if assigned(V) then
- Notify(V, lnDeleted);
- end;
- class procedure TList.Error(const Msg: string; Data: String);
- begin
- Raise EListError.CreateFmt(Msg,[Data]);
- end;
- procedure TList.Exchange(Index1, Index2: Integer);
- begin
- FList.Exchange(Index1, Index2);
- end;
- function TList.Expand: TList;
- begin
- FList.Expand;
- Result:=Self;
- end;
- function TList.Extract(Item: JSValue): JSValue;
- var c : integer;
- begin
- c := FList.Count;
- Result := FList.Extract(Item);
- if c <> FList.Count then
- Notify (Result, lnExtracted);
- end;
- function TList.First: JSValue;
- begin
- Result := FList.First;
- end;
- function TList.GetEnumerator: TListEnumerator;
- begin
- Result:=TListEnumerator.Create(Self);
- end;
- function TList.IndexOf(Item: JSValue): Integer;
- begin
- Result := FList.IndexOf(Item);
- end;
- procedure TList.Insert(Index: Integer; Item: JSValue);
- begin
- FList.Insert(Index, Item);
- if Assigned(Item) then
- Notify(Item,lnAdded);
- end;
- function TList.Last: JSValue;
- begin
- Result := FList.Last;
- end;
- procedure TList.Move(CurIndex, NewIndex: Integer);
- begin
- FList.Move(CurIndex, NewIndex);
- end;
- procedure TList.Assign(ListA: TList; AOperator: TListAssignOp; ListB: TList);
- begin
- case AOperator of
- laCopy : DoCopy (ListA, ListB); // replace dest with src
- laSrcUnique : DoSrcUnique (ListA, ListB); // replace dest with src that are not in dest
- laAnd : DoAnd (ListA, ListB); // remove from dest that are not in src
- laDestUnique: DoDestUnique (ListA, ListB);// remove from dest that are in src
- laOr : DoOr (ListA, ListB); // add to dest from src and not in dest
- laXOr : DoXOr (ListA, ListB); // add to dest from src and not in dest, remove from dest that are in src
- end;
- end;
- function TList.Remove(Item: JSValue): Integer;
- begin
- Result := IndexOf(Item);
- if Result <> -1 then
- Self.Delete(Result);
- end;
- procedure TList.Pack;
- begin
- FList.Pack;
- end;
- procedure TList.Sort(const Compare: TListSortCompare);
- begin
- FList.Sort(Compare);
- end;
- procedure TList.SortList(const Compare: TListSortCompareFunc);
- begin
- FList.SortList(Compare);
- end;
- { TPersistent }
- procedure TPersistent.AssignError(Source: TPersistent);
- var
- SourceName: String;
- begin
- if Source<>Nil then
- SourceName:=Source.ClassName
- else
- SourceName:='Nil';
- raise EConvertError.Create('Cannot assign a '+SourceName+' to a '+ClassName+'.');
- end;
- procedure TPersistent.DefineProperties(Filer: TFiler);
- begin
- if Filer=Nil then exit;
- // Do nothing
- end;
- procedure TPersistent.AssignTo(Dest: TPersistent);
- begin
- Dest.AssignError(Self);
- end;
- function TPersistent.GetOwner: TPersistent;
- begin
- Result:=nil;
- end;
- procedure TPersistent.Assign(Source: TPersistent);
- begin
- If Source<>Nil then
- Source.AssignTo(Self)
- else
- AssignError(Nil);
- end;
- function TPersistent.GetNamePath: string;
- var
- OwnerName: String;
- TheOwner: TPersistent;
- begin
- Result:=ClassName;
- TheOwner:=GetOwner;
- if TheOwner<>Nil then
- begin
- OwnerName:=TheOwner.GetNamePath;
- if OwnerName<>'' then Result:=OwnerName+'.'+Result;
- end;
- end;
- {
- This file is part of the Free Component Library (FCL)
- Copyright (c) 1999-2000 by the Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {****************************************************************************}
- {* TStringsEnumerator *}
- {****************************************************************************}
- constructor TStringsEnumerator.Create(AStrings: TStrings);
- begin
- inherited Create;
- FStrings := AStrings;
- FPosition := -1;
- end;
- function TStringsEnumerator.GetCurrent: String;
- begin
- Result := FStrings[FPosition];
- end;
- function TStringsEnumerator.MoveNext: Boolean;
- begin
- Inc(FPosition);
- Result := FPosition < FStrings.Count;
- end;
- {****************************************************************************}
- {* TStrings *}
- {****************************************************************************}
- // Function to quote text. Should move maybe to sysutils !!
- // Also, it is not clear at this point what exactly should be done.
- { //!! is used to mark unsupported things. }
- {
- For compatibility we can't add a Constructor to TSTrings to initialize
- the special characters. Therefore we add a routine which is called whenever
- the special chars are needed.
- }
- procedure TStrings.CheckSpecialChars;
- begin
- If Not FSpecialCharsInited then
- begin
- FQuoteChar:='"';
- FDelimiter:=',';
- FNameValueSeparator:='=';
- FLBS:=DefaultTextLineBreakStyle;
- FSpecialCharsInited:=true;
- FLineBreak:=sLineBreak;
- end;
- end;
- function TStrings.GetSkipLastLineBreak: Boolean;
- begin
- CheckSpecialChars;
- Result:=FSkipLastLineBreak;
- end;
- procedure TStrings.SetSkipLastLineBreak(const AValue : Boolean);
- begin
- CheckSpecialChars;
- FSkipLastLineBreak:=AValue;
- end;
- procedure TStrings.ReadData(Reader: TReader);
- begin
- Reader.ReadListBegin;
- BeginUpdate;
- try
- Clear;
- while not Reader.EndOfList do
- Add(Reader.ReadString);
- finally
- EndUpdate;
- end;
- Reader.ReadListEnd;
- end;
- procedure TStrings.WriteData(Writer: TWriter);
- var
- i: Integer;
- begin
- Writer.WriteListBegin;
- for i := 0 to Count - 1 do
- Writer.WriteString(Strings[i]);
- Writer.WriteListEnd;
- end;
- procedure TStrings.DefineProperties(Filer: TFiler);
- var
- HasData: Boolean;
- begin
- if Assigned(Filer.Ancestor) then
- // Only serialize if string list is different from ancestor
- if Filer.Ancestor.InheritsFrom(TStrings) then
- HasData := not Equals(TStrings(Filer.Ancestor))
- else
- HasData := True
- else
- HasData := Count > 0;
- Filer.DefineProperty('Strings', @ReadData, @WriteData, HasData);
- end;
- function TStrings.GetLBS: TTextLineBreakStyle;
- begin
- CheckSpecialChars;
- Result:=FLBS;
- end;
- procedure TStrings.SetLBS(AValue: TTextLineBreakStyle);
- begin
- CheckSpecialChars;
- FLBS:=AValue;
- end;
- procedure TStrings.SetDelimiter(c:Char);
- begin
- CheckSpecialChars;
- FDelimiter:=c;
- end;
- function TStrings.GetDelimiter: Char;
- begin
- CheckSpecialChars;
- Result:=FDelimiter;
- end;
- procedure TStrings.SetLineBreak(const S: String);
- begin
- CheckSpecialChars;
- FLineBreak:=S;
- end;
- function TStrings.GetLineBreak: String;
- begin
- CheckSpecialChars;
- Result:=FLineBreak;
- end;
- procedure TStrings.SetQuoteChar(c:Char);
- begin
- CheckSpecialChars;
- FQuoteChar:=c;
- end;
- function TStrings.GetQuoteChar: Char;
- begin
- CheckSpecialChars;
- Result:=FQuoteChar;
- end;
- procedure TStrings.SetNameValueSeparator(c:Char);
- begin
- CheckSpecialChars;
- FNameValueSeparator:=c;
- end;
- function TStrings.GetNameValueSeparator: Char;
- begin
- CheckSpecialChars;
- Result:=FNameValueSeparator;
- end;
- function TStrings.GetCommaText: string;
- Var
- C1,C2 : Char;
- FSD : Boolean;
- begin
- CheckSpecialChars;
- FSD:=StrictDelimiter;
- C1:=Delimiter;
- C2:=QuoteChar;
- Delimiter:=',';
- QuoteChar:='"';
- StrictDelimiter:=False;
- Try
- Result:=GetDelimitedText;
- Finally
- Delimiter:=C1;
- QuoteChar:=C2;
- StrictDelimiter:=FSD;
- end;
- end;
- function TStrings.GetDelimitedText: string;
- Var
- I: integer;
- RE : string;
- S : String;
- doQuote : Boolean;
- begin
- CheckSpecialChars;
- result:='';
- RE:=QuoteChar+'|'+Delimiter;
- if not StrictDelimiter then
- RE:=' |'+RE;
- RE:='/'+RE+'/';
- // Check for break characters and quote if required.
- For i:=0 to count-1 do
- begin
- S:=Strings[i];
- doQuote:=FAlwaysQuote or (TJSString(s).search(RE)<>-1);
- if DoQuote then
- Result:=Result+QuoteString(S,QuoteChar)
- else
- Result:=Result+S;
- if I<Count-1 then
- Result:=Result+Delimiter;
- end;
- // Quote empty string:
- If (Length(Result)=0) and (Count=1) then
- Result:=QuoteChar+QuoteChar;
- end;
- procedure TStrings.GetNameValue(Index: Integer; out AName, AValue: String);
- Var L : longint;
- begin
- CheckSpecialChars;
- AValue:=Strings[Index];
- L:=Pos(FNameValueSeparator,AValue);
- If L<>0 then
- begin
- AName:=Copy(AValue,1,L-1);
- // System.Delete(AValue,1,L);
- AValue:=Copy(AValue,L+1,length(AValue)-L);
- end
- else
- AName:='';
- end;
- procedure TStrings.LoadFromURL(const aURL: String; Async: Boolean; OnLoaded: TNotifyEventRef; OnError: TStringNotifyEventRef);
- procedure DoLoaded(const aString : String);
- begin
- Text:=aString;
- if Assigned(OnLoaded) then
- OnLoaded(Self);
- end;
- procedure DoError(const AError : String);
- begin
- if Assigned(OnError) then
- OnError(Self,aError)
- else
- Raise EInOutError.Create('Failed to load from URL:'+aError);
- end;
- begin
- CheckLoadHelper;
- GlobalLoadHelper.LoadText(aURL,aSync,@DoLoaded,@DoError);
- end;
- procedure TStrings.LoadFromFile(const aFileName: String; const OnLoaded: TProc; const AError: TProcString);
- begin
- LoadFromURL(aFileName,False,
- Procedure (Sender : TObject)
- begin
- If Assigned(OnLoaded) then
- OnLoaded
- end,
- Procedure (Sender : TObject; Const ErrorMsg : String)
- begin
- if Assigned(aError) then
- aError(ErrorMsg)
- end);
- end;
- function TStrings.ExtractName(const S: String): String;
- var
- L: Longint;
- begin
- CheckSpecialChars;
- L:=Pos(FNameValueSeparator,S);
- If L<>0 then
- Result:=Copy(S,1,L-1)
- else
- Result:='';
- end;
- function TStrings.GetName(Index: Integer): string;
- Var
- V : String;
- begin
- GetNameValue(Index,Result,V);
- end;
- function TStrings.GetValue(const Name: string): string;
- Var
- L : longint;
- N : String;
- begin
- Result:='';
- L:=IndexOfName(Name);
- If L<>-1 then
- GetNameValue(L,N,Result);
- end;
- function TStrings.GetValueFromIndex(Index: Integer): string;
- Var
- N : String;
- begin
- GetNameValue(Index,N,Result);
- end;
- procedure TStrings.SetValueFromIndex(Index: Integer; const Value: string);
- begin
- If (Value='') then
- Delete(Index)
- else
- begin
- If (Index<0) then
- Index:=Add('');
- CheckSpecialChars;
- Strings[Index]:=GetName(Index)+FNameValueSeparator+Value;
- end;
- end;
- procedure TStrings.SetDelimitedText(const AValue: string);
- var i,j:integer;
- aNotFirst:boolean;
- begin
- CheckSpecialChars;
- BeginUpdate;
- i:=1;
- j:=1;
- aNotFirst:=false;
- { Paraphrased from Delphi XE2 help:
- Strings must be separated by Delimiter characters or spaces.
- They may be enclosed in QuoteChars.
- QuoteChars in the string must be repeated to distinguish them from the QuoteChars enclosing the string.
- }
- try
- Clear;
- If StrictDelimiter then
- begin
- while i<=length(AValue) do begin
- // skip delimiter
- if aNotFirst and (i<=length(AValue)) and (AValue[i]=FDelimiter) then inc(i);
- // read next string
- if i<=length(AValue) then begin
- if AValue[i]=FQuoteChar then begin
- // next string is quoted
- j:=i+1;
- while (j<=length(AValue)) and
- ( (AValue[j]<>FQuoteChar) or
- ( (j+1<=length(AValue)) and (AValue[j+1]=FQuoteChar) ) ) do begin
- if (j<=length(AValue)) and (AValue[j]=FQuoteChar) then inc(j,2)
- else inc(j);
- end;
- // j is position of closing quote
- Add( StringReplace (Copy(AValue,i+1,j-i-1),
- FQuoteChar+FQuoteChar,FQuoteChar, [rfReplaceAll]));
- i:=j+1;
- end else begin
- // next string is not quoted; read until delimiter
- j:=i;
- while (j<=length(AValue)) and
- (AValue[j]<>FDelimiter) do inc(j);
- Add( Copy(AValue,i,j-i));
- i:=j;
- end;
- end else begin
- if aNotFirst then Add('');
- end;
- aNotFirst:=true;
- end;
- end
- else
- begin
- while i<=length(AValue) do begin
- // skip delimiter
- if aNotFirst and (i<=length(AValue)) and (AValue[i]=FDelimiter) then inc(i);
- // skip spaces
- while (i<=length(AValue)) and (Ord(AValue[i])<=Ord(' ')) do inc(i);
- // read next string
- if i<=length(AValue) then begin
- if AValue[i]=FQuoteChar then begin
- // next string is quoted
- j:=i+1;
- while (j<=length(AValue)) and
- ( (AValue[j]<>FQuoteChar) or
- ( (j+1<=length(AValue)) and (AValue[j+1]=FQuoteChar) ) ) do begin
- if (j<=length(AValue)) and (AValue[j]=FQuoteChar) then inc(j,2)
- else inc(j);
- end;
- // j is position of closing quote
- Add( StringReplace (Copy(AValue,i+1,j-i-1),
- FQuoteChar+FQuoteChar,FQuoteChar, [rfReplaceAll]));
- i:=j+1;
- end else begin
- // next string is not quoted; read until control character/space/delimiter
- j:=i;
- while (j<=length(AValue)) and
- (Ord(AValue[j])>Ord(' ')) and
- (AValue[j]<>FDelimiter) do inc(j);
- Add( Copy(AValue,i,j-i));
- i:=j;
- end;
- end else begin
- if aNotFirst then Add('');
- end;
- // skip spaces
- while (i<=length(AValue)) and (Ord(AValue[i])<=Ord(' ')) do inc(i);
- aNotFirst:=true;
- end;
- end;
- finally
- EndUpdate;
- end;
- end;
- procedure TStrings.SetCommaText(const Value: string);
- Var
- C1,C2 : Char;
- begin
- CheckSpecialChars;
- C1:=Delimiter;
- C2:=QuoteChar;
- Delimiter:=',';
- QuoteChar:='"';
- Try
- SetDelimitedText(Value);
- Finally
- Delimiter:=C1;
- QuoteChar:=C2;
- end;
- end;
- procedure TStrings.SetValue(const Name: String; const Value: string);
- Var L : longint;
- begin
- CheckSpecialChars;
- L:=IndexOfName(Name);
- if L=-1 then
- Add (Name+FNameValueSeparator+Value)
- else
- Strings[L]:=Name+FNameValueSeparator+value;
- end;
- procedure TStrings.Error(const Msg: string; Data: Integer);
- begin
- Raise EStringListError.CreateFmt(Msg,[IntToStr(Data)]);
- end;
- function TStrings.GetCapacity: Integer;
- begin
- Result:=Count;
- end;
- function TStrings.GetObject(Index: Integer): TObject;
- begin
- if Index=0 then ;
- Result:=Nil;
- end;
- function TStrings.GetTextStr: string;
- Var
- I : Longint;
- S,NL : String;
- begin
- CheckSpecialChars;
- // Determine needed place
- if FLineBreak<>sLineBreak then
- NL:=FLineBreak
- else
- Case FLBS of
- tlbsLF : NL:=#10;
- tlbsCRLF : NL:=#13#10;
- tlbsCR : NL:=#13;
- end;
- Result:='';
- For i:=0 To count-1 do
- begin
- S:=Strings[I];
- Result:=Result+S;
- if (I<Count-1) or Not SkipLastLineBreak then
- Result:=Result+NL;
- end;
- end;
- procedure TStrings.Put(Index: Integer; const S: string);
- Var Obj : TObject;
- begin
- Obj:=Objects[Index];
- Delete(Index);
- InsertObject(Index,S,Obj);
- end;
- procedure TStrings.PutObject(Index: Integer; AObject: TObject);
- begin
- // Empty.
- if Index=0 then exit;
- if AObject=nil then exit;
- end;
- procedure TStrings.SetCapacity(NewCapacity: Integer);
- begin
- // Empty.
- if NewCapacity=0 then ;
- end;
- function TStrings.GetNextLinebreak(const Value: String; out S: String; var P: Integer): Boolean;
- var
- PPLF,PPCR,PP,PL: Integer;
- begin
- S:='';
- Result:=False;
- If ((Length(Value)-P)<0) then
- Exit;
- PPLF:=TJSString(Value).IndexOf(#10,P-1)+1;
- PPCR:=TJSString(Value).IndexOf(#13,P-1)+1;
- PL:=1;
- if (PPLF>0) and (PPCR>0) then
- begin
- if (PPLF-PPCR)=1 then
- PL:=2;
- if PPLF<PPCR then
- PP:=PPLF
- else
- PP:=PPCR;
- end
- else if (PPLF>0) and (PPCR<1) then
- PP:=PPLF
- else if (PPCR > 0) and (PPLF<1) then
- PP:=PPCR
- else
- PP:=Length(Value)+1;
- S:=Copy(Value,P,PP-P);
- P:=PP+PL;
- Result:=True;
- end;
- procedure TStrings.DoSetTextStr(const Value: string; DoClear: Boolean);
- Var
- S : String;
- P : Integer;
- begin
- Try
- BeginUpdate;
- if DoClear then
- Clear;
- P:=1;
- While GetNextLineBreak (Value,S,P) do
- Add(S);
- finally
- EndUpdate;
- end;
- end;
- procedure TStrings.SetTextStr(const Value: string);
- begin
- CheckSpecialChars;
- DoSetTextStr(Value,True);
- end;
- procedure TStrings.AddText(const S: String);
- begin
- CheckSpecialChars;
- DoSetTextStr(S,False);
- end;
- procedure TStrings.SetUpdateState(Updating: Boolean);
- begin
- // FPONotifyObservers(Self,ooChange,Nil);
- if Updating then ;
- end;
- destructor TStrings.Destroy;
- begin
- inherited destroy;
- end;
- constructor TStrings.Create;
- begin
- inherited Create;
- FAlwaysQuote:=False;
- end;
- function TStrings.ToObjectArray: TObjectDynArray;
- begin
- Result:=ToObjectArray(0,Count-1);
- end;
- function TStrings.ToObjectArray(aStart,aEnd : Integer): TObjectDynArray;
- Var
- I : Integer;
- begin
- Result:=Nil;
- if aStart>aEnd then exit;
- SetLength(Result,aEnd-aStart+1);
- For I:=aStart to aEnd do
- Result[i-aStart]:=Objects[i];
- end;
- function TStrings.ToStringArray: TStringDynArray;
- begin
- Result:=ToStringArray(0,Count-1);
- end;
- function TStrings.ToStringArray(aStart,aEnd : Integer): TStringDynArray;
- Var
- I : Integer;
- begin
- Result:=Nil;
- if aStart>aEnd then exit;
- SetLength(Result,aEnd-aStart+1);
- For I:=aStart to aEnd do
- Result[i-aStart]:=Strings[i];
- end;
- function TStrings.Add(const S: string): Integer;
- begin
- Result:=Count;
- Insert (Count,S);
- end;
- function TStrings.Add(const Fmt: string; const Args: array of const): Integer;
- begin
- Result:=Add(Format(Fmt,Args));
- end;
- function TStrings.AddFmt(const Fmt: string; const Args: array of const): Integer;
- begin
- Result:=Add(Format(Fmt,Args));
- end;
- function TStrings.AddObject(const S: string; AObject: TObject): Integer;
- begin
- Result:=Add(S);
- Objects[result]:=AObject;
- end;
- function TStrings.AddObject(const Fmt: string; Args: array of const; AObject: TObject): Integer;
- begin
- Result:=AddObject(Format(Fmt,Args),AObject);
- end;
- procedure TStrings.Append(const S: string);
- begin
- Add (S);
- end;
- procedure TStrings.AddStrings(TheStrings: TStrings; ClearFirst: Boolean);
- begin
- beginupdate;
- try
- if ClearFirst then
- Clear;
- AddStrings(TheStrings);
- finally
- EndUpdate;
- end;
- end;
- procedure TStrings.AddStrings(TheStrings: TStrings);
- Var Runner : longint;
- begin
- For Runner:=0 to TheStrings.Count-1 do
- self.AddObject (Thestrings[Runner],TheStrings.Objects[Runner]);
- end;
- procedure TStrings.AddStrings(const TheStrings: array of string);
- Var Runner : longint;
- begin
- if Count + High(TheStrings)+1 > Capacity then
- Capacity := Count + High(TheStrings)+1;
- For Runner:=Low(TheStrings) to High(TheStrings) do
- self.Add(Thestrings[Runner]);
- end;
- procedure TStrings.AddStrings(const TheStrings: array of string; ClearFirst: Boolean);
- begin
- beginupdate;
- try
- if ClearFirst then
- Clear;
- AddStrings(TheStrings);
- finally
- EndUpdate;
- end;
- end;
- function TStrings.AddPair(const AName, AValue: string): TStrings;
- begin
- Result:=AddPair(AName,AValue,Nil);
- end;
- function TStrings.AddPair(const AName, AValue: string; AObject: TObject): TStrings;
- begin
- Result := Self;
- AddObject(AName+NameValueSeparator+AValue, AObject);
- end;
- procedure TStrings.Assign(Source: TPersistent);
- Var
- S : TStrings;
- begin
- If Source is TStrings then
- begin
- S:=TStrings(Source);
- BeginUpdate;
- Try
- clear;
- FSpecialCharsInited:=S.FSpecialCharsInited;
- FQuoteChar:=S.FQuoteChar;
- FDelimiter:=S.FDelimiter;
- FNameValueSeparator:=S.FNameValueSeparator;
- FLBS:=S.FLBS;
- FLineBreak:=S.FLineBreak;
- AddStrings(S);
- finally
- EndUpdate;
- end;
- end
- else
- Inherited Assign(Source);
- end;
- procedure TStrings.BeginUpdate;
- begin
- if FUpdateCount = 0 then SetUpdateState(true);
- inc(FUpdateCount);
- end;
- procedure TStrings.EndUpdate;
- begin
- If FUpdateCount>0 then
- Dec(FUpdateCount);
- if FUpdateCount=0 then
- SetUpdateState(False);
- end;
- function TStrings.Equals(Obj: TObject): Boolean;
- begin
- if Obj is TStrings then
- Result := Equals(TStrings(Obj))
- else
- Result := inherited Equals(Obj);
- end;
- function TStrings.Equals(TheStrings: TStrings): Boolean;
- Var Runner,Nr : Longint;
- begin
- Result:=False;
- Nr:=Self.Count;
- if Nr<>TheStrings.Count then exit;
- For Runner:=0 to Nr-1 do
- If Strings[Runner]<>TheStrings[Runner] then exit;
- Result:=True;
- end;
- procedure TStrings.Exchange(Index1, Index2: Integer);
- Var
- Obj : TObject;
- Str : String;
- begin
- beginUpdate;
- Try
- Obj:=Objects[Index1];
- Str:=Strings[Index1];
- Objects[Index1]:=Objects[Index2];
- Strings[Index1]:=Strings[Index2];
- Objects[Index2]:=Obj;
- Strings[Index2]:=Str;
- finally
- EndUpdate;
- end;
- end;
- function TStrings.GetEnumerator: TStringsEnumerator;
- begin
- Result:=TStringsEnumerator.Create(Self);
- end;
- function TStrings.DoCompareText(const s1, s2: string): PtrInt;
- begin
- result:=CompareText(s1,s2);
- end;
- function TStrings.IndexOf(const S: string): Integer;
- begin
- Result:=0;
- While (Result<Count) and (DoCompareText(Strings[Result],S)<>0) do Result:=Result+1;
- if Result=Count then Result:=-1;
- end;
- function TStrings.IndexOfName(const Name: string): Integer;
- Var
- len : longint;
- S : String;
- begin
- CheckSpecialChars;
- Result:=0;
- while (Result<Count) do
- begin
- S:=Strings[Result];
- len:=pos(FNameValueSeparator,S)-1;
- if (len>=0) and (DoCompareText(Name,Copy(S,1,Len))=0) then
- exit;
- inc(result);
- end;
- result:=-1;
- end;
- function TStrings.IndexOfObject(AObject: TObject): Integer;
- begin
- Result:=0;
- While (Result<count) and (Objects[Result]<>AObject) do Result:=Result+1;
- If Result=Count then Result:=-1;
- end;
- procedure TStrings.InsertObject(Index: Integer; const S: string; AObject: TObject);
- begin
- Insert (Index,S);
- Objects[Index]:=AObject;
- end;
- procedure TStrings.Move(CurIndex, NewIndex: Integer);
- Var
- Obj : TObject;
- Str : String;
- begin
- BeginUpdate;
- Try
- Obj:=Objects[CurIndex];
- Str:=Strings[CurIndex];
- Objects[CurIndex]:=Nil; // Prevent Delete from freeing.
- Delete(Curindex);
- InsertObject(NewIndex,Str,Obj);
- finally
- EndUpdate;
- end;
- end;
- {****************************************************************************}
- {* TStringList *}
- {****************************************************************************}
- procedure TStringList.ExchangeItemsInt(Index1, Index2: Integer);
- Var
- S : String;
- O : TObject;
- begin
- S:=Flist[Index1].FString;
- O:=Flist[Index1].FObject;
- Flist[Index1].Fstring:=Flist[Index2].Fstring;
- Flist[Index1].FObject:=Flist[Index2].FObject;
- Flist[Index2].Fstring:=S;
- Flist[Index2].FObject:=O;
- end;
- function TStringList.GetSorted: Boolean;
- begin
- Result:=FSortStyle in [sslUser,sslAuto];
- end;
- procedure TStringList.ExchangeItems(Index1, Index2: Integer);
- begin
- ExchangeItemsInt(Index1, Index2);
- end;
- procedure TStringList.Grow;
- Var
- NC : Integer;
- begin
- NC:=Capacity;
- If NC>=256 then
- NC:=NC+(NC Div 4)
- else if NC=0 then
- NC:=4
- else
- NC:=NC*4;
- SetCapacity(NC);
- end;
- procedure TStringList.InternalClear(FromIndex: Integer; ClearOnly: Boolean);
- Var
- I: Integer;
- begin
- if FromIndex < FCount then
- begin
- if FOwnsObjects then
- begin
- For I:=FromIndex to FCount-1 do
- begin
- Flist[I].FString:='';
- freeandnil(Flist[i].FObject);
- end;
- end
- else
- begin
- For I:=FromIndex to FCount-1 do
- Flist[I].FString:='';
- end;
- FCount:=FromIndex;
- end;
- if Not ClearOnly then
- SetCapacity(0);
- end;
- procedure TStringList.QuickSort(L, R: Integer; CompareFn: TStringListSortCompare
- );
- var
- Pivot, vL, vR: Integer;
- begin
- //if ExchangeItems is override call that, else call (faster) ExchangeItemsInt
- if R - L <= 1 then begin // a little bit of time saver
- if L < R then
- if CompareFn(Self, L, R) > 0 then
- ExchangeItems(L, R);
- Exit;
- end;
- vL := L;
- vR := R;
- Pivot := L + Random(R - L); // they say random is best
- while vL < vR do begin
- while (vL < Pivot) and (CompareFn(Self, vL, Pivot) <= 0) do
- Inc(vL);
- while (vR > Pivot) and (CompareFn(Self, vR, Pivot) > 0) do
- Dec(vR);
- ExchangeItems(vL, vR);
- if Pivot = vL then // swap pivot if we just hit it from one side
- Pivot := vR
- else if Pivot = vR then
- Pivot := vL;
- end;
- if Pivot - 1 >= L then
- QuickSort(L, Pivot - 1, CompareFn);
- if Pivot + 1 <= R then
- QuickSort(Pivot + 1, R, CompareFn);
- end;
- procedure TStringList.InsertItem(Index: Integer; const S: string);
- begin
- InsertItem(Index, S, nil);
- end;
- procedure TStringList.InsertItem(Index: Integer; const S: string; O: TObject);
- Var
- It : TStringItem;
-
- begin
- Changing;
- If FCount=Capacity then Grow;
- it.FString:=S;
- it.FObject:=O;
- TJSArray(FList).Splice(Index,0,It);
- Inc(FCount);
- Changed;
- end;
- procedure TStringList.SetSorted(Value: Boolean);
- begin
- If Value then
- SortStyle:=sslAuto
- else
- SortStyle:=sslNone
- end;
- procedure TStringList.Changed;
- begin
- If (FUpdateCount=0) Then
- begin
- If Assigned(FOnChange) then
- FOnchange(Self);
- end;
- end;
- procedure TStringList.Changing;
- begin
- If FUpdateCount=0 then
- if Assigned(FOnChanging) then
- FOnchanging(Self);
- end;
- function TStringList.Get(Index: Integer): string;
- begin
- CheckIndex(Index);
- Result:=Flist[Index].FString;
- end;
- function TStringList.GetCapacity: Integer;
- begin
- Result:=Length(FList);
- end;
- function TStringList.GetCount: Integer;
- begin
- Result:=FCount;
- end;
- function TStringList.GetObject(Index: Integer): TObject;
- begin
- CheckIndex(Index);
- Result:=Flist[Index].FObject;
- end;
- procedure TStringList.Put(Index: Integer; const S: string);
- begin
- If Sorted then
- Error(SSortedListError,0);
- CheckIndex(Index);
- Changing;
- Flist[Index].FString:=S;
- Changed;
- end;
- procedure TStringList.PutObject(Index: Integer; AObject: TObject);
- begin
- CheckIndex(Index);
- Changing;
- Flist[Index].FObject:=AObject;
- Changed;
- end;
- procedure TStringList.SetCapacity(NewCapacity: Integer);
- begin
- If (NewCapacity<0) then
- Error (SListCapacityError,NewCapacity);
- If NewCapacity<>Capacity then
- SetLength(FList,NewCapacity)
- end;
- procedure TStringList.SetUpdateState(Updating: Boolean);
- begin
- If Updating then
- Changing
- else
- Changed
- end;
- destructor TStringList.Destroy;
- begin
- InternalClear;
- Inherited destroy;
- end;
- function TStringList.Add(const S: string): Integer;
- begin
- If Not (SortStyle=sslAuto) then
- Result:=FCount
- else
- If Find (S,Result) then
- Case DUplicates of
- DupIgnore : Exit;
- DupError : Error(SDuplicateString,0)
- end;
- InsertItem (Result,S);
- end;
- procedure TStringList.Clear;
- begin
- if FCount = 0 then Exit;
- Changing;
- InternalClear;
- Changed;
- end;
- procedure TStringList.Delete(Index: Integer);
- begin
- CheckIndex(Index);
- Changing;
- if FOwnsObjects then
- FreeAndNil(Flist[Index].FObject);
- TJSArray(FList).splice(Index,1);
- FList[Count-1].FString:='';
- Flist[Count-1].FObject:=Nil;
- Dec(FCount);
- Changed;
- end;
- procedure TStringList.Exchange(Index1, Index2: Integer);
- begin
- CheckIndex(Index1);
- CheckIndex(Index2);
- Changing;
- ExchangeItemsInt(Index1,Index2);
- changed;
- end;
- procedure TStringList.SetCaseSensitive(b : boolean);
- begin
- if b=FCaseSensitive then
- Exit;
- FCaseSensitive:=b;
- if FSortStyle=sslAuto then
- begin
- FForceSort:=True;
- try
- Sort;
- finally
- FForceSort:=False;
- end;
- end;
- end;
- procedure TStringList.SetSortStyle(AValue: TStringsSortStyle);
- begin
- if FSortStyle=AValue then Exit;
- if (AValue=sslAuto) then
- Sort;
- FSortStyle:=AValue;
- end;
- procedure TStringList.CheckIndex(AIndex: Integer);
- begin
- If (AIndex<0) or (AIndex>=FCount) then
- Error(SListIndexError,AIndex);
- end;
- function TStringList.DoCompareText(const s1, s2: string): PtrInt;
- begin
- if FCaseSensitive then
- result:=CompareStr(s1,s2)
- else
- result:=CompareText(s1,s2);
- end;
- function TStringList.CompareStrings(const s1,s2 : string) : Integer;
- begin
- Result := DoCompareText(s1, s2);
- end;
- function TStringList.Find(const S: string; out Index: Integer): Boolean;
- var
- L, R, I: Integer;
- CompareRes: PtrInt;
- begin
- Result := false;
- Index:=-1;
- if Not Sorted then
- Raise EListError.Create(SErrFindNeedsSortedList);
- // Use binary search.
- L := 0;
- R := Count - 1;
- while (L<=R) do
- begin
- I := L + (R - L) div 2;
- CompareRes := DoCompareText(S, Flist[I].FString);
- if (CompareRes>0) then
- L := I+1
- else begin
- R := I-1;
- if (CompareRes=0) then begin
- Result := true;
- if (Duplicates<>dupAccept) then
- L := I; // forces end of while loop
- end;
- end;
- end;
- Index := L;
- end;
- function TStringList.IndexOf(const S: string): Integer;
- begin
- If Not Sorted then
- Result:=Inherited indexOf(S)
- else
- // faster using binary search...
- If Not Find (S,Result) then
- Result:=-1;
- end;
- procedure TStringList.Insert(Index: Integer; const S: string);
- begin
- If SortStyle=sslAuto then
- Error (SSortedListError,0)
- else
- begin
- If (Index<0) or (Index>FCount) then
- Error(SListIndexError,Index); // Cannot use CheckIndex, because there >= FCount...
- InsertItem (Index,S);
- end;
- end;
- procedure TStringList.CustomSort(CompareFn: TStringListSortCompare);
- begin
- If (FForceSort or (Not (FSortStyle=sslAuto))) and (FCount>1) then
- begin
- Changing;
- QuickSort(0,FCount-1, CompareFn);
- Changed;
- end;
- end;
- function StringListAnsiCompare(List: TStringList; Index1, Index: Integer): Integer;
- begin
- Result := List.DoCompareText(List.FList[Index1].FString,
- List.FList[Index].FString);
- end;
- procedure TStringList.Sort;
- begin
- CustomSort(@StringListAnsiCompare);
- end;
- {****************************************************************************}
- {* TCollectionItem *}
- {****************************************************************************}
- function TCollectionItem.GetIndex: Integer;
- begin
- if Assigned(FCollection) then
- Result:=FCollection.FItems.IndexOf(Self)
- else
- Result:=-1;
- end;
- procedure TCollectionItem.SetCollection(Value: TCollection);
- begin
- IF Value<>FCollection then
- begin
- if Assigned(FCollection) then FCollection.RemoveItem(Self);
- if Assigned(Value) then Value.InsertItem(Self);
- end;
- end;
- procedure TCollectionItem.Changed(AllItems: Boolean);
- begin
- If (FCollection<>Nil) and (FCollection.UpdateCount=0) then
- begin
- If AllItems then
- FCollection.Update(Nil)
- else
- FCollection.Update(Self);
- end;
- end;
- function TCollectionItem.GetNamePath: string;
- begin
- If FCollection<>Nil then
- Result:=FCollection.GetNamePath+'['+IntToStr(Index)+']'
- else
- Result:=ClassName;
- end;
- function TCollectionItem.GetOwner: TPersistent;
- begin
- Result:=FCollection;
- end;
- function TCollectionItem.GetDisplayName: string;
- begin
- Result:=ClassName;
- end;
- procedure TCollectionItem.SetIndex(Value: Integer);
- Var Temp : Longint;
- begin
- Temp:=GetIndex;
- If (Temp>-1) and (Temp<>Value) then
- begin
- FCollection.FItems.Move(Temp,Value);
- Changed(True);
- end;
- end;
- procedure TCollectionItem.SetDisplayName(const Value: string);
- begin
- Changed(False);
- if Value='' then ;
- end;
- constructor TCollectionItem.Create(ACollection: TCollection);
- begin
- Inherited Create;
- SetCollection(ACollection);
- end;
- destructor TCollectionItem.Destroy;
- begin
- SetCollection(Nil);
- Inherited Destroy;
- end;
- {****************************************************************************}
- {* TCollectionEnumerator *}
- {****************************************************************************}
- constructor TCollectionEnumerator.Create(ACollection: TCollection);
- begin
- inherited Create;
- FCollection := ACollection;
- FPosition := -1;
- end;
- function TCollectionEnumerator.GetCurrent: TCollectionItem;
- begin
- Result := FCollection.Items[FPosition];
- end;
- function TCollectionEnumerator.MoveNext: Boolean;
- begin
- Inc(FPosition);
- Result := FPosition < FCollection.Count;
- end;
- {****************************************************************************}
- {* TCollection *}
- {****************************************************************************}
- function TCollection.Owner: TPersistent;
- begin
- result:=getowner;
- end;
- function TCollection.GetCount: Integer;
- begin
- Result:=FItems.Count;
- end;
- Procedure TCollection.SetPropName;
- {
- Var
- TheOwner : TPersistent;
- PropList : PPropList;
- I, PropCount : Integer;
- }
- begin
- FPropName:='';
- {
- TheOwner:=GetOwner;
- // TODO: This needs to wait till Mattias finishes typeinfo.
- // It's normally only used in the designer so should not be a problem currently.
- if (TheOwner=Nil) Or (TheOwner.Classinfo=Nil) Then Exit;
- // get information from the owner RTTI
- PropCount:=GetPropList(TheOwner, PropList);
- Try
- For I:=0 To PropCount-1 Do
- If (PropList^[i]^.PropType^.Kind=tkClass) And
- (GetObjectProp(TheOwner, PropList^[i], ClassType)=Self) Then
- Begin
- FPropName:=PropList^[i]^.Name;
- Exit;
- End;
- Finally
- FreeMem(PropList);
- End;
- }
- end;
- function TCollection.GetPropName: string;
- {Var
- TheOwner : TPersistent;}
- begin
- Result:=FPropNAme;
- // TheOwner:=GetOwner;
- // If (Result<>'') or (TheOwner=Nil) Or (TheOwner.Classinfo=Nil) then exit;
- SetPropName;
- Result:=FPropName;
- end;
- procedure TCollection.InsertItem(Item: TCollectionItem);
- begin
- If Not(Item Is FitemClass) then
- exit;
- FItems.add(Item);
- Item.FCollection:=Self;
- Item.FID:=FNextID;
- inc(FNextID);
- SetItemName(Item);
- Notify(Item,cnAdded);
- Changed;
- end;
- procedure TCollection.RemoveItem(Item: TCollectionItem);
- Var
- I : Integer;
- begin
- Notify(Item,cnExtracting);
- I:=FItems.IndexOfItem(Item,fromEnd);
- If (I<>-1) then
- FItems.Delete(I);
- Item.FCollection:=Nil;
- Changed;
- end;
- function TCollection.GetAttrCount: Integer;
- begin
- Result:=0;
- end;
- function TCollection.GetAttr(Index: Integer): string;
- begin
- Result:='';
- if Index=0 then ;
- end;
- function TCollection.GetItemAttr(Index, ItemIndex: Integer): string;
- begin
- Result:=TCollectionItem(FItems.Items[ItemIndex]).DisplayName;
- if Index=0 then ;
- end;
- function TCollection.GetEnumerator: TCollectionEnumerator;
- begin
- Result := TCollectionEnumerator.Create(Self);
- end;
- function TCollection.GetNamePath: string;
- var o : TPersistent;
- begin
- o:=getowner;
- if assigned(o) and (propname<>'') then
- result:=o.getnamepath+'.'+propname
- else
- result:=classname;
- end;
- procedure TCollection.Changed;
- begin
- if FUpdateCount=0 then
- Update(Nil);
- end;
- function TCollection.GetItem(Index: Integer): TCollectionItem;
- begin
- Result:=TCollectionItem(FItems.Items[Index]);
- end;
- procedure TCollection.SetItem(Index: Integer; Value: TCollectionItem);
- begin
- TCollectionItem(FItems.items[Index]).Assign(Value);
- end;
- procedure TCollection.SetItemName(Item: TCollectionItem);
- begin
- if Item=nil then ;
- end;
- procedure TCollection.Update(Item: TCollectionItem);
- begin
- if Item=nil then ;
- end;
- constructor TCollection.Create(AItemClass: TCollectionItemClass);
- begin
- inherited create;
- FItemClass:=AItemClass;
- FItems:=TFpList.Create;
- end;
- destructor TCollection.Destroy;
- begin
- FUpdateCount:=1; // Prevent OnChange
- try
- DoClear;
- Finally
- FUpdateCount:=0;
- end;
- if assigned(FItems) then
- FItems.Destroy;
- Inherited Destroy;
- end;
- function TCollection.Add: TCollectionItem;
- begin
- Result:=FItemClass.Create(Self);
- end;
- procedure TCollection.Assign(Source: TPersistent);
- Var I : Longint;
- begin
- If Source is TCollection then
- begin
- Clear;
- For I:=0 To TCollection(Source).Count-1 do
- Add.Assign(TCollection(Source).Items[I]);
- exit;
- end
- else
- Inherited Assign(Source);
- end;
- procedure TCollection.BeginUpdate;
- begin
- inc(FUpdateCount);
- end;
- procedure TCollection.Clear;
- begin
- if FItems.Count=0 then
- exit; // Prevent Changed
- BeginUpdate;
- try
- DoClear;
- finally
- EndUpdate;
- end;
- end;
- procedure TCollection.DoClear;
- var
- Item: TCollectionItem;
- begin
- While FItems.Count>0 do
- begin
- Item:=TCollectionItem(FItems.Last);
- if Assigned(Item) then
- Item.Destroy;
- end;
- end;
- procedure TCollection.EndUpdate;
- begin
- if FUpdateCount>0 then
- dec(FUpdateCount);
- if FUpdateCount=0 then
- Changed;
- end;
- function TCollection.FindItemID(ID: Integer): TCollectionItem;
- Var
- I : Longint;
- begin
- For I:=0 to Fitems.Count-1 do
- begin
- Result:=TCollectionItem(FItems.items[I]);
- If Result.Id=Id then
- exit;
- end;
- Result:=Nil;
- end;
- procedure TCollection.Delete(Index: Integer);
- Var
- Item : TCollectionItem;
- begin
- Item:=TCollectionItem(FItems[Index]);
- Notify(Item,cnDeleting);
- If assigned(Item) then
- Item.Destroy;
- end;
- function TCollection.Insert(Index: Integer): TCollectionItem;
- begin
- Result:=Add;
- Result.Index:=Index;
- end;
- procedure TCollection.Notify(Item: TCollectionItem;Action: TCollectionNotification);
- begin
- if Item=nil then ;
- if Action=cnAdded then ;
- end;
- procedure TCollection.Sort(Const Compare : TCollectionSortCompare);
- begin
- BeginUpdate;
- try
- FItems.Sort(TListSortCompare(Compare));
- Finally
- EndUpdate;
- end;
- end;
- procedure TCollection.SortList(const Compare: TCollectionSortCompareFunc);
- begin
- BeginUpdate;
- try
- FItems.SortList(TListSortCompareFunc(Compare));
- Finally
- EndUpdate;
- end;
- end;
- procedure TCollection.Exchange(Const Index1, index2: integer);
- begin
- FItems.Exchange(Index1,Index2);
- end;
- {****************************************************************************}
- {* TOwnedCollection *}
- {****************************************************************************}
- Constructor TOwnedCollection.Create(AOwner: TPersistent; AItemClass: TCollectionItemClass);
- Begin
- FOwner := AOwner;
- inherited Create(AItemClass);
- end;
- Function TOwnedCollection.GetOwner: TPersistent;
- begin
- Result:=FOwner;
- end;
- {****************************************************************************}
- {* TComponent *}
- {****************************************************************************}
- function TComponent.GetComponent(AIndex: Integer): TComponent;
- begin
- If not assigned(FComponents) then
- Result:=Nil
- else
- Result:=TComponent(FComponents.Items[Aindex]);
- end;
- function TComponent.GetComponentCount: Integer;
- begin
- If not assigned(FComponents) then
- result:=0
- else
- Result:=FComponents.Count;
- end;
- function TComponent.GetComponentIndex: Integer;
- begin
- If Assigned(FOwner) and Assigned(FOwner.FComponents) then
- Result:=FOWner.FComponents.IndexOf(Self)
- else
- Result:=-1;
- end;
- procedure TComponent.Insert(AComponent: TComponent);
- begin
- If not assigned(FComponents) then
- FComponents:=TFpList.Create;
- FComponents.Add(AComponent);
- AComponent.FOwner:=Self;
- end;
- procedure TComponent.ReadLeft(AReader: TReader);
- begin
- FDesignInfo := (FDesignInfo and $ffff0000) or (AReader.ReadInteger and $ffff);
- end;
- procedure TComponent.ReadTop(AReader: TReader);
- begin
- FDesignInfo := ((AReader.ReadInteger and $ffff) shl 16) or (FDesignInfo and $ffff);
- end;
- procedure TComponent.Remove(AComponent: TComponent);
- begin
- AComponent.FOwner:=Nil;
- If assigned(FCOmponents) then
- begin
- FComponents.Remove(AComponent);
- IF FComponents.Count=0 then
- begin
- FComponents.Destroy;
- FComponents:=Nil;
- end;
- end;
- end;
- procedure TComponent.RemoveNotification(AComponent: TComponent);
- begin
- if FFreeNotifies<>nil then
- begin
- FFreeNotifies.Remove(AComponent);
- if FFreeNotifies.Count=0 then
- begin
- FFreeNotifies.Destroy;
- FFreeNotifies:=nil;
- Exclude(FComponentState,csFreeNotification);
- end;
- end;
- end;
- procedure TComponent.SetComponentIndex(Value: Integer);
- Var Temp,Count : longint;
- begin
- If Not assigned(Fowner) then exit;
- Temp:=getcomponentindex;
- If temp<0 then exit;
- If value<0 then value:=0;
- Count:=Fowner.FComponents.Count;
- If Value>=Count then value:=count-1;
- If Value<>Temp then
- begin
- FOWner.FComponents.Delete(Temp);
- FOwner.FComponents.Insert(Value,Self);
- end;
- end;
- procedure TComponent.ChangeName(const NewName: TComponentName);
- begin
- FName:=NewName;
- end;
- procedure TComponent.DefineProperties(Filer: TFiler);
- var
- Temp: LongInt;
- Ancestor: TComponent;
- begin
- Ancestor := TComponent(Filer.Ancestor);
- if Assigned(Ancestor) then
- Temp := Ancestor.FDesignInfo
- else
- Temp := 0;
- Filer.DefineProperty('Left', @ReadLeft, @WriteLeft, (FDesignInfo and $ffff) <> (Temp and $ffff));
- Filer.DefineProperty('Top', @ReadTop, @WriteTop, (FDesignInfo and $ffff0000) <> (Temp and $ffff0000));
- end;
- procedure TComponent.GetChildren(Proc: TGetChildProc; Root: TComponent);
- begin
- // Does nothing.
- if Proc=nil then ;
- if Root=nil then ;
- end;
- function TComponent.GetChildOwner: TComponent;
- begin
- Result:=Nil;
- end;
- function TComponent.GetChildParent: TComponent;
- begin
- Result:=Self;
- end;
- function TComponent.GetNamePath: string;
- begin
- Result:=FName;
- end;
- function TComponent.GetOwner: TPersistent;
- begin
- Result:=FOwner;
- end;
- procedure TComponent.Loaded;
- begin
- Exclude(FComponentState,csLoading);
- end;
- procedure TComponent.Loading;
- begin
- Include(FComponentState,csLoading);
- end;
- procedure TComponent.SetWriting(Value: Boolean);
- begin
- If Value then
- Include(FComponentState,csWriting)
- else
- Exclude(FComponentState,csWriting);
- end;
- procedure TComponent.SetReading(Value: Boolean);
- begin
- If Value then
- Include(FComponentState,csReading)
- else
- Exclude(FComponentState,csReading);
- end;
- procedure TComponent.Notification(AComponent: TComponent; Operation: TOperation);
- Var
- C : Longint;
- begin
- If (Operation=opRemove) then
- RemoveFreeNotification(AComponent);
- If Not assigned(FComponents) then
- exit;
- C:=FComponents.Count-1;
- While (C>=0) do
- begin
- TComponent(FComponents.Items[C]).Notification(AComponent,Operation);
- Dec(C);
- if C>=FComponents.Count then
- C:=FComponents.Count-1;
- end;
- end;
- procedure TComponent.PaletteCreated;
- begin
- end;
- procedure TComponent.ReadState(Reader: TReader);
- begin
- Reader.ReadData(Self);
- end;
- procedure TComponent.SetAncestor(Value: Boolean);
- Var Runner : Longint;
- begin
- If Value then
- Include(FComponentState,csAncestor)
- else
- Exclude(FCOmponentState,csAncestor);
- if Assigned(FComponents) then
- For Runner:=0 To FComponents.Count-1 do
- TComponent(FComponents.Items[Runner]).SetAncestor(Value);
- end;
- procedure TComponent.SetDesigning(Value: Boolean; SetChildren: Boolean);
- Var Runner : Longint;
- begin
- If Value then
- Include(FComponentState,csDesigning)
- else
- Exclude(FComponentState,csDesigning);
- if Assigned(FComponents) and SetChildren then
- For Runner:=0 To FComponents.Count - 1 do
- TComponent(FComponents.items[Runner]).SetDesigning(Value);
- end;
- procedure TComponent.SetDesignInstance(Value: Boolean);
- begin
- If Value then
- Include(FComponentState,csDesignInstance)
- else
- Exclude(FComponentState,csDesignInstance);
- end;
- procedure TComponent.SetInline(Value: Boolean);
- begin
- If Value then
- Include(FComponentState,csInline)
- else
- Exclude(FComponentState,csInline);
- end;
- procedure TComponent.SetName(const NewName: TComponentName);
- begin
- If FName=NewName then exit;
- If (NewName<>'') and not IsValidIdent(NewName) then
- Raise EComponentError.CreateFmt(SInvalidName,[NewName]);
- If Assigned(FOwner) Then
- FOwner.ValidateRename(Self,FName,NewName)
- else
- ValidateRename(Nil,FName,NewName);
- SetReference(False);
- ChangeName(NewName);
- SetReference(True);
- end;
- procedure TComponent.SetChildOrder(Child: TComponent; Order: Integer);
- begin
- // does nothing
- if Child=nil then ;
- if Order=0 then ;
- end;
- procedure TComponent.SetParentComponent(Value: TComponent);
- begin
- // Does nothing
- if Value=nil then ;
- end;
- procedure TComponent.Updating;
- begin
- Include (FComponentState,csUpdating);
- end;
- procedure TComponent.Updated;
- begin
- Exclude(FComponentState,csUpdating);
- end;
- procedure TComponent.ValidateRename(AComponent: TComponent; const CurName, NewName: string);
- begin
- //!! This contradicts the Delphi manual.
- If (AComponent<>Nil) and (CompareText(CurName,NewName)<>0) and (AComponent.Owner = Self) and
- (FindComponent(NewName)<>Nil) then
- raise EComponentError.Createfmt(SDuplicateName,[newname]);
- If (csDesigning in FComponentState) and (FOwner<>Nil) then
- FOwner.ValidateRename(AComponent,Curname,Newname);
- end;
- Procedure TComponent.SetReference(Enable: Boolean);
- var
- aField, aValue, aOwner : Pointer;
- begin
- if Name='' then
- exit;
- if Assigned(Owner) then
- begin
- aOwner:=Owner; // so as not to depend on low-level names
- aField := Owner.FieldAddress(Name);
- if Assigned(aField) then
- begin
- if Enable then
- aValue:= Self
- else
- aValue := nil;
- TJSObject(aOwner)[String(TJSObject(aField)['name'])]:=aValue;
- end;
- end;
- end;
- procedure TComponent.WriteLeft(AWriter: TWriter);
- begin
- AWriter.WriteInteger(FDesignInfo and $ffff);
- end;
- procedure TComponent.WriteTop(AWriter: TWriter);
- begin
- AWriter.WriteInteger((FDesignInfo shr 16) and $ffff);
- end;
- procedure TComponent.ValidateContainer(AComponent: TComponent);
- begin
- AComponent.ValidateInsert(Self);
- end;
- procedure TComponent.ValidateInsert(AComponent: TComponent);
- begin
- // Does nothing.
- if AComponent=nil then ;
- end;
- function TComponent._AddRef: Integer;
- begin
- Result:=-1;
- end;
- function TComponent._Release: Integer;
- begin
- Result:=-1;
- end;
- constructor TComponent.Create(AOwner: TComponent);
- begin
- FComponentStyle:=[csInheritable];
- If Assigned(AOwner) then AOwner.InsertComponent(Self);
- end;
- destructor TComponent.Destroy;
- Var
- I : Integer;
- C : TComponent;
- begin
- Destroying;
- If Assigned(FFreeNotifies) then
- begin
- I:=FFreeNotifies.Count-1;
- While (I>=0) do
- begin
- C:=TComponent(FFreeNotifies.Items[I]);
- // Delete, so one component is not notified twice, if it is owned.
- FFreeNotifies.Delete(I);
- C.Notification (self,opRemove);
- If (FFreeNotifies=Nil) then
- I:=0
- else if (I>FFreeNotifies.Count) then
- I:=FFreeNotifies.Count;
- dec(i);
- end;
- FreeAndNil(FFreeNotifies);
- end;
- DestroyComponents;
- If FOwner<>Nil Then FOwner.RemoveComponent(Self);
- inherited destroy;
- end;
- procedure TComponent.BeforeDestruction;
- begin
- if not(csDestroying in FComponentstate) then
- Destroying;
- end;
- procedure TComponent.DestroyComponents;
- Var acomponent: TComponent;
- begin
- While assigned(FComponents) do
- begin
- aComponent:=TComponent(FComponents.Last);
- Remove(aComponent);
- Acomponent.Destroy;
- end;
- end;
- procedure TComponent.Destroying;
- Var Runner : longint;
- begin
- If csDestroying in FComponentstate Then Exit;
- include (FComponentState,csDestroying);
- If Assigned(FComponents) then
- for Runner:=0 to FComponents.Count-1 do
- TComponent(FComponents.Items[Runner]).Destroying;
- end;
- function TComponent.QueryInterface(const IID: TGUID; out Obj): HRESULT;
- begin
- if GetInterface(IID, Obj) then
- Result := S_OK
- else
- Result := E_NOINTERFACE;
- end;
- procedure TComponent.WriteState(Writer: TWriter);
- begin
- Writer.WriteComponentData(Self);
- end;
- function TComponent.FindComponent(const AName: string): TComponent;
- Var I : longint;
- begin
- Result:=Nil;
- If (AName='') or Not assigned(FComponents) then exit;
- For i:=0 to FComponents.Count-1 do
- if (CompareText(TComponent(FComponents[I]).Name,AName)=0) then
- begin
- Result:=TComponent(FComponents.Items[I]);
- exit;
- end;
- end;
- procedure TComponent.FreeNotification(AComponent: TComponent);
- begin
- If (Owner<>Nil) and (AComponent=Owner) then exit;
- If not (Assigned(FFreeNotifies)) then
- FFreeNotifies:=TFpList.Create;
- If FFreeNotifies.IndexOf(AComponent)=-1 then
- begin
- FFreeNotifies.Add(AComponent);
- AComponent.FreeNotification (self);
- end;
- end;
- procedure TComponent.RemoveFreeNotification(AComponent: TComponent);
- begin
- RemoveNotification(AComponent);
- AComponent.RemoveNotification (self);
- end;
- function TComponent.GetParentComponent: TComponent;
- begin
- Result:=Nil;
- end;
- function TComponent.HasParent: Boolean;
- begin
- Result:=False;
- end;
- procedure TComponent.InsertComponent(AComponent: TComponent);
- begin
- AComponent.ValidateContainer(Self);
- ValidateRename(AComponent,'',AComponent.FName);
- Insert(AComponent);
- If csDesigning in FComponentState then
- AComponent.SetDesigning(true);
- Notification(AComponent,opInsert);
- end;
- procedure TComponent.RemoveComponent(AComponent: TComponent);
- begin
- Notification(AComponent,opRemove);
- Remove(AComponent);
- Acomponent.Setdesigning(False);
- ValidateRename(AComponent,AComponent.FName,'');
- end;
- procedure TComponent.SetSubComponent(ASubComponent: Boolean);
- begin
- if ASubComponent then
- Include(FComponentStyle, csSubComponent)
- else
- Exclude(FComponentStyle, csSubComponent);
- end;
- function TComponent.GetEnumerator: TComponentEnumerator;
- begin
- Result:=TComponentEnumerator.Create(Self);
- end;
- { ---------------------------------------------------------------------
- TStream
- ---------------------------------------------------------------------}
- Resourcestring
- SStreamInvalidSeek = 'Seek is not implemented for class %s';
- SStreamNoReading = 'Stream reading is not implemented for class %s';
- SStreamNoWriting = 'Stream writing is not implemented for class %s';
- SReadError = 'Could not read data from stream';
- SWriteError = 'Could not write data to stream';
- SMemoryStreamError = 'Could not allocate memory';
- SerrInvalidStreamSize = 'Invalid Stream size';
- procedure TStream.ReadNotImplemented;
- begin
- raise EStreamError.CreateFmt(SStreamNoReading, [ClassName]);
- end;
- procedure TStream.WriteNotImplemented;
- begin
- raise EStreamError.CreateFmt(SStreamNoWriting, [ClassName]);
- end;
- function TStream.Read(var Buffer: TBytes; Count: Longint): Longint;
- begin
- Result:=Read(Buffer,0,Count);
- end;
- function TStream.Write(const Buffer: TBytes; Count: Longint): Longint;
- begin
- Result:=Self.Write(Buffer,0,Count);
- end;
- function TStream.GetPosition: NativeInt;
- begin
- Result:=Seek(0,soCurrent);
- end;
- procedure TStream.SetPosition(const Pos: NativeInt);
- begin
- Seek(pos,soBeginning);
- end;
- procedure TStream.SetSize64(const NewSize: NativeInt);
- begin
- // Required because can't use overloaded functions in properties
- SetSize(NewSize);
- end;
- function TStream.GetSize: NativeInt;
- var
- p : NativeInt;
- begin
- p:=Seek(0,soCurrent);
- GetSize:=Seek(0,soEnd);
- Seek(p,soBeginning);
- end;
- procedure TStream.SetSize(const NewSize: NativeInt);
- begin
- if NewSize<0 then
- Raise EStreamError.Create(SerrInvalidStreamSize);
- end;
- procedure TStream.Discard(const Count: NativeInt);
- const
- CSmallSize =255;
- CLargeMaxBuffer =32*1024; // 32 KiB
- var
- Buffer: TBytes;
- begin
- if Count=0 then
- Exit;
- if (Count<=CSmallSize) then
- begin
- SetLength(Buffer,CSmallSize);
- ReadBuffer(Buffer,Count)
- end
- else
- DiscardLarge(Count,CLargeMaxBuffer);
- end;
- procedure TStream.DiscardLarge(Count: NativeInt; const MaxBufferSize: Longint);
- var
- Buffer: TBytes;
- begin
- if Count=0 then
- Exit;
- if Count>MaxBufferSize then
- SetLength(Buffer,MaxBufferSize)
- else
- SetLength(Buffer,Count);
- while (Count>=Length(Buffer)) do
- begin
- ReadBuffer(Buffer,Length(Buffer));
- Dec(Count,Length(Buffer));
- end;
- if Count>0 then
- ReadBuffer(Buffer,Count);
- end;
- procedure TStream.InvalidSeek;
- begin
- raise EStreamError.CreateFmt(SStreamInvalidSeek, [ClassName]);
- end;
- procedure TStream.FakeSeekForward(Offset: NativeInt; const Origin: TSeekOrigin; const Pos: NativeInt);
- begin
- if Origin=soBeginning then
- Dec(Offset,Pos);
- if (Offset<0) or (Origin=soEnd) then
- InvalidSeek;
- if Offset>0 then
- Discard(Offset);
- end;
- function TStream.ReadData({var} Buffer: TBytes; Count: NativeInt): NativeInt;
- begin
- Result:=Read(Buffer,0,Count);
- end;
- function TStream.ReadMaxSizeData(Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
- Var
- CP : NativeInt;
- begin
- if aCount<=aSize then
- Result:=read(Buffer,aCount)
- else
- begin
- Result:=Read(Buffer,aSize);
- CP:=Position;
- Result:=Result+Seek(aCount-aSize,soCurrent)-CP;
- end
- end;
- function TStream.WriteMaxSizeData(const Buffer : TBytes; aSize,aCount : NativeInt) : NativeInt;
- Var
- CP : NativeInt;
- begin
- if aCount<=aSize then
- Result:=Self.Write(Buffer,aCount)
- else
- begin
- Result:=Self.Write(Buffer,aSize);
- CP:=Position;
- Result:=Result+Seek(aCount-aSize,soCurrent)-CP;
- end
- end;
- procedure TStream.WriteExactSizeData(const Buffer : TBytes; aSize, aCount: NativeInt);
- begin
- // Embarcadero docs mentions no exception. Does not seem very logical
- WriteMaxSizeData(Buffer,aSize,ACount);
- end;
- procedure TStream.ReadExactSizeData(Buffer : TBytes; aSize, aCount: NativeInt);
- begin
- if ReadMaxSizeData(Buffer,aSize,ACount)<>aCount then
- Raise EReadError.Create(SReadError);
- end;
- function TStream.ReadData(var Buffer: Boolean): NativeInt;
- Var
- B : Byte;
- begin
- Result:=ReadData(B,1);
- if Result=1 then
- Buffer:=B<>0;
- end;
- function TStream.ReadData(var Buffer: Boolean; Count: NativeInt): NativeInt;
- Var
- B : TBytes;
- begin
- SetLength(B,Count);
- Result:=ReadMaxSizeData(B,1,Count);
- if Result>0 then
- Buffer:=B[0]<>0
- end;
- function TStream.ReadData(var Buffer: WideChar): NativeInt;
- begin
- Result:=ReadData(Buffer,2);
- end;
- function TStream.ReadData(var Buffer: WideChar; Count: NativeInt): NativeInt;
- Var
- W : Word;
- begin
- Result:=ReadData(W,Count);
- if Result=2 then
- Buffer:=WideChar(W);
- end;
- function TStream.ReadData(var Buffer: Int8): NativeInt;
- begin
- Result:=ReadData(Buffer,1);
- end;
- Function TStream.MakeInt(B : TBytes; aSize : Integer; Signed : Boolean) : NativeInt;
- Var
- Mem : TJSArrayBuffer;
- A : TJSUInt8Array;
- D : TJSDataView;
- isLittle : Boolean;
- begin
- IsLittle:=(Endian=TEndian.Little);
- Mem:=TJSArrayBuffer.New(Length(B));
- A:=TJSUInt8Array.new(Mem);
- A._set(B);
- D:=TJSDataView.New(Mem);
- if Signed then
- case aSize of
- 1 : Result:=D.getInt8(0);
- 2 : Result:=D.getInt16(0,IsLittle);
- 4 : Result:=D.getInt32(0,IsLittle);
- // Todo : fix sign
- 8 : Result:=Round(D.getFloat64(0,IsLittle));
- end
- else
- case aSize of
- 1 : Result:=D.getUInt8(0);
- 2 : Result:=D.getUInt16(0,IsLittle);
- 4 : Result:=D.getUInt32(0,IsLittle);
- 8 : Result:=Round(D.getFloat64(0,IsLittle));
- end
- end;
- function TStream.MakeBytes(B: NativeInt; aSize: Integer; Signed: Boolean): TBytes;
- Var
- Mem : TJSArrayBuffer;
- A : TJSUInt8Array;
- D : TJSDataView;
- isLittle : Boolean;
- begin
- IsLittle:=(Endian=TEndian.Little);
- Mem:=TJSArrayBuffer.New(aSize);
- D:=TJSDataView.New(Mem);
- if Signed then
- case aSize of
- 1 : D.setInt8(0,B);
- 2 : D.setInt16(0,B,IsLittle);
- 4 : D.setInt32(0,B,IsLittle);
- 8 : D.setFloat64(0,B,IsLittle);
- end
- else
- case aSize of
- 1 : D.SetUInt8(0,B);
- 2 : D.SetUInt16(0,B,IsLittle);
- 4 : D.SetUInt32(0,B,IsLittle);
- 8 : D.setFloat64(0,B,IsLittle);
- end;
- SetLength(Result,aSize);
- A:=TJSUInt8Array.new(Mem);
- Result:=TMemoryStream.MemoryToBytes(A);
- end;
- function TStream.ReadData(var Buffer: Int8; Count: NativeInt): NativeInt;
- Var
- B : TBytes;
- begin
- SetLength(B,Count);
- Result:=ReadMaxSizeData(B,1,Count);
- if Result>=1 then
- Buffer:=MakeInt(B,1,True);
- end;
- function TStream.ReadData(var Buffer: UInt8): NativeInt;
- begin
- Result:=ReadData(Buffer,1);
- end;
- function TStream.ReadData(var Buffer: UInt8; Count: NativeInt): NativeInt;
- Var
- B : TBytes;
- begin
- SetLength(B,Count);
- Result:=ReadMaxSizeData(B,1,Count);
- if Result>=1 then
- Buffer:=MakeInt(B,1,False);
- end;
- function TStream.ReadData(var Buffer: Int16): NativeInt;
- begin
- Result:=ReadData(Buffer,2);
- end;
- function TStream.ReadData(var Buffer: Int16; Count: NativeInt): NativeInt;
- Var
- B : TBytes;
- begin
- SetLength(B,Count);
- Result:=ReadMaxSizeData(B,2,Count);
- if Result>=2 then
- Buffer:=MakeInt(B,2,True);
- end;
- function TStream.ReadData(var Buffer: UInt16): NativeInt;
- begin
- Result:=ReadData(Buffer,2);
- end;
- function TStream.ReadData(var Buffer: UInt16; Count: NativeInt): NativeInt;
- Var
- B : TBytes;
- begin
- SetLength(B,Count);
- Result:=ReadMaxSizeData(B,2,Count);
- if Result>=2 then
- Buffer:=MakeInt(B,2,False);
- end;
- function TStream.ReadData(var Buffer: Int32): NativeInt;
- begin
- Result:=ReadData(Buffer,4);
- end;
- function TStream.ReadData(var Buffer: Int32; Count: NativeInt): NativeInt;
- Var
- B : TBytes;
- begin
- SetLength(B,Count);
- Result:=ReadMaxSizeData(B,4,Count);
- if Result>=4 then
- Buffer:=MakeInt(B,4,True);
- end;
- function TStream.ReadData(var Buffer: UInt32): NativeInt;
- begin
- Result:=ReadData(Buffer,4);
- end;
- function TStream.ReadData(var Buffer: UInt32; Count: NativeInt): NativeInt;
- Var
- B : TBytes;
- begin
- SetLength(B,Count);
- Result:=ReadMaxSizeData(B,4,Count);
- if Result>=4 then
- Buffer:=MakeInt(B,4,False);
- end;
- function TStream.ReadData(var Buffer: NativeInt): NativeInt;
- begin
- Result:=ReadData(Buffer,8);
- end;
- function TStream.ReadData(var Buffer: NativeInt; Count: NativeInt): NativeInt;
- Var
- B : TBytes;
- begin
- SetLength(B,Count);
- Result:=ReadMaxSizeData(B,8,8);
- if Result>=8 then
- Buffer:=MakeInt(B,8,True);
- end;
- function TStream.ReadData(var Buffer: NativeLargeUInt): NativeInt;
- begin
- Result:=ReadData(Buffer,8);
- end;
- function TStream.ReadData(var Buffer: NativeLargeUInt; Count: NativeInt): NativeInt;
- Var
- B : TBytes;
- B1 : Integer;
- begin
- SetLength(B,Count);
- Result:=ReadMaxSizeData(B,4,4);
- if Result>=4 then
- begin
- B1:=MakeInt(B,4,False);
- Result:=Result+ReadMaxSizeData(B,4,4);
- Buffer:=MakeInt(B,4,False);
- Buffer:=(Buffer shl 32) or B1;
- end;
- end;
- function TStream.ReadData(var Buffer: Double): NativeInt;
- begin
- Result:=ReadData(Buffer,8);
- end;
- function TStream.ReadData(var Buffer: Double; Count: NativeInt): NativeInt;
- Var
- B : TBytes;
- Mem : TJSArrayBuffer;
- A : TJSUInt8Array;
- D : TJSDataView;
- begin
- SetLength(B,Count);
- Result:=ReadMaxSizeData(B,8,Count);
- if Result>=8 then
- begin
- Mem:=TJSArrayBuffer.New(8);
- A:=TJSUInt8Array.new(Mem);
- A._set(B);
- D:=TJSDataView.New(Mem);
- Buffer:=D.getFloat64(0);
- end;
- end;
- procedure TStream.ReadBuffer(var Buffer: TBytes; Count: NativeInt);
- begin
- ReadBuffer(Buffer,0,Count);
- end;
- procedure TStream.ReadBuffer(var Buffer: TBytes; Offset, Count: NativeInt);
- begin
- if Read(Buffer,OffSet,Count)<>Count then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: Boolean);
- begin
- ReadBufferData(Buffer,1);
- end;
- procedure TStream.ReadBufferData(var Buffer: Boolean; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: WideChar);
- begin
- ReadBufferData(Buffer,2);
- end;
- procedure TStream.ReadBufferData(var Buffer: WideChar; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: Int8);
- begin
- ReadBufferData(Buffer,1);
- end;
- procedure TStream.ReadBufferData(var Buffer: Int8; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: UInt8);
- begin
- ReadBufferData(Buffer,1);
- end;
- procedure TStream.ReadBufferData(var Buffer: UInt8; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: Int16);
- begin
- ReadBufferData(Buffer,2);
- end;
- procedure TStream.ReadBufferData(var Buffer: Int16; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: UInt16);
- begin
- ReadBufferData(Buffer,2);
- end;
- procedure TStream.ReadBufferData(var Buffer: UInt16; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: Int32);
- begin
- ReadBufferData(Buffer,4);
- end;
- procedure TStream.ReadBufferData(var Buffer: Int32; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: UInt32);
- begin
- ReadBufferData(Buffer,4);
- end;
- procedure TStream.ReadBufferData(var Buffer: UInt32; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: NativeLargeInt);
- begin
- ReadBufferData(Buffer,8)
- end;
- procedure TStream.ReadBufferData(var Buffer: NativeLargeInt; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: NativeLargeUInt);
- begin
- ReadBufferData(Buffer,8);
- end;
- procedure TStream.ReadBufferData(var Buffer: NativeLargeUInt; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.ReadBufferData(var Buffer: Double);
- begin
- ReadBufferData(Buffer,8);
- end;
- procedure TStream.ReadBufferData(var Buffer: Double; Count: NativeInt);
- begin
- if (ReadData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SReadError);
- end;
- procedure TStream.WriteBuffer(const Buffer: TBytes; Count: NativeInt);
- begin
- WriteBuffer(Buffer,0,Count);
- end;
- procedure TStream.WriteBuffer(const Buffer: TBytes; Offset, Count: NativeInt);
- begin
- if Self.Write(Buffer,Offset,Count)<>Count then
- Raise EStreamError.Create(SWriteError);
- end;
- function TStream.WriteData(const Buffer: TBytes; Count: NativeInt): NativeInt;
- begin
- Result:=Self.Write(Buffer, 0, Count);
- end;
- function TStream.WriteData(const Buffer: Boolean): NativeInt;
- begin
- Result:=WriteData(Buffer,1);
- end;
- function TStream.WriteData(const Buffer: Boolean; Count: NativeInt): NativeInt;
- Var
- B : Int8;
- begin
- B:=Ord(Buffer);
- Result:=WriteData(B,Count);
- end;
- function TStream.WriteData(const Buffer: WideChar): NativeInt;
- begin
- Result:=WriteData(Buffer,2);
- end;
- function TStream.WriteData(const Buffer: WideChar; Count: NativeInt): NativeInt;
- Var
- U : UInt16;
- begin
- U:=Ord(Buffer);
- Result:=WriteData(U,Count);
- end;
- function TStream.WriteData(const Buffer: Int8): NativeInt;
- begin
- Result:=WriteData(Buffer,1);
- end;
- function TStream.WriteData(const Buffer: Int8; Count: NativeInt): NativeInt;
- begin
- Result:=WriteMaxSizeData(MakeBytes(Buffer,1,True),1,Count);
- end;
- function TStream.WriteData(const Buffer: UInt8): NativeInt;
- begin
- Result:=WriteData(Buffer,1);
- end;
- function TStream.WriteData(const Buffer: UInt8; Count: NativeInt): NativeInt;
- begin
- Result:=WriteMaxSizeData(MakeBytes(Buffer,1,False),1,Count);
- end;
- function TStream.WriteData(const Buffer: Int16): NativeInt;
- begin
- Result:=WriteData(Buffer,2);
- end;
- function TStream.WriteData(const Buffer: Int16; Count: NativeInt): NativeInt;
- begin
- Result:=WriteMaxSizeData(MakeBytes(Buffer,2,True),2,Count);
- end;
- function TStream.WriteData(const Buffer: UInt16): NativeInt;
- begin
- Result:=WriteData(Buffer,2);
- end;
- function TStream.WriteData(const Buffer: UInt16; Count: NativeInt): NativeInt;
- begin
- Result:=WriteMaxSizeData(MakeBytes(Buffer,2,True),2,Count);
- end;
- function TStream.WriteData(const Buffer: Int32): NativeInt;
- begin
- Result:=WriteData(Buffer,4);
- end;
- function TStream.WriteData(const Buffer: Int32; Count: NativeInt): NativeInt;
- begin
- Result:=WriteMaxSizeData(MakeBytes(Buffer,4,True),4,Count);
- end;
- function TStream.WriteData(const Buffer: UInt32): NativeInt;
- begin
- Result:=WriteData(Buffer,4);
- end;
- function TStream.WriteData(const Buffer: UInt32; Count: NativeInt): NativeInt;
- begin
- Result:=WriteMaxSizeData(MakeBytes(Buffer,4,False),4,Count);
- end;
- function TStream.WriteData(const Buffer: NativeLargeInt): NativeInt;
- begin
- Result:=WriteData(Buffer,8);
- end;
- function TStream.WriteData(const Buffer: NativeLargeInt; Count: NativeInt): NativeInt;
- begin
- Result:=WriteMaxSizeData(MakeBytes(Buffer,8,True),8,Count);
- end;
- function TStream.WriteData(const Buffer: NativeLargeUInt): NativeInt;
- begin
- Result:=WriteData(Buffer,8);
- end;
- function TStream.WriteData(const Buffer: NativeLargeUInt; Count: NativeInt): NativeInt;
- begin
- Result:=WriteMaxSizeData(MakeBytes(Buffer,8,False),8,Count);
- end;
- function TStream.WriteData(const Buffer: Double): NativeInt;
- begin
- Result:=WriteData(Buffer,8);
- end;
- function TStream.WriteData(const Buffer: Double; Count: NativeInt): NativeInt;
- Var
- Mem : TJSArrayBuffer;
- A : TJSUint8array;
- D : TJSDataview;
- B : TBytes;
- I : Integer;
- begin
- Mem:=TJSArrayBuffer.New(8);
- D:=TJSDataView.new(Mem);
- D.setFloat64(0,Buffer);
- SetLength(B,8);
- A:=TJSUint8array.New(Mem);
- For I:=0 to 7 do
- B[i]:=A[i];
- Result:=WriteMaxSizeData(B,8,Count);
- end;
- procedure TStream.WriteBufferData(Buffer: Int32);
- begin
- WriteBufferData(Buffer,4);
- end;
- procedure TStream.WriteBufferData(Buffer: Int32; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- procedure TStream.WriteBufferData(Buffer: Boolean);
- begin
- WriteBufferData(Buffer,1);
- end;
- procedure TStream.WriteBufferData(Buffer: Boolean; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- procedure TStream.WriteBufferData(Buffer: WideChar);
- begin
- WriteBufferData(Buffer,2);
- end;
- procedure TStream.WriteBufferData(Buffer: WideChar; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- procedure TStream.WriteBufferData(Buffer: Int8);
- begin
- WriteBufferData(Buffer,1);
- end;
- procedure TStream.WriteBufferData(Buffer: Int8; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- procedure TStream.WriteBufferData(Buffer: UInt8);
- begin
- WriteBufferData(Buffer,1);
- end;
- procedure TStream.WriteBufferData(Buffer: UInt8; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- procedure TStream.WriteBufferData(Buffer: Int16);
- begin
- WriteBufferData(Buffer,2);
- end;
- procedure TStream.WriteBufferData(Buffer: Int16; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- procedure TStream.WriteBufferData(Buffer: UInt16);
- begin
- WriteBufferData(Buffer,2);
- end;
- procedure TStream.WriteBufferData(Buffer: UInt16; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- procedure TStream.WriteBufferData(Buffer: UInt32);
- begin
- WriteBufferData(Buffer,4);
- end;
- procedure TStream.WriteBufferData(Buffer: UInt32; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- procedure TStream.WriteBufferData(Buffer: NativeInt);
- begin
- WriteBufferData(Buffer,8);
- end;
- procedure TStream.WriteBufferData(Buffer: NativeInt; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- procedure TStream.WriteBufferData(Buffer: NativeLargeUInt);
- begin
- WriteBufferData(Buffer,8);
- end;
- procedure TStream.WriteBufferData(Buffer: NativeLargeUInt; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- procedure TStream.WriteBufferData(Buffer: Double);
- begin
- WriteBufferData(Buffer,8);
- end;
- procedure TStream.WriteBufferData(Buffer: Double; Count: NativeInt);
- begin
- if (WriteData(Buffer,Count)<>Count) then
- Raise EStreamError.Create(SWriteError);
- end;
- function TStream.CopyFrom(Source: TStream; Count: NativeInt): NativeInt;
- var
- Buffer: TBytes;
- BufferSize, i: LongInt;
- const
- MaxSize = $20000;
- begin
- Result:=0;
- if Count=0 then
- Source.Position:=0; // This WILL fail for non-seekable streams...
- BufferSize:=MaxSize;
- if (Count>0) and (Count<BufferSize) then
- BufferSize:=Count; // do not allocate more than needed
- SetLength(Buffer,BufferSize);
- if Count=0 then
- repeat
- i:=Source.Read(Buffer,BufferSize);
- if i>0 then
- WriteBuffer(Buffer,i);
- Inc(Result,i);
- until i<BufferSize
- else
- while Count>0 do
- begin
- if Count>BufferSize then
- i:=BufferSize
- else
- i:=Count;
- Source.ReadBuffer(Buffer,i);
- WriteBuffer(Buffer,i);
- Dec(count,i);
- Inc(Result,i);
- end;
- end;
- function TStream.ReadComponent(Instance: TComponent): TComponent;
- var
- Reader: TReader;
- begin
- Reader := TReader.Create(Self);
- try
- Result := Reader.ReadRootComponent(Instance);
- finally
- Reader.Free;
- end;
- end;
- function TStream.ReadComponentRes(Instance: TComponent): TComponent;
- begin
- ReadResHeader;
- Result := ReadComponent(Instance);
- end;
- procedure TStream.WriteComponent(Instance: TComponent);
- begin
- WriteDescendent(Instance, nil);
- end;
- procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
- begin
- WriteDescendentRes(ResName, Instance, nil);
- end;
- procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
- var
- Driver : TAbstractObjectWriter;
- Writer : TWriter;
- begin
- Driver := TBinaryObjectWriter.Create(Self);
- Try
- Writer := TWriter.Create(Driver);
- Try
- Writer.WriteDescendent(Instance, Ancestor);
- Finally
- Writer.Destroy;
- end;
- Finally
- Driver.Free;
- end;
- end;
- procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
- var
- FixupInfo: Longint;
- begin
- { Write a resource header }
- WriteResourceHeader(ResName, FixupInfo);
- { Write the instance itself }
- WriteDescendent(Instance, Ancestor);
- { Insert the correct resource size into the resource header }
- FixupResourceHeader(FixupInfo);
- end;
- procedure TStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Longint);
- var
- ResType, Flags : word;
- B : Byte;
- I : Integer;
- begin
- ResType:=Word($000A);
- Flags:=Word($1030);
- { Note: This is a Windows 16 bit resource }
- { Numeric resource type }
- WriteByte($ff);
- { Application defined data }
- WriteWord(ResType);
- { write the name as asciiz }
- For I:=1 to Length(ResName) do
- begin
- B:=Ord(ResName[i]);
- WriteByte(B);
- end;
- WriteByte(0);
- { Movable, Pure and Discardable }
- WriteWord(Flags);
- { Placeholder for the resource size }
- WriteDWord(0);
- { Return current stream position so that the resource size can be
- inserted later }
- FixupInfo := Position;
- end;
- procedure TStream.FixupResourceHeader(FixupInfo: Longint);
- var
- ResSize,TmpResSize : Longint;
- begin
- ResSize := Position - FixupInfo;
- TmpResSize := longword(ResSize);
- { Insert the correct resource size into the placeholder written by
- WriteResourceHeader }
- Position := FixupInfo - 4;
- WriteDWord(TmpResSize);
- { Seek back to the end of the resource }
- Position := FixupInfo + ResSize;
- end;
- procedure TStream.ReadResHeader;
- var
- ResType, Flags : word;
- begin
- try
- { Note: This is a Windows 16 bit resource }
- { application specific resource ? }
- if ReadByte<>$ff then
- raise EInvalidImage.Create(SInvalidImage);
- ResType:=ReadWord;
- if ResType<>$000a then
- raise EInvalidImage.Create(SInvalidImage);
- { read name }
- while ReadByte<>0 do
- ;
- { check the access specifier }
- Flags:=ReadWord;
- if Flags<>$1030 then
- raise EInvalidImage.Create(SInvalidImage);
- { ignore the size }
- ReadDWord;
- except
- on EInvalidImage do
- raise;
- else
- raise EInvalidImage.create(SInvalidImage);
- end;
- end;
- function TStream.ReadByte : Byte;
- begin
- ReadBufferData(Result,1);
- end;
- function TStream.ReadWord : Word;
- begin
- ReadBufferData(Result,2);
- end;
- function TStream.ReadDWord : Cardinal;
- begin
- ReadBufferData(Result,4);
- end;
- function TStream.ReadQWord: NativeLargeUInt;
- begin
- ReadBufferData(Result,8);
- end;
- procedure TStream.WriteByte(b : Byte);
- begin
- WriteBufferData(b,1);
- end;
- procedure TStream.WriteWord(w : Word);
- begin
- WriteBufferData(W,2);
- end;
- procedure TStream.WriteDWord(d : Cardinal);
- begin
- WriteBufferData(d,4);
- end;
- procedure TStream.WriteQWord(q: NativeLargeUInt);
- begin
- WriteBufferData(q,8);
- end;
- {****************************************************************************}
- {* TCustomMemoryStream *}
- {****************************************************************************}
- procedure TCustomMemoryStream.SetPointer(Ptr: TJSArrayBuffer; ASize: PtrInt);
- begin
- FMemory:=Ptr;
- FSize:=ASize;
- FDataView:=Nil;
- FDataArray:=Nil;
- end;
- class function TCustomMemoryStream.MemoryToBytes(Mem: TJSArrayBuffer): TBytes;
- begin
- Result:=MemoryToBytes(TJSUint8Array.New(Mem));
- end;
- class function TCustomMemoryStream.MemoryToBytes(Mem: TJSUint8Array): TBytes;
- Var
- I : Integer;
- begin
- // This must be improved, but needs some asm or TJSFunction.call() to implement answers in
- // https://stackoverflow.com/questions/29676635/convert-uint8array-to-array-in-javascript
- for i:=0 to mem.length-1 do
- Result[i]:=Mem[i];
- end;
- class function TCustomMemoryStream.BytesToMemory(aBytes: TBytes): TJSArrayBuffer;
- Var
- a : TJSUint8Array;
- begin
- Result:=TJSArrayBuffer.new(Length(aBytes));
- A:=TJSUint8Array.New(Result);
- A._set(aBytes);
- end;
- function TCustomMemoryStream.GetDataArray: TJSUint8Array;
- begin
- if FDataArray=Nil then
- FDataArray:=TJSUint8Array.new(Memory);
- Result:=FDataArray;
- end;
- function TCustomMemoryStream.GetDataView: TJSDataview;
- begin
- if FDataView=Nil then
- FDataView:=TJSDataView.New(Memory);
- Result:=FDataView;
- end;
- function TCustomMemoryStream.GetSize: NativeInt;
- begin
- Result:=FSize;
- end;
- function TCustomMemoryStream.GetPosition: NativeInt;
- begin
- Result:=FPosition;
- end;
- function TCustomMemoryStream.Read(Buffer: TBytes; Offset, Count: LongInt): LongInt;
- Var
- I,Src,Dest : Integer;
- begin
- Result:=0;
- If (FSize>0) and (FPosition<Fsize) and (FPosition>=0) then
- begin
- Result:=Count;
- If (Result>(FSize-FPosition)) then
- Result:=(FSize-FPosition);
- Src:=FPosition;
- Dest:=Offset;
- I:=0;
- While I<Result do
- begin
- Buffer[Dest]:=DataView.getUint8(Src);
- inc(Src);
- inc(Dest);
- inc(I);
- end;
- FPosition:=Fposition+Result;
- end;
- end;
- function TCustomMemoryStream.Seek(const Offset: NativeInt; Origin: TSeekOrigin): NativeInt;
- begin
- Case Origin of
- soBeginning : FPosition:=Offset;
- soEnd : FPosition:=FSize+Offset;
- soCurrent : FPosition:=FPosition+Offset;
- end;
- if SizeBoundsSeek and (FPosition>FSize) then
- FPosition:=FSize;
- Result:=FPosition;
- {$IFDEF DEBUG}
- if Result < 0 then
- raise Exception.Create('TCustomMemoryStream');
- {$ENDIF}
- end;
- procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
- begin
- if FSize>0 then
- Stream.WriteBuffer(TMemoryStream.MemoryToBytes(Memory),FSize);
- end;
- procedure TCustomMemoryStream.LoadFromURL(const aURL: String; Async: Boolean; OnLoaded: TNotifyEventRef; OnError: TStringNotifyEventRef = Nil);
- procedure DoLoaded(const abytes : TJSArrayBuffer);
- begin
- SetPointer(aBytes,aBytes.byteLength);
- if Assigned(OnLoaded) then
- OnLoaded(Self);
- end;
- procedure DoError(const AError : String);
- begin
- if Assigned(OnError) then
- OnError(Self,aError)
- else
- Raise EInOutError.Create('Failed to load from URL:'+aError);
- end;
- begin
- CheckLoadHelper;
- GlobalLoadHelper.LoadBytes(aURL,aSync,@DoLoaded,@DoError);
- end;
- procedure TCustomMemoryStream.LoadFromFile(const aFileName: String; const OnLoaded: TProc; const AError: TProcString);
- begin
- LoadFromURL(aFileName,False,
- Procedure (Sender : TObject)
- begin
- If Assigned(OnLoaded) then
- OnLoaded
- end,
- Procedure (Sender : TObject; Const ErrorMsg : String)
- begin
- if Assigned(aError) then
- aError(ErrorMsg)
- end);
- end;
- {****************************************************************************}
- {* TMemoryStream *}
- {****************************************************************************}
- Const TMSGrow = 4096; { Use 4k blocks. }
- procedure TMemoryStream.SetCapacity(NewCapacity: PtrInt);
- begin
- SetPointer (Realloc(NewCapacity),Fsize);
- FCapacity:=NewCapacity;
- end;
- function TMemoryStream.Realloc(var NewCapacity: PtrInt): TJSArrayBuffer;
- Var
- GC : PtrInt;
- DestView : TJSUInt8array;
- begin
- If NewCapacity<0 Then
- NewCapacity:=0
- else
- begin
- GC:=FCapacity + (FCapacity div 4);
- // if growing, grow at least a quarter
- if (NewCapacity>FCapacity) and (NewCapacity < GC) then
- NewCapacity := GC;
- // round off to block size.
- NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
- end;
- // Only now check !
- If NewCapacity=FCapacity then
- Result:=FMemory
- else if NewCapacity=0 then
- Result:=Nil
- else
- begin
- // New buffer
- Result:=TJSArrayBuffer.New(NewCapacity);
- If (Result=Nil) then
- Raise EStreamError.Create(SMemoryStreamError);
- // Transfer
- DestView:=TJSUInt8array.New(Result);
- Destview._Set(Self.DataArray);
- end;
- end;
- destructor TMemoryStream.Destroy;
- begin
- Clear;
- Inherited Destroy;
- end;
- procedure TMemoryStream.Clear;
- begin
- FSize:=0;
- FPosition:=0;
- SetCapacity (0);
- end;
- procedure TMemoryStream.LoadFromStream(Stream: TStream);
- begin
- Position:=0;
- Stream.Position:=0;
- SetSize(Stream.Size);
- If (Size>0) then
- CopyFrom(Stream,0);
- end;
- procedure TMemoryStream.SetSize(const NewSize: NativeInt);
- begin
- SetCapacity (NewSize);
- FSize:=NewSize;
- IF FPosition>FSize then
- FPosition:=FSize;
- end;
- function TMemoryStream.Write(Const Buffer : TBytes; OffSet, Count: LongInt): LongInt;
- Var NewPos : PtrInt;
- begin
- If (Count=0) or (FPosition<0) then
- exit(0);
- NewPos:=FPosition+Count;
- If NewPos>Fsize then
- begin
- IF NewPos>FCapacity then
- SetCapacity (NewPos);
- FSize:=Newpos;
- end;
- DataArray._set(Copy(Buffer,Offset,Count),FPosition);
- FPosition:=NewPos;
- Result:=Count;
- end;
- {****************************************************************************}
- {* TBytesStream *}
- {****************************************************************************}
- constructor TBytesStream.Create(const ABytes: TBytes);
- begin
- inherited Create;
- SetPointer(TMemoryStream.BytesToMemory(aBytes),Length(ABytes));
- FCapacity:=Length(ABytes);
- end;
- function TBytesStream.GetBytes: TBytes;
- begin
- Result:=TMemoryStream.MemoryToBytes(Memory);
- end;
- { *********************************************************************
- * TFiler *
- *********************************************************************}
- procedure TFiler.SetRoot(ARoot: TComponent);
- begin
- FRoot := ARoot;
- end;
- {
- This file is part of the Free Component Library (FCL)
- Copyright (c) 1999-2000 by the Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {****************************************************************************}
- {* TBinaryObjectReader *}
- {****************************************************************************}
- function TBinaryObjectReader.ReadWord : word;
- begin
- FStream.ReadBufferData(Result);
- end;
- function TBinaryObjectReader.ReadDWord : longword;
- begin
- FStream.ReadBufferData(Result);
- end;
- constructor TBinaryObjectReader.Create(Stream: TStream);
- begin
- inherited Create;
- If (Stream=Nil) then
- Raise EReadError.Create(SEmptyStreamIllegalReader);
- FStream := Stream;
- end;
- function TBinaryObjectReader.ReadValue: TValueType;
- var
- b: byte;
- begin
- FStream.ReadBufferData(b);
- Result := TValueType(b);
- end;
- function TBinaryObjectReader.NextValue: TValueType;
- begin
- Result := ReadValue;
- { We only 'peek' at the next value, so seek back to unget the read value: }
- FStream.Seek(-1,soCurrent);
- end;
- procedure TBinaryObjectReader.BeginRootComponent;
- begin
- { Read filer signature }
- ReadSignature;
- end;
- procedure TBinaryObjectReader.BeginComponent(var Flags: TFilerFlags;
- var AChildPos: Integer; var CompClassName, CompName: String);
- var
- Prefix: Byte;
- ValueType: TValueType;
- begin
- { Every component can start with a special prefix: }
- Flags := [];
- if (Byte(NextValue) and $f0) = $f0 then
- begin
- Prefix := Byte(ReadValue);
- Flags:=[];
- if (Prefix and $01)<>0 then
- Include(Flags,ffInherited);
- if (Prefix and $02)<>0 then
- Include(Flags,ffChildPos);
- if (Prefix and $04)<>0 then
- Include(Flags,ffInline);
- if ffChildPos in Flags then
- begin
- ValueType := ReadValue;
- case ValueType of
- vaInt8:
- AChildPos := ReadInt8;
- vaInt16:
- AChildPos := ReadInt16;
- vaInt32:
- AChildPos := ReadInt32;
- vaNativeInt:
- AChildPos := ReadNativeInt;
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- end;
- end;
- CompClassName := ReadStr;
- CompName := ReadStr;
- end;
- function TBinaryObjectReader.BeginProperty: String;
- begin
- Result := ReadStr;
- end;
- procedure TBinaryObjectReader.Read(var Buffer: TBytes; Count: Longint);
- begin
- FStream.Read(Buffer,Count);
- end;
- procedure TBinaryObjectReader.ReadBinary(const DestData: TMemoryStream);
- var
- BinSize: LongInt;
- begin
- BinSize:=LongInt(ReadDWord);
- DestData.Size := BinSize;
- DestData.CopyFrom(FStream,BinSize);
- end;
- function TBinaryObjectReader.ReadFloat: Extended;
- begin
- FStream.ReadBufferData(Result);
- end;
- function TBinaryObjectReader.ReadCurrency: Currency;
- begin
- Result:=ReadFloat;
- end;
- function TBinaryObjectReader.ReadIdent(ValueType: TValueType): String;
- var
- i: Byte;
- c : Char;
- begin
- case ValueType of
- vaIdent:
- begin
- FStream.ReadBufferData(i);
- SetLength(Result,i);
- For I:=1 to Length(Result) do
- begin
- FStream.ReadBufferData(C);
- Result[I]:=C;
- end;
- end;
- vaNil:
- Result := 'nil';
- vaFalse:
- Result := 'False';
- vaTrue:
- Result := 'True';
- vaNull:
- Result := 'Null';
- end;
- end;
- function TBinaryObjectReader.ReadInt8: ShortInt;
- begin
- FStream.ReadBufferData(Result);
- end;
- function TBinaryObjectReader.ReadInt16: SmallInt;
- begin
- FStream.ReadBufferData(Result);
- end;
- function TBinaryObjectReader.ReadInt32: LongInt;
- begin
- FStream.ReadBufferData(Result);
- end;
- function TBinaryObjectReader.ReadNativeInt : NativeInt;
- begin
- FStream.ReadBufferData(Result);
- end;
- function TBinaryObjectReader.ReadSet(EnumType: TTypeInfoEnum): Integer;
- var
- Name: String;
- Value: Integer;
- begin
- try
- Result := 0;
- while True do
- begin
- Name := ReadStr;
- if Length(Name) = 0 then
- break;
- Value:=EnumType.EnumType.NameToInt[Name];
- if Value=-1 then
- raise EReadError.Create(SInvalidPropertyValue);
- Result:=Result or (1 shl Value);
- end;
- except
- SkipSetBody;
- raise;
- end;
- end;
- Const
- // Integer version of 4 chars 'TPF0'
- FilerSignatureInt = 809914452;
- procedure TBinaryObjectReader.ReadSignature;
- var
- Signature: LongInt;
- begin
- FStream.ReadBufferData(Signature);
- if Signature <> FilerSignatureInt then
- raise EReadError.Create(SInvalidImage);
- end;
- function TBinaryObjectReader.ReadStr: String;
- var
- l,i: Byte;
- c : Char;
- begin
- FStream.ReadBufferData(L);
- SetLength(Result,L);
- For I:=1 to L do
- begin
- FStream.ReadBufferData(C);
- Result[i]:=C;
- end;
- end;
- function TBinaryObjectReader.ReadString(StringType: TValueType): String;
- var
- i: Integer;
- C : Char;
- begin
- Result:='';
- if StringType<>vaString then
- Raise EFilerError.Create('Invalid string type passed to ReadString');
- i:=ReadDWord;
- SetLength(Result, i);
- for I:=1 to Length(Result) do
- begin
- FStream.ReadbufferData(C);
- Result[i]:=C;
- end;
- end;
- function TBinaryObjectReader.ReadWideString: WideString;
- begin
- Result:=ReadString(vaWString);
- end;
- function TBinaryObjectReader.ReadUnicodeString: UnicodeString;
- begin
- Result:=ReadString(vaWString);
- end;
- procedure TBinaryObjectReader.SkipComponent(SkipComponentInfos: Boolean);
- var
- Flags: TFilerFlags;
- Dummy: Integer;
- CompClassName, CompName: String;
- begin
- if SkipComponentInfos then
- { Skip prefix, component class name and component object name }
- BeginComponent(Flags, Dummy, CompClassName, CompName);
- { Skip properties }
- while NextValue <> vaNull do
- SkipProperty;
- ReadValue;
- { Skip children }
- while NextValue <> vaNull do
- SkipComponent(True);
- ReadValue;
- end;
- procedure TBinaryObjectReader.SkipValue;
- procedure SkipBytes(Count: LongInt);
- var
- Dummy: TBytes;
- SkipNow: Integer;
- begin
- while Count > 0 do
- begin
- if Count > 1024 then
- SkipNow := 1024
- else
- SkipNow := Count;
- SetLength(Dummy,SkipNow);
- Read(Dummy, SkipNow);
- Dec(Count, SkipNow);
- end;
- end;
- var
- Count: LongInt;
- begin
- case ReadValue of
- vaNull, vaFalse, vaTrue, vaNil: ;
- vaList:
- begin
- while NextValue <> vaNull do
- SkipValue;
- ReadValue;
- end;
- vaInt8:
- SkipBytes(1);
- vaInt16:
- SkipBytes(2);
- vaInt32:
- SkipBytes(4);
- vaInt64,
- vaDouble:
- SkipBytes(8);
- vaIdent:
- ReadStr;
- vaString:
- ReadString(vaString);
- vaBinary:
- begin
- Count:=LongInt(ReadDWord);
- SkipBytes(Count);
- end;
- vaSet:
- SkipSetBody;
- vaCollection:
- begin
- while NextValue <> vaNull do
- begin
- { Skip the order value if present }
- if NextValue in [vaInt8, vaInt16, vaInt32] then
- SkipValue;
- SkipBytes(1);
- while NextValue <> vaNull do
- SkipProperty;
- ReadValue;
- end;
- ReadValue;
- end;
- end;
- end;
- { private methods }
- procedure TBinaryObjectReader.SkipProperty;
- begin
- { Skip property name, then the property value }
- ReadStr;
- SkipValue;
- end;
- procedure TBinaryObjectReader.SkipSetBody;
- begin
- while Length(ReadStr) > 0 do;
- end;
- // Quadruple representing an unresolved component property.
- Type
- { TUnresolvedReference }
- TUnresolvedReference = class(TlinkedListItem)
- Private
- FRoot: TComponent; // Root component when streaming
- FPropInfo: TTypeMemberProperty; // Property to set.
- FGlobal, // Global component.
- FRelative : string; // Path relative to global component.
- Function Resolve(Instance : TPersistent) : Boolean; // Resolve this reference
- Function RootMatches(ARoot : TComponent) : Boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE} // True if Froot matches or ARoot is nil.
- Function NextRef : TUnresolvedReference; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- end;
- TLocalUnResolvedReference = class(TUnresolvedReference)
- Finstance : TPersistent;
- end;
- // Linked list of TPersistent items that have unresolved properties.
- { TUnResolvedInstance }
- TUnResolvedInstance = Class(TLinkedListItem)
- Public
- Instance : TPersistent; // Instance we're handling unresolveds for
- FUnresolved : TLinkedList; // The list
- Destructor Destroy; override;
- Function AddReference(ARoot : TComponent; APropInfo : TTypeMemberProperty; AGlobal,ARelative : String) : TUnresolvedReference;
- Function RootUnresolved : TUnresolvedReference; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE} // Return root element in list.
- Function ResolveReferences : Boolean; // Return true if all unresolveds were resolved.
- end;
- // Builds a list of TUnResolvedInstances, removes them from global list on free.
- TBuildListVisitor = Class(TLinkedListVisitor)
- Private
- List : TFPList;
- Public
- Procedure Add(Item : TlinkedListItem); // Add TUnResolvedInstance item to list. Create list if needed
- Destructor Destroy; override; // All elements in list (if any) are removed from the global list.
- end;
- // Visitor used to try and resolve instances in the global list
- TResolveReferenceVisitor = Class(TBuildListVisitor)
- Function Visit(Item : TLinkedListItem) : Boolean; override;
- end;
- // Visitor used to remove all references to a certain component.
- TRemoveReferenceVisitor = Class(TBuildListVisitor)
- Private
- FRef : String;
- FRoot : TComponent;
- Public
- Constructor Create(ARoot : TComponent;Const ARef : String);
- Function Visit(Item : TLinkedListItem) : Boolean; override;
- end;
- // Visitor used to collect reference names.
- TReferenceNamesVisitor = Class(TLinkedListVisitor)
- Private
- FList : TStrings;
- FRoot : TComponent;
- Public
- Function Visit(Item : TLinkedListItem) : Boolean; override;
- Constructor Create(ARoot : TComponent;AList : TStrings);
- end;
- // Visitor used to collect instance names.
- TReferenceInstancesVisitor = Class(TLinkedListVisitor)
- Private
- FList : TStrings;
- FRef : String;
- FRoot : TComponent;
- Public
- Function Visit(Item : TLinkedListItem) : Boolean; override;
- Constructor Create(ARoot : TComponent;Const ARef : String; AList : TStrings);
- end;
- // Visitor used to redirect links to another root component.
- TRedirectReferenceVisitor = Class(TLinkedListVisitor)
- Private
- FOld,
- FNew : String;
- FRoot : TComponent;
- Public
- Function Visit(Item : TLinkedListItem) : Boolean; override;
- Constructor Create(ARoot : TComponent;Const AOld,ANew : String);
- end;
- var
- NeedResolving : TLinkedList;
- // Add an instance to the global list of instances which need resolving.
- Function FindUnresolvedInstance(AInstance: TPersistent) : TUnResolvedInstance;
- begin
- Result:=Nil;
- {$ifdef FPC_HAS_FEATURE_THREADING}
- EnterCriticalSection(ResolveSection);
- Try
- {$endif}
- If Assigned(NeedResolving) then
- begin
- Result:=TUnResolvedInstance(NeedResolving.Root);
- While (Result<>Nil) and (Result.Instance<>AInstance) do
- Result:=TUnResolvedInstance(Result.Next);
- end;
- {$ifdef FPC_HAS_FEATURE_THREADING}
- finally
- LeaveCriticalSection(ResolveSection);
- end;
- {$endif}
- end;
- Function AddtoResolveList(AInstance: TPersistent) : TUnResolvedInstance;
- begin
- Result:=FindUnresolvedInstance(AInstance);
- If (Result=Nil) then
- begin
- {$ifdef FPC_HAS_FEATURE_THREADING}
- EnterCriticalSection(ResolveSection);
- Try
- {$endif}
- If not Assigned(NeedResolving) then
- NeedResolving:=TLinkedList.Create(TUnResolvedInstance);
- Result:=NeedResolving.Add as TUnResolvedInstance;
- Result.Instance:=AInstance;
- {$ifdef FPC_HAS_FEATURE_THREADING}
- finally
- LeaveCriticalSection(ResolveSection);
- end;
- {$endif}
- end;
- end;
- // Walk through the global list of instances to be resolved.
- Procedure VisitResolveList(V : TLinkedListVisitor);
- begin
- {$ifdef FPC_HAS_FEATURE_THREADING}
- EnterCriticalSection(ResolveSection);
- Try
- {$endif}
- try
- NeedResolving.Foreach(V);
- Finally
- FreeAndNil(V);
- end;
- {$ifdef FPC_HAS_FEATURE_THREADING}
- Finally
- LeaveCriticalSection(ResolveSection);
- end;
- {$endif}
- end;
- procedure GlobalFixupReferences;
- begin
- If (NeedResolving=Nil) then
- Exit;
- {$ifdef FPC_HAS_FEATURE_THREADING}
- GlobalNameSpace.BeginWrite;
- try
- {$endif}
- VisitResolveList(TResolveReferenceVisitor.Create);
- {$ifdef FPC_HAS_FEATURE_THREADING}
- finally
- GlobalNameSpace.EndWrite;
- end;
- {$endif}
- end;
- procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
- begin
- If (NeedResolving=Nil) then
- Exit;
- VisitResolveList(TReferenceNamesVisitor.Create(Root,Names));
- end;
- procedure GetFixupInstanceNames(Root: TComponent; const ReferenceRootName: string; Names: TStrings);
- begin
- If (NeedResolving=Nil) then
- Exit;
- VisitResolveList(TReferenceInstancesVisitor.Create(Root,ReferenceRootName,Names));
- end;
- procedure ObjectBinaryToText(aInput, aOutput: TStream);
- begin
- ObjectBinaryToText(aInput,aOutput,oteLFM);
- end;
- procedure ObjectBinaryToText(aInput, aOutput: TStream; aEncoding: TObjectTextEncoding);
- var
- Conv : TObjectStreamConverter;
- begin
- Conv:=TObjectStreamConverter.Create;
- try
- Conv.ObjectBinaryToText(aInput,aOutput,aEncoding);
- finally
- Conv.Free;
- end;
- end;
- procedure RedirectFixupReferences(Root: TComponent; const OldRootName, NewRootName: string);
- begin
- If (NeedResolving=Nil) then
- Exit;
- VisitResolveList(TRedirectReferenceVisitor.Create(Root,OldRootName,NewRootName));
- end;
- procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
- begin
- If (NeedResolving=Nil) then
- Exit;
- VisitResolveList(TRemoveReferenceVisitor.Create(Root,RootName));
- end;
- { TUnresolvedReference }
- Function TUnresolvedReference.Resolve(Instance : TPersistent) : Boolean;
- Var
- C : TComponent;
- begin
- C:=FindGlobalComponent(FGlobal);
- Result:=(C<>Nil);
- If Result then
- begin
- C:=FindNestedComponent(C,FRelative);
- Result:=C<>Nil;
- If Result then
- SetObjectProp(Instance, FPropInfo,C);
- end;
- end;
- Function TUnresolvedReference.RootMatches(ARoot : TComponent) : Boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- begin
- Result:=(ARoot=Nil) or (ARoot=FRoot);
- end;
- Function TUnResolvedReference.NextRef : TUnresolvedReference;
- begin
- Result:=TUnresolvedReference(Next);
- end;
- { TUnResolvedInstance }
- destructor TUnResolvedInstance.Destroy;
- begin
- FUnresolved.Free;
- inherited Destroy;
- end;
- function TUnResolvedInstance.AddReference(ARoot: TComponent; APropInfo : TTypeMemberProperty; AGlobal, ARelative: String): TUnresolvedReference;
- begin
- If (FUnResolved=Nil) then
- FUnResolved:=TLinkedList.Create(TUnresolvedReference);
- Result:=FUnResolved.Add as TUnresolvedReference;
- Result.FGlobal:=AGLobal;
- Result.FRelative:=ARelative;
- Result.FPropInfo:=APropInfo;
- Result.FRoot:=ARoot;
- end;
- Function TUnResolvedInstance.RootUnresolved : TUnresolvedReference;
- begin
- Result:=Nil;
- If Assigned(FUnResolved) then
- Result:=TUnresolvedReference(FUnResolved.Root);
- end;
- Function TUnResolvedInstance.ResolveReferences:Boolean;
- Var
- R,RN : TUnresolvedReference;
- begin
- R:=RootUnResolved;
- While (R<>Nil) do
- begin
- RN:=R.NextRef;
- If R.Resolve(Self.Instance) then
- FUnresolved.RemoveItem(R,True);
- R:=RN;
- end;
- Result:=RootUnResolved=Nil;
- end;
- { TReferenceNamesVisitor }
- Constructor TReferenceNamesVisitor.Create(ARoot : TComponent;AList : TStrings);
- begin
- FRoot:=ARoot;
- FList:=AList;
- end;
- Function TReferenceNamesVisitor.Visit(Item : TLinkedListItem) : Boolean;
- Var
- R : TUnresolvedReference;
- begin
- R:=TUnResolvedInstance(Item).RootUnresolved;
- While (R<>Nil) do
- begin
- If R.RootMatches(FRoot) then
- If (FList.IndexOf(R.FGlobal)=-1) then
- FList.Add(R.FGlobal);
- R:=R.NextRef;
- end;
- Result:=True;
- end;
- { TReferenceInstancesVisitor }
- Constructor TReferenceInstancesVisitor.Create(ARoot : TComponent; Const ARef : String;AList : TStrings);
- begin
- FRoot:=ARoot;
- FRef:=UpperCase(ARef);
- FList:=AList;
- end;
- Function TReferenceInstancesVisitor.Visit(Item : TLinkedListItem) : Boolean;
- Var
- R : TUnresolvedReference;
- begin
- R:=TUnResolvedInstance(Item).RootUnresolved;
- While (R<>Nil) do
- begin
- If (FRoot=R.FRoot) and (FRef=UpperCase(R.FGLobal)) Then
- If Flist.IndexOf(R.FRelative)=-1 then
- Flist.Add(R.FRelative);
- R:=R.NextRef;
- end;
- Result:=True;
- end;
- { TRedirectReferenceVisitor }
- Constructor TRedirectReferenceVisitor.Create(ARoot : TComponent; Const AOld,ANew : String);
- begin
- FRoot:=ARoot;
- FOld:=UpperCase(AOld);
- FNew:=ANew;
- end;
- Function TRedirectReferenceVisitor.Visit(Item : TLinkedListItem) : Boolean;
- Var
- R : TUnresolvedReference;
- begin
- R:=TUnResolvedInstance(Item).RootUnresolved;
- While (R<>Nil) do
- begin
- If R.RootMatches(FRoot) and (FOld=UpperCase(R.FGLobal)) Then
- R.FGlobal:=FNew;
- R:=R.NextRef;
- end;
- Result:=True;
- end;
- { TRemoveReferenceVisitor }
- Constructor TRemoveReferenceVisitor.Create(ARoot : TComponent; Const ARef : String);
- begin
- FRoot:=ARoot;
- FRef:=UpperCase(ARef);
- end;
- Function TRemoveReferenceVisitor.Visit(Item : TLinkedListItem) : Boolean;
- Var
- I : Integer;
- UI : TUnResolvedInstance;
- R : TUnresolvedReference;
- L : TFPList;
- begin
- UI:=TUnResolvedInstance(Item);
- R:=UI.RootUnresolved;
- L:=Nil;
- Try
- // Collect all matches.
- While (R<>Nil) do
- begin
- If R.RootMatches(FRoot) and ((FRef = '') or (FRef=UpperCase(R.FGLobal))) Then
- begin
- If Not Assigned(L) then
- L:=TFPList.Create;
- L.Add(R);
- end;
- R:=R.NextRef;
- end;
- // Remove all matches.
- IF Assigned(L) then
- begin
- For I:=0 to L.Count-1 do
- UI.FUnresolved.RemoveItem(TLinkedListitem(L[i]),True);
- end;
- // If any references are left, leave them.
- If UI.FUnResolved.Root=Nil then
- begin
- If List=Nil then
- List:=TFPList.Create;
- List.Add(UI);
- end;
- Finally
- L.Free;
- end;
- Result:=True;
- end;
- { TBuildListVisitor }
- Procedure TBuildListVisitor.Add(Item : TlinkedListItem);
- begin
- If (List=Nil) then
- List:=TFPList.Create;
- List.Add(Item);
- end;
- Destructor TBuildListVisitor.Destroy;
- Var
- I : Integer;
- begin
- If Assigned(List) then
- For I:=0 to List.Count-1 do
- NeedResolving.RemoveItem(TLinkedListItem(List[I]),True);
- FreeAndNil(List);
- Inherited;
- end;
- { TResolveReferenceVisitor }
- Function TResolveReferenceVisitor.Visit(Item : TLinkedListItem) : Boolean;
- begin
- If TUnResolvedInstance(Item).ResolveReferences then
- Add(Item);
- Result:=True;
- end;
- {****************************************************************************}
- {* TREADER *}
- {****************************************************************************}
- constructor TReader.Create(Stream: TStream);
- begin
- inherited Create;
- If (Stream=Nil) then
- Raise EReadError.Create(SEmptyStreamIllegalReader);
- FDriver := CreateDriver(Stream);
- end;
- destructor TReader.Destroy;
- begin
- FDriver.Free;
- inherited Destroy;
- end;
- procedure TReader.FlushBuffer;
- begin
- Driver.FlushBuffer;
- end;
- function TReader.CreateDriver(Stream: TStream): TAbstractObjectReader;
- begin
- Result := TBinaryObjectReader.Create(Stream);
- end;
- procedure TReader.BeginReferences;
- begin
- FLoaded := TFpList.Create;
- end;
- procedure TReader.CheckValue(Value: TValueType);
- begin
- if FDriver.NextValue <> Value then
- raise EReadError.Create(SInvalidPropertyValue)
- else
- FDriver.ReadValue;
- end;
- procedure TReader.DefineProperty(const Name: String; AReadData: TReaderProc;
- WriteData: TWriterProc; HasData: Boolean);
- begin
- if Assigned(AReadData) and SameText(Name,FPropName) then
- begin
- AReadData(Self);
- SetLength(FPropName, 0);
- end else if assigned(WriteData) and HasData then
- ;
- end;
- procedure TReader.DefineBinaryProperty(const Name: String;
- AReadData, WriteData: TStreamProc; HasData: Boolean);
- var
- MemBuffer: TMemoryStream;
- begin
- if Assigned(AReadData) and SameText(Name,FPropName) then
- begin
- { Check if the next property really is a binary property}
- if FDriver.NextValue <> vaBinary then
- begin
- FDriver.SkipValue;
- FCanHandleExcepts := True;
- raise EReadError.Create(SInvalidPropertyValue);
- end else
- FDriver.ReadValue;
- MemBuffer := TMemoryStream.Create;
- try
- FDriver.ReadBinary(MemBuffer);
- FCanHandleExcepts := True;
- AReadData(MemBuffer);
- finally
- MemBuffer.Free;
- end;
- SetLength(FPropName, 0);
- end else if assigned(WriteData) and HasData then ;
- end;
- function TReader.EndOfList: Boolean;
- begin
- Result := FDriver.NextValue = vaNull;
- end;
- procedure TReader.EndReferences;
- begin
- FLoaded.Free;
- FLoaded := nil;
- end;
- function TReader.Error(const Message: String): Boolean;
- begin
- Result := False;
- if Assigned(FOnError) then
- FOnError(Self, Message, Result);
- end;
- function TReader.FindMethod(ARoot: TComponent; const AMethodName: String): CodePointer;
- var
- ErrorResult: Boolean;
- begin
- Result:=nil;
- if (ARoot=Nil) or (aMethodName='') then
- exit;
- Result := ARoot.MethodAddress(AMethodName);
- ErrorResult := Result = nil;
- { always give the OnFindMethod callback a chance to locate the method }
- if Assigned(FOnFindMethod) then
- FOnFindMethod(Self, AMethodName, Result, ErrorResult);
- if ErrorResult then
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- procedure TReader.DoFixupReferences;
- Var
- R,RN : TLocalUnresolvedReference;
- G : TUnresolvedInstance;
- Ref : String;
- C : TComponent;
- P : integer;
- L : TLinkedList;
- begin
- If Assigned(FFixups) then
- begin
- L:=TLinkedList(FFixups);
- R:=TLocalUnresolvedReference(L.Root);
- While (R<>Nil) do
- begin
- RN:=TLocalUnresolvedReference(R.Next);
- Ref:=R.FRelative;
- If Assigned(FOnReferenceName) then
- FOnReferenceName(Self,Ref);
- C:=FindNestedComponent(R.FRoot,Ref);
- If Assigned(C) then
- if R.FPropInfo.TypeInfo.Kind = tkInterface then
- SetInterfaceProp(R.FInstance,R.FPropInfo,C)
- else
- SetObjectProp(R.FInstance,R.FPropInfo,C)
- else
- begin
- P:=Pos('.',R.FRelative);
- If (P<>0) then
- begin
- G:=AddToResolveList(R.FInstance);
- G.Addreference(R.FRoot,R.FPropInfo,Copy(R.FRelative,1,P-1),Copy(R.FRelative,P+1,Length(R.FRelative)-P));
- end;
- end;
- L.RemoveItem(R,True);
- R:=RN;
- end;
- FreeAndNil(FFixups);
- end;
- end;
- procedure TReader.FixupReferences;
- var
- i: Integer;
- begin
- DoFixupReferences;
- GlobalFixupReferences;
- for i := 0 to FLoaded.Count - 1 do
- TComponent(FLoaded[I]).Loaded;
- end;
- function TReader.NextValue: TValueType;
- begin
- Result := FDriver.NextValue;
- end;
- procedure TReader.Read(var Buffer : TBytes; Count: LongInt);
- begin
- //This should give an exception if read is not implemented (i.e. TTextObjectReader)
- //but should work with TBinaryObjectReader.
- Driver.Read(Buffer, Count);
- end;
- procedure TReader.PropertyError;
- begin
- FDriver.SkipValue;
- raise EReadError.CreateFmt(SUnknownProperty,[FPropName]);
- end;
- function TReader.ReadBoolean: Boolean;
- var
- ValueType: TValueType;
- begin
- ValueType := FDriver.ReadValue;
- if ValueType = vaTrue then
- Result := True
- else if ValueType = vaFalse then
- Result := False
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- function TReader.ReadChar: Char;
- var
- s: String;
- begin
- s := ReadString;
- if Length(s) = 1 then
- Result := s[1]
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- function TReader.ReadWideChar: WideChar;
- var
- W: WideString;
- begin
- W := ReadWideString;
- if Length(W) = 1 then
- Result := W[1]
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- function TReader.ReadUnicodeChar: UnicodeChar;
- var
- U: UnicodeString;
- begin
- U := ReadUnicodeString;
- if Length(U) = 1 then
- Result := U[1]
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- procedure TReader.ReadCollection(Collection: TCollection);
- var
- Item: TCollectionItem;
- begin
- Collection.BeginUpdate;
- if not EndOfList then
- Collection.Clear;
- while not EndOfList do begin
- ReadListBegin;
- Item := Collection.Add;
- while NextValue<>vaNull do
- ReadProperty(Item);
- ReadListEnd;
- end;
- Collection.EndUpdate;
- ReadListEnd;
- end;
- function TReader.ReadComponent(Component: TComponent): TComponent;
- var
- Flags: TFilerFlags;
- function Recover(E : Exception; var aComponent: TComponent): Boolean;
- begin
- Result := False;
- if not ((ffInherited in Flags) or Assigned(Component)) then
- aComponent.Free;
- aComponent := nil;
- FDriver.SkipComponent(False);
- Result := Error(E.Message);
- end;
- var
- CompClassName, Name: String;
- n, ChildPos: Integer;
- SavedParent, SavedLookupRoot: TComponent;
- ComponentClass: TComponentClass;
- C, NewComponent: TComponent;
- SubComponents: TList;
- begin
- FDriver.BeginComponent(Flags, ChildPos, CompClassName, Name);
- SavedParent := Parent;
- SavedLookupRoot := FLookupRoot;
- SubComponents := nil;
- try
- Result := Component;
- if not Assigned(Result) then
- try
- if ffInherited in Flags then
- begin
- { Try to locate the existing ancestor component }
- if Assigned(FLookupRoot) then
- Result := FLookupRoot.FindComponent(Name)
- else
- Result := nil;
- if not Assigned(Result) then
- begin
- if Assigned(FOnAncestorNotFound) then
- FOnAncestorNotFound(Self, Name,
- FindComponentClass(CompClassName), Result);
- if not Assigned(Result) then
- raise EReadError.CreateFmt(SAncestorNotFound, [Name]);
- end;
- Parent := Result.GetParentComponent;
- if not Assigned(Parent) then
- Parent := Root;
- end else
- begin
- Result := nil;
- ComponentClass := FindComponentClass(CompClassName);
- if Assigned(FOnCreateComponent) then
- FOnCreateComponent(Self, ComponentClass, Result);
- if not Assigned(Result) then
- begin
- asm
- NewComponent = Object.create(ComponentClass);
- NewComponent.$init();
- end;
- if ffInline in Flags then
- NewComponent.FComponentState :=
- NewComponent.FComponentState + [csLoading, csInline];
- NewComponent.Create(Owner);
- NewComponent.AfterConstruction;
- { Don't set Result earlier because else we would come in trouble
- with the exception recover mechanism! (Result should be NIL if
- an error occurred) }
- Result := NewComponent;
- end;
- Include(Result.FComponentState, csLoading);
- end;
- except
- On E: Exception do
- if not Recover(E,Result) then
- raise;
- end;
- if Assigned(Result) then
- try
- Include(Result.FComponentState, csLoading);
- { create list of subcomponents and set loading}
- SubComponents := TList.Create;
- for n := 0 to Result.ComponentCount - 1 do
- begin
- C := Result.Components[n];
- if csSubcomponent in C.ComponentStyle
- then begin
- SubComponents.Add(C);
- Include(C.FComponentState, csLoading);
- end;
- end;
- if not (ffInherited in Flags) then
- try
- Result.SetParentComponent(Parent);
- if Assigned(FOnSetName) then
- FOnSetName(Self, Result, Name);
- Result.Name := Name;
- if FindGlobalComponent(Name) = Result then
- Include(Result.FComponentState, csInline);
- except
- On E : Exception do
- if not Recover(E,Result) then
- raise;
- end;
- if not Assigned(Result) then
- exit;
- if csInline in Result.ComponentState then
- FLookupRoot := Result;
- { Read the component state }
- Include(Result.FComponentState, csReading);
- for n := 0 to Subcomponents.Count - 1 do
- Include(TComponent(Subcomponents[n]).FComponentState, csReading);
- Result.ReadState(Self);
- Exclude(Result.FComponentState, csReading);
- for n := 0 to Subcomponents.Count - 1 do
- Exclude(TComponent(Subcomponents[n]).FComponentState, csReading);
- if ffChildPos in Flags then
- Parent.SetChildOrder(Result, ChildPos);
- { Add component to list of loaded components, if necessary }
- if (not ((ffInherited in Flags) or (csInline in Result.ComponentState))) or
- (FLoaded.IndexOf(Result) < 0)
- then begin
- for n := 0 to Subcomponents.Count - 1 do
- FLoaded.Add(Subcomponents[n]);
- FLoaded.Add(Result);
- end;
- except
- if ((ffInherited in Flags) or Assigned(Component)) then
- Result.Free;
- raise;
- end;
- finally
- Parent := SavedParent;
- FLookupRoot := SavedLookupRoot;
- Subcomponents.Free;
- end;
- end;
- procedure TReader.ReadData(Instance: TComponent);
- var
- SavedOwner, SavedParent: TComponent;
- begin
- { Read properties }
- while not EndOfList do
- ReadProperty(Instance);
- ReadListEnd;
- { Read children }
- SavedOwner := Owner;
- SavedParent := Parent;
- try
- Owner := Instance.GetChildOwner;
- if not Assigned(Owner) then
- Owner := Root;
- Parent := Instance.GetChildParent;
- while not EndOfList do
- ReadComponent(nil);
- ReadListEnd;
- finally
- Owner := SavedOwner;
- Parent := SavedParent;
- end;
- { Fixup references if necessary (normally only if this is the root) }
- If (Instance=FRoot) then
- DoFixupReferences;
- end;
- function TReader.ReadFloat: Extended;
- begin
- if FDriver.NextValue = vaExtended then
- begin
- ReadValue;
- Result := FDriver.ReadFloat
- end else
- Result := ReadNativeInt;
- end;
- procedure TReader.ReadSignature;
- begin
- FDriver.ReadSignature;
- end;
- function TReader.ReadCurrency: Currency;
- begin
- if FDriver.NextValue = vaCurrency then
- begin
- FDriver.ReadValue;
- Result := FDriver.ReadCurrency;
- end else
- Result := ReadInteger;
- end;
- function TReader.ReadIdent: String;
- var
- ValueType: TValueType;
- begin
- ValueType := FDriver.ReadValue;
- if ValueType in [vaIdent, vaNil, vaFalse, vaTrue, vaNull] then
- Result := FDriver.ReadIdent(ValueType)
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- function TReader.ReadInteger: LongInt;
- begin
- case FDriver.ReadValue of
- vaInt8:
- Result := FDriver.ReadInt8;
- vaInt16:
- Result := FDriver.ReadInt16;
- vaInt32:
- Result := FDriver.ReadInt32;
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- end;
- function TReader.ReadNativeInt: NativeInt;
- begin
- if FDriver.NextValue = vaInt64 then
- begin
- FDriver.ReadValue;
- Result := FDriver.ReadNativeInt;
- end else
- Result := ReadInteger;
- end;
- function TReader.ReadSet(EnumType: Pointer): Integer;
- begin
- if FDriver.NextValue = vaSet then
- begin
- FDriver.ReadValue;
- Result := FDriver.ReadSet(enumtype);
- end
- else
- Result := ReadInteger;
- end;
- procedure TReader.ReadListBegin;
- begin
- CheckValue(vaList);
- end;
- procedure TReader.ReadListEnd;
- begin
- CheckValue(vaNull);
- end;
- function TReader.ReadVariant: JSValue;
- var
- nv: TValueType;
- begin
- nv:=NextValue;
- case nv of
- vaNil:
- begin
- Result:=Undefined;
- readvalue;
- end;
- vaNull:
- begin
- Result:=Nil;
- readvalue;
- end;
- { all integer sizes must be split for big endian systems }
- vaInt8,vaInt16,vaInt32:
- begin
- Result:=ReadInteger;
- end;
- vaInt64:
- begin
- Result:=ReadNativeInt;
- end;
- {
- vaQWord:
- begin
- Result:=QWord(ReadInt64);
- end;
- } vaFalse,vaTrue:
- begin
- Result:=(nv<>vaFalse);
- readValue;
- end;
- vaCurrency:
- begin
- Result:=ReadCurrency;
- end;
- vaDouble:
- begin
- Result:=ReadFloat;
- end;
- vaString:
- begin
- Result:=ReadString;
- end;
- else
- raise EReadError.CreateFmt(SUnsupportedPropertyVariantType, [Ord(nv)]);
- end;
- end;
- procedure TReader.ReadProperty(AInstance: TPersistent);
- var
- Path: String;
- Instance: TPersistent;
- PropInfo: TTypeMemberProperty;
- Obj: TObject;
- Name: String;
- Skip: Boolean;
- Handled: Boolean;
- OldPropName: String;
- DotPos : String;
- NextPos: Integer;
- function HandleMissingProperty(IsPath: Boolean): boolean;
- begin
- Result:=true;
- if Assigned(OnPropertyNotFound) then begin
- // user defined property error handling
- OldPropName:=FPropName;
- Handled:=false;
- Skip:=false;
- OnPropertyNotFound(Self,Instance,FPropName,IsPath,Handled,Skip);
- if Handled and (not Skip) and (OldPropName<>FPropName) then
- // try alias property
- PropInfo := GetPropInfo(Instance.ClassType, FPropName);
- if Skip then begin
- FDriver.SkipValue;
- Result:=false;
- exit;
- end;
- end;
- end;
- begin
- try
- Path := FDriver.BeginProperty;
- try
- Instance := AInstance;
- FCanHandleExcepts := True;
- DotPos := Path;
- while True do
- begin
- NextPos := Pos('.',DotPos);
- if NextPos>0 then
- FPropName := Copy(DotPos, 1, NextPos-1)
- else
- begin
- FPropName := DotPos;
- break;
- end;
- Delete(DotPos,1,NextPos);
- PropInfo := GetPropInfo(Instance.ClassType, FPropName);
- if not Assigned(PropInfo) then begin
- if not HandleMissingProperty(true) then exit;
- if not Assigned(PropInfo) then
- PropertyError;
- end;
- if PropInfo.TypeInfo.Kind = tkClass then
- Obj := TObject(GetObjectProp(Instance, PropInfo))
- //else if PropInfo^.PropType^.Kind = tkInterface then
- // Obj := TObject(GetInterfaceProp(Instance, PropInfo))
- else
- Obj := nil;
- if not (Obj is TPersistent) then
- begin
- { All path elements must be persistent objects! }
- FDriver.SkipValue;
- raise EReadError.Create(SInvalidPropertyPath);
- end;
- Instance := TPersistent(Obj);
- end;
- PropInfo := GetPropInfo(Instance.ClassType, FPropName);
- if Assigned(PropInfo) then
- ReadPropValue(Instance, PropInfo)
- else
- begin
- FCanHandleExcepts := False;
- Instance.DefineProperties(Self);
- FCanHandleExcepts := True;
- if Length(FPropName) > 0 then begin
- if not HandleMissingProperty(false) then exit;
- if not Assigned(PropInfo) then
- PropertyError;
- end;
- end;
- except
- on e: Exception do
- begin
- SetLength(Name, 0);
- if AInstance.InheritsFrom(TComponent) then
- Name := TComponent(AInstance).Name;
- if Length(Name) = 0 then
- Name := AInstance.ClassName;
- raise EReadError.CreateFmt(SPropertyException, [Name, '.', Path, e.Message]);
- end;
- end;
- except
- on e: Exception do
- if not FCanHandleExcepts or not Error(E.Message) then
- raise;
- end;
- end;
- procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: TTypeMemberProperty);
- const
- NullMethod: TMethod = (Code: nil; Data: nil);
- var
- PropType: TTypeInfo;
- Value: LongInt;
- { IdentToIntFn: TIdentToInt; }
- Ident: String;
- Method: TMethod;
- Handled: Boolean;
- TmpStr: String;
- begin
- if (PropInfo.Setter='') then
- raise EReadError.Create(SReadOnlyProperty);
- PropType := PropInfo.TypeInfo;
- case PropType.Kind of
- tkInteger:
- case FDriver.NextValue of
- vaIdent :
- begin
- Ident := ReadIdent;
- if GlobalIdentToInt(Ident,Value) then
- SetOrdProp(Instance, PropInfo, Value)
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- vaNativeInt :
- SetOrdProp(Instance, PropInfo, ReadNativeInt);
- vaCurrency:
- SetFloatProp(Instance, PropInfo, ReadCurrency);
- else
- SetOrdProp(Instance, PropInfo, ReadInteger);
- end;
- tkBool:
- SetOrdProp(Instance, PropInfo, Ord(ReadBoolean));
- tkChar:
- SetOrdProp(Instance, PropInfo, Ord(ReadChar));
- tkEnumeration:
- begin
- Value := GetEnumValue(TTypeInfoEnum(PropType), ReadIdent);
- if Value = -1 then
- raise EReadError.Create(SInvalidPropertyValue);
- SetOrdProp(Instance, PropInfo, Value);
- end;
- {$ifndef FPUNONE}
- tkFloat:
- SetFloatProp(Instance, PropInfo, ReadFloat);
- {$endif}
- tkSet:
- begin
- CheckValue(vaSet);
- if TTypeInfoSet(PropType).CompType.Kind=tkEnumeration then
- SetOrdProp(Instance, PropInfo, FDriver.ReadSet(TTypeInfoEnum(TTypeInfoSet(PropType).CompType)));
- end;
- tkMethod, tkRefToProcVar:
- if FDriver.NextValue = vaNil then
- begin
- FDriver.ReadValue;
- SetMethodProp(Instance, PropInfo, NullMethod);
- end else
- begin
- Handled:=false;
- Ident:=ReadIdent;
- if Assigned(OnSetMethodProperty) then
- OnSetMethodProperty(Self,Instance,PropInfo,Ident,Handled);
- if not Handled then begin
- Method.Code := FindMethod(Root, Ident);
- Method.Data := Root;
- if Assigned(Method.Code) then
- SetMethodProp(Instance, PropInfo, Method);
- end;
- end;
- tkString:
- begin
- TmpStr:=ReadString;
- if Assigned(FOnReadStringProperty) then
- FOnReadStringProperty(Self,Instance,PropInfo,TmpStr);
- SetStrProp(Instance, PropInfo, TmpStr);
- end;
- tkJSValue:
- begin
- SetJSValueProp(Instance,PropInfo,ReadVariant);
- end;
- tkClass, tkInterface:
- case FDriver.NextValue of
- vaNil:
- begin
- FDriver.ReadValue;
- SetOrdProp(Instance, PropInfo, 0)
- end;
- vaCollection:
- begin
- FDriver.ReadValue;
- ReadCollection(TCollection(GetObjectProp(Instance, PropInfo)));
- end
- else
- begin
- If Not Assigned(FFixups) then
- FFixups:=TLinkedList.Create(TLocalUnresolvedReference);
- With TLocalUnresolvedReference(TLinkedList(FFixups).Add) do
- begin
- FInstance:=Instance;
- FRoot:=Root;
- FPropInfo:=PropInfo;
- FRelative:=ReadIdent;
- end;
- end;
- end;
- {tkint64:
- SetInt64Prop(Instance, PropInfo, ReadInt64);}
- else
- raise EReadError.CreateFmt(SUnknownPropertyType, [Str(PropType.Kind)]);
- end;
- end;
- function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
- var
- Dummy, i: Integer;
- Flags: TFilerFlags;
- CompClassName, CompName, ResultName: String;
- begin
- FDriver.BeginRootComponent;
- Result := nil;
- {!!!: GlobalNameSpace.BeginWrite; // Loading from stream adds to name space
- try}
- try
- FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
- if not Assigned(ARoot) then
- begin
- { Read the class name and the object name and create a new object: }
- Result := TComponentClass(FindClass(CompClassName)).Create(nil);
- Result.Name := CompName;
- end else
- begin
- Result := ARoot;
- if not (csDesigning in Result.ComponentState) then
- begin
- Result.FComponentState :=
- Result.FComponentState + [csLoading, csReading];
- { We need an unique name }
- i := 0;
- { Don't use Result.Name directly, as this would influence
- FindGlobalComponent in successive loop runs }
- ResultName := CompName;
- while Assigned(FindGlobalComponent(ResultName)) do
- begin
- Inc(i);
- ResultName := CompName + '_' + IntToStr(i);
- end;
- Result.Name := ResultName;
- end;
- end;
- FRoot := Result;
- FLookupRoot := Result;
- if Assigned(GlobalLoaded) then
- FLoaded := GlobalLoaded
- else
- FLoaded := TFpList.Create;
- try
- if FLoaded.IndexOf(FRoot) < 0 then
- FLoaded.Add(FRoot);
- FOwner := FRoot;
- FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
- FRoot.ReadState(Self);
- Exclude(FRoot.FComponentState, csReading);
- if not Assigned(GlobalLoaded) then
- for i := 0 to FLoaded.Count - 1 do
- TComponent(FLoaded[i]).Loaded;
- finally
- if not Assigned(GlobalLoaded) then
- FLoaded.Free;
- FLoaded := nil;
- end;
- GlobalFixupReferences;
- except
- RemoveFixupReferences(ARoot, '');
- if not Assigned(ARoot) then
- Result.Free;
- raise;
- end;
- {finally
- GlobalNameSpace.EndWrite;
- end;}
- end;
- procedure TReader.ReadComponents(AOwner, AParent: TComponent;
- Proc: TReadComponentsProc);
- var
- Component: TComponent;
- begin
- Root := AOwner;
- Owner := AOwner;
- Parent := AParent;
- BeginReferences;
- try
- while not EndOfList do
- begin
- FDriver.BeginRootComponent;
- Component := ReadComponent(nil);
- if Assigned(Proc) then
- Proc(Component);
- end;
- ReadListEnd;
- FixupReferences;
- finally
- EndReferences;
- end;
- end;
- function TReader.ReadString: String;
- var
- StringType: TValueType;
- begin
- StringType := FDriver.ReadValue;
- if StringType=vaString then
- Result := FDriver.ReadString(StringType)
- else
- raise EReadError.Create(SInvalidPropertyValue);
- end;
- function TReader.ReadWideString: WideString;
- begin
- Result:=ReadString;
- end;
- function TReader.ReadUnicodeString: UnicodeString;
- begin
- Result:=ReadString;
- end;
- function TReader.ReadValue: TValueType;
- begin
- Result := FDriver.ReadValue;
- end;
- procedure TReader.CopyValue(Writer: TWriter);
- (*
- procedure CopyBytes(Count: Integer);
- { var
- Buffer: array[0..1023] of Byte; }
- begin
- {!!!: while Count > 1024 do
- begin
- FDriver.Read(Buffer, 1024);
- Writer.Driver.Write(Buffer, 1024);
- Dec(Count, 1024);
- end;
- if Count > 0 then
- begin
- FDriver.Read(Buffer, Count);
- Writer.Driver.Write(Buffer, Count);
- end;}
- end;
- *)
- {var
- s: String;
- Count: LongInt; }
- begin
- case FDriver.NextValue of
- vaNull:
- Writer.WriteIdent('NULL');
- vaFalse:
- Writer.WriteIdent('FALSE');
- vaTrue:
- Writer.WriteIdent('TRUE');
- vaNil:
- Writer.WriteIdent('NIL');
- {!!!: vaList, vaCollection:
- begin
- Writer.WriteValue(FDriver.ReadValue);
- while not EndOfList do
- CopyValue(Writer);
- ReadListEnd;
- Writer.WriteListEnd;
- end;}
- vaInt8, vaInt16, vaInt32:
- Writer.WriteInteger(ReadInteger);
- {$ifndef FPUNONE}
- vaExtended:
- Writer.WriteFloat(ReadFloat);
- {$endif}
- vaString:
- Writer.WriteString(ReadString);
- vaIdent:
- Writer.WriteIdent(ReadIdent);
- {!!!: vaBinary, vaLString, vaWString:
- begin
- Writer.WriteValue(FDriver.ReadValue);
- FDriver.Read(Count, SizeOf(Count));
- Writer.Driver.Write(Count, SizeOf(Count));
- CopyBytes(Count);
- end;}
- {!!!: vaSet:
- Writer.WriteSet(ReadSet);}
- {!!!: vaCurrency:
- Writer.WriteCurrency(ReadCurrency);}
- vaInt64:
- Writer.WriteInteger(ReadNativeInt);
- end;
- end;
- function TReader.FindComponentClass(const AClassName: String): TComponentClass;
- var
- PersistentClass: TPersistentClass;
- function FindClassInFieldTable(Instance: TComponent): TComponentClass;
- var
- aClass: TClass;
- i: longint;
- ClassTI, MemberClassTI: TTypeInfoClass;
- MemberTI: TTypeInfo;
- begin
- aClass:=Instance.ClassType;
- while aClass<>nil do
- begin
- ClassTI:=typeinfo(aClass);
- for i:=0 to ClassTI.FieldCount-1 do
- begin
- MemberTI:=ClassTI.GetField(i).TypeInfo;
- if MemberTI.Kind=tkClass then
- begin
- MemberClassTI:=TTypeInfoClass(MemberTI);
- if SameText(MemberClassTI.Name,aClassName)
- and (MemberClassTI.ClassType is TComponent) then
- exit(TComponentClass(MemberClassTI.ClassType));
- end;
- end;
- aClass:=aClass.ClassParent;
- end;
- end;
- begin
- Result := nil;
- Result:=FindClassInFieldTable(Root);
- if (Result=nil) and assigned(LookupRoot) and (LookupRoot<>Root) then
- Result:=FindClassInFieldTable(LookupRoot);
- if (Result=nil) then begin
- PersistentClass := GetClass(AClassName);
- if PersistentClass.InheritsFrom(TComponent) then
- Result := TComponentClass(PersistentClass);
- end;
- if (Result=nil) and assigned(OnFindComponentClass) then
- OnFindComponentClass(Self, AClassName, Result);
- if (Result=nil) or (not Result.InheritsFrom(TComponent)) then
- raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
- end;
- { TAbstractObjectReader }
- procedure TAbstractObjectReader.FlushBuffer;
- begin
- // Do nothing
- end;
- {
- This file is part of the Free Component Library (FCL)
- Copyright (c) 1999-2000 by the Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {****************************************************************************}
- {* TBinaryObjectWriter *}
- {****************************************************************************}
- procedure TBinaryObjectWriter.WriteWord(w : word);
- begin
- FStream.WriteBufferData(w);
- end;
- procedure TBinaryObjectWriter.WriteDWord(lw : longword);
- begin
- FStream.WriteBufferData(lw);
- end;
- constructor TBinaryObjectWriter.Create(Stream: TStream);
- begin
- inherited Create;
- If (Stream=Nil) then
- Raise EWriteError.Create(SEmptyStreamIllegalWriter);
- FStream := Stream;
- end;
- procedure TBinaryObjectWriter.BeginCollection;
- begin
- WriteValue(vaCollection);
- end;
- procedure TBinaryObjectWriter.WriteSignature;
- begin
- FStream.WriteBufferData(FilerSignatureInt);
- end;
- procedure TBinaryObjectWriter.BeginComponent(Component: TComponent;
- Flags: TFilerFlags; ChildPos: Integer);
- var
- Prefix: Byte;
- begin
- { Only write the flags if they are needed! }
- if Flags <> [] then
- begin
- Prefix:=0;
- if ffInherited in Flags then
- Prefix:=Prefix or $01;
- if ffChildPos in Flags then
- Prefix:=Prefix or $02;
- if ffInline in Flags then
- Prefix:=Prefix or $04;
- Prefix := Prefix or $f0;
- FStream.WriteBufferData(Prefix);
- if ffChildPos in Flags then
- WriteInteger(ChildPos);
- end;
- WriteStr(Component.ClassName);
- WriteStr(Component.Name);
- end;
- procedure TBinaryObjectWriter.BeginList;
- begin
- WriteValue(vaList);
- end;
- procedure TBinaryObjectWriter.EndList;
- begin
- WriteValue(vaNull);
- end;
- procedure TBinaryObjectWriter.BeginProperty(const PropName: String);
- begin
- WriteStr(PropName);
- end;
- procedure TBinaryObjectWriter.EndProperty;
- begin
- end;
- procedure TBinaryObjectWriter.FlushBuffer;
- begin
- // Do nothing;
- end;
- procedure TBinaryObjectWriter.WriteBinary(const Buffer : TBytes; Count: LongInt);
- begin
- WriteValue(vaBinary);
- WriteDWord(longword(Count));
- FStream.Write(Buffer, Count);
- end;
- procedure TBinaryObjectWriter.WriteBoolean(Value: Boolean);
- begin
- if Value then
- WriteValue(vaTrue)
- else
- WriteValue(vaFalse);
- end;
- procedure TBinaryObjectWriter.WriteFloat(const Value: Extended);
- begin
- WriteValue(vaDouble);
- FStream.WriteBufferData(Value);
- end;
- procedure TBinaryObjectWriter.WriteCurrency(const Value: Currency);
- Var
- F : Double;
- begin
- WriteValue(vaCurrency);
- F:=Value;
- FStream.WriteBufferData(F);
- end;
- procedure TBinaryObjectWriter.WriteIdent(const Ident: string);
- begin
- { Check if Ident is a special identifier before trying to just write
- Ident directly }
- if UpperCase(Ident) = 'NIL' then
- WriteValue(vaNil)
- else if UpperCase(Ident) = 'FALSE' then
- WriteValue(vaFalse)
- else if UpperCase(Ident) = 'TRUE' then
- WriteValue(vaTrue)
- else if UpperCase(Ident) = 'NULL' then
- WriteValue(vaNull) else
- begin
- WriteValue(vaIdent);
- WriteStr(Ident);
- end;
- end;
- procedure TBinaryObjectWriter.WriteInteger(Value: NativeInt);
- var
- s: ShortInt;
- i: SmallInt;
- l: Longint;
- begin
- { Use the smallest possible integer type for the given value: }
- if (Value >= -128) and (Value <= 127) then
- begin
- WriteValue(vaInt8);
- s := Value;
- FStream.WriteBufferData(s);
- end else if (Value >= -32768) and (Value <= 32767) then
- begin
- WriteValue(vaInt16);
- i := Value;
- WriteWord(word(i));
- end else if (Value >= -$80000000) and (Value <= $7fffffff) then
- begin
- WriteValue(vaInt32);
- l := Value;
- WriteDWord(longword(l));
- end else
- begin
- WriteValue(vaInt64);
- FStream.WriteBufferData(Value);
- end;
- end;
- procedure TBinaryObjectWriter.WriteNativeInt(Value: NativeInt);
- var
- s: Int8;
- i: Int16;
- l: Int32;
- begin
- { Use the smallest possible integer type for the given value: }
- if (Value <= 127) then
- begin
- WriteValue(vaInt8);
- s := Value;
- FStream.WriteBufferData(s);
- end else if (Value <= 32767) then
- begin
- WriteValue(vaInt16);
- i := Value;
- WriteWord(word(i));
- end else if (Value <= $7fffffff) then
- begin
- WriteValue(vaInt32);
- l := Value;
- WriteDWord(longword(l));
- end else
- begin
- WriteValue(vaQWord);
- FStream.WriteBufferData(Value);
- end;
- end;
- procedure TBinaryObjectWriter.WriteMethodName(const Name: String);
- begin
- if Length(Name) > 0 then
- begin
- WriteValue(vaIdent);
- WriteStr(Name);
- end else
- WriteValue(vaNil);
- end;
- procedure TBinaryObjectWriter.WriteSet(Value: LongInt; SetType: Pointer);
- var
- i: Integer;
- b : Integer;
- begin
- WriteValue(vaSet);
- B:=1;
- for i:=0 to 31 do
- begin
- if (Value and b) <>0 then
- begin
- WriteStr(GetEnumName(PTypeInfo(SetType), i));
- end;
- b:=b shl 1;
- end;
- WriteStr('');
- end;
- procedure TBinaryObjectWriter.WriteString(const Value: String);
- var
- i, len: Integer;
- begin
- len := Length(Value);
- WriteValue(vaString);
- WriteDWord(len);
- For I:=1 to len do
- FStream.WriteBufferData(Value[i]);
- end;
- procedure TBinaryObjectWriter.WriteWideString(const Value: WideString);
- begin
- WriteString(Value);
- end;
- procedure TBinaryObjectWriter.WriteUnicodeString(const Value: UnicodeString);
- begin
- WriteString(Value);
- end;
- procedure TBinaryObjectWriter.WriteVariant(const VarValue: JSValue);
- begin
- if isUndefined(varValue) then
- WriteValue(vaNil)
- else if IsNull(VarValue) then
- WriteValue(vaNull)
- else if IsNumber(VarValue) then
- begin
- if Frac(Double(varValue))=0 then
- WriteInteger(NativeInt(VarValue))
- else
- WriteFloat(Double(varValue))
- end
- else if isBoolean(varValue) then
- WriteBoolean(Boolean(VarValue))
- else if isString(varValue) then
- WriteString(String(VarValue))
- else
- raise EWriteError.Create(SUnsupportedPropertyVariantType);
- end;
- procedure TBinaryObjectWriter.Write(const Buffer : TBytes; Count: LongInt);
- begin
- FStream.Write(Buffer,Count);
- end;
- procedure TBinaryObjectWriter.WriteValue(Value: TValueType);
- var
- b: uint8;
- begin
- b := uint8(Value);
- FStream.WriteBufferData(b);
- end;
- procedure TBinaryObjectWriter.WriteStr(const Value: String);
- var
- len,i: integer;
- b: uint8;
- begin
- len:= Length(Value);
- if len > 255 then
- len := 255;
- b := len;
- FStream.WriteBufferData(b);
- For I:=1 to len do
- FStream.WriteBufferData(Value[i]);
- end;
- {****************************************************************************}
- {* TWriter *}
- {****************************************************************************}
- constructor TWriter.Create(ADriver: TAbstractObjectWriter);
- begin
- inherited Create;
- FDriver := ADriver;
- end;
- constructor TWriter.Create(Stream: TStream);
- begin
- inherited Create;
- If (Stream=Nil) then
- Raise EWriteError.Create(SEmptyStreamIllegalWriter);
- FDriver := CreateDriver(Stream);
- FDestroyDriver := True;
- end;
- destructor TWriter.Destroy;
- begin
- if FDestroyDriver then
- FDriver.Free;
- inherited Destroy;
- end;
- function TWriter.CreateDriver(Stream: TStream): TAbstractObjectWriter;
- begin
- Result := TBinaryObjectWriter.Create(Stream);
- end;
- Type
- TPosComponent = Class(TObject)
- Private
- FPos : Integer;
- FComponent : TComponent;
- Public
- Constructor Create(APos : Integer; AComponent : TComponent);
- end;
- Constructor TPosComponent.Create(APos : Integer; AComponent : TComponent);
- begin
- FPos:=APos;
- FComponent:=AComponent;
- end;
- // Used as argument for calls to TComponent.GetChildren:
- procedure TWriter.AddToAncestorList(Component: TComponent);
- begin
- FAncestors.AddObject(Component.Name,TPosComponent.Create(FAncestors.Count,Component));
- end;
- procedure TWriter.DefineProperty(const Name: String;
- ReadData: TReaderProc; AWriteData: TWriterProc; HasData: Boolean);
- begin
- if HasData and Assigned(AWriteData) then
- begin
- // Write the property name and then the data itself
- Driver.BeginProperty(FPropPath + Name);
- AWriteData(Self);
- Driver.EndProperty;
- end else if assigned(ReadData) then ;
- end;
- procedure TWriter.DefineBinaryProperty(const Name: String;
- ReadData, AWriteData: TStreamProc; HasData: Boolean);
- begin
- if HasData and Assigned(AWriteData) then
- begin
- // Write the property name and then the data itself
- Driver.BeginProperty(FPropPath + Name);
- WriteBinary(AWriteData);
- Driver.EndProperty;
- end else if assigned(ReadData) then ;
- end;
- procedure TWriter.FlushBuffer;
- begin
- Driver.FlushBuffer;
- end;
- procedure TWriter.Write(const Buffer : TBytes; Count: Longint);
- begin
- //This should give an exception if write is not implemented (i.e. TTextObjectWriter)
- //but should work with TBinaryObjectWriter.
- Driver.Write(Buffer, Count);
- end;
- procedure TWriter.SetRoot(ARoot: TComponent);
- begin
- inherited SetRoot(ARoot);
- // Use the new root as lookup root too
- FLookupRoot := ARoot;
- end;
- procedure TWriter.WriteSignature;
- begin
- FDriver.WriteSignature;
- end;
- procedure TWriter.WriteBinary(AWriteData: TStreamProc);
- var
- MemBuffer: TBytesStream;
- begin
- { First write the binary data into a memory stream, then copy this buffered
- stream into the writing destination. This is necessary as we have to know
- the size of the binary data in advance (we're assuming that seeking within
- the writer stream is not possible) }
- MemBuffer := TBytesStream.Create;
- try
- AWriteData(MemBuffer);
- Driver.WriteBinary(MemBuffer.Bytes, MemBuffer.Size);
- finally
- MemBuffer.Free;
- end;
- end;
- procedure TWriter.WriteBoolean(Value: Boolean);
- begin
- Driver.WriteBoolean(Value);
- end;
- procedure TWriter.WriteChar(Value: Char);
- begin
- WriteString(Value);
- end;
- procedure TWriter.WriteWideChar(Value: WideChar);
- begin
- WriteWideString(Value);
- end;
- procedure TWriter.WriteCollection(Value: TCollection);
- var
- i: Integer;
- begin
- Driver.BeginCollection;
- if Assigned(Value) then
- for i := 0 to Value.Count - 1 do
- begin
- { Each collection item needs its own ListBegin/ListEnd tag, or else the
- reader wouldn't be able to know where an item ends and where the next
- one starts }
- WriteListBegin;
- WriteProperties(Value.Items[i]);
- WriteListEnd;
- end;
- WriteListEnd;
- end;
- procedure TWriter.DetermineAncestor(Component : TComponent);
- Var
- I : Integer;
- begin
- // Should be set only when we write an inherited with children.
- if Not Assigned(FAncestors) then
- exit;
- I:=FAncestors.IndexOf(Component.Name);
- If (I=-1) then
- begin
- FAncestor:=Nil;
- FAncestorPos:=-1;
- end
- else
- With TPosComponent(FAncestors.Objects[i]) do
- begin
- FAncestor:=FComponent;
- FAncestorPos:=FPos;
- end;
- end;
- procedure TWriter.DoFindAncestor(Component : TComponent);
- Var
- C : TComponent;
- begin
- if Assigned(FOnFindAncestor) then
- if (Ancestor=Nil) or (Ancestor is TComponent) then
- begin
- C:=TComponent(Ancestor);
- FOnFindAncestor(Self,Component,Component.Name,C,FRootAncestor);
- Ancestor:=C;
- end;
- end;
- procedure TWriter.WriteComponent(Component: TComponent);
- var
- SA : TPersistent;
- SR, SRA : TComponent;
- begin
- SR:=FRoot;
- SA:=FAncestor;
- SRA:=FRootAncestor;
- Try
- Component.FComponentState:=Component.FComponentState+[csWriting];
- Try
- // Possibly set ancestor.
- DetermineAncestor(Component);
- DoFindAncestor(Component); // Mainly for IDE when a parent form had an ancestor renamed...
- // Will call WriteComponentData.
- Component.WriteState(Self);
- FDriver.EndList;
- Finally
- Component.FComponentState:=Component.FComponentState-[csWriting];
- end;
- Finally
- FAncestor:=SA;
- FRoot:=SR;
- FRootAncestor:=SRA;
- end;
- end;
- procedure TWriter.WriteChildren(Component : TComponent);
- Var
- SRoot, SRootA : TComponent;
- SList : TStringList;
- SPos, I , SAncestorPos: Integer;
- O : TObject;
- begin
- // Write children list.
- // While writing children, the ancestor environment must be saved
- // This is recursive...
- SRoot:=FRoot;
- SRootA:=FRootAncestor;
- SList:=FAncestors;
- SPos:=FCurrentPos;
- SAncestorPos:=FAncestorPos;
- try
- FAncestors:=Nil;
- FCurrentPos:=0;
- FAncestorPos:=-1;
- if csInline in Component.ComponentState then
- FRoot:=Component;
- if (FAncestor is TComponent) then
- begin
- FAncestors:=TStringList.Create;
- if csInline in TComponent(FAncestor).ComponentState then
- FRootAncestor := TComponent(FAncestor);
- TComponent(FAncestor).GetChildren(@AddToAncestorList,FRootAncestor);
- FAncestors.Sorted:=True;
- end;
- try
- Component.GetChildren(@WriteComponent, FRoot);
- Finally
- If Assigned(Fancestors) then
- For I:=0 to FAncestors.Count-1 do
- begin
- O:=FAncestors.Objects[i];
- FAncestors.Objects[i]:=Nil;
- O.Free;
- end;
- FreeAndNil(FAncestors);
- end;
- finally
- FAncestors:=Slist;
- FRoot:=SRoot;
- FRootAncestor:=SRootA;
- FCurrentPos:=SPos;
- FAncestorPos:=SAncestorPos;
- end;
- end;
- procedure TWriter.WriteComponentData(Instance: TComponent);
- var
- Flags: TFilerFlags;
- begin
- Flags := [];
- If (Assigned(FAncestor)) and //has ancestor
- (not (csInline in Instance.ComponentState) or // no inline component
- // .. or the inline component is inherited
- (csAncestor in Instance.Componentstate) and (FAncestors <> nil)) then
- Flags:=[ffInherited]
- else If csInline in Instance.ComponentState then
- Flags:=[ffInline];
- If (FAncestors<>Nil) and ((FCurrentPos<>FAncestorPos) or (FAncestor=Nil)) then
- Include(Flags,ffChildPos);
- FDriver.BeginComponent(Instance,Flags,FCurrentPos);
- If (FAncestors<>Nil) then
- Inc(FCurrentPos);
- WriteProperties(Instance);
- WriteListEnd;
- // Needs special handling of ancestor.
- If not IgnoreChildren then
- WriteChildren(Instance);
- end;
- procedure TWriter.WriteDescendent(ARoot: TComponent; AAncestor: TComponent);
- begin
- FRoot := ARoot;
- FAncestor := AAncestor;
- FRootAncestor := AAncestor;
- FLookupRoot := ARoot;
- WriteSignature;
- WriteComponent(ARoot);
- end;
- procedure TWriter.WriteFloat(const Value: Extended);
- begin
- Driver.WriteFloat(Value);
- end;
- procedure TWriter.WriteCurrency(const Value: Currency);
- begin
- Driver.WriteCurrency(Value);
- end;
- procedure TWriter.WriteIdent(const Ident: string);
- begin
- Driver.WriteIdent(Ident);
- end;
- procedure TWriter.WriteInteger(Value: LongInt);
- begin
- Driver.WriteInteger(Value);
- end;
- procedure TWriter.WriteInteger(Value: NativeInt);
- begin
- Driver.WriteInteger(Value);
- end;
- procedure TWriter.WriteSet(Value: LongInt; SetType: Pointer);
- begin
- Driver.WriteSet(Value,SetType);
- end;
- procedure TWriter.WriteVariant(const VarValue: JSValue);
- begin
- Driver.WriteVariant(VarValue);
- end;
- procedure TWriter.WriteListBegin;
- begin
- Driver.BeginList;
- end;
- procedure TWriter.WriteListEnd;
- begin
- Driver.EndList;
- end;
- procedure TWriter.WriteProperties(Instance: TPersistent);
- var
- PropCount,i : integer;
- PropList : TTypeMemberPropertyDynArray;
- begin
- PropList:=GetPropList(Instance);
- PropCount:=Length(PropList);
- if PropCount>0 then
- for i := 0 to PropCount-1 do
- if IsStoredProp(Instance,PropList[i]) then
- WriteProperty(Instance,PropList[i]);
- Instance.DefineProperties(Self);
- end;
- procedure TWriter.WriteProperty(Instance: TPersistent; PropInfo: TTypeMemberProperty);
- var
- HasAncestor: Boolean;
- PropType: TTypeInfo;
- N,Value, DefValue: LongInt;
- Ident: String;
- IntToIdentFn: TIntToIdent;
- {$ifndef FPUNONE}
- FloatValue, DefFloatValue: Extended;
- {$endif}
- MethodValue: TMethod;
- DefMethodValue: TMethod;
- StrValue, DefStrValue: String;
- AncestorObj: TObject;
- C,Component: TComponent;
- ObjValue: TObject;
- SavedAncestor: TPersistent;
- Key, SavedPropPath, Name, lMethodName: String;
- VarValue, DefVarValue : JSValue;
- BoolValue, DefBoolValue: boolean;
- Handled: Boolean;
- O : TJSObject;
- begin
- // do not stream properties without getter
- if PropInfo.Getter='' then
- exit;
- // properties without setter are only allowed, if they are subcomponents
- PropType := PropInfo.TypeInfo;
- if (PropInfo.Setter='') then
- begin
- if PropType.Kind<>tkClass then
- exit;
- ObjValue := TObject(GetObjectProp(Instance, PropInfo));
- if not ObjValue.InheritsFrom(TComponent) or
- not (csSubComponent in TComponent(ObjValue).ComponentStyle) then
- exit;
- end;
- { Check if the ancestor can be used }
- HasAncestor := Assigned(Ancestor) and ((Instance = Root) or
- (Instance.ClassType = Ancestor.ClassType));
- //writeln('TWriter.WriteProperty Name=',PropType^.Name,' Kind=',GetEnumName(TypeInfo(TTypeKind),ord(PropType^.Kind)),' HasAncestor=',HasAncestor);
- case PropType.Kind of
- tkInteger, tkChar, tkEnumeration, tkSet:
- begin
- Value := GetOrdProp(Instance, PropInfo);
- if HasAncestor then
- DefValue := GetOrdProp(Ancestor, PropInfo)
- else
- begin
- if PropType.Kind<>tkSet then
- DefValue := Longint(PropInfo.Default)
- else
- begin
- o:=TJSObject(PropInfo.Default);
- DefValue:=0;
- for Key in o do
- begin
- n:=parseInt(Key,10);
- if n<32 then
- DefValue:=DefValue+(1 shl n);
- end;
- end;
- end;
- // writeln(PPropInfo(PropInfo)^.Name, ', HasAncestor=', ord(HasAncestor), ', Value=', Value, ', Default=', DefValue);
- if (Value <> DefValue) or (DefValue=longint($80000000)) then
- begin
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- case PropType.Kind of
- tkInteger:
- begin
- // Check if this integer has a string identifier
- IntToIdentFn := FindIntToIdent(PropInfo.TypeInfo);
- if Assigned(IntToIdentFn) and IntToIdentFn(Value, Ident) then
- // Integer can be written a human-readable identifier
- WriteIdent(Ident)
- else
- // Integer has to be written just as number
- WriteInteger(Value);
- end;
- tkChar:
- WriteChar(Chr(Value));
- tkSet:
- begin
- Driver.WriteSet(Value, TTypeInfoSet(PropType).CompType);
- end;
- tkEnumeration:
- WriteIdent(GetEnumName(TTypeInfoEnum(PropType), Value));
- end;
- Driver.EndProperty;
- end;
- end;
- {$ifndef FPUNONE}
- tkFloat:
- begin
- FloatValue := GetFloatProp(Instance, PropInfo);
- if HasAncestor then
- DefFloatValue := GetFloatProp(Ancestor, PropInfo)
- else
- begin
- // This is really ugly..
- DefFloatValue:=Double(PropInfo.Default);
- end;
- if (FloatValue<>DefFloatValue) or (not HasAncestor and (int(DefFloatValue)=longint($80000000))) then
- begin
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- WriteFloat(FloatValue);
- Driver.EndProperty;
- end;
- end;
- {$endif}
- tkMethod:
- begin
- MethodValue := GetMethodProp(Instance, PropInfo);
- if HasAncestor then
- DefMethodValue := GetMethodProp(Ancestor, PropInfo)
- else begin
- DefMethodValue.Data := nil;
- DefMethodValue.Code := nil;
- end;
- Handled:=false;
- if Assigned(OnWriteMethodProperty) then
- OnWriteMethodProperty(Self,Instance,PropInfo,MethodValue,
- DefMethodValue,Handled);
- if isString(MethodValue.Code) then
- lMethodName:=String(MethodValue.Code)
- else
- lMethodName:=FLookupRoot.MethodName(MethodValue.Code);
- //Writeln('Writeln A: ',lMethodName);
- if (not Handled) and
- (MethodValue.Code <> DefMethodValue.Code) and
- ((not Assigned(MethodValue.Code)) or
- ((Length(lMethodName) > 0))) then
- begin
- //Writeln('Writeln B',FPropPath + PropInfo.Name);
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- if Assigned(MethodValue.Code) then
- Driver.WriteMethodName(lMethodName)
- else
- Driver.WriteMethodName('');
- Driver.EndProperty;
- end;
- end;
- tkString: // tkSString, tkLString, tkAString are not supported
- begin
- StrValue := GetStrProp(Instance, PropInfo);
- if HasAncestor then
- DefStrValue := GetStrProp(Ancestor, PropInfo)
- else
- begin
- DefValue :=Longint(PropInfo.Default);
- SetLength(DefStrValue, 0);
- end;
- if (StrValue<>DefStrValue) or (not HasAncestor and (DefValue=longint($80000000))) then
- begin
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- if Assigned(FOnWriteStringProperty) then
- FOnWriteStringProperty(Self,Instance,PropInfo,StrValue);
- WriteString(StrValue);
- Driver.EndProperty;
- end;
- end;
- tkJSValue:
- begin
- { Ensure that a Variant manager is installed }
- VarValue := GetJSValueProp(Instance, PropInfo);
- if HasAncestor then
- DefVarValue := GetJSValueProp(Ancestor, PropInfo)
- else
- DefVarValue:=null;
- if (VarValue<>DefVarValue) then
- begin
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- { can't use variant() typecast, pulls in variants unit }
- WriteVariant(VarValue);
- Driver.EndProperty;
- end;
- end;
- tkClass:
- begin
- ObjValue := TObject(GetObjectProp(Instance, PropInfo));
- if HasAncestor then
- begin
- AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo));
- if (AncestorObj is TComponent) and
- (ObjValue is TComponent) then
- begin
- //writeln('TWriter.WriteProperty AncestorObj=',TComponent(AncestorObj).Name,' OwnerFit=',TComponent(AncestorObj).Owner = FRootAncestor,' ',TComponent(ObjValue).Name,' OwnerFit=',TComponent(ObjValue).Owner = Root);
- if (AncestorObj<> ObjValue) and
- (TComponent(AncestorObj).Owner = FRootAncestor) and
- (TComponent(ObjValue).Owner = Root) and
- (UpperCase(TComponent(AncestorObj).Name) = UpperCase(TComponent(ObjValue).Name)) then
- begin
- // different components, but with the same name
- // treat it like an override
- AncestorObj := ObjValue;
- end;
- end;
- end else
- AncestorObj := nil;
- if not Assigned(ObjValue) then
- begin
- if ObjValue <> AncestorObj then
- begin
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- Driver.WriteIdent('NIL');
- Driver.EndProperty;
- end
- end
- else if ObjValue.InheritsFrom(TPersistent) then
- begin
- { Subcomponents are streamed the same way as persistents }
- if ObjValue.InheritsFrom(TComponent)
- and ((not (csSubComponent in TComponent(ObjValue).ComponentStyle))
- or ((TComponent(ObjValue).Owner<>Instance) and (TComponent(ObjValue).Owner<>Nil))) then
- begin
- Component := TComponent(ObjValue);
- if (ObjValue <> AncestorObj)
- and not (csTransient in Component.ComponentStyle) then
- begin
- Name:= '';
- C:= Component;
- While (C<>Nil) and (C.Name<>'') do
- begin
- If (Name<>'') Then
- Name:='.'+Name;
- if C.Owner = LookupRoot then
- begin
- Name := C.Name+Name;
- break;
- end
- else if C = LookupRoot then
- begin
- Name := 'Owner' + Name;
- break;
- end;
- Name:=C.Name + Name;
- C:= C.Owner;
- end;
- if (C=nil) and (Component.Owner=nil) then
- if (Name<>'') then //foreign root
- Name:=Name+'.Owner';
- if Length(Name) > 0 then
- begin
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- WriteIdent(Name);
- Driver.EndProperty;
- end; // length Name>0
- end; //(ObjValue <> AncestorObj)
- end // ObjValue.InheritsFrom(TComponent)
- else
- begin
- SavedAncestor := Ancestor;
- SavedPropPath := FPropPath;
- try
- FPropPath := FPropPath + PropInfo.Name + '.';
- if HasAncestor then
- Ancestor := TPersistent(GetObjectProp(Ancestor, PropInfo));
- WriteProperties(TPersistent(ObjValue));
- finally
- Ancestor := SavedAncestor;
- FPropPath := SavedPropPath;
- end;
- if ObjValue.InheritsFrom(TCollection) then
- begin
- if (not HasAncestor) or (not CollectionsEqual(TCollection(ObjValue),
- TCollection(GetObjectProp(Ancestor, PropInfo)),root,rootancestor)) then
- begin
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- SavedPropPath := FPropPath;
- try
- SetLength(FPropPath, 0);
- WriteCollection(TCollection(ObjValue));
- finally
- FPropPath := SavedPropPath;
- Driver.EndProperty;
- end;
- end;
- end // Tcollection
- end;
- end; // Inheritsfrom(TPersistent)
- end;
- { tkInt64, tkQWord:
- begin
- Int64Value := GetInt64Prop(Instance, PropInfo);
- if HasAncestor then
- DefInt64Value := GetInt64Prop(Ancestor, PropInfo)
- else
- DefInt64Value := 0;
- if Int64Value <> DefInt64Value then
- begin
- Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
- WriteInteger(Int64Value);
- Driver.EndProperty;
- end;
- end;}
- tkBool:
- begin
- BoolValue := GetOrdProp(Instance, PropInfo)<>0;
- if HasAncestor then
- DefBoolValue := GetOrdProp(Ancestor, PropInfo)<>0
- else
- begin
- DefBoolValue := PropInfo.Default<>0;
- DefValue:=Longint(PropInfo.Default);
- end;
- // writeln(PropInfo.Name, ', HasAncestor=', ord(HasAncestor), ', Value=', Value, ', Default=', DefBoolValue);
- if (BoolValue<>DefBoolValue) or (DefValue=longint($80000000)) then
- begin
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- WriteBoolean(BoolValue);
- Driver.EndProperty;
- end;
- end;
- tkInterface:
- begin
- { IntfValue := GetInterfaceProp(Instance, PropInfo);
- if Assigned(IntfValue) and Supports(IntfValue, IInterfaceComponentReference, CompRef) then
- begin
- Component := CompRef.GetComponent;
- if HasAncestor then
- begin
- AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo));
- if (AncestorObj is TComponent) then
- begin
- //writeln('TWriter.WriteProperty AncestorObj=',TComponent(AncestorObj).Name,' OwnerFit=',TComponent(AncestorObj).Owner = FRootAncestor,' ',TComponent(ObjValue).Name,' OwnerFit=',TComponent(ObjValue).Owner = Root);
- if (AncestorObj<> Component) and
- (TComponent(AncestorObj).Owner = FRootAncestor) and
- (Component.Owner = Root) and
- (UpperCase(TComponent(AncestorObj).Name) = UpperCase(Component.Name)) then
- begin
- // different components, but with the same name
- // treat it like an override
- AncestorObj := Component;
- end;
- end;
- end else
- AncestorObj := nil;
- if not Assigned(Component) then
- begin
- if Component <> AncestorObj then
- begin
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- Driver.WriteIdent('NIL');
- Driver.EndProperty;
- end
- end
- else if ((not (csSubComponent in Component.ComponentStyle))
- or ((Component.Owner<>Instance) and (Component.Owner<>Nil))) then
- begin
- if (Component <> AncestorObj)
- and not (csTransient in Component.ComponentStyle) then
- begin
- Name:= '';
- C:= Component;
- While (C<>Nil) and (C.Name<>'') do
- begin
- If (Name<>'') Then
- Name:='.'+Name;
- if C.Owner = LookupRoot then
- begin
- Name := C.Name+Name;
- break;
- end
- else if C = LookupRoot then
- begin
- Name := 'Owner' + Name;
- break;
- end;
- Name:=C.Name + Name;
- C:= C.Owner;
- end;
- if (C=nil) and (Component.Owner=nil) then
- if (Name<>'') then //foreign root
- Name:=Name+'.Owner';
- if Length(Name) > 0 then
- begin
- Driver.BeginProperty(FPropPath + PropInfo.Name);
- WriteIdent(Name);
- Driver.EndProperty;
- end; // length Name>0
- end; //(Component <> AncestorObj)
- end;
- end; //Assigned(IntfValue) and Supports(IntfValue,..
- //else write NIL ?
- } end;
- end;
- end;
- procedure TWriter.WriteRootComponent(ARoot: TComponent);
- begin
- WriteDescendent(ARoot, nil);
- end;
- procedure TWriter.WriteString(const Value: String);
- begin
- Driver.WriteString(Value);
- end;
- procedure TWriter.WriteWideString(const Value: WideString);
- begin
- Driver.WriteWideString(Value);
- end;
- procedure TWriter.WriteUnicodeString(const Value: UnicodeString);
- begin
- Driver.WriteUnicodeString(Value);
- end;
- { TAbstractObjectWriter }
- { ---------------------------------------------------------------------
- Global routines
- ---------------------------------------------------------------------}
- var
- ClassList : TJSObject;
- InitHandlerList : TList;
- FindGlobalComponentList : TFPList;
- Procedure RegisterClass(AClass : TPersistentClass);
- begin
- ClassList[AClass.ClassName]:=AClass;
- end;
- Procedure RegisterClasses(AClasses : specialize TArray<TPersistentClass>);
- var
- AClass : TPersistentClass;
- begin
- for AClass in AClasses do
- RegisterClass(AClass);
- end;
- Function GetClass(AClassName : string) : TPersistentClass;
- begin
- Result:=nil;
- if AClassName='' then exit;
- if not ClassList.hasOwnProperty(AClassName) then exit;
- Result:=TPersistentClass(ClassList[AClassName]);
- end;
- procedure RegisterFindGlobalComponentProc(AFindGlobalComponent: TFindGlobalComponent);
- begin
- if not(assigned(FindGlobalComponentList)) then
- FindGlobalComponentList:=TFPList.Create;
- if FindGlobalComponentList.IndexOf(CodePointer(AFindGlobalComponent))<0 then
- FindGlobalComponentList.Add(CodePointer(AFindGlobalComponent));
- end;
- procedure UnregisterFindGlobalComponentProc(AFindGlobalComponent: TFindGlobalComponent);
- begin
- if assigned(FindGlobalComponentList) then
- FindGlobalComponentList.Remove(CodePointer(AFindGlobalComponent));
- end;
- function FindGlobalComponent(const Name: string): TComponent;
- var
- i : sizeint;
- begin
- Result:=nil;
- if assigned(FindGlobalComponentList) then
- begin
- for i:=FindGlobalComponentList.Count-1 downto 0 do
- begin
- FindGlobalComponent:=TFindGlobalComponent(FindGlobalComponentList[i])(name);
- if assigned(Result) then
- break;
- end;
- end;
- end;
- Function FindNestedComponent(Root : TComponent; APath : String; CStyle : Boolean = True) : TComponent;
- Function GetNextName : String; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- Var
- P : Integer;
- CM : Boolean;
- begin
- P:=Pos('.',APath);
- CM:=False;
- If (P=0) then
- begin
- If CStyle then
- begin
- P:=Pos('->',APath);
- CM:=P<>0;
- end;
- If (P=0) Then
- P:=Length(APath)+1;
- end;
- Result:=Copy(APath,1,P-1);
- Delete(APath,1,P+Ord(CM));
- end;
- Var
- C : TComponent;
- S : String;
- begin
- If (APath='') then
- Result:=Nil
- else
- begin
- Result:=Root;
- While (APath<>'') And (Result<>Nil) do
- begin
- C:=Result;
- S:=Uppercase(GetNextName);
- Result:=C.FindComponent(S);
- If (Result=Nil) And (S='OWNER') then
- Result:=C;
- end;
- end;
- end;
- Type
- TInitHandler = Class(TObject)
- AHandler : TInitComponentHandler;
- AClass : TComponentClass;
- end;
- procedure RegisterInitComponentHandler(ComponentClass: TComponentClass; Handler: TInitComponentHandler);
- Var
- I : Integer;
- H: TInitHandler;
- begin
- If (InitHandlerList=Nil) then
- InitHandlerList:=TList.Create;
- H:=TInitHandler.Create;
- H.Aclass:=ComponentClass;
- H.AHandler:=Handler;
- try
- With InitHandlerList do
- begin
- I:=0;
- While (I<Count) and not H.AClass.InheritsFrom(TInitHandler(Items[I]).AClass) do
- Inc(I);
- { override? }
- if (I<Count) and (TInitHandler(Items[I]).AClass=H.AClass) then
- begin
- TInitHandler(Items[I]).AHandler:=Handler;
- H.Free;
- end
- else
- InitHandlerList.Insert(I,H);
- end;
- except
- H.Free;
- raise;
- end;
- end;
- procedure TObjectStreamConverter.OutStr(s: String);
- Var
- I : integer;
- begin
- For I:=1 to Length(S) do
- Output.WriteBufferData(s[i]);
- end;
- procedure TObjectStreamConverter.OutLn(s: String);
- begin
- OutStr(s + LineEnding);
- end;
- (*
- procedure TObjectStreamConverter.Outchars(P, LastP : Pointer; CharToOrdFunc: CharToOrdFuncty; UseBytes: boolean = false);
- var
- res, NewStr: String;
- w: Cardinal;
- InString, NewInString: Boolean;
- begin
- if p = nil then begin
- res:= '''''';
- end
- else
- begin
- res := '';
- InString := False;
- while P < LastP do
- begin
- NewInString := InString;
- w := CharToOrdfunc(P);
- if w = ord('''') then
- begin //quote char
- if not InString then
- NewInString := True;
- NewStr := '''''';
- end
- else if (Ord(w) >= 32) and ((Ord(w) < 127) or (UseBytes and (Ord(w)<256))) then
- begin //printable ascii or bytes
- if not InString then
- NewInString := True;
- NewStr := char(w);
- end
- else
- begin //ascii control chars, non ascii
- if InString then
- NewInString := False;
- NewStr := '#' + IntToStr(w);
- end;
- if NewInString <> InString then
- begin
- NewStr := '''' + NewStr;
- InString := NewInString;
- end;
- res := res + NewStr;
- end;
- if InString then
- res := res + '''';
- end;
- OutStr(res);
- end;
- *)
- procedure TObjectStreamConverter.OutString(s: String);
- begin
- OutStr(S);
- end;
- (*
- procedure TObjectStreamConverter.OutUtf8Str(s: String);
- begin
- if Encoding=oteLFM then
- OutChars(Pointer(S),PChar(S)+Length(S),@CharToOrd)
- else
- OutChars(Pointer(S),PChar(S)+Length(S),@Utf8ToOrd);
- end;
- *)
- function TObjectStreamConverter.ReadWord : word; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
- begin
- Input.ReadBufferData(Result);
- end;
- function TObjectStreamConverter.ReadDWord : longword; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
- begin
- Input.ReadBufferData(Result);
- end;
- function TObjectStreamConverter.ReadNativeInt : NativeInt; {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
- begin
- Input.ReadBufferData(Result);
- end;
- function TObjectStreamConverter.ReadInt(ValueType: TValueType): NativeInt;
- begin
- case ValueType of
- vaInt8: Result := ShortInt(Input.ReadByte);
- vaInt16: Result := SmallInt(ReadWord);
- vaInt32: Result := LongInt(ReadDWord);
- vaNativeInt: Result := ReadNativeInt;
- end;
- end;
- function TObjectStreamConverter.ReadInt: NativeInt;
- begin
- Result := ReadInt(TValueType(Input.ReadByte));
- end;
- function TObjectStreamConverter.ReadDouble : Double;
- begin
- Input.ReadBufferData(Result);
- end;
- function TObjectStreamConverter.ReadStr: String;
- var
- l,i: Byte;
- c : Char;
- begin
- Input.ReadBufferData(L);
- SetLength(Result,L);
- For I:=1 to L do
- begin
- Input.ReadBufferData(C);
- Result[i]:=C;
- end;
- end;
- function TObjectStreamConverter.ReadString(StringType: TValueType): String;
- var
- i: Integer;
- C : Char;
- begin
- Result:='';
- if StringType<>vaString then
- Raise EFilerError.Create('Invalid string type passed to ReadString');
- i:=ReadDWord;
- SetLength(Result, i);
- for I:=1 to Length(Result) do
- begin
- Input.ReadbufferData(C);
- Result[i]:=C;
- end;
- end;
- procedure TObjectStreamConverter.ProcessBinary;
- var
- ToDo, DoNow, i: LongInt;
- lbuf: TBytes;
- s: String;
- begin
- ToDo := ReadDWord;
- SetLength(lBuf,32);
- OutLn('{');
- while ToDo > 0 do
- begin
- DoNow := ToDo;
- if DoNow > 32 then
- DoNow := 32;
- Dec(ToDo, DoNow);
- s := Indent + ' ';
- Input.ReadBuffer(lbuf, DoNow);
- for i := 0 to DoNow - 1 do
- s := s + IntToHex(lbuf[i], 2);
- OutLn(s);
- end;
- OutLn(indent + '}');
- end;
- procedure TObjectStreamConverter.ProcessValue(ValueType: TValueType; Indent: String);
- var
- s: String;
- { len: LongInt; }
- IsFirst: Boolean;
- {$ifndef FPUNONE}
- ext: Extended;
- {$endif}
- begin
- case ValueType of
- vaList: begin
- OutStr('(');
- IsFirst := True;
- while True do begin
- ValueType := TValueType(Input.ReadByte);
- if ValueType = vaNull then break;
- if IsFirst then begin
- OutLn('');
- IsFirst := False;
- end;
- OutStr(Indent + ' ');
- ProcessValue(ValueType, Indent + ' ');
- end;
- OutLn(Indent + ')');
- end;
- vaInt8: OutLn(IntToStr(ShortInt(Input.ReadByte)));
- vaInt16: OutLn( IntToStr(SmallInt(ReadWord)));
- vaInt32: OutLn(IntToStr(LongInt(ReadDWord)));
- vaNativeInt: OutLn(IntToStr(ReadNativeInt));
- vaDouble: begin
- ext:=ReadDouble;
- Str(ext,S);// Do not use localized strings.
- OutLn(S);
- end;
- vaString: begin
- OutString(''''+StringReplace(ReadString(vaString),'''','''''',[rfReplaceAll])+'''');
- OutLn('');
- end;
- vaIdent: OutLn(ReadStr);
- vaFalse: OutLn('False');
- vaTrue: OutLn('True');
- vaBinary: ProcessBinary;
- vaSet: begin
- OutStr('[');
- IsFirst := True;
- while True do begin
- s := ReadStr;
- if Length(s) = 0 then break;
- if not IsFirst then OutStr(', ');
- IsFirst := False;
- OutStr(s);
- end;
- OutLn(']');
- end;
- vaNil:
- OutLn('nil');
- vaCollection: begin
- OutStr('<');
- while Input.ReadByte <> 0 do begin
- OutLn(Indent);
- Input.Seek(-1, soCurrent);
- OutStr(indent + ' item');
- ValueType := TValueType(Input.ReadByte);
- if ValueType <> vaList then
- OutStr('[' + IntToStr(ReadInt(ValueType)) + ']');
- OutLn('');
- ReadPropList(indent + ' ');
- OutStr(indent + ' end');
- end;
- OutLn('>');
- end;
- {vaSingle: begin OutLn('!!Single!!'); exit end;
- vaCurrency: begin OutLn('!!Currency!!'); exit end;
- vaDate: begin OutLn('!!Date!!'); exit end;}
- else
- Raise EReadError.CreateFmt(SErrInvalidPropertyType,[Ord(ValueType)]);
- end;
- end;
- procedure TObjectStreamConverter.ReadPropList(indent: String);
- begin
- while Input.ReadByte <> 0 do begin
- Input.Seek(-1, soCurrent);
- OutStr(indent + ReadStr + ' = ');
- ProcessValue(TValueType(Input.ReadByte), Indent);
- end;
- end;
- procedure TObjectStreamConverter.ReadObject(indent: String);
- var
- b: Byte;
- ObjClassName, ObjName: String;
- ChildPos: LongInt;
- begin
- // Check for FilerFlags
- b := Input.ReadByte;
- if (b and $f0) = $f0 then begin
- if (b and 2) <> 0 then ChildPos := ReadInt;
- end else begin
- b := 0;
- Input.Seek(-1, soCurrent);
- end;
- ObjClassName := ReadStr;
- ObjName := ReadStr;
- OutStr(Indent);
- if (b and 1) <> 0 then OutStr('inherited')
- else
- if (b and 4) <> 0 then OutStr('inline')
- else OutStr('object');
- OutStr(' ');
- if ObjName <> '' then
- OutStr(ObjName + ': ');
- OutStr(ObjClassName);
- if (b and 2) <> 0 then OutStr('[' + IntToStr(ChildPos) + ']');
- OutLn('');
- ReadPropList(indent + ' ');
- while Input.ReadByte <> 0 do begin
- Input.Seek(-1, soCurrent);
- ReadObject(indent + ' ');
- end;
- OutLn(indent + 'end');
- end;
- procedure TObjectStreamConverter.ObjectBinaryToText(aInput, aOutput: TStream; aEncoding: TObjectTextEncoding);
- begin
- FInput:=aInput;
- FOutput:=aOutput;
- FEncoding:=aEncoding;
- Execute;
- end;
- procedure TObjectStreamConverter.Execute;
- var
- Signature: LongInt;
- begin
- if FIndent = '' then FInDent:=' ';
- If Not Assigned(Input) then
- raise EReadError.Create('Missing input stream');
- If Not Assigned(Output) then
- raise EReadError.Create('Missing output stream');
- FInput.ReadBufferData(Signature);
- if Signature <> FilerSignatureInt then
- raise EReadError.Create(SInvalidImage);
- ReadObject('');
- end;
- procedure TObjectStreamConverter.ObjectBinaryToText(aInput, aOutput: TStream);
- begin
- ObjectBinaryToText(aInput,aOutput,oteDFM);
- end;
- {
- This file is part of the Free Component Library (FCL)
- Copyright (c) 1999-2007 by the Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {****************************************************************************}
- {* TParser *}
- {****************************************************************************}
- const
- {$ifdef CPU16}
- { Avoid too big local stack use for
- MSDOS tiny memory model that uses less than 4096
- bytes for total stack by default. }
- ParseBufSize = 512;
- {$else not CPU16}
- ParseBufSize = 4096;
- {$endif not CPU16}
- TokNames : array[TParserToken] of string = (
- '?',
- 'EOF',
- 'Symbol',
- 'String',
- 'Integer',
- 'Float',
- '-',
- '[',
- '(',
- '<',
- '{',
- ']',
- ')',
- '>',
- '}',
- ',',
- '.',
- '=',
- ':',
- '+'
- );
- function TParser.GetTokenName(aTok: TParserToken): string;
- begin
- Result:=TokNames[aTok]
- end;
- procedure TParser.LoadBuffer;
- var
- CharsRead,i: integer;
- begin
- CharsRead:=0;
- for I:=0 to ParseBufSize-1 do
- begin
- if FStream.ReadData(FBuf[i])<>2 then
- Break;
- Inc(CharsRead);
- end;
- Inc(FDeltaPos, CharsRead);
- FPos := 0;
- FBufLen := CharsRead;
- FEofReached:=CharsRead = 0;
- end;
- procedure TParser.CheckLoadBuffer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- begin
- if fPos>=FBufLen then
- LoadBuffer;
- end;
- procedure TParser.ProcessChar; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- begin
- fLastTokenStr:=fLastTokenStr+fBuf[fPos];
- GotoToNextChar;
- end;
- function TParser.IsNumber: boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- begin
- Result:=fBuf[fPos] in ['0'..'9'];
- end;
- function TParser.IsHexNum: boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- begin
- Result:=fBuf[fPos] in ['0'..'9','A'..'F','a'..'f'];
- end;
- function TParser.IsAlpha: boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- begin
- Result:=fBuf[fPos] in ['_','A'..'Z','a'..'z'];
- end;
- function TParser.IsAlphaNum: boolean; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- begin
- Result:=IsAlpha or IsNumber;
- end;
- function TParser.GetHexValue(c: char): byte; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
- begin
- case c of
- '0'..'9' : Result:=ord(c)-$30;
- 'A'..'F' : Result:=ord(c)-$37; //-$41+$0A
- 'a'..'f' : Result:=ord(c)-$57; //-$61+$0A
- end;
- end;
- function TParser.GetAlphaNum: string;
- begin
- if not IsAlpha then
- ErrorFmt(SParserExpected,[GetTokenName(toSymbol)]);
- Result:='';
- while IsAlphaNum do
- begin
- Result:=Result+fBuf[fPos];
- GotoToNextChar;
- end;
- end;
- procedure TParser.HandleNewLine;
- begin
- if fBuf[fPos]=#13 then //CR
- GotoToNextChar;
- if fBuf[fPos]=#10 then //LF
- GotoToNextChar;
- inc(fSourceLine);
- fDeltaPos:=-(fPos-1);
- end;
- procedure TParser.SkipBOM;
- begin
- // No BOM support
- end;
- procedure TParser.SkipSpaces;
- begin
- while not FEofReached and (fBuf[fPos] in [' ',#9]) do GotoToNextChar;
- end;
- procedure TParser.SkipWhitespace;
- begin
- while not FEofReached do
- begin
- case fBuf[fPos] of
- ' ',#9 : SkipSpaces;
- #10,#13 : HandleNewLine
- else break;
- end;
- end;
- end;
- procedure TParser.HandleEof;
- begin
- fToken:=toEOF;
- fLastTokenStr:='';
- end;
- procedure TParser.HandleAlphaNum;
- begin
- fLastTokenStr:=GetAlphaNum;
- fToken:=toSymbol;
- end;
- procedure TParser.HandleNumber;
- type
- floatPunct = (fpDot,fpE);
- floatPuncts = set of floatPunct;
- var
- allowed : floatPuncts;
- begin
- fLastTokenStr:='';
- while IsNumber do
- ProcessChar;
- fToken:=toInteger;
- if (fBuf[fPos] in ['.','e','E']) then
- begin
- fToken:=toFloat;
- allowed:=[fpDot,fpE];
- while (fBuf[fPos] in ['.','e','E','0'..'9']) do
- begin
- case fBuf[fPos] of
- '.' : if fpDot in allowed then Exclude(allowed,fpDot) else break;
- 'E','e' : if fpE in allowed then
- begin
- allowed:=[];
- ProcessChar;
- if (fBuf[fPos] in ['+','-']) then ProcessChar;
- if not (fBuf[fPos] in ['0'..'9']) then
- ErrorFmt(SParserInvalidFloat,[fLastTokenStr+fBuf[fPos]]);
- end
- else break;
- end;
- ProcessChar;
- end;
- end;
- if (fBuf[fPos] in ['s','S','d','D','c','C']) then //single, date, currency
- begin
- fFloatType:=fBuf[fPos];
- GotoToNextChar;
- fToken:=toFloat;
- end
- else fFloatType:=#0;
- end;
- procedure TParser.HandleHexNumber;
- var valid : boolean;
- begin
- fLastTokenStr:='$';
- GotoToNextChar;
- valid:=false;
- while IsHexNum do
- begin
- valid:=true;
- ProcessChar;
- end;
- if not valid then
- ErrorFmt(SParserInvalidInteger,[fLastTokenStr]);
- fToken:=toInteger;
- end;
- function TParser.HandleQuotedString: string;
- begin
- Result:='';
- GotoToNextChar;
- while true do
- begin
- case fBuf[fPos] of
- #0 : ErrorStr(SParserUnterminatedString);
- #13,#10 : ErrorStr(SParserUnterminatedString);
- '''' : begin
- GotoToNextChar;
- if fBuf[fPos]<>'''' then exit;
- end;
- end;
- Result:=Result+fBuf[fPos];
- GotoToNextChar;
- end;
- end;
- Function TParser.HandleDecimalCharacter : Char;
- var
- i : integer;
- begin
- GotoToNextChar;
- // read a word number
- i:=0;
- while IsNumber and (i<high(word)) do
- begin
- i:=i*10+Ord(fBuf[fPos])-ord('0');
- GotoToNextChar;
- end;
- if i>high(word) then i:=0;
- Result:=Char(i);
- end;
- procedure TParser.HandleString;
- var
- s: string;
- begin
- fLastTokenStr:='';
- while true do
- begin
- case fBuf[fPos] of
- '''' :
- begin
- s:=HandleQuotedString;
- fLastTokenStr:=fLastTokenStr+s;
- end;
- '#' :
- begin
- fLastTokenStr:=fLastTokenStr+HandleDecimalCharacter;
- end;
- else break;
- end;
- end;
- fToken:=Classes.toString
- end;
- procedure TParser.HandleMinus;
- begin
- GotoToNextChar;
- if IsNumber then
- begin
- HandleNumber;
- fLastTokenStr:='-'+fLastTokenStr;
- end
- else
- begin
- fToken:=toMinus;
- fLastTokenStr:='-';
- end;
- end;
- procedure TParser.HandleUnknown;
- begin
- fToken:=toUnknown;
- fLastTokenStr:=fBuf[fPos];
- GotoToNextChar;
- end;
- constructor TParser.Create(Stream: TStream);
- begin
- fStream:=Stream;
- SetLength(fBuf,ParseBufSize);
- fBufLen:=0;
- fPos:=0;
- fDeltaPos:=1;
- fSourceLine:=1;
- fEofReached:=false;
- fLastTokenStr:='';
- fFloatType:=#0;
- fToken:=toEOF;
- LoadBuffer;
- SkipBom;
- NextToken;
- end;
- procedure TParser.GotoToNextChar;
- begin
- Inc(FPos);
- CheckLoadBuffer;
- end;
- destructor TParser.Destroy;
- Var
- aCount : Integer;
- begin
- aCount:=Length(fLastTokenStr)*2;
- fStream.Position:=SourcePos-aCount;
- end;
- procedure TParser.CheckToken(T: tParserToken);
- begin
- if fToken<>T then
- ErrorFmt(SParserWrongTokenType,[GetTokenName(T),GetTokenName(fToken)]);
- end;
- procedure TParser.CheckTokenSymbol(const S: string);
- begin
- CheckToken(toSymbol);
- if CompareText(fLastTokenStr,S)<>0 then
- ErrorFmt(SParserWrongTokenSymbol,[s,fLastTokenStr]);
- end;
- procedure TParser.Error(const Ident: string);
- begin
- ErrorStr(Ident);
- end;
- procedure TParser.ErrorFmt(const Ident: string; const Args: array of const);
- begin
- ErrorStr(Format(Ident,Args));
- end;
- procedure TParser.ErrorStr(const Message: string);
- begin
- raise EParserError.CreateFmt(Message+SParserLocInfo,[SourceLine,fPos+fDeltaPos,SourcePos]);
- end;
- procedure TParser.HexToBinary(Stream: TStream);
- var
- outbuf : TBytes;
- b : byte;
- i : integer;
- begin
- SetLength(OutBuf,ParseBufSize);
- i:=0;
- SkipWhitespace;
- while IsHexNum do
- begin
- b:=(GetHexValue(fBuf[fPos]) shl 4);
- GotoToNextChar;
- if not IsHexNum then
- Error(SParserUnterminatedBinValue);
- b:=b or GetHexValue(fBuf[fPos]);
- GotoToNextChar;
- outbuf[i]:=b;
- inc(i);
- if i>=ParseBufSize then
- begin
- Stream.WriteBuffer(outbuf,i);
- i:=0;
- end;
- SkipWhitespace;
- end;
- if i>0 then
- Stream.WriteBuffer(outbuf,i);
- NextToken;
- end;
- function TParser.NextToken: TParserToken;
- Procedure SetToken(aToken : TParserToken);
- begin
- FToken:=aToken;
- GotoToNextChar;
- end;
- begin
- SkipWhiteSpace;
- if fEofReached then
- HandleEof
- else
- case fBuf[fPos] of
- '_','A'..'Z','a'..'z' : HandleAlphaNum;
- '$' : HandleHexNumber;
- '-' : HandleMinus;
- '0'..'9' : HandleNumber;
- '''','#' : HandleString;
- '[' : SetToken(toSetStart);
- '(' : SetToken(toListStart);
- '<' : SetToken(toCollectionStart);
- '{' : SetToken(toBinaryStart);
- ']' : SetToken(toSetEnd);
- ')' : SetToken(toListEnd);
- '>' : SetToken(toCollectionEnd);
- '}' : SetToken(toBinaryEnd);
- ',' : SetToken(toComma);
- '.' : SetToken(toDot);
- '=' : SetToken(toEqual);
- ':' : SetToken(toColon);
- '+' : SetToken(toPlus);
- else
- HandleUnknown;
- end;
- Result:=fToken;
- end;
- function TParser.SourcePos: Longint;
- begin
- Result:=fStream.Position-fBufLen+fPos;
- end;
- function TParser.TokenComponentIdent: string;
- begin
- if fToken<>toSymbol then
- ErrorFmt(SParserExpected,[GetTokenName(toSymbol)]);
- CheckLoadBuffer;
- while fBuf[fPos]='.' do
- begin
- ProcessChar;
- fLastTokenStr:=fLastTokenStr+GetAlphaNum;
- end;
- Result:=fLastTokenStr;
- end;
- Function TParser.TokenFloat: double;
- var
- errcode : integer;
- begin
- Val(fLastTokenStr,Result,errcode);
- if errcode<>0 then
- ErrorFmt(SParserInvalidFloat,[fLastTokenStr]);
- end;
- Function TParser.TokenInt: NativeInt;
- begin
- if not TryStrToInt64(fLastTokenStr,Result) then
- Result:=StrToQWord(fLastTokenStr); //second chance for malformed files
- end;
- function TParser.TokenString: string;
- begin
- case fToken of
- toFloat : if fFloatType<>#0 then
- Result:=fLastTokenStr+fFloatType
- else Result:=fLastTokenStr;
- else
- Result:=fLastTokenStr;
- end;
- end;
- function TParser.TokenSymbolIs(const S: string): Boolean;
- begin
- Result:=(fToken=toSymbol) and (CompareText(fLastTokenStr,S)=0);
- end;
- procedure TObjectTextConverter.WriteWord(w : word); {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
- begin
- Output.WriteBufferData(w);
- end;
- procedure TObjectTextConverter.WriteDWord(lw : longword); {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
- begin
- Output.WriteBufferData(lw);
- end;
- procedure TObjectTextConverter.WriteQWord(q : NativeInt); {$ifdef CLASSESINLINE}inline;{$endif CLASSESINLINE}
- begin
- Output.WriteBufferData(q);
- end;
- procedure TObjectTextConverter.WriteDouble(e : double);
- begin
- Output.WriteBufferData(e);
- end;
- procedure TObjectTextConverter.WriteString(s: String);
- var
- i,size : byte;
- begin
- if length(s)>255 then
- size:=255
- else
- size:=length(s);
- Output.WriteByte(size);
- For I:=1 to Length(S) do
- Output.WriteBufferData(s[i]);
- end;
- procedure TObjectTextConverter.WriteWString(Const s: WideString);
- var
- i : Integer;
- begin
- WriteDWord(Length(s));
- For I:=1 to Length(S) do
- Output.WriteBufferData(s[i]);
- end;
- procedure TObjectTextConverter.WriteInteger(value: NativeInt);
- begin
- if (value >= -128) and (value <= 127) then begin
- Output.WriteByte(Ord(vaInt8));
- Output.WriteByte(byte(value));
- end else if (value >= -32768) and (value <= 32767) then begin
- Output.WriteByte(Ord(vaInt16));
- WriteWord(word(value));
- end else if (value >= -2147483648) and (value <= 2147483647) then begin
- Output.WriteByte(Ord(vaInt32));
- WriteDWord(longword(value));
- end else begin
- Output.WriteByte(ord(vaInt64));
- WriteQWord(NativeUInt(value));
- end;
- end;
- procedure TObjectTextConverter.ProcessWideString(const left : string);
- var
- ws : string;
- begin
- ws:=left+parser.TokenString;
- while parser.NextToken = toPlus do
- begin
- parser.NextToken; // Get next string fragment
- if not (parser.Token=Classes.toString) then
- parser.CheckToken(Classes.toString);
- ws:=ws+parser.TokenString;
- end;
- Output.WriteByte(Ord(vaWstring));
- WriteWString(ws);
- end;
- procedure TObjectTextConverter.ProcessValue;
- var
- flt: double;
- stream: TBytesStream;
- begin
- case parser.Token of
- toInteger:
- begin
- WriteInteger(parser.TokenInt);
- parser.NextToken;
- end;
- toFloat:
- begin
- Output.WriteByte(Ord(vaExtended));
- flt := Parser.TokenFloat;
- WriteDouble(flt);
- parser.NextToken;
- end;
- classes.toString:
- ProcessWideString('');
- toSymbol:
- begin
- if CompareText(parser.TokenString, 'True') = 0 then
- Output.WriteByte(Ord(vaTrue))
- else if CompareText(parser.TokenString, 'False') = 0 then
- Output.WriteByte(Ord(vaFalse))
- else if CompareText(parser.TokenString, 'nil') = 0 then
- Output.WriteByte(Ord(vaNil))
- else
- begin
- Output.WriteByte(Ord(vaIdent));
- WriteString(parser.TokenComponentIdent);
- end;
- Parser.NextToken;
- end;
- // Set
- toSetStart:
- begin
- parser.NextToken;
- Output.WriteByte(Ord(vaSet));
- if parser.Token <> toSetEnd then
- while True do
- begin
- parser.CheckToken(toSymbol);
- WriteString(parser.TokenString);
- parser.NextToken;
- if parser.Token = toSetEnd then
- break;
- parser.CheckToken(toComma);
- parser.NextToken;
- end;
- Output.WriteByte(0);
- parser.NextToken;
- end;
- // List
- toListStart:
- begin
- parser.NextToken;
- Output.WriteByte(Ord(vaList));
- while parser.Token <> toListEnd do
- ProcessValue;
- Output.WriteByte(0);
- parser.NextToken;
- end;
- // Collection
- toCollectionStart:
- begin
- parser.NextToken;
- Output.WriteByte(Ord(vaCollection));
- while parser.Token <> toCollectionEnd do
- begin
- parser.CheckTokenSymbol('item');
- parser.NextToken;
- // ConvertOrder
- Output.WriteByte(Ord(vaList));
- while not parser.TokenSymbolIs('end') do
- ProcessProperty;
- parser.NextToken; // Skip 'end'
- Output.WriteByte(0);
- end;
- Output.WriteByte(0);
- parser.NextToken;
- end;
- // Binary data
- toBinaryStart:
- begin
- Output.WriteByte(Ord(vaBinary));
- stream := TBytesStream.Create;
- try
- parser.HexToBinary(stream);
- WriteDWord(stream.Size);
- Output.WriteBuffer(Stream.Bytes,Stream.Size);
- finally
- stream.Free;
- end;
- parser.NextToken;
- end;
- else
- parser.Error(SParserInvalidProperty);
- end;
- end;
- procedure TObjectTextConverter.ProcessProperty;
- var
- name: String;
- begin
- // Get name of property
- parser.CheckToken(toSymbol);
- name := parser.TokenString;
- while True do begin
- parser.NextToken;
- if parser.Token <> toDot then break;
- parser.NextToken;
- parser.CheckToken(toSymbol);
- name := name + '.' + parser.TokenString;
- end;
- WriteString(name);
- parser.CheckToken(toEqual);
- parser.NextToken;
- ProcessValue;
- end;
- procedure TObjectTextConverter.ProcessObject;
- var
- Flags: Byte;
- ObjectName, ObjectType: String;
- ChildPos: Integer;
- begin
- if parser.TokenSymbolIs('OBJECT') then
- Flags :=0 { IsInherited := False }
- else begin
- if parser.TokenSymbolIs('INHERITED') then
- Flags := 1 { IsInherited := True; }
- else begin
- parser.CheckTokenSymbol('INLINE');
- Flags := 4;
- end;
- end;
- parser.NextToken;
- parser.CheckToken(toSymbol);
- ObjectName := '';
- ObjectType := parser.TokenString;
- parser.NextToken;
- if parser.Token = toColon then begin
- parser.NextToken;
- parser.CheckToken(toSymbol);
- ObjectName := ObjectType;
- ObjectType := parser.TokenString;
- parser.NextToken;
- if parser.Token = toSetStart then begin
- parser.NextToken;
- ChildPos := parser.TokenInt;
- parser.NextToken;
- parser.CheckToken(toSetEnd);
- parser.NextToken;
- Flags := Flags or 2;
- end;
- end;
- if Flags <> 0 then begin
- Output.WriteByte($f0 or Flags);
- if (Flags and 2) <> 0 then
- WriteInteger(ChildPos);
- end;
- WriteString(ObjectType);
- WriteString(ObjectName);
- // Convert property list
- while not (parser.TokenSymbolIs('END') or
- parser.TokenSymbolIs('OBJECT') or
- parser.TokenSymbolIs('INHERITED') or
- parser.TokenSymbolIs('INLINE')) do
- ProcessProperty;
- Output.WriteByte(0); // Terminate property list
- // Convert child objects
- while not parser.TokenSymbolIs('END') do ProcessObject;
- parser.NextToken; // Skip end token
- Output.WriteByte(0); // Terminate property list
- end;
- procedure TObjectTextConverter.ObjectTextToBinary(aInput, aOutput: TStream);
- begin
- FinPut:=aInput;
- FOutput:=aOutput;
- Execute;
- end;
- procedure TObjectTextConverter.Execute;
- begin
- If Not Assigned(Input) then
- raise EReadError.Create('Missing input stream');
- If Not Assigned(Output) then
- raise EReadError.Create('Missing output stream');
- FParser := TParser.Create(Input);
- try
- Output.WriteBufferData(FilerSignatureInt);
- ProcessObject;
- finally
- FParser.Free;
- end;
- end;
- procedure ObjectTextToBinary(aInput, aOutput: TStream);
- var
- Conv : TObjectTextConverter;
- begin
- Conv:=TObjectTextConverter.Create;
- try
- Conv.ObjectTextToBinary(aInput, aOutput);
- finally
- Conv.free;
- end;
- end;
- initialization
- ClassList:=TJSObject.New;
- end.
|