LogCabin
Core/Config.h
Go to the documentation of this file.
00001 /*
00002  * This file was downloaded from:
00003  * http://www-personal.umich.edu/~wagnerr/ConfigFile.html
00004  *
00005  * Copyright (c) 2004 Richard J. Wagner
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a copy
00008  * of this software and associated documentation files (the "Software"), to
00009  * deal in the Software without restriction, including without limitation the
00010  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00011  * sell copies of the Software, and to permit persons to whom the Software is
00012  * furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included in
00015  * all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00020  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00022  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
00023  * IN THE SOFTWARE.
00024  *
00025  * ------------------------------------------------
00026  *
00027  * It was subsequently modified:
00028  *
00029  * Copyright (c) 2012 Stanford University
00030  * Copyright (c) 2015 Diego Ongaro
00031  *
00032  * Permission to use, copy, modify, and distribute this software for any
00033  * purpose with or without fee is hereby granted, provided that the above
00034  * copyright notice and this permission notice appear in all copies.
00035  *
00036  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
00037  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00038  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
00039  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00040  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00041  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00042  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00043  */
00044 
00045 #include <iostream>
00046 #include <map>
00047 #include <sstream>
00048 #include <stdexcept>
00049 #include <string>
00050 #include <typeinfo>
00051 
00052 #ifndef LOGCABIN_CORE_CONFIG_H
00053 #define LOGCABIN_CORE_CONFIG_H
00054 
00055 namespace LogCabin {
00056 namespace Core {
00057 
00058 /**
00059  * Reads and writes configuration files.
00060  */
00061 class Config {
00062     typedef std::string string;
00063 
00064   public:
00065     /**
00066      * Base class for Config exceptions.
00067      */
00068     struct Exception : public std::runtime_error {
00069         explicit Exception(const std::string& error);
00070     };
00071 
00072 
00073     struct FileNotFound : public Exception {
00074         explicit FileNotFound(const string& filename);
00075         virtual ~FileNotFound() throw() {}
00076         string filename;
00077     };
00078 
00079     // thrown only by T read(key) variant of read()
00080     struct KeyNotFound : public Exception {
00081         explicit KeyNotFound(const string& key);
00082         virtual ~KeyNotFound() throw() {}
00083         string key;
00084     };
00085 
00086     struct ConversionError : public Exception {
00087         ConversionError(const string& key,
00088                         const string& value,
00089                         const string& typeName);
00090         virtual ~ConversionError() throw() {}
00091         string key;
00092         string value;
00093         string typeName;
00094     };
00095 
00096     /**
00097      * Construct an empty Config.
00098      */
00099     explicit Config(const string& delimiter = "=",
00100                     const string& comment = "#");
00101 
00102     /**
00103      * Construct a Config from the given map of options.
00104      */
00105     explicit Config(const std::map<string, string>& options);
00106 
00107     /**
00108      * Load a Config from a file.
00109      * This is a convenience wrapper around operator>>.
00110      * \throw FileNotFound
00111      */
00112     void readFile(const string& filename);
00113 
00114     /**
00115      * Read configuration.
00116      */
00117     friend std::istream& operator>>(std::istream& is, Config& cf);
00118 
00119     /**
00120      * Write configuration.
00121      */
00122     friend std::ostream& operator<<(std::ostream& os, const Config& cf);
00123 
00124     /**
00125      * Read the value corresponding to a key.
00126      * \return
00127      *      The desired value, converted to a T.
00128      * \throw KeyNotFound
00129      *      If the key does not exist.
00130      * \throw ConversionError
00131      *      If the value could not be converted to a T.
00132      */
00133     template<class T = string>
00134     T read(const string& key) const;
00135 
00136     /**
00137      * Return the value corresponding to key or given default value if key is
00138      * not found.
00139      * \throw ConversionError
00140      *      If the value could not be converted to a T.
00141      */
00142     template<class T = string>
00143     T read(const string& key, const T& value) const;
00144 
00145     /**
00146      * Check whether key exists in configuration.
00147      */
00148     bool keyExists(const string& key) const;
00149 
00150     /**
00151      * Set a key to the given value.
00152      */
00153     template<class T> void set(const string& key, const T& value);
00154 
00155     /**
00156      * Set a key to the given string value.
00157      */
00158     void set(const string& key, const string& value);
00159 
00160     /**
00161      * Remove a key and its value.
00162      * If the key does not exist, this will do nothing.
00163      */
00164     void remove(const string& key);
00165 
00166   private:
00167     /**
00168      * Convert from a T to a string.
00169      * Type T must support << operator.
00170      */
00171     template<class T>
00172     static string toString(const T& t);
00173 
00174     /**
00175      * Convert from a string to a T.
00176      * Type T must support >> operator.
00177      *
00178      * For boolean conversions, "false", "f", "no", "n", "0" are false, and
00179      * "true", "t", "yes", "y", "1" are true.
00180      *
00181      * \throw ConversionError
00182      */
00183     template<class T>
00184     static T fromString(const string& key, const string& s);
00185 
00186     /**
00187      * Read a line, strip comments, and trim it.
00188      */
00189     std::string readLine(std::istream& is) const;
00190 
00191     /// Separator between key and value, usually "=".
00192     const string delimiter;
00193 
00194     /// Starts a comment, usually "#".
00195     const string comment;
00196 
00197     /// Extracted keys and values.
00198     std::map<string, string> contents;
00199 };
00200 
00201 template<class T>
00202 std::string
00203 Config::toString(const T& t)
00204 {
00205     std::ostringstream ost;
00206     ost.setf(std::ostringstream::boolalpha);
00207     ost << t;
00208     return ost.str();
00209 }
00210 
00211 template<class T>
00212 T
00213 Config::fromString(const string& key, const string& s)
00214 {
00215     T t;
00216     std::istringstream ist(s);
00217     ist >> t;
00218     if (!ist || !ist.eof())
00219         throw ConversionError(key, s, typeid(T).name());
00220     return t;
00221 }
00222 
00223 template<>
00224 std::string
00225 Config::fromString<std::string>(const string& key, const string& s);
00226 
00227 template<>
00228 bool
00229 Config::fromString<bool>(const string& key, const string& s);
00230 
00231 
00232 template<class T>
00233 T
00234 Config::read(const string& key) const
00235 {
00236     auto p = contents.find(key);
00237     if (p == contents.end())
00238         throw KeyNotFound(key);
00239     return fromString<T>(key, p->second);
00240 }
00241 
00242 template<class T>
00243 T
00244 Config::read(const string& key, const T& value) const
00245 {
00246     auto p = contents.find(key);
00247     if (p == contents.end())
00248         return value;
00249     return fromString<T>(key, p->second);
00250 }
00251 
00252 template<class T>
00253 void
00254 Config::set(const string& key, const T& value)
00255 {
00256     set(key, toString(value));
00257 }
00258 
00259 } // namespace LogCabin::Core
00260 } // namespace LogCabin
00261 
00262 #endif /* LOGCABIN_CORE_CONFIG_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines