classes.pas 266 KB

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