1 
2 #ifndef __INI_HPP__
3 #define __INI_HPP__
4 
5 /* "Species" - a CoreWars evolver.  Copyright (C) 2003 'Varfar'
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 1, or (at your option) any later
10  * version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 
22 
23 #include <iostream>
24 #include <string>
25 
26 /**
27  *
28  * this INI parsing thingy is designed to work with binary streams,
29  * coping internally with either \n or \r\n line endings
30  *
31  **/
32 
33 /*******************************************************************
34  * class KeyValuePair
35  * sequentially parses lines and splits them into key-value pairs
36  * to parse, >> from an input stream in a loop while isValid()
37  *******************************************************************/
38 
39 class KeyValuePair {
operator >>(std::istream & is,KeyValuePair & kvp)40    friend std::istream &operator>>(std::istream &is,KeyValuePair &kvp) { return kvp.fromSerial(is); }
41    public:
42       KeyValuePair();
43       ~KeyValuePair();
44       // error states
45       enum KVP_ERROR {
46       	VALUE_NOT_INT,
47       	VALUE_NOT_BOOL,
48       	VALUE_NOT_FLOAT,
49       	VALUE_NOT_DOUBLE,
50       	KEY_NOT_VALID,
51       	KEY_HAS_NO_CATEGORY,
52       	KVP_ERROR_LAST
53       };
54       static const char *ERROR_MSG(const KVP_ERROR err);
55       // something to check?
isValid() const56       bool isValid() const { return valid; }
57       // is a key?
is(const std::string & key) const58       bool is(const std::string &key) const { return is(key.c_str()); }
59       bool is(const char *key) const;
60       // get key
61       void getKeyAsString(std::string &key); // will set key to error message if not a valid line
62       const char *getKeyAsChar(); // copy to your own var before you manipulate or save for later!
63       // keys can be categorised by being of the form "category.key" so "guidence.range" makes
64       // more sense
hasCategory() const65       bool hasCategory() const { return hascategory; } // simply returns if has a category
isCategory(const std::string & category) const66       bool isCategory(const std::string &category) const { return isCategory(category.c_str()); }
67       bool isCategory(const char *category);
68       bool hasSubCategory(); // more categories?  category.category...key
69       bool getSubCategory(); // will divide the current key into category.key; returns hasCategory() now
70       // get key; will throw KVP_ERROR in error conditions
71       void getCategoryAsString(std::string &category);
72       const char *getCategoryAsChar() const; // copy to your own var before you manipulate or save for later!
73 			// check values
isValue(const std::string & val) const74 			bool isValue(const std::string &val) const { return isValue(val.c_str()); }
75 			bool isValue(const char *val) const;
76       // get value (where a default is set, will return def if parse failed); else will throw KVP_ERROR
77       void getValueAsString(std::string &value);
78       const char *getValueAsChar(); // copy your own var before manipulate or save for later!
79       int getValueAsInt(int def=0);
80       float getValueAsFloat(float def=0.0f,bool percent_allowed=true);
81       double getValueAsDouble(double def=0.0,bool percent_allowed=true);
82       bool getValueAsBool(bool def=true);
83       // misc
getLineNum() const84       unsigned int getLineNum() const { return linenum; }
85       static const int MAX_KVP_LINE_LEN = 132;
86    protected:
87       bool valid, // should key and value be used?
88          hascategory; // has a category?
89       unsigned int linenum;
90       char line[MAX_KVP_LINE_LEN], *key, *value, *category;
91       std::istream &fromSerial(std::istream & is);
92 };
93 
94 class INIFile {
95 	public:
96 		INIFile(std::istream &is);
97 		bool seek(const std::string &section); // returns success
98 		KeyValuePair *get(const std::string &key); // returns null if no such key
99 	protected:
100 		static const int NO_SECTION = -1;
101 		std::istream *_is;
102 		int _section_ofs;
103 		char _section[KeyValuePair::MAX_KVP_LINE_LEN];
104 		KeyValuePair _kvp;
105 		bool _bad_stream;
106 };
107 
108 #endif // ifndef __INI_HPP__
109 
110