Back
1 //------------------------------------------------------------------------------
2 // Module FileUtil.cpp //
3 // //
4 // Utility functions to read values/strings from a stream. You can //
5 // realize format-sensitive reading without the "always read a whoole //
6 // line" concept. //
7 // //
8 // copyright (c) 1998-2004 by Lars Haendel //
9 // home: www.newty.de //
10 // //
11 // This program is free software; you can redistribute it and/or modify //
12 // it under the terms of the GNU General Public License as published by //
13 // the Free Software Foundation as version 2 of the License. //
14 // //
15 // This program is distributed in the hope that it will be useful, //
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
18 // GNU General Public License for more details. //
19 // //
20 // You should have received a copy of the GNU General Public License //
21 // along with this program; if not, write to the Free Software //
22 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //
23 // //
24 //------------------------------------------------------------------------------
25
26
27 #ifndef FileUtilH
28 #define FileUtilH
29
30
31 //----------------------------------------------------------------------------------------------------------------------
32 #include <iostream> // due to ifstream ...
33 #include <fstream>
34 #include <ctype> // isspace()
35 #include <limits> // INT_MAX
36
37 #include "defines.h" // general defines
38
39
40 //----------------------------------------------------------------------------------------------------------------------
41 // exception codes
42 #define UnexpectedEndl (int) 42 // encountered unexpected end of line (endl)
43 #define UnexpectedEOF (int) 43 // " " end of file (EOF)
44 #define NoEndlFound (int) 44 // an endl was expected but not found
45 #define IllegalCharacter (int) 45 // encountered illegal character
46 #define NoWhitespace (int) 46 // no whitespace after value
47 #define KeyNotFound (int) 47
48 #define BoolReadFailed (int) 48
49 #define ValueMissing (int) 49 // string/value missing in ReadKey...() functions
50 #define ErrReadingBits (int) 50
51 #define UnterminatedBits (int) 51
52
53
54
55 //----------------------------------------------------------------------------------------------------------------------
56 // Misc
57
58 // returns true if 'c' is a comment character, i.e. a character starting a comment
59 inline bool IsComment(const char c) { return (c == '#' || c == '%' || c == '*'); };
60
61 // return flag (bool) as string 'true' or 'false'
62 const char* FlagToString(const int& flag, const bool& f_LeftAlign=false);
63
64 //----------------------------------------------------------------------------------------------------------------------
65 // error handling
66 const char* GetLastError(const int& errNo); // get error description
67 char& GetIllegalCharacter();
68 const char* GetLastKey();
69
70 //int CountLinesEx (ifstream& file);
71
72
73 //----------------------------------------------------------------------------------------------------------------------
74 // functions skipws()/skipwsEx() and wrappers
75
76 // functions to remove whitespaces out of an ifstream returning the number of encountered endl's
77 // the extended version also removes all comments
78 int skipws (ifstream& file);
79 int skipwsEx(ifstream& file);
80
81
82 // wrapper for the two functions above which are throwing an exception depending on the number of
83 // encountered endl's
84 int skipwsEndl (ifstream& file); // use skipws() throwing exception if no endl occurs
85 void skipwsNoEndl (ifstream& file); // " " " " " an " "
86
87 int skipwsExEndl (ifstream& file); // like above but use skipwsEx()
88 void skipwsExNoEndl(ifstream& file); // " " " " "
89
90
91
92 //----------------------------------------------------------------------------------------------------------------------
93 // "Read"-functions
94
95
96 // Read a string from an ifstream. All whitespaces, comments and the delimiterterminate the string. The delimiter is
97 // left in the stream and is returned.
98 char ReadString(ifstream& file, char* szString, const int& size, const char& delimiter=' ');
99
100
101 //-------------------------------------------------------------------------------------------------------------------
102 // Reads an object of type T from an ifstream throwing an exception if the reading causes a failstate of the stream.
103 // Note: Whitespaces like line feeds are skipped. Thus if you track the actual line number in the file don't forget
104 // to call skipws()/skipwsEx() before.
105
106 void ReadFailed(ifstream& file); // utility function - private :-))
107
108 template <class T> T Read(ifstream& file, const T)
109 {
110 file.clear(); // reset stream state
111
112 T value;
113 file >> value; // try to read from stream
114
115 if(file.fail()!=0) // examine in case of a failstate
116 ReadFailed(file);
117
118
119 // check if the next character after the value is a ws or a comment ...
120 if(!isspace(file.peek()) && !IsComment((char) file.peek()))
121 {
122 GetIllegalCharacter() = (char) file.peek(); // set as "illegal character"
123 throw NoWhitespace; // ... otherwise: throw exception
124 }
125
126 return value;
127 };
128
129
130 //-------------------------------------------------------------------------------------------------------------------
131 // wrapper: read a value and throw an exception if an endl occurs
132 template < class T > T ReadExpNoEndl(ifstream& file, T value)
133 {
134 skipwsNoEndl(file);
135 return Read(file, value);
136 };
137
138
139
140 //----------------------------------------------------------------------------------------------------------------------
141 // SearchKey and the "ReadKey..." functions
142 // Note: The "ReadKey..." functions always restore the previous stream position. SearchKey does this only if an error
143 // has occured.
144
145
146 //-------------------------------------------------------------------------------------------------------------------
147 //
148 int SearchKey(ifstream& file, const char*const& szKey, const int& maxLines=INT_MAX, const char& delimiter=EOF,
149 const bool& f_EnableExceptions=true);
150
151
152 //-------------------------------------------------------------------------------------------------------------------
153 int ReadKeyBool (ifstream& file, const char*const& szKey, const int defaultValue=-1, const int& maxLines=INT_MAX);
154 bool ReadKeyString(ifstream& file, const char*const& szKey, char* szString, const int& size, const int& maxLines=INT_MAX);
155
156
157 //-------------------------------------------------------------------------------------------------------------------
158 // Search stream for string <szKey> followed by a '=' and read the following value. If read fails
159 // throw an exception. Return default value if key is not found.
160 template < class T > T ReadKeyValue(ifstream& file, const char* szKey, const T defaultValue,
161 const int& maxLines=INT_MAX)
162 {
163 file.clear();
164 streampos curPos = file.tellg(); // preserve actual stream position
165 try{
166 SearchKey(file, szKey, maxLines, '['); // search key
167 } catch(int errNo) { goto __ReturnDefault__; }
168
169 if(file.get()!='=') // if next character is not '=' -> return default value
170 goto __ReturnDefault__;
171
172 if(skipws(file)!=0)
173 throw ValueMissing;
174
175 T value;
176 try{
177 value=Read(file, defaultValue); // read
178 } catch(int errNo) { file.seekg(curPos); throw errNo; }
179
180 file.seekg(curPos); // restore stream position
181 return value;
182
183 __ReturnDefault__:
184 file.seekg(curPos); // restore stream position
185 return defaultValue;
186 };
187 #endif
Top |