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 <algorithm> 33#include <fstream> 34#include <iostream> 35#include <string> 36#include <vector> 37 38#include "base/inifile.hh" 39#include "base/str.hh" 40 41using namespace std; 42 43IniFile::IniFile() 44{} 45 46IniFile::~IniFile() 47{ 48 SectionTable::iterator i = table.begin(); 49 SectionTable::iterator end = table.end(); 50 51 while (i != end) { 52 delete (*i).second; 53 ++i; 54 } 55} 56 57bool 58IniFile::load(const string &file) 59{ 60 ifstream f(file.c_str()); 61 62 if (!f.is_open()) 63 return false; 64 65 return load(f); 66} 67 68 69const string & 70IniFile::Entry::getValue() const 71{ 72 referenced = true; 73 return value; 74} 75 76 77void 78IniFile::Section::addEntry(const std::string &entryName, 79 const std::string &value, 80 bool append) 81{ 82 EntryTable::iterator ei = table.find(entryName); 83 84 if (ei == table.end()) { 85 // new entry 86 table[entryName] = new Entry(value); 87 } 88 else if (append) { 89 // append new reult to old entry 90 ei->second->appendValue(value); 91 } 92 else { 93 // override old entry 94 ei->second->setValue(value); 95 } 96} 97 98 99bool 100IniFile::Section::add(const std::string &assignment) 101{ 102 string::size_type offset = assignment.find('='); 103 if (offset == string::npos) { 104 // no '=' found 105 cerr << "Can't parse .ini line " << assignment << endl; 106 return false; 107 } 108 109 // if "+=" rather than just "=" then append value 110 bool append = (assignment[offset-1] == '+'); 111 112 string entryName = assignment.substr(0, append ? offset-1 : offset); 113 string value = assignment.substr(offset + 1); 114 115 eat_white(entryName); 116 eat_white(value); 117 118 addEntry(entryName, value, append); 119 return true; 120} 121 122 123IniFile::Entry * 124IniFile::Section::findEntry(const std::string &entryName) const 125{ 126 referenced = true; 127 128 EntryTable::const_iterator ei = table.find(entryName); 129 130 return (ei == table.end()) ? NULL : ei->second; 131} 132 133 134IniFile::Section * 135IniFile::addSection(const string §ionName) 136{ 137 SectionTable::iterator i = table.find(sectionName); 138 139 if (i != table.end()) { 140 return i->second; 141 } 142 else { 143 // new entry 144 Section *sec = new Section(); 145 table[sectionName] = sec; 146 return sec; 147 } 148} 149 150 151IniFile::Section * 152IniFile::findSection(const string §ionName) const 153{ 154 SectionTable::const_iterator i = table.find(sectionName); 155 156 return (i == table.end()) ? NULL : i->second; 157} 158 159 160// Take string of the form "<section>:<parameter>=<value>" and add to 161// database. Return true if successful, false if parse error. 162bool 163IniFile::add(const string &str) 164{ 165 // find ':' 166 string::size_type offset = str.find(':'); 167 if (offset == string::npos) // no ':' found 168 return false; 169 170 string sectionName = str.substr(0, offset); 171 string rest = str.substr(offset + 1); 172 173 eat_white(sectionName); 174 Section *s = addSection(sectionName); 175 176 return s->add(rest); 177} 178 179bool 180IniFile::load(istream &f) 181{ 182 Section *section = NULL; 183 184 while (!f.eof()) { 185 f >> ws; // Eat whitespace 186 if (f.eof()) { 187 break; 188 } 189 190 string line; 191 getline(f, line); 192 if (line.size() == 0) 193 continue; 194 195 eat_end_white(line); 196 int last = line.size() - 1; 197 198 if (line[0] == '[' && line[last] == ']') { 199 string sectionName = line.substr(1, last - 1); 200 eat_white(sectionName); 201 section = addSection(sectionName); 202 continue; 203 } 204 205 if (section == NULL) 206 continue; 207 208 if (!section->add(line)) 209 return false; 210 } 211 212 return true; 213} 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;
| 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 <algorithm> 33#include <fstream> 34#include <iostream> 35#include <string> 36#include <vector> 37 38#include "base/inifile.hh" 39#include "base/str.hh" 40 41using namespace std; 42 43IniFile::IniFile() 44{} 45 46IniFile::~IniFile() 47{ 48 SectionTable::iterator i = table.begin(); 49 SectionTable::iterator end = table.end(); 50 51 while (i != end) { 52 delete (*i).second; 53 ++i; 54 } 55} 56 57bool 58IniFile::load(const string &file) 59{ 60 ifstream f(file.c_str()); 61 62 if (!f.is_open()) 63 return false; 64 65 return load(f); 66} 67 68 69const string & 70IniFile::Entry::getValue() const 71{ 72 referenced = true; 73 return value; 74} 75 76 77void 78IniFile::Section::addEntry(const std::string &entryName, 79 const std::string &value, 80 bool append) 81{ 82 EntryTable::iterator ei = table.find(entryName); 83 84 if (ei == table.end()) { 85 // new entry 86 table[entryName] = new Entry(value); 87 } 88 else if (append) { 89 // append new reult to old entry 90 ei->second->appendValue(value); 91 } 92 else { 93 // override old entry 94 ei->second->setValue(value); 95 } 96} 97 98 99bool 100IniFile::Section::add(const std::string &assignment) 101{ 102 string::size_type offset = assignment.find('='); 103 if (offset == string::npos) { 104 // no '=' found 105 cerr << "Can't parse .ini line " << assignment << endl; 106 return false; 107 } 108 109 // if "+=" rather than just "=" then append value 110 bool append = (assignment[offset-1] == '+'); 111 112 string entryName = assignment.substr(0, append ? offset-1 : offset); 113 string value = assignment.substr(offset + 1); 114 115 eat_white(entryName); 116 eat_white(value); 117 118 addEntry(entryName, value, append); 119 return true; 120} 121 122 123IniFile::Entry * 124IniFile::Section::findEntry(const std::string &entryName) const 125{ 126 referenced = true; 127 128 EntryTable::const_iterator ei = table.find(entryName); 129 130 return (ei == table.end()) ? NULL : ei->second; 131} 132 133 134IniFile::Section * 135IniFile::addSection(const string §ionName) 136{ 137 SectionTable::iterator i = table.find(sectionName); 138 139 if (i != table.end()) { 140 return i->second; 141 } 142 else { 143 // new entry 144 Section *sec = new Section(); 145 table[sectionName] = sec; 146 return sec; 147 } 148} 149 150 151IniFile::Section * 152IniFile::findSection(const string §ionName) const 153{ 154 SectionTable::const_iterator i = table.find(sectionName); 155 156 return (i == table.end()) ? NULL : i->second; 157} 158 159 160// Take string of the form "<section>:<parameter>=<value>" and add to 161// database. Return true if successful, false if parse error. 162bool 163IniFile::add(const string &str) 164{ 165 // find ':' 166 string::size_type offset = str.find(':'); 167 if (offset == string::npos) // no ':' found 168 return false; 169 170 string sectionName = str.substr(0, offset); 171 string rest = str.substr(offset + 1); 172 173 eat_white(sectionName); 174 Section *s = addSection(sectionName); 175 176 return s->add(rest); 177} 178 179bool 180IniFile::load(istream &f) 181{ 182 Section *section = NULL; 183 184 while (!f.eof()) { 185 f >> ws; // Eat whitespace 186 if (f.eof()) { 187 break; 188 } 189 190 string line; 191 getline(f, line); 192 if (line.size() == 0) 193 continue; 194 195 eat_end_white(line); 196 int last = line.size() - 1; 197 198 if (line[0] == '[' && line[last] == ']') { 199 string sectionName = line.substr(1, last - 1); 200 eat_white(sectionName); 201 section = addSection(sectionName); 202 continue; 203 } 204 205 if (section == NULL) 206 continue; 207 208 if (!section->add(line)) 209 return false; 210 } 211 212 return true; 213} 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;
|