config_file luokka

gummikana 30.03.03 16:52

Luokka jolla voi hakea asetukset tekstitiedostosta, vähän luettavamman version saa osotteesta http://koti.mbnet.fi/kumikana/cpp/config_file/config_file_taulukoilla.zip

 Tekstiversio  Arvo: 2 (2 ääntä)  Äänestä: +  -
////////////////////////////////////////////////////////////////////////////////////////////
// --- config_file.h -------------------------------------------------------------------- //
//                                                                                        //
// alkaa                                                                                  //
// -------------------------------------------------------------------------------------- //
//                                                                                        //
// Mureakuha versio....                                                                   //
//                                                                                        //
// Tämä on nyt vähän käsi versio, koska tässä kaikki vaan kopattu yhteen putkeen.         //
//                                                                                        //
// alkuperäsen version joka sisältää kunnollisen tiedostorakenteen ( nää on leikattu      // 
// valmiiksi omiksi tiedostoikseen ) voi hakea osotteesta                                 //
//                                                                                        //
// http://koti.mbnet.fi/kumikana/cpp/config_file/config_file_taulukoilla.zip              //
//                                                                                        //
// osotteessa http://koti.mbnet.fi/kumikana/cpp/config_file/                              //
// voi ihailla näitä tiedostoja, ilman että tarvii ladata koko zippiä                     //
//                                                                                        //
////////////////////////////////////////////////////////////////////////////////////////////



/*

 
     ****  ***  *   * ***** *****  ****       ***** ***** *     *****
    *     *   * *   * *       *   *           *       *   *     *     
    *     *   * **  * *       *   *           *       *   *     *     
    *     *   * * * * ****    *   * ***       ****    *   *     **** 
    *     *   * *  ** *       *   *   *       *       *   *     *     
    *     *   * *   * *       *   *   *       *       *   *     *     
     ****  ***  *   * *     *****  **** ***** *     ***** ***** *****
   
                        =[ kirjotettu 26.01.2003 ]=
                          -----------------------
                           muokattu   30.03.2003

                            pete@markkupurho.fi


    Sepostus:

        Kirjotin tässä aika äkkiä luokan jonka avulla pystyy lataamaan muuttujia
        tekstitiedostosta. Toimii vähän samaan tapaan .ini tiedostot. Sitä voi
        käyttää erinäkösten asetusten tallentamiseen ja lataamiseen. Muuttujat
        ja niiden arvot ladataan muistiin, josta niitä voi vapauttaa käsin
        (funktiolla poista() ) tai putsaamalla koko hoidon funktiolla
        (poista_kaikki() ) tai tuhoamalla olion joka automaattisesti vapauttaa
        kaiken muistin. Mä tein tän itse yhtä peliä varten sen asetusten
        tallentamiseen ja toivottavasti tästä on hyötyä muillekkin. Yritin meinaan
        itse etsiä googlella vastaavanlaista luokkaa enkä löytäny mitään. Tätä
        saa käyttää kuka tahansa ja mihin tahansa
       
       
    Käytöstä:
       
        Homman pitäis toimia pelkästään liittämällä config_file.h eli lisäämällä
        #include "config_file.h"
        siihen tiedostoon missä haluat config_fileä käyttää.
       
        Suurin osa config_filen funktioista haluaa muuttujan nimen, joka annetaan
        stringinä.
       
        Config_file tuntee neljä muuttuja tyyppiä jotka ovat tyhjä, stringi,
        numero ja taulukko. Stringi on c++ string ja numero on double. Taulukko on
        vähän kinkkisempi tapaus.
       
        Taulukkoa voidaan käyttää kahdella tapaa joko suoraan kutsumalla esim.
        hae_num("taulukko[2]") tai sitten indexin avulla elikkä
        hae_num("taulukko", 2). Kaikkien funnktoiden pitäisi toimia taulukoille
        molemmilla tavoilla. Tosin "taulukko[2]" käskyn käyttäminen on hitaampaa
        kuin "taulukko", 2 käskyn. Mutta ero on niin pieni, että sillä ei ole
        mitään merkitystä.
       
        Koko funktio palauttaa suurimman taulukkoon tallennetun arvon. Ei siis
        suoraan elementtien määrää vaan suurimman arvon. Elikkä seuraavanlaisen
        taulukon koko olisi 100 :

        taulukko[1]   = tekstiä
        taulukko[2]   = tekstiä
        taulukko[100] = tekstiä

        Tyhjien solujen yli voi hyppiä käyttämällä onko funktiota, joka kertoo
        onko kyseiseen kohtaan tallennettu mitään. Taulukoista sen verran vielä,
        että ne hyväksyvät indekseikseen vain numeroita elikkä seuraavanlainen
        taulukon solu olisi laiton

        taulukko[ kymmenen ] = 10
       
       
        Idea on käyttää config_fileä muuttujien tiedostosta lataamiseen ja sinne
        tallentamiseen, ei niiden säilyttämiseen! Se on liian hidas ja kömpelö
        siihen, että muuttujia käsiteltäisiin sen läpi. Joten kannattaa tehdä
        niin, että lataa tavarat tekstitiedostosta muuttujiin ja tyhjentää
        config_filen. Ja ohjelman loputtua / saivaiksen yhteydessä tallennetaan
        muuttujat takasin tiedostoon.
       
       
    Yhteystiedot:
       
        Tän pitäis olla muistivuoto vapaa, mutta bugeja on saattanu eksyä joukoon.
        Niistä voi pistää mulle mailia osotteeseen pete@markkupurho.fi .  Mä voin
        yrittää korjata niitä parhaani kykyni mukaan. Samoin muutakin palautetta
        saa pistää.
       
        Petri Purho ( c ) 2003




*/



