inifile.cc revision 10385
113221Sodanrc@yahoo.com.br/* 213221Sodanrc@yahoo.com.br * Copyright (c) 2001-2005 The Regents of The University of Michigan 313221Sodanrc@yahoo.com.br * All rights reserved. 413221Sodanrc@yahoo.com.br * 513221Sodanrc@yahoo.com.br * Redistribution and use in source and binary forms, with or without 613221Sodanrc@yahoo.com.br * modification, are permitted provided that the following conditions are 713221Sodanrc@yahoo.com.br * met: redistributions of source code must retain the above copyright 813221Sodanrc@yahoo.com.br * notice, this list of conditions and the following disclaimer; 913221Sodanrc@yahoo.com.br * redistributions in binary form must reproduce the above copyright 1013221Sodanrc@yahoo.com.br * notice, this list of conditions and the following disclaimer in the 1113221Sodanrc@yahoo.com.br * documentation and/or other materials provided with the distribution; 1213221Sodanrc@yahoo.com.br * neither the name of the copyright holders nor the names of its 1313221Sodanrc@yahoo.com.br * contributors may be used to endorse or promote products derived from 1413221Sodanrc@yahoo.com.br * this software without specific prior written permission. 1513221Sodanrc@yahoo.com.br * 1613221Sodanrc@yahoo.com.br * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1713221Sodanrc@yahoo.com.br * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1813221Sodanrc@yahoo.com.br * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1913221Sodanrc@yahoo.com.br * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2013221Sodanrc@yahoo.com.br * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2113221Sodanrc@yahoo.com.br * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2213221Sodanrc@yahoo.com.br * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2313221Sodanrc@yahoo.com.br * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2413221Sodanrc@yahoo.com.br * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2513221Sodanrc@yahoo.com.br * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2613221Sodanrc@yahoo.com.br * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2713221Sodanrc@yahoo.com.br * 2813221Sodanrc@yahoo.com.br * Authors: Nathan Binkert 2913221Sodanrc@yahoo.com.br * Steve Reinhardt 3013221Sodanrc@yahoo.com.br */ 3113221Sodanrc@yahoo.com.br 3213221Sodanrc@yahoo.com.br#include <algorithm> 3313221Sodanrc@yahoo.com.br#include <fstream> 3413221Sodanrc@yahoo.com.br#include <iostream> 3513221Sodanrc@yahoo.com.br#include <string> 3613221Sodanrc@yahoo.com.br#include <vector> 3713221Sodanrc@yahoo.com.br 3813221Sodanrc@yahoo.com.br#include "base/inifile.hh" 3913221Sodanrc@yahoo.com.br#include "base/str.hh" 4013221Sodanrc@yahoo.com.br 4113221Sodanrc@yahoo.com.brusing namespace std; 4213221Sodanrc@yahoo.com.br 4313221Sodanrc@yahoo.com.brIniFile::IniFile() 4413221Sodanrc@yahoo.com.br{} 4513221Sodanrc@yahoo.com.br 4613221Sodanrc@yahoo.com.brIniFile::~IniFile() 4713221Sodanrc@yahoo.com.br{ 4813221Sodanrc@yahoo.com.br SectionTable::iterator i = table.begin(); 4913221Sodanrc@yahoo.com.br SectionTable::iterator end = table.end(); 5013221Sodanrc@yahoo.com.br 5113221Sodanrc@yahoo.com.br while (i != end) { 5213221Sodanrc@yahoo.com.br delete (*i).second; 5313221Sodanrc@yahoo.com.br ++i; 5413221Sodanrc@yahoo.com.br } 5513221Sodanrc@yahoo.com.br} 5613221Sodanrc@yahoo.com.br 5713221Sodanrc@yahoo.com.brbool 5813221Sodanrc@yahoo.com.brIniFile::load(const string &file) 5913221Sodanrc@yahoo.com.br{ 6013221Sodanrc@yahoo.com.br ifstream f(file.c_str()); 6113221Sodanrc@yahoo.com.br 6213221Sodanrc@yahoo.com.br if (!f.is_open()) 6313221Sodanrc@yahoo.com.br return false; 6413221Sodanrc@yahoo.com.br 6513221Sodanrc@yahoo.com.br return load(f); 6613221Sodanrc@yahoo.com.br} 6713221Sodanrc@yahoo.com.br 6813221Sodanrc@yahoo.com.br 6913221Sodanrc@yahoo.com.brconst string & 7013221Sodanrc@yahoo.com.brIniFile::Entry::getValue() const 7113221Sodanrc@yahoo.com.br{ 7213221Sodanrc@yahoo.com.br referenced = true; 7313221Sodanrc@yahoo.com.br return value; 7413221Sodanrc@yahoo.com.br} 7513221Sodanrc@yahoo.com.br 7613221Sodanrc@yahoo.com.br 7713221Sodanrc@yahoo.com.brvoid 7813221Sodanrc@yahoo.com.brIniFile::Section::addEntry(const std::string &entryName, 7913221Sodanrc@yahoo.com.br const std::string &value, 8013221Sodanrc@yahoo.com.br bool append) 8113221Sodanrc@yahoo.com.br{ 8213221Sodanrc@yahoo.com.br EntryTable::iterator ei = table.find(entryName); 8313221Sodanrc@yahoo.com.br 8413221Sodanrc@yahoo.com.br if (ei == table.end()) { 8513221Sodanrc@yahoo.com.br // new entry 8613221Sodanrc@yahoo.com.br table[entryName] = new Entry(value); 8713221Sodanrc@yahoo.com.br } 8813221Sodanrc@yahoo.com.br else if (append) { 8913221Sodanrc@yahoo.com.br // append new reult to old entry 9013221Sodanrc@yahoo.com.br ei->second->appendValue(value); 9113221Sodanrc@yahoo.com.br } 9213221Sodanrc@yahoo.com.br else { 9313221Sodanrc@yahoo.com.br // override old entry 9413221Sodanrc@yahoo.com.br ei->second->setValue(value); 9513221Sodanrc@yahoo.com.br } 9613221Sodanrc@yahoo.com.br} 9713221Sodanrc@yahoo.com.br 9813221Sodanrc@yahoo.com.br 9913221Sodanrc@yahoo.com.brbool 10013221Sodanrc@yahoo.com.brIniFile::Section::add(const std::string &assignment) 10113221Sodanrc@yahoo.com.br{ 10213221Sodanrc@yahoo.com.br string::size_type offset = assignment.find('='); 10313221Sodanrc@yahoo.com.br if (offset == string::npos) { 10413221Sodanrc@yahoo.com.br // no '=' found 10513221Sodanrc@yahoo.com.br cerr << "Can't parse .ini line " << assignment << endl; 10613221Sodanrc@yahoo.com.br return false; 10713221Sodanrc@yahoo.com.br } 10813221Sodanrc@yahoo.com.br 10913221Sodanrc@yahoo.com.br // if "+=" rather than just "=" then append value 11013221Sodanrc@yahoo.com.br bool append = (assignment[offset-1] == '+'); 11113221Sodanrc@yahoo.com.br 11213221Sodanrc@yahoo.com.br string entryName = assignment.substr(0, append ? offset-1 : offset); 11313221Sodanrc@yahoo.com.br string value = assignment.substr(offset + 1); 11413221Sodanrc@yahoo.com.br 11513221Sodanrc@yahoo.com.br eat_white(entryName); 11613221Sodanrc@yahoo.com.br eat_white(value); 11713221Sodanrc@yahoo.com.br 11813221Sodanrc@yahoo.com.br addEntry(entryName, value, append); 11913221Sodanrc@yahoo.com.br return true; 12013221Sodanrc@yahoo.com.br} 12113221Sodanrc@yahoo.com.br 12213221Sodanrc@yahoo.com.br 12313221Sodanrc@yahoo.com.brIniFile::Entry * 12413221Sodanrc@yahoo.com.brIniFile::Section::findEntry(const std::string &entryName) const 12513221Sodanrc@yahoo.com.br{ 12613221Sodanrc@yahoo.com.br referenced = true; 12713221Sodanrc@yahoo.com.br 12813221Sodanrc@yahoo.com.br EntryTable::const_iterator ei = table.find(entryName); 12913221Sodanrc@yahoo.com.br 13013221Sodanrc@yahoo.com.br return (ei == table.end()) ? NULL : ei->second; 13113221Sodanrc@yahoo.com.br} 13213221Sodanrc@yahoo.com.br 13313221Sodanrc@yahoo.com.br 13413221Sodanrc@yahoo.com.brIniFile::Section * 13513221Sodanrc@yahoo.com.brIniFile::addSection(const string §ionName) 13613221Sodanrc@yahoo.com.br{ 13713221Sodanrc@yahoo.com.br SectionTable::iterator i = table.find(sectionName); 13813221Sodanrc@yahoo.com.br 13913221Sodanrc@yahoo.com.br if (i != table.end()) { 14013221Sodanrc@yahoo.com.br return i->second; 14113221Sodanrc@yahoo.com.br } 14213221Sodanrc@yahoo.com.br else { 14313221Sodanrc@yahoo.com.br // new entry 14413221Sodanrc@yahoo.com.br Section *sec = new Section(); 14513221Sodanrc@yahoo.com.br table[sectionName] = sec; 14613221Sodanrc@yahoo.com.br return sec; 14713221Sodanrc@yahoo.com.br } 14813221Sodanrc@yahoo.com.br} 14913221Sodanrc@yahoo.com.br 15013221Sodanrc@yahoo.com.br 15113221Sodanrc@yahoo.com.brIniFile::Section * 15213221Sodanrc@yahoo.com.brIniFile::findSection(const string §ionName) const 15313221Sodanrc@yahoo.com.br{ 15413221Sodanrc@yahoo.com.br SectionTable::const_iterator i = table.find(sectionName); 15513221Sodanrc@yahoo.com.br 15613221Sodanrc@yahoo.com.br return (i == table.end()) ? NULL : i->second; 15713221Sodanrc@yahoo.com.br} 15813221Sodanrc@yahoo.com.br 15913221Sodanrc@yahoo.com.br 16013221Sodanrc@yahoo.com.br// Take string of the form "<section>:<parameter>=<value>" and add to 16113221Sodanrc@yahoo.com.br// database. Return true if successful, false if parse error. 16213221Sodanrc@yahoo.com.brbool 16313221Sodanrc@yahoo.com.brIniFile::add(const string &str) 16413221Sodanrc@yahoo.com.br{ 16513221Sodanrc@yahoo.com.br // find ':' 16613221Sodanrc@yahoo.com.br string::size_type offset = str.find(':'); 16713221Sodanrc@yahoo.com.br if (offset == string::npos) // no ':' found 16813221Sodanrc@yahoo.com.br return false; 16913221Sodanrc@yahoo.com.br 17013221Sodanrc@yahoo.com.br string sectionName = str.substr(0, offset); 17113221Sodanrc@yahoo.com.br string rest = str.substr(offset + 1); 17213221Sodanrc@yahoo.com.br 17313221Sodanrc@yahoo.com.br eat_white(sectionName); 17413221Sodanrc@yahoo.com.br Section *s = addSection(sectionName); 17513221Sodanrc@yahoo.com.br 17613221Sodanrc@yahoo.com.br return s->add(rest); 17713221Sodanrc@yahoo.com.br} 17813221Sodanrc@yahoo.com.br 17913221Sodanrc@yahoo.com.brbool 18013221Sodanrc@yahoo.com.brIniFile::load(istream &f) 18113221Sodanrc@yahoo.com.br{ 18213221Sodanrc@yahoo.com.br Section *section = NULL; 18313221Sodanrc@yahoo.com.br 18413221Sodanrc@yahoo.com.br while (!f.eof()) { 18513221Sodanrc@yahoo.com.br f >> ws; // Eat whitespace 18613221Sodanrc@yahoo.com.br if (f.eof()) { 18713221Sodanrc@yahoo.com.br break; 18813221Sodanrc@yahoo.com.br } 18913221Sodanrc@yahoo.com.br 19013221Sodanrc@yahoo.com.br string line; 19113221Sodanrc@yahoo.com.br getline(f, line); 19213221Sodanrc@yahoo.com.br if (line.size() == 0) 19313221Sodanrc@yahoo.com.br continue; 19413221Sodanrc@yahoo.com.br 19513221Sodanrc@yahoo.com.br eat_end_white(line); 19613221Sodanrc@yahoo.com.br int last = line.size() - 1; 19713221Sodanrc@yahoo.com.br 19813221Sodanrc@yahoo.com.br if (line[0] == '[' && line[last] == ']') { 19913221Sodanrc@yahoo.com.br string sectionName = line.substr(1, last - 1); 20013221Sodanrc@yahoo.com.br eat_white(sectionName); 20113221Sodanrc@yahoo.com.br section = addSection(sectionName); 20213221Sodanrc@yahoo.com.br continue; 20313221Sodanrc@yahoo.com.br } 20413221Sodanrc@yahoo.com.br 20513221Sodanrc@yahoo.com.br if (section == NULL) 20613221Sodanrc@yahoo.com.br continue; 20713221Sodanrc@yahoo.com.br 20813221Sodanrc@yahoo.com.br if (!section->add(line)) 20913221Sodanrc@yahoo.com.br return false; 21013221Sodanrc@yahoo.com.br } 21113221Sodanrc@yahoo.com.br 21213221Sodanrc@yahoo.com.br return true; 21313221Sodanrc@yahoo.com.br} 214 215bool 216IniFile::find(const string §ionName, const string &entryName, 217 string &value) const 218{ 219 Section *section = findSection(sectionName); 220 if (section == NULL) 221 return false; 222 223 Entry *entry = section->findEntry(entryName); 224 if (entry == NULL) 225 return false; 226 227 value = entry->getValue(); 228 229 return true; 230} 231 232bool 233IniFile::sectionExists(const string §ionName) const 234{ 235 return findSection(sectionName) != NULL; 236} 237 238 239bool 240IniFile::Section::printUnreferenced(const string §ionName) 241{ 242 bool unref = false; 243 bool search_unref_entries = false; 244 vector<string> unref_ok_entries; 245 246 Entry *entry = findEntry("unref_entries_ok"); 247 if (entry != NULL) { 248 tokenize(unref_ok_entries, entry->getValue(), ' '); 249 if (unref_ok_entries.size()) { 250 search_unref_entries = true; 251 } 252 } 253 254 for (EntryTable::iterator ei = table.begin(); 255 ei != table.end(); ++ei) { 256 const string &entryName = ei->first; 257 entry = ei->second; 258 259 if (entryName == "unref_section_ok" || 260 entryName == "unref_entries_ok") 261 { 262 continue; 263 } 264 265 if (!entry->isReferenced()) { 266 if (search_unref_entries && 267 (std::find(unref_ok_entries.begin(), unref_ok_entries.end(), 268 entryName) != unref_ok_entries.end())) 269 { 270 continue; 271 } 272 273 cerr << "Parameter " << sectionName << ":" << entryName 274 << " not referenced." << endl; 275 unref = true; 276 } 277 } 278 279 return unref; 280} 281 282 283void 284IniFile::getSectionNames(vector<string> &list) const 285{ 286 for (SectionTable::const_iterator i = table.begin(); 287 i != table.end(); ++i) 288 { 289 list.push_back((*i).first); 290 } 291} 292 293bool 294IniFile::printUnreferenced() 295{ 296 bool unref = false; 297 298 for (SectionTable::iterator i = table.begin(); 299 i != table.end(); ++i) { 300 const string §ionName = i->first; 301 Section *section = i->second; 302 303 if (!section->isReferenced()) { 304 if (section->findEntry("unref_section_ok") == NULL) { 305 cerr << "Section " << sectionName << " not referenced." 306 << endl; 307 unref = true; 308 } 309 } 310 else { 311 if (section->printUnreferenced(sectionName)) { 312 unref = true; 313 } 314 } 315 } 316 317 return unref; 318} 319 320 321void 322IniFile::Section::dump(const string §ionName) 323{ 324 for (EntryTable::iterator ei = table.begin(); 325 ei != table.end(); ++ei) { 326 cout << sectionName << ": " << (*ei).first << " => " 327 << (*ei).second->getValue() << "\n"; 328 } 329} 330 331void 332IniFile::dump() 333{ 334 for (SectionTable::iterator i = table.begin(); 335 i != table.end(); ++i) { 336 i->second->dump(i->first); 337 } 338} 339