classes.pas 268 KB

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