#ifndef INC_CONFIG_FILE_H
#define INC_CONFIG_FILE_H

#pragma warning(disable:4786) // Poistaa ilkeet warningit mitä stl antaa jos käyttää stringiä



#include <string>
#include <map>






#define CF_TYHJA  -1
#define CF_STRING 1
#define CF_NUMBER 2
#define CF_TABLE  3



class config_file {

       
public:
       

        // Konstruktorit ja dekonstruktorit
        config_file() { }
        config_file( std::string tiedoston_nimi ) { lataa_tiedosto( tiedoston_nimi ); }
        ~config_file() { poista_kaikki(); }

        // "rajapinnat", eli toiminta periaatteet

        // jos haettavia muuttujia ei ole olemassa palautetaan tyhjät arvot, eli stringinä "" ja doublena 0
        std::string hae_str( std::string muuttujan_nimi );      // Palauttaa stringinä kyseessä olevan muuttujan arvon,
                                                                                                                // jos muuttuja on numero ja sitä pyydetään stringinä niin
                                                                                                                // palautetaan stringinä se numero
       
        double hae_num( std::string muuttujan_nimi );      // Palauttaa doublena kyseessä olevan muuttujan arvon,
                                                                                                                // jos taas kyseinen muuttuja on teksti ja sitä pyydetään
                                                                                                                // numerona palautetaan arvo 0

        std::string hae_str( std::string muuttujan_nimi, int index );   // Tekee samat kun edelliset, mutta taulukoille
        double    hae_num( std::string muuttujan_nimi, int index )// Sama homma


        bool onko_str( std::string muuttujan_nimi );        // Kertoo onko kyseinen muuttuja string tyyppiä
        bool onko_num( std::string muuttujan_nimi );        // Kertoo onko kyseinen muuttuja numero
        bool onko_tab( std::string muuttujan_nimi );        // Kertoo onko kyseinen muuttuja taulukko
        bool onko    ( std::string muuttujan_nimi );        // Kertoo onko meillä muistissa kyseistä muuttujaa

        bool onko_str( std::string muuttujan_nimi, int index ); // Taulukko vastine onko_str:lle
        bool onko_num( std::string muuttujan_nimi, int index ); // Taulukko vastine onko_num:lle
        bool onko( std::string muuttujan_nimi, int index );          // Taulukko vastine onko:lle


        int      tyyppi  ( std::string muuttujan_nimi );               // Kertoo muuttujan tyypin
        int      tyyppi  ( std::string muuttujan_nimi, int index )// Kertoo muuttujan tyypin taulukon solusta

        int  koko( std::string muuttujan_nimi );                                // Palauttaa kyseisen muuttujan koon eli perus muuttujissa palauttaa nollan ja taulukossa se palauttaa taulukon koon

        // tallenna funktioita voi myös käyttää arvojen muuttamiseen
        void tallenna( std::string muuttujan_nimi, std::string arvo );        // tallentaa muuttujan ja sen arvon muistiin
        void tallenna( std::string muuttujan_nimi, double arvo );                                   // tallentaa muuttujan ja sen arvon muistiin
        void tallenna( std::string muuttujan_nimi, int index, std::string arvo );       // tallentaa muuttujan ja sen taulukon arvon muistiin
        void tallenna( std::string muuttujan_nimi, int index, double arvo );        // tallentaa muuttujan ja sen taulukon arvon muistiin


