classes.pas 268 KB

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