classes.pas 225 KB

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