classes.pas 258 KB

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