MaGetzUb wrote:Tässä tuli taas pitkästäaikaa räplättyä CoolBasicilla enemmän ja "hakkeroitua" sitä. Ei siis ole kyse kräkkeröinnistä. Huomasin että tekstinhän saa helposti laitettua muistipalaan pelkällä Encrypt kutsulla, kunhan vain luo ensiksi muistipalan jonka pituus on tekstinpituus.
Mielenkiintoinen havainto. CoolBasic käyttää muutenkin muistipaloja aika laajasti joka puolella. Kirjoitan nyt aika pitkästi, eikä tämä sepustukseni nyt välttämättä liity suoraan mihinkään. Kunhan vain tykkään itsekkin kokeilla erikoisia juttuja CoolBasicissa
.
Jokainen merkkijono itsessään on muistipala. Vähän aikaa sitten koitin hieman räpeltää tyyppien kanssa. Jokainen typin jäsenhän on muistipala, joka sisältää tiedon edeltävästä jäsenestä, seuraavasta jäsenestä, tyyppikokoelmasta johon jäsen kuuluu, jäseneen tallennetut arvot sekä vielä "ylimääräiset" neljä tavua, joiden merkitys ei itselleni auennut. Nuo tavut sijaitsevat jäsenen muistipalan lopussa, ja testeissäni ne olivat aina arvoltaan nollia.
Näissä testeissä havaitsin jäsenen ensimmäisen kentän arvon sijaitsevan positiossa 12. Arvo tulee lukea kentän tyypin mukaisella funktiolla, esimerkiksi kokonaisluvun olessa kyseessä:
Code: Select all
PeekInt(ConvertToInteger(tyypin_jäsen), 12)
Käytännön ongelmaksi muodostuu se, että tietotyyppiä ei saa automaattisesti mistään selville - se täytyy tietää. Itse tyyppikokoelman määritystietoihin en testeissäni päässyt käsiksi. Muuttujien suhteen homma toimii niin, että tyyppijäsenmuuttujat sisältävät suoraan osoittimen jäsenen muistipalaan. Sen sijaan tyyppiekokoelman tunnisteet - joita jopa niitäkin pystyy joissain tapauksissa
lukemaan muuttujina - ovat juoksevia numeroita alkaen ykkösestä.
Tällä koodilla saa tyyppikokoelman numeron selville:
Code: Select all
Type HELLO_WORLD
//Kenttien määritykset tähän....
EndType
Function Blah(type_index)
MakeError type_index
EndFunction
Blah(HELLO_WORLD)
Voisi kuvitella, että tuosta tulisi syntaksivirheilmoitus. Ei tule. Tyyppikokoelman tunnisteen voi lukea harvoissa tilanteissa, mutta yksi niistä on käyttäminen funktion parametrina.
(Mielenkiintoinen sivuhuomio on se, että tuo juokseva numero vaikuttaa myös objektien juoksevaan numerointiin: jos ohjelmassa ei ole ainuttakaan tyyppikokoelmaa, ensimmäinen objekti saa numerokseen 1, mutta jos tyyppikokoelmia on, ensimmäisen objektin numero ei ole ykkönen, vaan se on riippuvainen tyyppikokoelmien määrästä). Lisäksi ConvertToInteger() ja ConvertToType() ovat varsin kummallisia funktioita. Mihin niitä tarvitaan? Kyseessä on jonkinlainen syntaksitarkistukseen liittyvä kiertotie. Ne eivät varsinaisesti konvertoi tyyppijäsentä millään tavalla. Muistaakseni CoolBasic sallii suoraan tyyppijäsenen asettamisen kokonaislukumuuttujaan ilman ConvertToIntegerin käyttöä. Sen sijaan itse muuttujan tyyppi on tärkeä jos halutaan lukea tai asettaa jäsenen sisältämiä arvoja: kenoviivan käyttö kokonaislukumuuttujan kohdalla ei ole mitenkään mahdollista.
Jäsenen arvojen lukeminen vaatii siis tietoisuuden arvojen tyypeistä. Jos kyseessä on merkkijono, jäsenen muistipalasta löytyy kokonaisluku, joka kertoo osoittimen itse tekstin sisältävään muistipalaan. Tuon muistipalan voi vaikka käydä poistamassa ja asettamassa tilalle toisen muistipalan. Tai voi muokkailla alkuperäistä muistipalaa. Voit vaikka syöttää saman muistipalan osoittimen kaikille tyyppikokoelman jäsenille johonkin kenttään: näin niillä on yhteinen, jaettu merkkijonomuuttuja. En nyt tiedä sitten, mitä järkeä tässä olisi
.
Näitä jippoja voisi melkein käyttää vaikkapa universaalin tyyppikokoelman tallennusfunktion tekemiseen: funktio kykenisi tallentamaan minkä tahansa tyyppikokoelman kaikki jäsenet. Mutta valitettavasti ei ihan. Periaatteessa jäsenen muistipalan voisi kyllä käydä läpi loopissa ja tallentaa kaikkien kenttien arvot tiedostoon, mutta tekstimuuttujien tunnistaminen ei ikävä kyllä ole mahdollista. Jollain pitäisi saada selville, onko käsiteltävä nelitavuinen tieto osoitin olemassa olevaan muistipalaan vai ei. Kiertotienä voisi käyttää sitä, että funktiolle erikseen kerrotaan, mitkä kentät ovat merkkijonokenttiä.
Tallennusfunktion tekeminen siis kutakuinkin onnistuisi - lataamisfunktiossa taas olisi omat ongelmansa: Koska itse tyyppikokoelman määritykseen ei saa mitään otetta, ei muistipalakomennoilla minun kokemukseni mukaan ole mahdollista vaikuttaa kokoelman First()- ja Last()-arvoihin. Latausfunktio voisi luoda muistipalan, jossa on sama sisältö kuin tallennetulla jäsenellä, mutta sitä ei pystyisi liittämään tyyppikokoelman ensimmäiseksi tai viimeiseksi jäseneksi niin, että CoolBasic sen noteeraisi. Ongelmia seuraisi For Eachia sekä First():a ja Last():a käyttävissä ohjelmissa.
Periaatteessa voisi kuitenkin luopua tyyppikokoelmista järjestettynä listana ja tyytyä luomaan jäseniä ilman listaa. Jäsen saadaan täysin katoamaan tyyppikokoelman listasta jos sen sisältö kopioidaan toiseen muistipalaan (ja sen sisältämät merkkijonot kopioidaan myös ihan uusiin muistipaloihin) ja sen jälkeen poistetaan alkuperäinen jäsen. Jäsenen uuden muistipalan osoitin voidaan asettaa
jäsen.TYYPPi-muuttujan arvoksi, jolloin päästään taas suoraan käsiksi jäsenen kenttien arvoihin. Jäsenen voisi jopa syöttää jäseneksi ihan toiseen tyyppikokoelmaan, mutta aiemmin mainittujen ongelmien vuoksi First() ja Last() -funktiot eivät koskaan näkisi kyseistä jäsentä. Myöskään For Each ei osaisi aloittaa lenkkiä uudesta jäsenestä, mutta toki se kävisi tuon uudenkin jäsenen läpi, jos ketjutus on tehty oikein: uuden kokoelman jonkin jäsenen täytyy sisältää tieto siitä että tämä uusi jäsen on sen seuraaja. Tämä on mahdollista toteuttaa, koska kuten aiemmin mainitsin, jokaisen jäsenen muistipala sisältää osoittimen seuraavan jäsenen muistipalaan - ja myös edellisen jäsenen muistipalaan.
Wall of text päättyy. Varmaan jotkut kohdat olivat aika epäselvästi esitettyjä. Jos asia kiinnostaa, juttelen siitä mielelläni lisää. Sähköpostillakin voi ottaa yhteyttä j-jare.fi. Elikkä viiva pitää muuttaa @-merkiksi. En käy täällä nykyään kovin usein, niin tuo meili on parempi vaihtoehto.