        void poista( std::string muuttujan_nimi );                        // poistaa kyseisen muuttujan muistista
        void poista( std::string muuttujan_nimi, int index );   // poistaa yhden solun taulusta
        void poista_kaikki();                           // poistaa kaikki muuttujat ja niiden arvot

        void lataa_tiedosto( std::string                tiedoston_nimi );              // lataa muuttujat tiedostosta
        void tallenna_tiedostoon( std::string   tiedoston_nimi )// tallentaa kaikki muistissa olevat muuttujat ASCII tiedostoon,
                                                                                                                                // tää muuten sitten tuhoaa sen tiedoston jonka päälle kirjotetaan

        class cf_muuttuja;
        class cf_muuttuja_str;
        class cf_muuttuja_num;
        class cf_muuttuja_tab;
       
private: // parts of howard stern

        // muuttuja luokka, tätä käytetään muuttujien arvojen tallentamiseen
        // Valitettavasti tätä sisäistä toimintaa ei oo kauheesti kommentoitu, koska ei yksinkertasesti ollu aikaa.
        // mun pitää lähteä tossa reilu kolmen tunnin päästä takasin inttiin, joten tää kommentointi jäi aika vähäseks
       
        // pikasesti idea on siinä, että tallennetaan mappiin pointteri cf_muuttujaan nämä pointterit sitten tuhotaan
        // deletellä sopivassa välissä...

        bool        tau_onko_table( std::string muuttujan_nimi ) { if ( muuttujan_nimi.find_last_of( "[" ) != muuttujan_nimi.npos && muuttujan_nimi.find_last_of( "]" ) != muuttujan_nimi.npos ) return true; else return false; }
        std::string     tau_lue_nimi( std::string muuttujan_nimi ) {

                size_t kohdistin = muuttujan_nimi.find_last_of( "[" );
               
                // Tarkistetaan onko taulu
                if ( kohdistin != muuttujan_nimi.npos && muuttujan_nimi.find_last_of( "]" ) != muuttujan_nimi.npos ) {
                       
                        muuttujan_nimi  = muuttujan_nimi.substr( 0, kohdistin );

                        // Poistetaan whitespacet
                        kohdistin = muuttujan_nimi.find_first_not_of(" \t");
                        muuttujan_nimi.erase( 0,  kohdistin );

                        kohdistin = muuttujan_nimi.find_last_not_of(" \t");
                        muuttujan_nimi.erase( kohdistin+1 );
                }

                return muuttujan_nimi;
               

        }

        int tau_lue_index( std::string muuttujan_nimi ) {
                int index = 0;

                size_t kohdistin =  muuttujan_nimi.find_last_of( "[" );

                // Tarkistetaan onko taulu
                if ( kohdistin != muuttujan_nimi.npos && muuttujan_nimi.find_last_of( "]" ) != muuttujan_nimi.npos ) {
                       
                        std::string muuttujan_index;

                        // Leikataan eka osa
                        muuttujan_index = muuttujan_nimi.substr( kohdistin + 1);
                       

                                       
                        // poistetaan whitespacet alusta
                        kohdistin = muuttujan_index.find_first_not_of(" \t");
                        muuttujan_index.erase( 0,  kohdistin );

                        // etsitään kohta jossa numerot muuttuu joskin muuks
                        kohdistin = muuttujan_index.find_first_not_of("0123456789.+-");

                        muuttujan_index = muuttujan_index.erase( kohdistin );

                        // cout << "index on " << muuttujan_index << endl;

                        index = atoi( muuttujan_index.c_str() );
                       
                       
                }
                return index;
        }


        std::map < std::string, cf_muuttuja* >        sisalto;    // sisältää kaikki muuttujat ja niiden arvot
        std::map < std::string, cf_muuttuja* >::iterator        sisalto_selain; // tällä voidaan surffailla sisallossä

 
};


#endif

////////////////////////////////////////////////////////////////////////////////////////////                                                                                          //
// loppuu                                                                                                                                              //
//                                                                                                                                      //
// --- config_file.h -------------------------------------------------------------------- //
////////////////////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////////////////////////
// --- config_file.cpp------------------------------------------------------------------- //
//                                                                                                                                      //
// alkaa                                                                                                                                                                  //
////////////////////////////////////////////////////////////////////////////////////////////



