
-info- -----------------------------------------------------------------------------------------------
-info- Dit document is automatisch gegenereerd uit source 'examples/hini.hxx' met 
-info- behulp van de documentatietool 'doc', versie 3.00.
-info- -----------------------------------------------------------------------------------------------



-doc-Algemeen
   library : libbasic.a
   module  : hini
   include : hini.hxx
   link    : -lbasic
  
   Versie Wie              Datum       Wijziging/Opdracht/Omschrijving
   --------------------------------------------------------------------------
   8.00   HNM Dijkema      27-12-1999  Algemeen bruikbare library ten behoeve
                                       van C++ projecten.
-h2- Revisies
   Versie Revisieinformatie
   --------------------------------------------------------------------------
   8.00   Initiele versie
  
-h1- Doel van de library
   Doel van de hini library is om de functionaliteit van Windows .INI files 
   te implementeren, zodat de programmeur een eenvoudige interface heeft
   voor definitie en configuratie files.
  
   De Windows .INI files bestaan uit secties en assignments. Een sectie
   is een identifier tussen rechte haken. Per sectie zijn er assignments
   mogelijk van de vorm 'identifier=...'. Bovendien kunnen comments in de 
   vorm van '; comment' worden gegeven. Voorbeeld:
-ref- testbook
  
   [sectie1]
   ; sectie 1
   id1=abc
   ; Dit was id 1
  
   Doel van de hini library is om iets meer functionaliteit te geven en
   bovendien tolerant te zijn m.b.t. de input. De hini library heeft de 
   volgende functionaliteit:
  
   1. Iets tussen haken is een sectie.
   2. id=... is een identifier met een waarde.
   3. Al het ander is commentaar, netjes is hierbij wel om de ';' te 
      gebruiken, maar het hoeft niet.
   4. De lege sectie wordt herkend; Alle 'id=...' regels voor
      de eerste sectie zijn id's met de lege sectie. 
   5. De mogelijkheid tot gebruik van array elementen is er, d.w.z.
      id[n]=... is een mogelijkheid.
  

-h1- Classes en functies
-h2- class hini
   Deze class implementeert het lezen en schrijven van .INI files.
  
   Indien id 'hallo' wordt gelezen uit sectie 'groet', dan gebeurt dit met
   read("groet","hallo",variabele).
  
   Toegevoegd aan de windows .INI functionaliteit is de volgende 
   functionaliteit:
  
      1. Indien de lege sectie wordt opgegeven, wordt naar ID's
         die niet onder een sectie vallen gekeken.
      2. Bij iedere variabele kan een index worden opgegeven;
         hetgeen resulteert in een variabele met een index, indien
         de index>=0 is. Functieaanroep zonder een index, resulteert
         in een aanroep van dezelfde functie met index==-1 (C++
         functionaliteit voor default invulling van argumenten).
  
   De class hini wordt geinstantieerd met de naam van de .INI file.
   Bij constructie wordt de file in zijn geheel ingelezen in het 
   geheugen. Bij destructie wordt, indien er op de .INI structuur geschreven
   is, de .INI structuur weer weggeschreven naar de .INI file.
  
-bold-   De hini class kan dus niet concurrent gebruikt kan worden!
  
-h3- Grenzen:
   Maximale regellengte in de .INI file:
  
   #define MAX_INI_LINE_LEN 16384

-mem-Private members
-def-
    string        _name;
    harray<string> entries;
    hsarray<int>   sections;
    hsarray<int>   ids;
    bool           written;
    string        _section,_entry;
  
   _name                bevat de naam van de .INI file.
   entries              bevat de regels uit de .INI file.
   sections             bevat offsets in entries, waarvoor isSection() geldt.
   ids                  bevat voor elke regel in entries mkId(regel)
   written              =true, na de eerste write().
   _section             opslag variabele voor member getSection()
   _entry               opslag variabele voor member getEntry()

