classes.pas 281 KB

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