// jos leikkelet nämä omiin tiedostoihinsa niin muista, että tämä config_file.cpp tarvitsee
// ton #include "config_file.h" alkuun
// #include "config_file.h"
#include <fstream>
#include <stdlib.h>

using namespace std;



class config_file::cf_muuttuja {
public:
       
        cf_muuttuja() { }
        virtual ~cf_muuttuja() { }

        virtual string  lue_str() { return ""; }
        virtual double  lue_num() { return 0}

        virtual string  lue_str( int index ) { return ""; }
        virtual double  lue_num( int index ) { return 0; }

        virtual void    sijota( string arvo ) { }
        virtual void    sijota( double arvo ) { }

        virtual void    sijota( int index, string arvo ) { }
        virtual void    sijota( int index, double arvo ) { }

        virtual int          tyyppi() { return -1; }
        virtual int          tyyppi( int index ) { return -1; }

        virtual bool    onko( int index ) { if (index != 0) return false; else return true; }
        virtual int          koko() { return 0; }

       

};

class config_file::cf_muuttuja_str : public config_file::cf_muuttuja {
public:
        cf_muuttuja_str() { }
        ~cf_muuttuja_str() { }

        string lue_str() { return sisalto; }
        double lue_num() { return 0;       }

        string lue_str( int index ) { return sisalto; }
        double lue_num( int index ) { return 0; }

        void sijota( string arvo ) { sisalto = arvo; }
        void sijota( int index, string arvo ) { sisalto = arvo; }

        int tyyppi()            { return CF_STRING; }
        int tyyppi( int index ) { return CF_STRING; }

private:
        string sisalto;

       

};



class config_file::cf_muuttuja_num : public config_file::cf_muuttuja {
public:
        cf_muuttuja_num() { sisalto = 0; }
        ~cf_muuttuja_num() { }

       
        string lue_str() { string tmp( "  " ); gcvt( sisalto, 10, &tmp[0] )return tmp; }
        double lue_num() { return sisalto; }

        string lue_str( int index ) { string tmp( "  " ); gcvt( sisalto, 10, &tmp[0] )return tmp; }
        double lue_num( int index ) { return sisalto; }

        void sijota( double arvo ) { sisalto = arvo; }
        void sijota( int index, double arvo ) { sisalto = arvo; }
       
        int tyyppi()            { return CF_NUMBER; }
        int tyyppi( int index ) { return CF_STRING; }

private:
        double sisalto;

};


class config_file::cf_muuttuja_tab : public config_file::cf_muuttuja {
public:

        cf_muuttuja_tab() : suurin(0) { sisalto.insert( map< int, cf_muuttuja* >::value_type( 0, new cf_muuttuja )  ); }
        cf_muuttuja_tab( cf_muuttuja* nolla ) : suurin(0) { sisalto.insert( map< int, cf_muuttuja* >::value_type( 0, nolla ) ); }
       

        ~cf_muuttuja_tab() {
       
                // poisetaan tavarat muistista
                while ( ! sisalto.empty() ) {

                        map < int, cf_muuttuja* >::iterator sisalto_selain;
                        sisalto_selain = sisalto.begin();
                        delete sisalto_selain->second;
                        sisalto.erase( sisalto_selain );
                }

               
        }

       
        string lue_str() { return etsi( 0 )->lue_str(); }
        double lue_num() { return etsi( 0 )->lue_num(); }

        string lue_str( int index ) { if ( onko( index ) ) return etsi( index )->lue_str(); else return ""; }
        double lue_num( int index ) { if ( onko( index ) ) return etsi( index )->lue_num(); else return 0}

        void sijota( string arvo ) { muunna_str( 0 )->sijota( arvo ); }
        void sijota( double arvo ) { muunna_num( 0 )->sijota( arvo ); }
        void sijota( int index, string arvo ) { if ( suurin < index ) suurin = index; muunna_str( index )->sijota( arvo ); }
        void sijota( int index, double arvo ) { if ( suurin < index ) suurin = index; muunna_num( index )->sijota( arvo ); }
       
        int tyyppi()            { return CF_TABLE; }
        int tyyppi( int index ) { return etsi( index )->tyyppi() ; }

        bool onko( int index ) { if ( sisalto.find( index ) != sisalto.end() ) return true; else return false; }
        int  koko() { return suurin; }
       
        void poista( int index ) {
                map < int, cf_muuttuja* >::iterator selain;

                selain = sisalto.find( index );

                if ( selain != sisalto.end() ) {

                        delete selain->second;
                        sisalto.erase( selain );


                }

        }

private:

       