-mem-Public members
-def-
    hini(char *filename,bool _mustExist=false);
  
    Op het moment dat een variabele van type hini wordt geinstantieerd, 
    wordt deze functie per definitie aangeroepen.
  
    pre:  filename is een geldige filename.
          Indien filename bestaat, is het een .INI file.
    post: indien filename bestaat, zijn de regels van de file
          ingelezen.
          Anders, indien _mustExist==true, wordt een fatale fout
          gegenereerd, en wordt het programma verlaten.

-def-
   ~hini();
  
    Op het moment dat een variabele van type hini wordt opgeruimd, wordt 
    deze functie per definitie aangeroepen.
  
    pre:  indien written == true, moet filename schrijfbaar zijn.
    post: indien written == true, wordt de .INI file naar
          filename weggeschreven.

-mem-Public members
-def-
    bool write(string id,string & value,int index=-1) 
    bool write(string id,char *value,int index=-1)
    bool write(string id,int value,int index=-1)
    bool write(string id,double value,int index=-1)
    bool write(string section,string id,string & value,int index=-1)
    bool write(string section,string id,char *value,int index=-1)
    bool write(string section,string id,int value,int index=-1)
    bool write(string section,string id,double value,int index=-1)
    bool write(char *section,char *id,string & value,int index=-1);
    bool write(char *section,char *id,char *value,int index=-1);
    bool write(char *section,char *id,int value,int index=-1);
    bool write(char *section,char *id,double value,int index=-1);
   
   pre : index>=0 ==> er wordt gezocht naar id[index].
         anders   ==> er wordt gezocht naar id.
         section mag "" zijn. 
   post: Indien id of id[index] niet werd gevonden onder sectie section
         dan is er een nieuwe id onder section aangemaakt.
         Indien section niet kon worden gevonden, is er een nieuwe sectie
         section aangemaakt.
         id of id[index] heeft de waarde van value gekregen.
   alg.: Voor het zoekalgoritme, zie members read().
         Bij het invoegen worden variabelen sections en ids geupdate.

-mem-Public members
-def-
    bool sectionExists(string section);
    
    pre: -
    post: =true, indien sectie section bestaat
          =false, otherwise.

-mem-Public members
-def-
    bool read(string id,string & value,int index=-1)
    bool read(string id,int & value,int index=-1)
    bool read(string id,double & value,int index=-1)
    bool read(string section,string id,string & value,int index=-1)
    bool read(string section,string id,int & value,int index=-1)
    bool read(string section,string id,double & value,int index=-1)
    bool read(char *section,char *id,string & value,int index=-1);
    bool read(char *section,char *id,int & value,int index=-1);
    bool read(char *section,char *id,double & value,int index=-1);
   
    pre : index>=0 ==> er wordt gezocht naar id[index].
          anders   ==> er wordt gezocht naar id.
          section mag "" zijn. 
  
    post: =false,  id niet gevonden, of de waarde van id is niet
                   van het type van value.
          =true,   otherwise --> value is de waarde van id.
  
    alg.: Het zoek algoritme is als volgt:
            IDint=mkId(id)
            1. De sectie wordt gezocht via private variabele sections[].
            2. Binnen de gevonden sectie wordt gezocht naar de id. Dit
               is een lineaire zoekmethode met een tweetraps manier van 
               zoeken. 
               Indien IDint=ids[line], dan, indien rightEntry(line,id),
               dan is de id gevonden.

-mem-Public members
-def-
  string & section(int i);
  
   pre  : i>=0
   post : ="", i==0 (de eerste sectie is geen sectie, maar kan worden
                     gebruikt voor variabelen zonder sectie id)
          =sectie(i), otherwise

-def-
  int      numOfSections(void) 
  
   pre  : true
   post : = het aantal secties in de .INI file+1 voor de lege sectie.
  

-def-
  string & name(void) 
  
   pre  : true
   post : = de naam van de .ini file.
  

-mem-Private members
-def-
    bool isSection(int line);
  
     post : =true, indien regel 'line' van de .INI file is een 
                   sectie ([...]).
  
