1/* 2 * Copyright (c) 2001-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Nathan Binkert 29 * Steve Reinhardt 30 */ 31 |
32#include <fstream> 33#include <iostream> |
34#include <vector> 35#include <string> 36 37#include "base/inifile.hh" 38#include "base/str.hh" 39 40using namespace std; 41 42IniFile::IniFile() 43{} 44 45IniFile::~IniFile() 46{ 47 SectionTable::iterator i = table.begin(); 48 SectionTable::iterator end = table.end(); 49 50 while (i != end) { 51 delete (*i).second; 52 ++i; 53 } 54} 55 |
56bool |
57IniFile::load(const string &file) 58{ 59 ifstream f(file.c_str()); 60 61 if (!f.is_open()) 62 return false; 63 64 return load(f); 65} 66 67 68const string & 69IniFile::Entry::getValue() const 70{ 71 referenced = true; 72 return value; 73} 74 75 76void 77IniFile::Section::addEntry(const std::string &entryName, 78 const std::string &value, 79 bool append) 80{ 81 EntryTable::iterator ei = table.find(entryName); 82 83 if (ei == table.end()) { 84 // new entry 85 table[entryName] = new Entry(value); 86 } 87 else if (append) { 88 // append new reult to old entry 89 ei->second->appendValue(value); 90 } 91 else { 92 // override old entry 93 ei->second->setValue(value); 94 } 95} 96 97 98bool 99IniFile::Section::add(const std::string &assignment) 100{ 101 string::size_type offset = assignment.find('='); 102 if (offset == string::npos) { 103 // no '=' found 104 cerr << "Can't parse .ini line " << assignment << endl; 105 return false; 106 } 107 108 // if "+=" rather than just "=" then append value 109 bool append = (assignment[offset-1] == '+'); 110 111 string entryName = assignment.substr(0, append ? offset-1 : offset); 112 string value = assignment.substr(offset + 1); 113 114 eat_white(entryName); 115 eat_white(value); 116 117 addEntry(entryName, value, append); 118 return true; 119} 120 121 122IniFile::Entry * 123IniFile::Section::findEntry(const std::string &entryName) const 124{ 125 referenced = true; 126 127 EntryTable::const_iterator ei = table.find(entryName); 128 129 return (ei == table.end()) ? NULL : ei->second; 130} 131 132 133IniFile::Section * 134IniFile::addSection(const string §ionName) 135{ 136 SectionTable::iterator i = table.find(sectionName); 137 138 if (i != table.end()) { 139 return i->second; 140 } 141 else { 142 // new entry 143 Section *sec = new Section(); 144 table[sectionName] = sec; 145 return sec; 146 } 147} 148 149 150IniFile::Section * 151IniFile::findSection(const string §ionName) const 152{ 153 SectionTable::const_iterator i = table.find(sectionName); 154 155 return (i == table.end()) ? NULL : i->second; 156} 157 158 159// Take string of the form "<section>:<parameter>=<value>" and add to 160// database. Return true if successful, false if parse error. 161bool 162IniFile::add(const string &str) 163{ 164 // find ':' 165 string::size_type offset = str.find(':'); 166 if (offset == string::npos) // no ':' found 167 return false; 168 169 string sectionName = str.substr(0, offset); 170 string rest = str.substr(offset + 1); 171 172 eat_white(sectionName); 173 Section *s = addSection(sectionName); 174 175 return s->add(rest); 176} 177 178bool 179IniFile::load(istream &f) 180{ 181 Section *section = NULL; 182 183 while (!f.eof()) { 184 f >> ws; // Eat whitespace 185 if (f.eof()) { 186 break; 187 } 188 189 string line; 190 getline(f, line); 191 if (line.size() == 0) 192 continue; 193 194 eat_end_white(line); 195 int last = line.size() - 1; 196 197 if (line[0] == '[' && line[last] == ']') { 198 string sectionName = line.substr(1, last - 1); 199 eat_white(sectionName); 200 section = addSection(sectionName); 201 continue; 202 } 203 204 if (section == NULL) 205 continue; 206 207 if (!section->add(line)) 208 return false; 209 } 210 211 return true; 212} 213 214bool 215IniFile::find(const string §ionName, const string &entryName, 216 string &value) const 217{ 218 Section *section = findSection(sectionName); 219 if (section == NULL) 220 return false; 221 222 Entry *entry = section->findEntry(entryName); 223 if (entry == NULL) 224 return false; 225 226 value = entry->getValue(); 227 228 return true; 229} 230 231bool 232IniFile::sectionExists(const string §ionName) const 233{ 234 return findSection(sectionName) != NULL; 235} 236 237 238bool 239IniFile::Section::printUnreferenced(const string §ionName) 240{ 241 bool unref = false; 242 bool search_unref_entries = false; 243 vector<string> unref_ok_entries; 244 245 Entry *entry = findEntry("unref_entries_ok"); 246 if (entry != NULL) { 247 tokenize(unref_ok_entries, entry->getValue(), ' '); 248 if (unref_ok_entries.size()) { 249 search_unref_entries = true; 250 } 251 } 252 253 for (EntryTable::iterator ei = table.begin(); 254 ei != table.end(); ++ei) { 255 const string &entryName = ei->first; 256 Entry *entry = ei->second; 257 258 if (entryName == "unref_section_ok" || 259 entryName == "unref_entries_ok") 260 { 261 continue; 262 } 263 264 if (!entry->isReferenced()) { 265 if (search_unref_entries && 266 (std::find(unref_ok_entries.begin(), unref_ok_entries.end(), 267 entryName) != unref_ok_entries.end())) 268 { 269 continue; 270 } 271 272 cerr << "Parameter " << sectionName << ":" << entryName 273 << " not referenced." << endl; 274 unref = true; 275 } 276 } 277 278 return unref; 279} 280 281 282bool 283IniFile::printUnreferenced() 284{ 285 bool unref = false; 286 287 for (SectionTable::iterator i = table.begin(); 288 i != table.end(); ++i) { 289 const string §ionName = i->first; 290 Section *section = i->second; 291 292 if (!section->isReferenced()) { 293 if (section->findEntry("unref_section_ok") == NULL) { 294 cerr << "Section " << sectionName << " not referenced." 295 << endl; 296 unref = true; 297 } 298 } 299 else { 300 if (section->printUnreferenced(sectionName)) { 301 unref = true; 302 } 303 } 304 } 305 306 return unref; 307} 308 309 310void 311IniFile::Section::dump(const string §ionName) 312{ 313 for (EntryTable::iterator ei = table.begin(); 314 ei != table.end(); ++ei) { 315 cout << sectionName << ": " << (*ei).first << " => " 316 << (*ei).second->getValue() << "\n"; 317 } 318} 319 320void 321IniFile::dump() 322{ 323 for (SectionTable::iterator i = table.begin(); 324 i != table.end(); ++i) { 325 i->second->dump(i->first); 326 } 327} |