inifile.cc revision 10385
15952Ssaidi@eecs.umich.edu/* 25952Ssaidi@eecs.umich.edu * Copyright (c) 2001-2005 The Regents of The University of Michigan 35952Ssaidi@eecs.umich.edu * All rights reserved. 45952Ssaidi@eecs.umich.edu * 55952Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 65952Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 75952Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 85952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 95952Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 105952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 115952Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 125952Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 135952Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 145952Ssaidi@eecs.umich.edu * this software without specific prior written permission. 155952Ssaidi@eecs.umich.edu * 165952Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175952Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185952Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195952Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205952Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215952Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225952Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235952Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245952Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255952Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265952Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275952Ssaidi@eecs.umich.edu * 285952Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 295952Ssaidi@eecs.umich.edu * Steve Reinhardt 305952Ssaidi@eecs.umich.edu */ 315952Ssaidi@eecs.umich.edu 325952Ssaidi@eecs.umich.edu#include <algorithm> 335952Ssaidi@eecs.umich.edu#include <fstream> 345952Ssaidi@eecs.umich.edu#include <iostream> 355952Ssaidi@eecs.umich.edu#include <string> 365952Ssaidi@eecs.umich.edu#include <vector> 375952Ssaidi@eecs.umich.edu 385952Ssaidi@eecs.umich.edu#include "base/inifile.hh" 395952Ssaidi@eecs.umich.edu#include "base/str.hh" 405952Ssaidi@eecs.umich.edu 415952Ssaidi@eecs.umich.eduusing namespace std; 425952Ssaidi@eecs.umich.edu 435952Ssaidi@eecs.umich.eduIniFile::IniFile() 445952Ssaidi@eecs.umich.edu{} 455952Ssaidi@eecs.umich.edu 465952Ssaidi@eecs.umich.eduIniFile::~IniFile() 475952Ssaidi@eecs.umich.edu{ 485952Ssaidi@eecs.umich.edu SectionTable::iterator i = table.begin(); 495952Ssaidi@eecs.umich.edu SectionTable::iterator end = table.end(); 505952Ssaidi@eecs.umich.edu 515952Ssaidi@eecs.umich.edu while (i != end) { 525952Ssaidi@eecs.umich.edu delete (*i).second; 535952Ssaidi@eecs.umich.edu ++i; 545952Ssaidi@eecs.umich.edu } 555952Ssaidi@eecs.umich.edu} 565952Ssaidi@eecs.umich.edu 575952Ssaidi@eecs.umich.edubool 585952Ssaidi@eecs.umich.eduIniFile::load(const string &file) 595952Ssaidi@eecs.umich.edu{ 605952Ssaidi@eecs.umich.edu ifstream f(file.c_str()); 615952Ssaidi@eecs.umich.edu 625952Ssaidi@eecs.umich.edu if (!f.is_open()) 635952Ssaidi@eecs.umich.edu return false; 645952Ssaidi@eecs.umich.edu 655952Ssaidi@eecs.umich.edu return load(f); 665952Ssaidi@eecs.umich.edu} 675952Ssaidi@eecs.umich.edu 685952Ssaidi@eecs.umich.edu 695952Ssaidi@eecs.umich.educonst string & 705952Ssaidi@eecs.umich.eduIniFile::Entry::getValue() const 715952Ssaidi@eecs.umich.edu{ 725952Ssaidi@eecs.umich.edu referenced = true; 735952Ssaidi@eecs.umich.edu return value; 745952Ssaidi@eecs.umich.edu} 755952Ssaidi@eecs.umich.edu 765952Ssaidi@eecs.umich.edu 775952Ssaidi@eecs.umich.eduvoid 785952Ssaidi@eecs.umich.eduIniFile::Section::addEntry(const std::string &entryName, 795952Ssaidi@eecs.umich.edu const std::string &value, 805952Ssaidi@eecs.umich.edu bool append) 815952Ssaidi@eecs.umich.edu{ 825952Ssaidi@eecs.umich.edu EntryTable::iterator ei = table.find(entryName); 835952Ssaidi@eecs.umich.edu 845952Ssaidi@eecs.umich.edu if (ei == table.end()) { 855952Ssaidi@eecs.umich.edu // new entry 865952Ssaidi@eecs.umich.edu table[entryName] = new Entry(value); 875952Ssaidi@eecs.umich.edu } 885952Ssaidi@eecs.umich.edu else if (append) { 895952Ssaidi@eecs.umich.edu // append new reult to old entry 905952Ssaidi@eecs.umich.edu ei->second->appendValue(value); 915952Ssaidi@eecs.umich.edu } 925952Ssaidi@eecs.umich.edu else { 935952Ssaidi@eecs.umich.edu // override old entry 945952Ssaidi@eecs.umich.edu ei->second->setValue(value); 955952Ssaidi@eecs.umich.edu } 965952Ssaidi@eecs.umich.edu} 975952Ssaidi@eecs.umich.edu 985952Ssaidi@eecs.umich.edu 995952Ssaidi@eecs.umich.edubool 1005952Ssaidi@eecs.umich.eduIniFile::Section::add(const std::string &assignment) 1015952Ssaidi@eecs.umich.edu{ 1025952Ssaidi@eecs.umich.edu string::size_type offset = assignment.find('='); 1035952Ssaidi@eecs.umich.edu if (offset == string::npos) { 1045952Ssaidi@eecs.umich.edu // no '=' found 1055952Ssaidi@eecs.umich.edu cerr << "Can't parse .ini line " << assignment << endl; 1065952Ssaidi@eecs.umich.edu return false; 1075952Ssaidi@eecs.umich.edu } 1085952Ssaidi@eecs.umich.edu 1095952Ssaidi@eecs.umich.edu // if "+=" rather than just "=" then append value 1105952Ssaidi@eecs.umich.edu bool append = (assignment[offset-1] == '+'); 1115952Ssaidi@eecs.umich.edu 1125952Ssaidi@eecs.umich.edu string entryName = assignment.substr(0, append ? offset-1 : offset); 1135952Ssaidi@eecs.umich.edu string value = assignment.substr(offset + 1); 1145952Ssaidi@eecs.umich.edu 1155952Ssaidi@eecs.umich.edu eat_white(entryName); 1165952Ssaidi@eecs.umich.edu eat_white(value); 1175952Ssaidi@eecs.umich.edu 1185952Ssaidi@eecs.umich.edu addEntry(entryName, value, append); 1195952Ssaidi@eecs.umich.edu return true; 1205952Ssaidi@eecs.umich.edu} 1215952Ssaidi@eecs.umich.edu 1225952Ssaidi@eecs.umich.edu 1235952Ssaidi@eecs.umich.eduIniFile::Entry * 1245952Ssaidi@eecs.umich.eduIniFile::Section::findEntry(const std::string &entryName) const 1255952Ssaidi@eecs.umich.edu{ 1265952Ssaidi@eecs.umich.edu referenced = true; 1275952Ssaidi@eecs.umich.edu 1285952Ssaidi@eecs.umich.edu EntryTable::const_iterator ei = table.find(entryName); 1295952Ssaidi@eecs.umich.edu 1305952Ssaidi@eecs.umich.edu return (ei == table.end()) ? NULL : ei->second; 1315952Ssaidi@eecs.umich.edu} 1325952Ssaidi@eecs.umich.edu 1335952Ssaidi@eecs.umich.edu 1345952Ssaidi@eecs.umich.eduIniFile::Section * 1355952Ssaidi@eecs.umich.eduIniFile::addSection(const string §ionName) 1365952Ssaidi@eecs.umich.edu{ 1375952Ssaidi@eecs.umich.edu SectionTable::iterator i = table.find(sectionName); 1385952Ssaidi@eecs.umich.edu 1395952Ssaidi@eecs.umich.edu if (i != table.end()) { 1405952Ssaidi@eecs.umich.edu return i->second; 1415952Ssaidi@eecs.umich.edu } 1425952Ssaidi@eecs.umich.edu else { 1435952Ssaidi@eecs.umich.edu // new entry 1445952Ssaidi@eecs.umich.edu Section *sec = new Section(); 1455952Ssaidi@eecs.umich.edu table[sectionName] = sec; 1465952Ssaidi@eecs.umich.edu return sec; 1475952Ssaidi@eecs.umich.edu } 1485952Ssaidi@eecs.umich.edu} 1495952Ssaidi@eecs.umich.edu 1505952Ssaidi@eecs.umich.edu 1515952Ssaidi@eecs.umich.eduIniFile::Section * 1525952Ssaidi@eecs.umich.eduIniFile::findSection(const string §ionName) const 1535952Ssaidi@eecs.umich.edu{ 1545952Ssaidi@eecs.umich.edu SectionTable::const_iterator i = table.find(sectionName); 1555952Ssaidi@eecs.umich.edu 1565952Ssaidi@eecs.umich.edu return (i == table.end()) ? NULL : i->second; 1575952Ssaidi@eecs.umich.edu} 1585952Ssaidi@eecs.umich.edu 1595952Ssaidi@eecs.umich.edu 1605952Ssaidi@eecs.umich.edu// Take string of the form "<section>:<parameter>=<value>" and add to 1615952Ssaidi@eecs.umich.edu// database. Return true if successful, false if parse error. 1625952Ssaidi@eecs.umich.edubool 1635952Ssaidi@eecs.umich.eduIniFile::add(const string &str) 1645952Ssaidi@eecs.umich.edu{ 1655952Ssaidi@eecs.umich.edu // find ':' 1665952Ssaidi@eecs.umich.edu string::size_type offset = str.find(':'); 1675952Ssaidi@eecs.umich.edu if (offset == string::npos) // no ':' found 1685952Ssaidi@eecs.umich.edu return false; 1695952Ssaidi@eecs.umich.edu 1705952Ssaidi@eecs.umich.edu string sectionName = str.substr(0, offset); 1715952Ssaidi@eecs.umich.edu string rest = str.substr(offset + 1); 1725952Ssaidi@eecs.umich.edu 1735952Ssaidi@eecs.umich.edu eat_white(sectionName); 1745952Ssaidi@eecs.umich.edu Section *s = addSection(sectionName); 1755952Ssaidi@eecs.umich.edu 1765952Ssaidi@eecs.umich.edu return s->add(rest); 1775952Ssaidi@eecs.umich.edu} 1785952Ssaidi@eecs.umich.edu 1795952Ssaidi@eecs.umich.edubool 1805952Ssaidi@eecs.umich.eduIniFile::load(istream &f) 1815952Ssaidi@eecs.umich.edu{ 1825952Ssaidi@eecs.umich.edu Section *section = NULL; 1835952Ssaidi@eecs.umich.edu 1845952Ssaidi@eecs.umich.edu while (!f.eof()) { 1855952Ssaidi@eecs.umich.edu f >> ws; // Eat whitespace 1865952Ssaidi@eecs.umich.edu if (f.eof()) { 1875952Ssaidi@eecs.umich.edu break; 1885952Ssaidi@eecs.umich.edu } 1895952Ssaidi@eecs.umich.edu 1905952Ssaidi@eecs.umich.edu string line; 1915952Ssaidi@eecs.umich.edu getline(f, line); 1925952Ssaidi@eecs.umich.edu if (line.size() == 0) 1935952Ssaidi@eecs.umich.edu continue; 1945952Ssaidi@eecs.umich.edu 1955952Ssaidi@eecs.umich.edu eat_end_white(line); 1965952Ssaidi@eecs.umich.edu int last = line.size() - 1; 1975952Ssaidi@eecs.umich.edu 1985952Ssaidi@eecs.umich.edu if (line[0] == '[' && line[last] == ']') { 1995952Ssaidi@eecs.umich.edu string sectionName = line.substr(1, last - 1); 2005952Ssaidi@eecs.umich.edu eat_white(sectionName); 2015952Ssaidi@eecs.umich.edu section = addSection(sectionName); 2025952Ssaidi@eecs.umich.edu continue; 2035952Ssaidi@eecs.umich.edu } 2045952Ssaidi@eecs.umich.edu 2055952Ssaidi@eecs.umich.edu if (section == NULL) 2065952Ssaidi@eecs.umich.edu continue; 2075952Ssaidi@eecs.umich.edu 2085952Ssaidi@eecs.umich.edu if (!section->add(line)) 2095952Ssaidi@eecs.umich.edu return false; 2105952Ssaidi@eecs.umich.edu } 2115952Ssaidi@eecs.umich.edu 2125952Ssaidi@eecs.umich.edu return true; 2135952Ssaidi@eecs.umich.edu} 2145952Ssaidi@eecs.umich.edu 2155952Ssaidi@eecs.umich.edubool 2165952Ssaidi@eecs.umich.eduIniFile::find(const string §ionName, const string &entryName, 2175952Ssaidi@eecs.umich.edu string &value) const 2185952Ssaidi@eecs.umich.edu{ 2195952Ssaidi@eecs.umich.edu Section *section = findSection(sectionName); 2205952Ssaidi@eecs.umich.edu if (section == NULL) 2215952Ssaidi@eecs.umich.edu return false; 2225952Ssaidi@eecs.umich.edu 2235952Ssaidi@eecs.umich.edu Entry *entry = section->findEntry(entryName); 2245952Ssaidi@eecs.umich.edu if (entry == NULL) 2255952Ssaidi@eecs.umich.edu return false; 2265952Ssaidi@eecs.umich.edu 2275952Ssaidi@eecs.umich.edu value = entry->getValue(); 2285952Ssaidi@eecs.umich.edu 2295952Ssaidi@eecs.umich.edu return true; 2305952Ssaidi@eecs.umich.edu} 2315952Ssaidi@eecs.umich.edu 2325952Ssaidi@eecs.umich.edubool 2335952Ssaidi@eecs.umich.eduIniFile::sectionExists(const string §ionName) const 2345952Ssaidi@eecs.umich.edu{ 2355952Ssaidi@eecs.umich.edu return findSection(sectionName) != NULL; 2365952Ssaidi@eecs.umich.edu} 2375952Ssaidi@eecs.umich.edu 2385952Ssaidi@eecs.umich.edu 2395952Ssaidi@eecs.umich.edubool 2405952Ssaidi@eecs.umich.eduIniFile::Section::printUnreferenced(const string §ionName) 2415952Ssaidi@eecs.umich.edu{ 2425952Ssaidi@eecs.umich.edu bool unref = false; 2435952Ssaidi@eecs.umich.edu bool search_unref_entries = false; 2445952Ssaidi@eecs.umich.edu vector<string> unref_ok_entries; 2455952Ssaidi@eecs.umich.edu 2465952Ssaidi@eecs.umich.edu Entry *entry = findEntry("unref_entries_ok"); 2475952Ssaidi@eecs.umich.edu if (entry != NULL) { 2485952Ssaidi@eecs.umich.edu tokenize(unref_ok_entries, entry->getValue(), ' '); 2495952Ssaidi@eecs.umich.edu if (unref_ok_entries.size()) { 2505952Ssaidi@eecs.umich.edu search_unref_entries = true; 2515952Ssaidi@eecs.umich.edu } 2525952Ssaidi@eecs.umich.edu } 2535952Ssaidi@eecs.umich.edu 2545952Ssaidi@eecs.umich.edu for (EntryTable::iterator ei = table.begin(); 2555952Ssaidi@eecs.umich.edu ei != table.end(); ++ei) { 2565952Ssaidi@eecs.umich.edu const string &entryName = ei->first; 2575952Ssaidi@eecs.umich.edu entry = ei->second; 2585952Ssaidi@eecs.umich.edu 2595952Ssaidi@eecs.umich.edu if (entryName == "unref_section_ok" || 2605952Ssaidi@eecs.umich.edu entryName == "unref_entries_ok") 2615952Ssaidi@eecs.umich.edu { 2625952Ssaidi@eecs.umich.edu continue; 2635952Ssaidi@eecs.umich.edu } 2645952Ssaidi@eecs.umich.edu 2655952Ssaidi@eecs.umich.edu if (!entry->isReferenced()) { 2665952Ssaidi@eecs.umich.edu if (search_unref_entries && 2675952Ssaidi@eecs.umich.edu (std::find(unref_ok_entries.begin(), unref_ok_entries.end(), 2685952Ssaidi@eecs.umich.edu entryName) != unref_ok_entries.end())) 2695952Ssaidi@eecs.umich.edu { 2705952Ssaidi@eecs.umich.edu continue; 2715952Ssaidi@eecs.umich.edu } 2725952Ssaidi@eecs.umich.edu 2735952Ssaidi@eecs.umich.edu cerr << "Parameter " << sectionName << ":" << entryName 2745952Ssaidi@eecs.umich.edu << " not referenced." << endl; 2755952Ssaidi@eecs.umich.edu unref = true; 2765952Ssaidi@eecs.umich.edu } 2775952Ssaidi@eecs.umich.edu } 2785952Ssaidi@eecs.umich.edu 2795952Ssaidi@eecs.umich.edu return unref; 2805952Ssaidi@eecs.umich.edu} 2815952Ssaidi@eecs.umich.edu 2825952Ssaidi@eecs.umich.edu 2835952Ssaidi@eecs.umich.eduvoid 2845952Ssaidi@eecs.umich.eduIniFile::getSectionNames(vector<string> &list) const 2855952Ssaidi@eecs.umich.edu{ 2865952Ssaidi@eecs.umich.edu for (SectionTable::const_iterator i = table.begin(); 2875952Ssaidi@eecs.umich.edu i != table.end(); ++i) 2885952Ssaidi@eecs.umich.edu { 2895952Ssaidi@eecs.umich.edu list.push_back((*i).first); 2905952Ssaidi@eecs.umich.edu } 2915952Ssaidi@eecs.umich.edu} 2925952Ssaidi@eecs.umich.edu 2935952Ssaidi@eecs.umich.edubool 2945952Ssaidi@eecs.umich.eduIniFile::printUnreferenced() 2955952Ssaidi@eecs.umich.edu{ 2965952Ssaidi@eecs.umich.edu bool unref = false; 2975952Ssaidi@eecs.umich.edu 2985952Ssaidi@eecs.umich.edu for (SectionTable::iterator i = table.begin(); 2995952Ssaidi@eecs.umich.edu i != table.end(); ++i) { 3005952Ssaidi@eecs.umich.edu const string §ionName = i->first; 3015952Ssaidi@eecs.umich.edu Section *section = i->second; 3025952Ssaidi@eecs.umich.edu 3035952Ssaidi@eecs.umich.edu if (!section->isReferenced()) { 3045952Ssaidi@eecs.umich.edu if (section->findEntry("unref_section_ok") == NULL) { 3055952Ssaidi@eecs.umich.edu cerr << "Section " << sectionName << " not referenced." 3065952Ssaidi@eecs.umich.edu << endl; 3075952Ssaidi@eecs.umich.edu unref = true; 3085952Ssaidi@eecs.umich.edu } 3095952Ssaidi@eecs.umich.edu } 3105952Ssaidi@eecs.umich.edu else { 3115952Ssaidi@eecs.umich.edu if (section->printUnreferenced(sectionName)) { 3125952Ssaidi@eecs.umich.edu unref = true; 3135952Ssaidi@eecs.umich.edu } 3145952Ssaidi@eecs.umich.edu } 3155952Ssaidi@eecs.umich.edu } 3165952Ssaidi@eecs.umich.edu 3175952Ssaidi@eecs.umich.edu return unref; 3185952Ssaidi@eecs.umich.edu} 3195952Ssaidi@eecs.umich.edu 3205952Ssaidi@eecs.umich.edu 3215952Ssaidi@eecs.umich.eduvoid 3225952Ssaidi@eecs.umich.eduIniFile::Section::dump(const string §ionName) 3235952Ssaidi@eecs.umich.edu{ 3245952Ssaidi@eecs.umich.edu for (EntryTable::iterator ei = table.begin(); 3255952Ssaidi@eecs.umich.edu ei != table.end(); ++ei) { 3265952Ssaidi@eecs.umich.edu cout << sectionName << ": " << (*ei).first << " => " 3275952Ssaidi@eecs.umich.edu << (*ei).second->getValue() << "\n"; 3285952Ssaidi@eecs.umich.edu } 3295952Ssaidi@eecs.umich.edu} 3305952Ssaidi@eecs.umich.edu 3315952Ssaidi@eecs.umich.eduvoid 3325952Ssaidi@eecs.umich.eduIniFile::dump() 3335952Ssaidi@eecs.umich.edu{ 3345952Ssaidi@eecs.umich.edu for (SectionTable::iterator i = table.begin(); 3355952Ssaidi@eecs.umich.edu i != table.end(); ++i) { 3365952Ssaidi@eecs.umich.edu i->second->dump(i->first); 3375952Ssaidi@eecs.umich.edu } 3385952Ssaidi@eecs.umich.edu} 3395952Ssaidi@eecs.umich.edu