rllib  1
rlinifile.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           rlinifile.cpp  -  description
00003                              -------------------
00004     begin                : Tue Jan 02 2001
00005     copyright            : (C) 2001 by Rainer Lehrig
00006     email                : lehrig@t-online.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as        *
00013  *   published by the Free Software Foundation                             *
00014  *                                                                         *
00015  ***************************************************************************/
00016 #include "rldefine.h"
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <stdarg.h>
00020 #include <string.h>
00021 #ifdef RLWIN32
00022 #include <windows.h>
00023 #endif
00024 #include "rlinifile.h"
00025 #include "rlcutil.h"
00026 
00027 static const char null_string[] = "";
00028 
00029 rlIniFile::rlIniFile()
00030 {
00031   _firstSection = new rlSection;      // first section holds names with section name = null_string
00032   _firstSection->nextSection = NULL;
00033   _firstSection->firstName = NULL;
00034   _firstSection->name = new char[1];
00035   _firstSection->name[0] = '\0';
00036   currentSection = currentName = -1;
00037 }
00038 
00039 rlIniFile::~rlIniFile()
00040 {
00041   rlSection *section, *last_section;
00042 
00043   section = _firstSection;
00044   while(section != NULL)
00045   {
00046     deleteSectionNames(section);
00047     last_section = section;
00048     section = section->nextSection;
00049     delete last_section;
00050   }
00051 }
00052 
00053 void rlIniFile::deleteSectionNames(rlSection *section)
00054 {
00055   rlSectionName *name, *last_name;
00056 
00057   if(section == NULL) return;
00058   name = section->firstName;
00059   while(name != NULL)
00060   {
00061     if(name->name  != NULL) delete [] name->name;
00062     if(name->param != NULL) delete [] name->param;
00063     last_name = name;
00064     name = name->nextName;
00065     delete [] last_name;
00066   }
00067   if(section->name != NULL) delete [] section->name;
00068 }
00069 
00070 void rlIniFile::copyIdentifier(char *buf, const char *line)
00071 {
00072   int i = 1;
00073   buf[0] = '\0';
00074   if(line[0] != '[') return;
00075   while(line[i] != ']' && line[i] != '\0')
00076   {
00077     *buf++ = line[i++];
00078   }
00079   *buf = '\0';
00080 }
00081 
00082 void rlIniFile::copyName(char *buf, const char *line)
00083 {
00084   int i = 0;
00085   buf[0] = '\0';
00086   //while(line[i] > ' ' && line[i] != '=')
00087   while(line[i] != '\0' && line[i] != '=')
00088   {
00089     *buf++ = line[i++];
00090   }
00091   *buf = '\0';
00092   i--; // eventually delete spaces
00093   while(i>=0 && (buf[i] == ' ' || buf[i] == '\t'))
00094   {
00095     buf[i--] = '\0';
00096   } 
00097 }
00098 
00099 void rlIniFile::copyParam(char *buf, const char *line)
00100 {
00101   const char *cptr;
00102   buf[0] = '\0';
00103   cptr = strchr(line,'=');
00104   if(cptr == NULL) return;
00105   cptr++;
00106   while((*cptr == ' ' || *cptr == '\t') && *cptr != '\0') cptr++;
00107   if(*cptr == '\0') return;
00108   while(*cptr != '\0' && *cptr != '\n') *buf++ = *cptr++;
00109   *buf = '\0';
00110 }
00111 
00112 int rlIniFile::read(const char *filename)
00113 {
00114   FILE *fp;
00115   char line[rl_PRINTF_LENGTH],
00116        name_section[rl_PRINTF_LENGTH],
00117        name_name[rl_PRINTF_LENGTH],
00118        name_param[rl_PRINTF_LENGTH],
00119        *cptr;
00120   rlSection *s, *s_old;
00121 
00122   // delete old content
00123   s = _firstSection;
00124   while(s != NULL)
00125   {
00126     deleteSectionNames(s);
00127     s_old = s;
00128     s = s->nextSection;
00129     delete s_old;
00130   }
00131 
00132   // read the file
00133   fname.setText(filename);
00134   _firstSection = new rlSection;      // first section holds names with section name = null_string
00135   _firstSection->nextSection = NULL;
00136   _firstSection->firstName = NULL;
00137   _firstSection->name = new char[1];
00138   _firstSection->name[0] = '\0';
00139   fp = fopen(filename,"r");
00140   if(fp == NULL) return -1;
00141   name_section[0] = name_name[0] = name_param[0] = '\0';
00142   while(fgets(line,sizeof(line)-1,fp) != NULL)
00143   {
00144     cptr = strchr(line,0x0d);
00145     if(cptr != NULL) *cptr = '\0';
00146     cptr = strchr(line,0x0a);
00147     if(cptr != NULL) *cptr = '\0';
00148     if(line[0] == '[') // section identifier
00149     {
00150       copyIdentifier(name_section,line);
00151       setText(name_section, NULL, NULL);
00152     }
00153     else if(line[0] > ' ' && line[0] != '\t' && line[0] != '#') // name identifier
00154     {
00155       copyName(name_name,line);
00156       copyParam(name_param,line);
00157       setText(name_section, name_name, name_param);
00158     }
00159     else // it must be a comment line
00160     {
00161       setText(name_section, line, NULL);
00162     }
00163   }
00164   fclose(fp);
00165   return 0;
00166 }
00167 
00168 int rlIniFile::write(const char *filename)
00169 {
00170   FILE *fp;
00171   rlSection *s;
00172   rlSectionName *n;
00173 
00174   fp = fopen(filename,"w");
00175   if(fp == NULL) return -1;
00176 
00177   s = _firstSection;
00178   while(s != NULL)
00179   {
00180     if     (s->name[0] == '#')  fprintf(fp,"%s\n",s->name);
00181     else if(s->name[0] == '\0') ;
00182     else                        fprintf(fp,"[%s]\n",s->name);
00183     n = s->firstName;
00184     while(n != NULL)
00185     {
00186       if     (n->name[0]  == '#')  fprintf(fp,"%s\n",n->name);
00187       else if(n->name[0]  == '\0') fprintf(fp,"\n");
00188       else if(n->param[0] == '\0') fprintf(fp,"\n");
00189       else                         fprintf(fp,"%s=%s\n",n->name,n->param);
00190       n = n->nextName;
00191     }
00192     s = s->nextSection;
00193   }
00194 
00195   fclose(fp);
00196   return 0;
00197 }
00198 
00199 const char *rlIniFile::filename()
00200 {
00201   return fname.text();
00202 }
00203 
00204 const char *rlIniFile::text(const char *section, const char *name)
00205 {
00206   rlSection *s;
00207   rlSectionName *n;
00208 
00209   s = _firstSection;
00210   while(s != NULL)
00211   {
00212     if(strcmp(section,s->name) == 0)
00213     {
00214       n = s->firstName;
00215       while(n != NULL)
00216       {
00217         if(n->name != NULL && strcmp(name,n->name) == 0)
00218         {
00219           return n->param;
00220         }
00221         n = n->nextName;
00222       }
00223       return null_string;
00224     }
00225     s = s->nextSection;
00226   }
00227   return null_string;
00228 }
00229 
00230 void rlIniFile::setText(const char *section, const char *name, const char *text)
00231 {
00232   rlSection *s, *last_section;
00233   rlSectionName *n, *last_name;
00234 
00235   if(section == NULL) return;
00236   last_section = NULL;
00237   last_name = NULL;
00238   s = _firstSection;
00239   while(s != NULL)
00240   {
00241     if(strcmp(section,s->name) == 0)
00242     {
00243       last_name = NULL;
00244       n = s->firstName;
00245       while(n != NULL)
00246       {
00247         if(name != NULL && name[0] != '#' && name[0] != '\0' && strcmp(name,n->name) == 0)
00248         {
00249           if(n->param != NULL) delete [] n->param;
00250           if(text == NULL)
00251           {
00252             n->param = new char[1];
00253             n->param[0] = '\0';
00254           }
00255           else
00256           {
00257             n->param = new char[strlen(text)+1];
00258             strcpy(n->param,text);
00259           }
00260           return;
00261         }
00262         last_name = n;
00263         n = n->nextName;
00264       }
00265       if(last_name == NULL)
00266       {
00267         s->firstName = new rlSectionName;
00268         n = s->firstName;
00269       }
00270       else
00271       {
00272         last_name->nextName = new rlSectionName;
00273         n = last_name->nextName;
00274       }
00275       if(name == NULL)
00276       {
00277         n->name = new char[1];
00278         n->name[0] = '\0';
00279       }
00280       else
00281       {
00282         n->name = new char[strlen(name)+1];
00283         strcpy(n->name,name);
00284       }
00285       if(text == NULL)
00286       {
00287         n->param = new char[1];
00288         n->param[0] = '\0';
00289       }
00290       else
00291       {
00292         n->param = new char[strlen(text)+1];
00293         strcpy(n->param,text);
00294       }
00295       n->nextName = NULL;
00296       return;
00297     }
00298     last_section = s;
00299     s = s->nextSection;
00300   }
00301   if(last_section == NULL)
00302   {
00303     _firstSection = new rlSection;
00304     last_section = _firstSection;
00305   }
00306   else
00307   {
00308     last_section->nextSection = new rlSection;
00309     last_section = last_section->nextSection;
00310   }
00311   last_section->name = new char[strlen(section)+1];
00312   strcpy(last_section->name,section);
00313   last_section->nextSection = NULL;
00314   if(name == NULL)
00315   {
00316     last_section->firstName = NULL;
00317   }
00318   else
00319   {
00320     last_section->firstName = new rlSectionName;
00321     n = last_section->firstName;
00322     n->name = new char[strlen(name)+1];
00323     strcpy(n->name,name);
00324     if(text == NULL)
00325     {
00326       n->param = new char[1];
00327       n->param[0] = '\0';
00328     }
00329     else
00330     {
00331       n->param = new char[strlen(text)+1];
00332       strcpy(n->param,text);
00333     }
00334     n->nextName = NULL;
00335   }
00336   return;
00337 }
00338 
00339 int rlIniFile::printf(const char *section, const char *name, const char *format, ...)
00340 {
00341   int ret;
00342   char buf[rl_PRINTF_LENGTH]; // should be big enough
00343   
00344   va_list ap;
00345   va_start(ap,format);
00346   ret = rlvsnprintf(buf, rl_PRINTF_LENGTH - 1, format, ap);
00347   va_end(ap);
00348   if(ret > 0) setText(section, name, buf);
00349   return ret;
00350 }
00351 
00352 void rlIniFile::remove(const char *section)
00353 {
00354   rlSection *s, *last;
00355 
00356   last = NULL;
00357   s = _firstSection;
00358   while(s != NULL)
00359   {
00360     if(strcmp(section,s->name) == 0)
00361     {
00362       deleteSectionNames(s);
00363       if(last != NULL) last->nextSection = s->nextSection;
00364       delete s;
00365       return;
00366     }
00367     last = s;
00368     s = s->nextSection;
00369   }
00370 }
00371 
00372 void rlIniFile::remove(const char *section, const char *name)
00373 {
00374   rlSection *s;
00375   rlSectionName *n, *last;
00376 
00377   s = _firstSection;
00378   while(s != NULL)
00379   {
00380     if(strcmp(section,s->name) == 0)
00381     {
00382       last = NULL;
00383       n = s->firstName;
00384       while(n != NULL)
00385       {
00386         if(strcmp(name,n->name) == 0)
00387         {
00388           if(n->name  != NULL) delete [] n->name;
00389           if(n->param != NULL) delete [] n->param;
00390           if(last != NULL) last->nextName = n->nextName;
00391           delete n;
00392           return;
00393         }
00394         last = n;
00395         n = n->nextName;
00396       }
00397       return;
00398     }
00399     s = s->nextSection;
00400   }
00401 }
00402 
00403 const char *rlIniFile::firstSection()
00404 {
00405   currentSection = 0;
00406   return _firstSection->name;
00407 }
00408 
00409 const char *rlIniFile::nextSection()
00410 {  
00411   rlSection *s;
00412   int i;
00413     
00414   if(currentSection < 0) return NULL;
00415   currentSection++;
00416   i = 0;
00417   s = _firstSection;
00418   while(s != NULL)
00419   {
00420     if(i == currentSection) return s->name;
00421     s = s->nextSection;
00422     i++;
00423   }
00424   currentSection = -1;
00425   return NULL;
00426 }
00427 
00428 const char *rlIniFile::firstName(const char *section)
00429 {
00430   rlSection *s;
00431   rlSectionName *n;
00432 
00433   s = _firstSection;
00434   while(s != NULL)
00435   {
00436     if(strcmp(section,s->name) == 0)
00437     {
00438       n = s->firstName;
00439       currentName = 0;
00440       return n->name;
00441     }
00442     s = s->nextSection;
00443   }
00444   return NULL;
00445 }
00446 
00447 const char *rlIniFile::nextName(const char *section)
00448 {
00449   rlSection *s;
00450   rlSectionName *n;
00451   int i;
00452   
00453   if(currentName < 0) return NULL;
00454   currentName++;
00455   i = 0;
00456   s = _firstSection;
00457   while(s != NULL)
00458   {
00459     if(strcmp(section,s->name) == 0)
00460     {
00461       n = s->firstName;
00462       while(n != NULL)
00463       {
00464         if(i == currentName) return n->name;
00465   i++;
00466         n = n->nextName;
00467       }
00468       return NULL;
00469     }
00470     s = s->nextSection;
00471   }
00472   return NULL;
00473 }
00474 
00475 void rlIniFile::setDefaultSection(const char *section)
00476 {
00477   default_section.setText(section);
00478 }
00479 
00480 const char *rlIniFile::defaultSection()
00481 {
00482   return default_section.text();
00483 }
00484 
00485 const char *rlIniFile::i18n(const char *tag, const char *default_text)
00486 {
00487   const char *cptr = text(default_section.text(), tag);
00488   if(strcmp(cptr,null_string) == 0) return default_text;
00489   else                              return cptr;
00490 }
00491 
00492 const char *rlIniFile::tr(const char *txt)
00493 {
00494   if(txt == NULL) return "ERROR:txt=NULL";
00495   char default_text[1024];
00496   if(strlen(txt) < (sizeof(default_text) - 40)) sprintf(default_text,"tr_error:%s", txt);
00497   else                                          strcpy(default_text,"tr_error:text too long");
00498   return i18n(txt,default_text);
00499 }