classes.pas 264 KB

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