-def-
    bool isEntry(int line);
  
     post : =true, indien regel 'line' van de .INI file een id=... is.
  
-def-
    string & getEntry(int line);
  
     post: =het ... gedeelte van id=...
  
-def-
    int  mkId(int line);
  
     returns mkId(char *) over regel 'line'
  
-def-
    int  mkId(char *id);
  
     post: =versnel id (integer) over een string.
     opm.: Dit is een functie die van een hele regel uit de .INI file
           een integer identifier maakt, m.b.v. een berekening.
           Door op identifier te zoeken in plaats van op hele strings
           wordt het zoeken in de .INI file aanzienlijk versneld.
  
-def-
    bool rightSection(int line,char *section);
  
     post: =true, isSection(line) && section==de ... uit [...]
  
-def-
    bool rightEntry(int line,char *id);
  
     post: =true, isEntry(line) && id==de id uit id=...
  
-def-
    void getValue(int line,string & r);
  
     pre : isEntry(line)
     post: r=de ... uit id=...
  
-def-
    void getSection(int line,string & r);
  
     pre : isSection(line)
     post: r=de ... uit [...]
  

-h1- Verwijzingen
      n.v.t.



-h1- Gegevensbenadering
-h2- hini files
      Files worden als standaard C streams benaderd.
      Ze worden gesloten, onmiddellijk nadat ze gelezen of geschreven zijn.



-h1- Voorbeeldprogramma(s)
-h2- tst_hini.cxx
    #include <hini.hxx>
    
    int main()
    {
    hini   I("tst.ini");
    string v;
    int    vi;
    double vd;
    bool   a;
    
    try{
      a=I.read("IDonly",v);
      printf("%d:%s:%d\n",a,v.c_str(),v.length());
    
      a=I.read("testsection","testid",v);
      printf("%d:%s:%d\n",a,v.c_str(),v.length());
      a=I.read("testsection","testid",v,1);
      printf("%d:%s:%d\n",a,v.c_str(),v.length());
      a=I.read("testsection","testid",v,2);
      printf("%d:%s:%d\n",a,v.c_str(),v.length());
      a=I.read("testsection","testid",vi,2);
      printf("%d:%d\n",a,vi);
      a=I.read("testsection","testid",vi);
      printf("%d:%d\n",a,vi);
      a=I.read("sectie2","t",vd);
      printf("%d:%lf\n",a,vd);
      a=I.read("sectie2","t",vd,1);
      printf("%d:%lf\n",a,vd);
      a=I.read("sectie2","t",vd,2);
      printf("%d:%lf\n",a,vd);
      a=I.read("sectie2","t",vd,3);
      printf("%d:%lf\n",a,vd);
      a=I.read("sectie2","t",vd,4);
      printf("%d:%lf\n",a,vd);
      a=I.read("sectie2","t",vd,5);
      printf("%d:%lf\n",a,vd);
    
      printf("\nwriting...\n");
    
      a=I.write("wsectie","HalloID","Hallo allemaal");
      a=I.write("wsectie","HalloID","Hallo allemaal",1021);
      a=I.write("wsectie","int",8923742);
      a=I.write("wsectie","double",8923742.98932);
      a=I.write("wsectie","double",0.1,1);
    
      string w="hoi allemaal";
      a=I.write("wsectie string","string",w,1);
      w=w+" nou?";
      a=I.write("wsectie string","string",w,0);
    
      printf("\nreading...\n");
    
      a=I.read("wsectie string","string",v,1);
      printf("%d:%s:%d\n",a,v.c_str(),v.length());
    
      a=I.read("wsectie string","string",v,0);
      printf("%d:%s:%d\n",a,v.c_str(),v.length());
    
      a=I.read("wsectie","int",v);
      printf -REF-(testbook) ("%d:%s:%d\n",a,v.c_str(),v.length());
    }
    
      catch(char *msg) {int e;
        printf("%s\n",msg);
        e=atoi(msg+1);
        exit(e);
      }
    
    } -REF-(testbook)