        cf_muuttuja* etsi( int index ) {
               
                map < int, cf_muuttuja* >::iterator paluu_arvo;

                paluu_arvo = sisalto.find( index );
               
                if ( paluu_arvo == sisalto.end() ) {

                        paluu_arvo = sisalto.find( 0 );

                }
               
                return paluu_arvo->second;
        }

        cf_muuttuja* muunna_str( int index ) {

                map < int, cf_muuttuja* >::iterator paluu_arvo;

                paluu_arvo = sisalto.find( index );
               
                if ( paluu_arvo != sisalto.end() ) {

                        if ( paluu_arvo->second->tyyppi() != CF_STRING ) {
                                delete paluu_arvo->second;
                                paluu_arvo->second = new cf_muuttuja_str;
                        }
                       

                       

                } else {

                        sisalto.insert( map< int, cf_muuttuja* >::value_type( index, new cf_muuttuja_str )  );
                        paluu_arvo = sisalto.find( index );
               
                }
               
                return paluu_arvo->second;
        }

        cf_muuttuja* muunna_num( int index ) {

                map < int, cf_muuttuja* >::iterator paluu_arvo;

                paluu_arvo = sisalto.find( index );
               
                if ( paluu_arvo != sisalto.end() ) {

                        if ( paluu_arvo->second->tyyppi() != CF_NUMBER ) {
                                delete paluu_arvo->second;
                                paluu_arvo->second = new cf_muuttuja_num;
                        }
                       

                       

                } else {

                        sisalto.insert( map< int, cf_muuttuja* >::value_type( index, new cf_muuttuja_num )  );
                        paluu_arvo = sisalto.find( index );
               
                }
               
                return paluu_arvo->second;
        }


        map < int, cf_muuttuja* > sisalto;
        int suurin;

};




// nää tarvis varmaan vähän kommenttia, että näistä joku jotain ymmärtäis...

string config_file::hae_str( string muuttujan_nimi ) {

        if ( tau_onko_table( muuttujan_nimi ) ) { return hae_str( tau_lue_nimi( muuttujan_nimi ), tau_lue_index( muuttujan_nimi ) ); }

        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() ) {
                return sisalto_selain->second->lue_str();
       
        } else { return ""; }

}

double config_file::hae_num( string muuttujan_nimi ) {

        if ( tau_onko_table( muuttujan_nimi ) ) { return hae_num( tau_lue_nimi( muuttujan_nimi ), tau_lue_index( muuttujan_nimi ) ); }

        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() ) {
                return sisalto_selain->second->lue_num();
       
        } else { return 0; }


}


string config_file::hae_str( string muuttujan_nimi, int index ) {

        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() ) {
                return sisalto_selain->second->lue_str( index );
       
        } else { return ""; }

}

double config_file::hae_num( string muuttujan_nimi, int index ) {

        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() ) {
                return sisalto_selain->second->lue_num( index );
       
        } else { return 0; }


}

bool config_file::onko_num( string muuttujan_nimi ) {

        if ( tau_onko_table( muuttujan_nimi ) ) { return onko_num( tau_lue_nimi( muuttujan_nimi ), tau_lue_index( muuttujan_nimi ) ); }

        sisalto_selain = sisalto.find( muuttujan_nimi );

        if (sisalto_selain != sisalto.end() ) {
                if ( sisalto_selain->second->tyyppi() == CF_NUMBER )  return true; else return false;
        }

        return false;

}

bool config_file::onko_num( string muuttujan_nimi, int index ) {

        sisalto_selain = sisalto.find( muuttujan_nimi );

        if (sisalto_selain != sisalto.end() ) {
                if ( sisalto_selain->second->tyyppi( index ) == CF_NUMBER )  return true; else return false;
        }

        return false;

}

bool config_file::onko_str( string muuttujan_nimi ) {
       
        if ( tau_onko_table( muuttujan_nimi ) ) { return onko_str( tau_lue_nimi( muuttujan_nimi ), tau_lue_index( muuttujan_nimi ) ); }

        sisalto_selain = sisalto.find( muuttujan_nimi );

        if (sisalto_selain != sisalto.end() ) {
                if ( sisalto_selain->second->tyyppi() == CF_STRING )  return true; else return false;
        }

        return false;
}

bool config_file::onko_str( string muuttujan_nimi, int index ) {

        sisalto_selain = sisalto.find( muuttujan_nimi );

        if (sisalto_selain != sisalto.end() ) {
                if ( sisalto_selain->second->tyyppi( index ) == CF_STRING )  return true; else return false;
        }

        return false;
}


