classes.pas 257 KB

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