classes.pas 270 KB

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