bool config_file::onko_tab( string muuttujan_nimi ) {


        sisalto_selain = sisalto.find( muuttujan_nimi );

        if (sisalto_selain != sisalto.end() ) {
                if ( sisalto_selain->second->tyyppi() == CF_TABLE )  return true; else return false;
        }

        return false;

}


bool config_file::onko( string muuttujan_nimi ) {

        if ( tau_onko_table( muuttujan_nimi ) ) { return onko( tau_lue_nimi( muuttujan_nimi ), tau_lue_index( muuttujan_nimi ) ); }
       
        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() )
                 return true;
        else return false;
}

bool config_file::onko( string muuttujan_nimi, int index ) {

        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() ) {
                 return sisalto_selain->second->onko( index );
                 // return true;
        }
        else return false;
}


int config_file::tyyppi( string muuttujan_nimi ) {

        if ( tau_onko_table( muuttujan_nimi ) ) { return tyyppi( tau_lue_nimi( muuttujan_nimi ), tau_lue_index( muuttujan_nimi ) ); }

        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() ) {
       
                return sisalto_selain->second->tyyppi();
        }
       
        return CF_TYHJA;


}


int config_file::tyyppi( string muuttujan_nimi, int index ) {

        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() ) {
       
                return sisalto_selain->second->tyyppi( index );
        }
       
        return CF_TYHJA;

}


int config_file::koko( string muuttujan_nimi ) {

        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() ) {
       
                return sisalto_selain->second->koko( );
        }
       
        return 0;


}

void config_file::tallenna( string muuttujan_nimi, string arvo ) {
       
        size_t kohdistin = muuttujan_nimi.find_last_of( "[" );
       
        // Tarkistetaan onko taulu
        if ( kohdistin != muuttujan_nimi.npos && muuttujan_nimi.find_last_of( "]" ) != muuttujan_nimi.npos ) {
               
                string muuttujan_index;

                // Leikataan eka osa
                muuttujan_index = muuttujan_nimi.substr( kohdistin + 1);
                muuttujan_nimi  = muuttujan_nimi.substr( 0, kohdistin );

                               
                // poistetaan whitespacet alusta
                kohdistin = muuttujan_index.find_first_not_of(" \t");
                muuttujan_index.erase( 0,  kohdistin );

                // etsitään kohta jossa numerot muuttuu joskin muuks
                kohdistin = muuttujan_index.find_first_not_of("0123456789.+-");

                muuttujan_index = muuttujan_index.erase( kohdistin );

                // cout << "index on " << muuttujan_index << endl;

                tallenna( muuttujan_nimi, atoi( muuttujan_index.c_str() ), arvo );
                return;
               
        }

        cf_muuttuja *tallennettava_arvo;

        tallennettava_arvo = new cf_muuttuja_str;

        tallennettava_arvo->sijota( arvo );

        sisalto_selain = sisalto.find( muuttujan_nimi );
        if ( sisalto_selain != sisalto.end() ) {
               
                delete sisalto_selain->second;
                sisalto_selain->second = tallennettava_arvo;

        } else {

                // survoo sen sisään, ei tosin mitenkään kovin kauniisti, typedeffiä olis voinu käyttää...
                sisalto.insert( map<string, cf_muuttuja*>::value_type( muuttujan_nimi, tallennettava_arvo )  );
        }
       

}
void config_file::tallenna( string muuttujan_nimi, double arvo ) {
       
        size_t kohdistin =  muuttujan_nimi.find_last_of( "[" );

        // Tarkistetaan onko taulu
        if ( kohdistin != muuttujan_nimi.npos && muuttujan_nimi.find_last_of( "]" ) != muuttujan_nimi.npos ) {
               
                string muuttujan_index;

                // Leikataan eka osa
                muuttujan_index = muuttujan_nimi.substr( kohdistin + 1);
                muuttujan_nimi  = muuttujan_nimi.substr( 0, kohdistin );

                               
                // poistetaan whitespacet alusta
                kohdistin = muuttujan_index.find_first_not_of(" \t");
                muuttujan_index.erase( 0,  kohdistin );

                // etsitään kohta jossa numerot muuttuu joskin muuks
                kohdistin = muuttujan_index.find_first_not_of("0123456789.+-");

                muuttujan_index = muuttujan_index.erase( kohdistin );

                // cout << "index on " << muuttujan_index << endl;

                tallenna( muuttujan_nimi, atoi( muuttujan_index.c_str() ), arvo );
                return;
               
        }

        cf_muuttuja *tallennettava_arvo;

        tallennettava_arvo = new cf_muuttuja_num;

        tallennettava_arvo->sijota( arvo );

        sisalto_selain = sisalto.find( muuttujan_nimi );
        if ( sisalto_selain != sisalto.end() ) {
               
                delete sisalto_selain->second;
                sisalto_selain->second = tallennettava_arvo;

        } else {

                // survoo sen sisään, ei tosin mitenkään kovin kauniisti, typedeffiä olis voinu käyttää...
                sisalto.insert( map<string, cf_muuttuja*>::value_type( muuttujan_nimi, tallennettava_arvo )  );
               
        }
}

