classes.pas 265 KB

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