classes.pas 259 KB

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