classes.pas 271 KB

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