12SN/A/*
21762SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
292665Ssaidi@eecs.umich.edu *          Steve Reinhardt
302SN/A */
312SN/A
322SN/A#ifndef __INIFILE_HH__
332SN/A#define __INIFILE_HH__
342SN/A
352SN/A#include <fstream>
362SN/A#include <list>
372SN/A#include <string>
3811168Sandreas.hansson@arm.com#include <unordered_map>
392SN/A#include <vector>
402SN/A
41229SN/A/**
42229SN/A * @file
43229SN/A * Declaration of IniFile object.
44229SN/A * @todo Change comments to match documentation style.
45229SN/A */
46160SN/A
47160SN/A///
48160SN/A/// This class represents the contents of a ".ini" file.
49160SN/A///
50160SN/A/// It's basically a two level lookup table: a set of named sections,
51160SN/A/// where each section is a set of key/value pairs.  Section names,
52160SN/A/// keys, and values are all uninterpreted strings.
53160SN/A///
542SN/Aclass IniFile
552SN/A{
562SN/A  protected:
57160SN/A
58160SN/A    ///
59160SN/A    /// A single key/value pair.
60160SN/A    ///
612SN/A    class Entry
622SN/A    {
635543Ssaidi@eecs.umich.edu        std::string     value;          ///< The entry value.
645543Ssaidi@eecs.umich.edu        mutable bool    referenced;     ///< Has this entry been used?
652SN/A
662SN/A      public:
67160SN/A        /// Constructor.
682SN/A        Entry(const std::string &v)
692SN/A            : value(v), referenced(false)
702SN/A        {
712SN/A        }
722SN/A
73160SN/A        /// Has this entry been used?
742SN/A        bool isReferenced() { return referenced; }
752SN/A
76160SN/A        /// Fetch the value.
772SN/A        const std::string &getValue() const;
782SN/A
79160SN/A        /// Set the value.
802SN/A        void setValue(const std::string &v) { value = v; }
81160SN/A
82160SN/A        /// Append the given string to the value.  A space is inserted
83160SN/A        /// between the existing value and the new value.  Since this
84160SN/A        /// operation is typically used with values that are
85160SN/A        /// space-separated lists of tokens, this keeps the tokens
86160SN/A        /// separate.
87160SN/A        void appendValue(const std::string &v) { value += " "; value += v; }
882SN/A    };
892SN/A
90160SN/A    ///
91160SN/A    /// A section.
92160SN/A    ///
932SN/A    class Section
942SN/A    {
95160SN/A        /// EntryTable type.  Map of strings to Entry object pointers.
9611168Sandreas.hansson@arm.com        typedef std::unordered_map<std::string, Entry *> EntryTable;
972SN/A
985543Ssaidi@eecs.umich.edu        EntryTable      table;          ///< Table of entries.
995543Ssaidi@eecs.umich.edu        mutable bool    referenced;     ///< Has this section been used?
1002SN/A
1012SN/A      public:
102160SN/A        /// Constructor.
1032SN/A        Section()
1042SN/A            : table(), referenced(false)
1052SN/A        {
1062SN/A        }
1072SN/A
108160SN/A        /// Has this section been used?
1092SN/A        bool isReferenced() { return referenced; }
1102SN/A
111160SN/A        /// Add an entry to the table.  If an entry with the same name
112160SN/A        /// already exists, the 'append' parameter is checked If true,
113160SN/A        /// the new value will be appended to the existing entry.  If
114160SN/A        /// false, the new value will replace the existing entry.
115160SN/A        void addEntry(const std::string &entryName, const std::string &value,
116160SN/A                      bool append);
117160SN/A
118160SN/A        /// Add an entry to the table given a string assigment.
119160SN/A        /// Assignment should be of the form "param=value" or
120160SN/A        /// "param+=value" (for append).  This funciton parses the
121160SN/A        /// assignment statment and calls addEntry().
122160SN/A        /// @retval True for success, false if parse error.
123160SN/A        bool add(const std::string &assignment);
124160SN/A
125160SN/A        /// Find the entry with the given name.
126160SN/A        /// @retval Pointer to the entry object, or NULL if none.
1272SN/A        Entry *findEntry(const std::string &entryName) const;
1282SN/A
129160SN/A        /// Print the unreferenced entries in this section to cerr.
130160SN/A        /// Messages can be suppressed using "unref_section_ok" and
131160SN/A        /// "unref_entries_ok".
132160SN/A        /// @param sectionName Name of this section, for use in output message.
133160SN/A        /// @retval True if any entries were printed.
1342SN/A        bool printUnreferenced(const std::string &sectionName);
135160SN/A
136160SN/A        /// Print the contents of this section to cout (for debugging).
1372SN/A        void dump(const std::string &sectionName);
1382SN/A    };
1392SN/A
140160SN/A    /// SectionTable type.  Map of strings to Section object pointers.
14111168Sandreas.hansson@arm.com    typedef std::unordered_map<std::string, Section *> SectionTable;
1422SN/A
1432SN/A  protected:
144160SN/A    /// Hash of section names to Section object pointers.
145160SN/A    SectionTable table;
1462SN/A
147160SN/A    /// Look up section with the given name, creating a new section if
148160SN/A    /// not found.
149160SN/A    /// @retval Pointer to section object.
1502SN/A    Section *addSection(const std::string &sectionName);
151160SN/A
152160SN/A    /// Look up section with the given name.
153160SN/A    /// @retval Pointer to section object, or NULL if not found.
1542SN/A    Section *findSection(const std::string &sectionName) const;
1552SN/A
1562SN/A  public:
157160SN/A    /// Constructor.
1582SN/A    IniFile();
159160SN/A
160160SN/A    /// Destructor.
1612SN/A    ~IniFile();
1622SN/A
1631046SN/A    /// Load parameter settings from given istream.  This is a helper
1641046SN/A    /// function for load(string) and loadCPP(), which open a file
1651046SN/A    /// and then pass it here.
1661046SN/A    /// @retval True if successful, false if errors were encountered.
1671046SN/A    bool load(std::istream &f);
1681046SN/A
169160SN/A    /// Load the specified file.
170160SN/A    /// Parameter settings found in the file will be merged with any
171160SN/A    /// already defined in this object.
172160SN/A    /// @param file The path of the file to load.
173160SN/A    /// @retval True if successful, false if errors were encountered.
1742SN/A    bool load(const std::string &file);
1752SN/A
176160SN/A    /// Take string of the form "<section>:<parameter>=<value>" or
177160SN/A    /// "<section>:<parameter>+=<value>" and add to database.
178160SN/A    /// @retval True if successful, false if parse error.
1792SN/A    bool add(const std::string &s);
1802SN/A
181160SN/A    /// Find value corresponding to given section and entry names.
182160SN/A    /// Value is returned by reference in 'value' param.
183160SN/A    /// @retval True if found, false if not.
1842SN/A    bool find(const std::string &section, const std::string &entry,
1852SN/A              std::string &value) const;
186160SN/A
18711655Sandreas.sandberg@arm.com    /// Determine whether the entry exists within named section exists
18811655Sandreas.sandberg@arm.com    /// in the .ini file.
18911655Sandreas.sandberg@arm.com    /// @return True if the section exists.
19011655Sandreas.sandberg@arm.com    bool entryExists(const std::string &section,
19111655Sandreas.sandberg@arm.com                     const std::string &entry) const;
19211655Sandreas.sandberg@arm.com
193304SN/A    /// Determine whether the named section exists in the .ini file.
194304SN/A    /// Note that the 'Section' class is (intentionally) not public,
195304SN/A    /// so all clients can do is get a bool that says whether there
196304SN/A    /// are any values in that section or not.
197304SN/A    /// @return True if the section exists.
198304SN/A    bool sectionExists(const std::string &section) const;
199304SN/A
20010385SAndrew.Bardsley@arm.com    /// Push all section names into the given vector
20110385SAndrew.Bardsley@arm.com    void getSectionNames(std::vector<std::string> &list) const;
20210385SAndrew.Bardsley@arm.com
203160SN/A    /// Print unreferenced entries in object.  Iteratively calls
204160SN/A    /// printUnreferend() on all the constituent sections.
2052SN/A    bool printUnreferenced();
2062SN/A
207160SN/A    /// Dump contents to cout.  For debugging.
2082SN/A    void dump();
2092SN/A};
2102SN/A
2112SN/A#endif // __INIFILE_HH__
212