classes.pas 267 KB

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