void config_file::tallenna( string muuttujan_nimi, int index, double arvo ) {

        // taulukko tallennus
        /*cf_muuttuja *tallennettava_arvo;

        tallennettava_arvo = new cf_muuttuja_num;

        tallennettava_arvo->sijota( arvo );*/


        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() ) {
               
                if ( sisalto_selain->second->tyyppi() != CF_TABLE ) {
                        sisalto_selain->second = new cf_muuttuja_tab( sisalto_selain->second );

                }

                sisalto_selain->second->sijota( index, arvo );

        } else {

                // survoo sen sisään, ei tosin mitenkään kovin kauniisti, typedeffiä olis voinu käyttää...
                cf_muuttuja* tallennettava_arvo;

                tallennettava_arvo = new cf_muuttuja_tab;

                tallennettava_arvo->sijota( index, arvo );

                sisalto.insert( map<string, cf_muuttuja*>::value_type( muuttujan_nimi, tallennettava_arvo )  );
               
        }

}


void config_file::tallenna( string muuttujan_nimi, int index, string arvo ) {

        sisalto_selain = sisalto.find( muuttujan_nimi );
       
        if ( sisalto_selain != sisalto.end() ) {
               
                if ( sisalto_selain->second->tyyppi() != CF_TABLE ) {
                        sisalto_selain->second = new cf_muuttuja_tab( sisalto_selain->second );

                }

                sisalto_selain->second->sijota( index, arvo );

        } else {

                // survoo sen sisään, ei tosin mitenkään kovin kauniisti, typedeffiä olis voinu käyttää...
                cf_muuttuja* tallennettava_arvo;

                tallennettava_arvo = new cf_muuttuja_tab;

                tallennettava_arvo->sijota( index, arvo );

                sisalto.insert( map<string, cf_muuttuja*>::value_type( muuttujan_nimi, tallennettava_arvo )  );
               
        }
}


void config_file::poista( string muuttujan_nimi ) {

        if ( tau_onko_table( muuttujan_nimi ) ) { poista( tau_lue_nimi( muuttujan_nimi), tau_lue_index( muuttujan_nimi ) ); return; }

        sisalto_selain = sisalto.find ( muuttujan_nimi );
        if ( sisalto_selain == sisalto.end() ) return;

        delete sisalto_selain->second;

        sisalto.erase( sisalto_selain );
        sisalto_selain = sisalto.begin();

}

void config_file::poista( string muuttujan_nimi, int index ) {

        sisalto_selain = sisalto.find ( muuttujan_nimi );
        if ( sisalto_selain == sisalto.end() ) return;

        reinterpret_cast<cf_muuttuja_tab*>( sisalto_selain->second )->poista( index );
}

void config_file::poista_kaikki() {

        while ( !sisalto.empty() ) {

                sisalto_selain = sisalto.begin();
                delete sisalto_selain->second;
                sisalto.erase( sisalto_selain );
               
        }

}

