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