src/configfile.cpp

Go to the documentation of this file.
00001 /* vim: set noexpandtab shiftwidth=8 cino=:
00002  ***************************************************************************
00003  *            configfile.cc
00004  *
00005  *  Sun Oct  2 18:34:08 2005
00006  *  Copyright  2005  Joe Venzon
00007  *  joe@venzon.net
00008  ****************************************************************************/
00009 
00010 /*
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License
00022  *  along with this program; if not, write to the Free Software
00023  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00024  */
00025  
00026 #include "configfile.h"
00027 #include <stdexcept>
00028 
00029 CONFIGFILE::CONFIGFILE()
00030 {
00031         vars = NULL;
00032         filename = "";
00033         SUPPRESS_ERROR = false;
00034 }
00035 
00036 CONFIGFILE::CONFIGFILE(string fname)
00037 {
00038         vars = NULL;
00039         
00040         SUPPRESS_ERROR = false;
00041         
00042         Load(fname);
00043 }
00044 
00045 CONFIGFILE::~CONFIGFILE()
00046 {
00047         Clear();
00048 }
00049 
00050 bool CONFIGFILE::GetParam(string param, int & outvar)
00051 {
00052         CONFIGVARIABLE * cur = vars;
00053         bool found = false;
00054         while (cur != NULL)
00055         {
00056                 //if the var section/name matches the param name, set outvar
00057                 
00058                 string pname = param;
00059                 string psec = "";
00060                 string::size_type ppos;
00061                 ppos = param.find(".", 0);
00062                 if (ppos < /*(int)*/ param.length())
00063                 {
00064                         psec = param.substr(0, ppos);
00065                         ppos++;
00066                         pname = param.substr(ppos, param.length() - ppos);
00067                 }
00068                 
00069                 if (pname == cur->name && psec == cur->section)
00070                 {
00071                         found = true;
00072                         outvar = cur->val_i;
00073                 }
00074                 
00075                 cur = cur->next;
00076         }
00077         
00078         if (!found && !SUPPRESS_ERROR)
00079         {
00080                 cout << "CONFIGFILE::GetParam():  " << param << " not found in " << filename << endl;
00081         }
00082         
00083         return found;
00084 }
00085 
00086 bool CONFIGFILE::GetParam(string param, bool & outvar)
00087 {
00088         CONFIGVARIABLE * cur = vars;
00089         bool found = false;
00090         while (cur != NULL)
00091         {
00092                 //if the var section/name matches the param name, set outvar
00093                 
00094                 string pname = param;
00095                 string psec = "";
00096                 string::size_type ppos;
00097                 ppos = param.find(".", 0);
00098                 if (ppos < /*(int)*/ param.length())
00099                 {
00100                         psec = param.substr(0, ppos);
00101                         ppos++;
00102                         pname = param.substr(ppos, param.length() - ppos);
00103                 }
00104                 
00105                 if (pname == cur->name && psec == cur->section)
00106                 {
00107                         found = true;
00108                         outvar = cur->val_b;
00109                 }
00110                 
00111                 cur = cur->next;
00112         }
00113         
00114         if (!found && !SUPPRESS_ERROR)
00115         {
00116                 cout << "CONFIGFILE::GetParam():  " << param << " not found in " << filename << endl;
00117         }
00118         
00119         return found;
00120 }
00121 
00122 bool CONFIGFILE::GetParam(string param, float & outvar)
00123 {
00124         CONFIGVARIABLE * cur = vars;
00125         bool found = false;
00126         while (cur != NULL)
00127         {
00128                 //if the var section/name matches the param name, set outvar
00129                 
00130                 string pname = param;
00131                 string psec = "";
00132                 string::size_type ppos;
00133                 ppos = param.find(".", 0);
00134                 if (ppos < /*(int)*/ param.length())
00135                 {
00136                         psec = param.substr(0, ppos);
00137                         ppos++;
00138                         pname = param.substr(ppos, param.length() - ppos);
00139                 }
00140                 
00141                 if (pname == cur->name && psec == cur->section)
00142                 {
00143                         found = true;
00144                         outvar = cur->val_f;
00145                 }
00146                 
00147                 cur = cur->next;
00148         }
00149         
00150         if (!found && !SUPPRESS_ERROR)
00151         {
00152                 cout << "CONFIGFILE::GetParam():  " << param << " not found in " << filename << endl;
00153         }
00154         
00155         return found;
00156 }
00157 
00158 bool CONFIGFILE::GetParam(string param, float * outvar)
00159 {
00160         CONFIGVARIABLE * cur = vars;
00161         bool found = false;
00162         while (cur != NULL)
00163         {
00164                 //if the var section/name matches the param name, set outvar
00165                 
00166                 string pname = param;
00167                 string psec = "";
00168                 string::size_type ppos;
00169                 ppos = param.find(".", 0);
00170                 if (ppos < /*(int)*/ param.length())
00171                 {
00172                         psec = param.substr(0, ppos);
00173                         ppos++;
00174                         pname = param.substr(ppos, param.length() - ppos);
00175                 }
00176                 
00177                 if (pname == cur->name && psec == cur->section)
00178                 {
00179                         found = true;
00180                         
00181                         int i;
00182                         for (i = 0; i < 3; i++)
00183                                 outvar[i] = cur->val_v[i];
00184                 }
00185                 
00186                 cur = cur->next;
00187         }
00188         
00189         if (!found && !SUPPRESS_ERROR)
00190         {
00191                 cout << "CONFIGFILE::GetParam():  " << param << " not found in " << filename << endl;
00192         }
00193         
00194         return found;
00195 }
00196 
00197 bool CONFIGFILE::GetParam(string param, string & outvar)
00198 {
00199         CONFIGVARIABLE * cur = vars;
00200         bool found = false;
00201         while (cur != NULL)
00202         {
00203                 //if the var section/name matches the param name, set outvar
00204                 
00205                 string pname = param;
00206                 string psec = "";
00207                 string::size_type ppos;
00208                 ppos = param.find(".", 0);
00209                 if (ppos < /*(int)*/ param.length())
00210                 {
00211                         psec = param.substr(0, ppos);
00212                         ppos++;
00213                         pname = param.substr(ppos, param.length() - ppos);
00214                 }
00215                 
00216                 if (pname == cur->name && psec == cur->section)
00217                 {
00218                         found = true;
00219                         outvar = cur->val_s;
00220                 }
00221                 
00222                 cur = cur->next;
00223         }
00224         
00225         if (!found && !SUPPRESS_ERROR)
00226         {
00227                 cout << "CONFIGFILE::GetParam():  " << param << " not found in " << filename << endl;
00228         }
00229         
00230         return found;
00231 }
00232 
00233 void CONFIGFILE::Clear()
00234 {
00235         int count = 0;
00236         
00237         //cout << "Clear " << filename << endl;
00238         
00239         CONFIGVARIABLE * cur = vars;
00240         while (cur != NULL)
00241         {
00242                 count++;
00243                 //cout << count << ": " << cur << ", " << cur->GetFullName() << endl;
00244                 CONFIGVARIABLE * todel = cur;
00245                 
00246                 if (cur != 0)
00247                         cur = cur->next;
00248 
00249                 delete todel;
00250         }
00251         
00252         vars = NULL;
00253 }
00254 
00255 void CONFIGFILE::Add(CONFIGVARIABLE * newvar)
00256 {
00257         newvar->next = NULL;
00258         //check for dups
00259         CONFIGVARIABLE * cur = vars;
00260         bool isdup = false;
00261         while (cur != NULL)
00262         {
00263                 if (cur->section == newvar->section && cur->name == newvar->name)
00264                 {
00265                         isdup = true;
00266                         cur->Set(newvar->val_s);
00267                 }
00268                 
00269                 cur = cur->next;
00270         }
00271         
00272         //go ahead and insert
00273         if (!isdup)
00274         {
00275                 /*CONFIGVARIABLE * oldfirst = vars;
00276                 
00277                 vars = newvar;
00278                 vars->next = oldfirst;*/
00279 
00280                 cur = vars;
00281                 CONFIGVARIABLE * last = vars;
00282                 while (cur != NULL)
00283                 {
00284                         last = cur;
00285                         cur = cur->next;
00286                 }
00287                 if (vars == NULL)
00288                 {
00289                         vars = newvar;
00290                         vars->next = NULL;
00291                 }
00292                 else
00293                 {
00294                         last->next = newvar;
00295                         last->next->next = cur;
00296                 }
00297                 //newvar->next = cur;
00298         }
00299         else
00300                 delete newvar;
00301 }
00302 
00303 CONFIGVARIABLE::CONFIGVARIABLE()
00304 {
00305         val_s = "";
00306         val_i = 0;
00307         val_f = 0;
00308         val_b = false;
00309         int i;
00310         for (i = 0; i < 3; i++)
00311                 val_v[i] = 0;
00312         
00313         next = NULL;
00314 }
00315 
00316 string CONFIGVARIABLE::GetFullName()
00317 {
00318         string outstr = "";
00319         
00320         if (section != "")
00321                 outstr = outstr + section + ".";
00322         outstr = outstr + name;
00323         
00324         return outstr;
00325 }
00326 
00327 void CONFIGVARIABLE::Set(string newval)
00328 {
00329         newval = strTrim(newval);
00330         
00331         val_i = atoi(newval.c_str());
00332         val_f = atof(newval.c_str());
00333         val_s = newval;
00334         
00335         val_b = false;
00336         if (val_i == 0)
00337                 val_b = false;
00338         if (val_i == 1)
00339                 val_b = true;
00340         if (strLCase(newval) == "true")
00341                 val_b = true;
00342         if (strLCase(newval) == "false")
00343                 val_b = false;
00344         if (strLCase(newval) == "on")
00345                 val_b = true;
00346         if (strLCase(newval) == "off")
00347                 val_b = false;
00348         
00349         //now process as vector information
00350         int pos = 0;
00351         int arraypos = 0;
00352         string::size_type nextpos = newval.find(",", pos);
00353         string frag;
00354         
00355         while (nextpos < /*(int)*/ newval.length() && arraypos < 3)
00356         {
00357                 frag = newval.substr(pos, nextpos - pos);
00358                 val_v[arraypos] = atof(frag.c_str());
00359                 
00360                 pos = nextpos+1;
00361                 arraypos++;
00362                 nextpos = newval.find(",", pos);
00363         }
00364         
00365         //don't forget the very last one
00366         if (arraypos < 3)
00367         {
00368                 frag = newval.substr(pos, newval.length() - pos);
00369                 val_v[arraypos] = atof(frag.c_str());
00370         }
00371 }
00372 
00373 void CONFIGVARIABLE::DebugPrint()
00374 {
00375         if (section != "")
00376                 cout << section << ".";
00377         cout << name << endl;
00378         cout << "string: " << val_s << endl;
00379         cout << "int: " << val_i << endl;
00380         cout << "float: " << val_f << endl;
00381         cout << "vector: (" << val_v[0] << "," << val_v[1] << "," << val_v[2] << ")" << endl;
00382         cout << "bool: " << val_b << endl;
00383         
00384         cout << endl;
00385 }
00386 
00387 string CONFIGVARIABLE::strLTrim(string instr)
00388 {
00389         return instr.erase(0, instr.find_first_not_of(" \t"));
00390 }
00391 
00392 string CONFIGVARIABLE::strRTrim(string instr)
00393 {
00394         try {
00395                 return instr.erase(instr.find_last_not_of(" \t") + 1);
00396         } catch(std::out_of_range) {
00397                 return instr;
00398         }
00399 }
00400 
00401 string CONFIGVARIABLE::strTrim(string instr)
00402 {
00403         return strLTrim(strRTrim(instr));
00404 }
00405 
00406 void CONFIGFILE::Load(string fname)
00407 {
00408         filename = fname;
00409         
00410         string cursection = "";
00411         
00412         //work string
00413         string ws;
00414         const int MAXIMUMCHAR = 1024;
00415         char trashchar[MAXIMUMCHAR];
00416         
00417         ifstream f;
00418         f.open(fname.c_str());
00419         
00420         if (!f && !SUPPRESS_ERROR)
00421         {
00422                 cout << "CONFIGFILE.Load: Couldn't find file:  " << fname << endl;
00423         }
00424                 
00425         while (f && !f.eof())
00426         {
00427                 f.getline(trashchar, MAXIMUMCHAR, '\n');
00428                 ProcessLine(cursection, trashchar);
00429         }
00430         
00431         f.close();
00432         
00433         //DebugPrint();
00434 }
00435 
00436 string CONFIGFILE::Trim(string instr)
00437 {
00438         CONFIGVARIABLE trimmer;
00439         string outstr = trimmer.strTrim(instr);
00440         return outstr;
00441 }
00442 
00443 void CONFIGFILE::ProcessLine(string & cursection, string linestr)
00444 {
00445         linestr = Trim(linestr);
00446         linestr = Strip(linestr, '\r');
00447         linestr = Strip(linestr, '\n');
00448         
00449         //remove comments
00450         string::size_type commentpos = linestr.find("#", 0);
00451         if (commentpos < /*(int)*/ linestr.length())
00452         {
00453                 linestr = linestr.substr(0, commentpos);
00454         }
00455         
00456         linestr = Trim(linestr);
00457         
00458         //only continue if not a blank line or comment-only line
00459         if (linestr.length() > 0)
00460         {
00461                 if (linestr.find("=", 0) < linestr.length())
00462                 {
00463                         //find the name part
00464                         string::size_type equalpos = linestr.find("=", 0);
00465                         string name = linestr.substr(0, equalpos);
00466                         equalpos++;
00467                         string val = linestr.substr(equalpos, linestr.length() - equalpos);
00468                         name = Trim(name);
00469                         val = Trim(val);
00470                         
00471                         //only continue if valid
00472                         if (name.length() > 0 && val.length() > 0)
00473                         {
00474                                 CONFIGVARIABLE * newvar;
00475                                 newvar = new CONFIGVARIABLE;
00476                                 newvar->section = cursection;
00477                                 newvar->name = name;
00478                                 newvar->Set(val);
00479                                 newvar->next = NULL;
00480                                 
00481                                 Add(newvar);
00482                         }
00483                 }
00484                 else
00485                 {
00486                         //section header
00487                         linestr = Strip(linestr, '[');
00488                         linestr = Strip(linestr, ']');
00489                         linestr = Trim(linestr);
00490                         cursection = linestr;
00491                 }
00492         }
00493 }
00494 
00495 string CONFIGFILE::Strip(string instr, char stripchar)
00496 {
00497         string::size_type pos = 0;
00498         string outstr = "";
00499         
00500         while (pos < /*(int)*/ instr.length())
00501         {
00502                 if (instr.c_str()[pos] != stripchar)
00503                         outstr = outstr + instr.substr(pos, 1);
00504                 
00505                 pos++;
00506         }
00507         
00508         return outstr;
00509 }
00510 
00511 void CONFIGFILE::DebugPrint()
00512 {
00513         CONFIGVARIABLE * cur = vars;
00514         cout << "*** " << filename << " ***" << endl << endl;
00515         while (cur != NULL)
00516         {
00517                 cur->DebugPrint();
00518                 
00519                 cur = cur->next;
00520         }
00521 }
00522 
00523 string CONFIGVARIABLE::strLCase(string instr)
00524 {
00525         char tc[2];
00526         tc[1] = '\0';
00527         string outstr = "";
00528         
00529         string::size_type pos = 0;
00530         while (pos < /*(int)*/ instr.length())
00531         {
00532                 if (instr.c_str()[pos] <= 90 && instr.c_str()[pos] >= 65)
00533                 {
00534                         tc[0] = instr.c_str()[pos] + 32;
00535                         string tstr = tc;
00536                         outstr = outstr + tc;
00537                 }
00538                 else
00539                         outstr = outstr + instr.substr(pos, 1);
00540                 
00541                 pos++;
00542         }
00543         
00544         return outstr;
00545 }
00546 
00547 string CONFIGFILE::LCase(string instr)
00548 {
00549         CONFIGVARIABLE lcaser;
00550         string outstr = lcaser.strLCase(instr);
00551         return outstr;
00552 }
00553 
00554 bool CONFIGFILE::SetParam(string param, int invar)
00555 {
00556         char tc[256];
00557         
00558         sprintf(tc, "%i", invar);
00559         
00560         string tstr = tc;
00561         
00562         return SetParam(param, tstr);
00563 }
00564 
00565 bool CONFIGFILE::SetParam(string param, bool invar)
00566 {
00567         //char tc[256];
00568         
00569         //sprintf(tc, "%i", invar);
00570         
00571         string tstr = "off";
00572         
00573         if (invar)
00574                 tstr = "on";
00575         
00576         return SetParam(param, tstr);
00577 }
00578 
00579 bool CONFIGFILE::SetParam(string param, float invar)
00580 {
00581         char tc[256];
00582         
00583         sprintf(tc, "%f", invar);
00584         
00585         string tstr = tc;
00586         
00587         return SetParam(param, tstr);
00588 }
00589 
00590 bool CONFIGFILE::SetParam(string param, float * invar)
00591 {
00592         char tc[256];
00593         
00594         sprintf(tc, "%f,%f,%f", invar[0], invar[1], invar[2]);
00595         
00596         string tstr = tc;
00597         
00598         return SetParam(param, tstr);
00599 }
00600 
00601 bool CONFIGFILE::SetParam(string param, string invar)
00602 {
00603         CONFIGVARIABLE * newvar;
00604         newvar = new CONFIGVARIABLE;
00605         
00606         newvar->name = param;
00607         newvar->section = "";
00608         string::size_type ppos;
00609         ppos = param.find(".", 0);
00610         if (ppos < /*(int)*/ param.length())
00611         {
00612                 newvar->section = param.substr(0, ppos);
00613                 ppos++;
00614                 newvar->name = param.substr(ppos, param.length() - ppos);
00615         }
00616         
00617         newvar->Set(invar);
00618         newvar->next = NULL;
00619         
00620         Add(newvar);
00621         
00622         return true;
00623 }
00624 
00625 bool CONFIGFILE::Write(bool with_brackets)
00626 {
00627         return Write(with_brackets, filename);
00628 }
00629 
00630 bool CONFIGFILE::Write(bool with_brackets, string save_as)
00631 {
00632         ofstream f;
00633         f.open(save_as.c_str());
00634         
00635         if (f)
00636         {
00637                 //clear out written flags
00638                 CONFIGVARIABLE * cur = vars;
00639                 while (cur != NULL)
00640                 {
00641                         cur->written = false;
00642                         cur = cur->next;
00643                 }
00644                 
00645                 //write non-section variables first
00646                 bool nosection = false;
00647                 cur = vars;
00648                 while (cur != NULL)
00649                 {
00650                         if (cur->section == "")
00651                         {
00652                                 f << cur->name << " = " << cur->val_s << endl;
00653                                 
00654                                 nosection = true;
00655                                 
00656                                 cur->written = true;
00657                         }
00658                         
00659                         cur = cur->next;
00660                 }
00661                 
00662                 if (nosection)
00663                         f << endl;
00664                 
00665                 //write variables by section
00666                 cur = vars;
00667                 while (cur != NULL)
00668                 {
00669                         if (!cur->written)
00670                         {
00671                                 if (with_brackets)
00672                                         f << "[ " << cur->section << " ]" << endl;
00673                                 else
00674                                         f << cur->section << endl;
00675                                 
00676                                 CONFIGVARIABLE * sub = vars;
00677                                 while (sub != NULL)
00678                                 {
00679                                         if (!sub->written && cur->section == sub->section)
00680                                         {
00681                                                 f << sub->name << " = " << sub->val_s << endl;
00682                                                 
00683                                                 sub->written = true;
00684                                         }
00685                                         
00686                                         sub = sub->next;
00687                                 }
00688                                 
00689                                 f << endl;
00690                                 
00691                                 cur->written = true;
00692                         }
00693                         
00694                         cur = cur->next;
00695                 }
00696                 
00697                 f.close();
00698                 return true;
00699         }
00700         else
00701                 return false;
00702 }
00703 
00704 bool CONFIGFILE::Write()
00705 {
00706         Write(true);
00707         return true;
00708 }
00709 
00710 bool CONFIGFILE::ClearParam(string param)
00711 {
00712         /*CONFIGVARIABLE * cur = vars;
00713         while (cur != NULL)
00714         {
00715                 CONFIGVARIABLE * todel = cur;
00716                 cur = cur->next;
00717                 
00718                 delete todel;
00719         }
00720         
00721         vars = NULL;*/
00722         
00723         CONFIGVARIABLE * cur = vars;
00724         CONFIGVARIABLE * prev = vars;
00725         bool found = false;
00726         while (cur != NULL)
00727         {
00728                 //if the var section/name matches the param name, set outvar
00729                 
00730                 string pname = param;
00731                 string psec = "";
00732                 string::size_type ppos;
00733                 ppos = param.find(".", 0);
00734                 if (ppos < /*(int)*/ param.length())
00735                 {
00736                         psec = param.substr(0, ppos);
00737                         ppos++;
00738                         pname = param.substr(ppos, param.length() - ppos);
00739                 }
00740                 
00741                 if (pname == cur->name && psec == cur->section)
00742                 {
00743                         found = true;
00744 
00745                         CONFIGVARIABLE * todel = cur;
00746                         if (cur == vars)
00747                         {
00748                                 vars = vars->next;
00749                                 prev = vars;
00750                                 cur = vars;
00751                         }
00752                         else
00753                         {
00754                                 cur = cur->next;
00755                                 prev->next = cur;
00756                         }
00757                         
00758                         delete todel;
00759                 }
00760                 else
00761                 {               
00762                         prev = cur;
00763                         cur = cur->next;
00764                 }
00765         }
00766 
00767         /*      
00768         if (!found && !SUPPRESS_ERROR)
00769         {
00770                 cout << "CONFIGFILE::GetParam():  " << param << " not found in " << filename << endl;
00771         }*/
00772         
00773         return found;
00774 }

Generated on Thu Oct 19 04:05:48 2006 by  doxygen 1.4.6