classes.pas 264 KB

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