classes.pas 263 KB

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