void config_file::lataa_tiedosto( string tiedoston_nimi ) {

        size_t  kohdistin;
        fstream filetsu;        // tiedosto_streami
        string  rivi, muuttujan_nimi, muuttujan_arvo_str;
//      double        muuttujan_arvo_num;

        filetsu.open( tiedoston_nimi.c_str(), ios::in );

        // luetaan tiedostosta tavaraa niin kauan kun sitä riittää
        while ( filetsu.good() ) {
               
                getline ( filetsu, rivi );      // luetaan rivi

                // if ( filetsu.good() ) {
                        kohdistin = rivi.find_first_of("=");
                       
                        // tarkistetaan löytykö koko onyhtäkuin merkkiä
                        if ( kohdistin == rivi.npos ) {
                                // ERROR
                                // rivillä se ja se ei löytyny yhtäsuuruus merkkiä, joten sitä riviä ei otettu mukaan operaatioihin
                                // voit kirjottaa johonkin jos huvittaa
                                continue;
                        }
                       
                       
                        muuttujan_nimi     = rivi.substr(0, kohdistin);
                        muuttujan_arvo_str = rivi.substr(kohdistin+1);

                        // poistetaan whitespacet muuttujan_nimestä
                        kohdistin = muuttujan_nimi.find_first_not_of(" \t");
                        muuttujan_nimi.erase( 0,  kohdistin );

                        kohdistin = muuttujan_nimi.find_last_not_of(" \t");
                        muuttujan_nimi.erase( kohdistin+1 );

                        // poistetaan whitespacet muuttujan arvosta
                        kohdistin = muuttujan_arvo_str.find_first_not_of(" \t");
                        muuttujan_arvo_str.erase( 0,  kohdistin );

                        kohdistin = muuttujan_arvo_str.find_last_not_of(" \t");
                        muuttujan_arvo_str.erase( kohdistin+1 );


                       
                        // kohdistin = muuttujan_arvo_str.find_first_not_of("0123456789.+-");

                        // jos löyty jotain muita merkkejä se tarkottaa sitä, että se on stringi
                       
                        // Katotaan mitä tyyppiä meidän muuttuja on
                       
                        if ( muuttujan_arvo_str.find_first_not_of("0123456789.+-") != muuttujan_arvo_str.npos && muuttujan_arvo_str.size() > 0 ) {
                               
                                tallenna( muuttujan_nimi, muuttujan_arvo_str );
                       
                        } else {
                                // jos taas ei löytyny muita merkkejä niin se on numero
                                tallenna( muuttujan_nimi, atof( muuttujan_arvo_str.c_str() ) );
                               

                        }

                        // selvitetään onko muuttujan arvo stringi vai numero


                //}

        }

        filetsu.close();

}

void config_file::tallenna_tiedostoon( string tiedoston_nimi ) {


        ofstream filetsu( tiedoston_nimi.c_str() );
        if (!filetsu) return;
        int i = 0;

        // käydään kaikki muistissa olevat palaset läpi

        for ( sisalto_selain = sisalto.begin(); sisalto_selain != sisalto.end(); ++sisalto_selain ) {

                if ( sisalto_selain->second->tyyppi() != CF_TABLE ) {
                        filetsu << sisalto_selain->first << "=";

                        // tarkistetaan, onko kyseessä oleva muuttuja numero vai stringi
                        if ( sisalto_selain->second->tyyppi() == CF_NUMBER ) filetsu << sisalto_selain->second->lue_num();
                        if ( sisalto_selain->second->tyyppi() == CF_STRING ) filetsu << sisalto_selain->second->lue_str();
               
                } else {
                       
                        i = 0;
                        while ( i <= sisalto_selain->second->koko() ) {
                               
                                if ( sisalto_selain->second->onko( i ) ) {

                                        filetsu << sisalto_selain->first << "[" << i << "]=";
                                                                // tarkistetaan, onko kyseessä oleva muuttuja numero vai stringi
                                        if ( sisalto_selain->second->tyyppi( i ) == CF_NUMBER ) filetsu << sisalto_selain->second->lue_num( i );
                                        if ( sisalto_selain->second->tyyppi( i ) == CF_STRING ) filetsu << sisalto_selain->second->lue_str( i );

                                        filetsu << endl;

                                }

                                i++;

                        }

                }



                filetsu << endl;
        }

        filetsu.close();


}

////////////////////////////////////////////////////////////////////////////////////////////
// loppuu                                                                                                                                              //
//                                                                                                                                      //
// --- config_file.cpp------------------------------------------------------------------- //
////////////////////////////////////////////////////////////////////////////////////////////




////////////////////////////////////////////////////////////////////////////////////////////
// --- main.cpp ------------------------------------------------------------------------- //
//                                                                                                                                      //
// alkaa                                                                                                                                                                  //
////////////////////////////////////////////////////////////////////////////////////////////

/*

  Ja mikäs tämä ny sitten on?

  Tämä on semmonen luokka millä pystyy latamaan ja kirjottamaan muuttujia teksti
  tiedostosta. Näppärä varsinkin erinäkösten asetusten lukemiseen. Tarkempi
  sepostus löytyy config_file.h:sta. Ja tässä main.cpp:ssä on pari-kolme
  hyödyllistä esimerkkiä mitkä kannattaa lukasta.

*/


// jos leikkaat nää omiin tiedostoihinsa niin muista lisätä toi
// #includ