File: leoini.h

package info (click to toggle)
xstow 1.0.2-1
  • links: PTS
  • area: main
  • in suites: bullseye, buster, sid, stretch
  • size: 1,064 kB
  • ctags: 1,073
  • sloc: cpp: 7,264; sh: 1,216; makefile: 196; awk: 26
file content (275 lines) | stat: -rw-r--r-- 8,527 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/** \class LeoIni
    \brief Leo Ini file reader.
    \author King Leo (Martin Oberzalek)
    \version 2.0
    \date    2002
    \bug     there are no known bugs 
    \warning This class reads an ini file into the memory. 
             That can waste your memory.
 */
/*
 * $Log: leoini.h,v $
 * Revision 1.2  2005/07/04 21:59:42  martin
 * added logging to all files
 *
 */


#ifndef Leo_Ini_h
#define Leo_Ini_h

#include <string>
#include <fstream>
#include <list>

#include "local_config.h"
#include "range.h"

#ifdef CAN_USE_INI

namespace Leo
{

  /// a class for easy accessing ini files
  class Ini 
  {
  public:
    struct Element ///< This structure represents an ini-file entry 
    {
      std::string section; ///< the name of the current section
      std::string key;     ///< the name of the key
      std::string value;   ///< the value of the key
      
      typedef std::list<Element> element_list;  
      typedef element_list::iterator element_list_it;
      
      /// subelements
      /** if you read a whole section the subelements are stored in this list */
      mutable element_list elements; 
      
	struct EnumType {
	    enum ETYPE
	    {
		FIRST__,
		SECTION_LIST, ///< the element is a section list
		SECTION,      ///< the element is a whole section
		KEY,          ///< the element is a key
		UNDEF,        ///< not defined
		LAST__
	    };
	};
      
	typedef EnumRange<EnumType> TYPE;

      TYPE type; ///< the type of the element
      
      Element( TYPE type = TYPE::UNDEF, std::string section = "", std::string key = "", std::string value = "" )
	: section( section ), key( key ), value( value ), type( type ) {}
      
      /// adds a section to the section list, or adds a key to the section
      /** returns false on error */
      bool add( Element& element ); 
    };
    
  private:
    struct Line ///< structure representing a whole line
    {
      struct String  ///< structure representing a substring of a whole line
      {
	std::string::size_type pos;   ///< the cursor position
	std::string str;              ///< the string
	String() : pos(0) {}          
	void clear() { pos = 0; str =""; } ///< clear the String
      };
      
      int number;      ///< the line number
      String comment;  ///< the possible comment 
      String tag;      ///< the stripped key, section,.. 
      std::string str; ///< the whole line
      
      Line() : number( 0 ) {}
      void clear()  ///< clears the Line
      { number = 0; comment.clear(); tag.clear(); str = ""; }
      std::string get_line(); ///< returns regenerated Line
    };
    
    typedef std::list<Line> line_list;
    typedef line_list::iterator line_list_it;
    
    struct MemElement : Element ///< class Representing an Element within the memory
    {
      Line line;   ///< the Line
      
      typedef std::list<MemElement> mem_element_list;
      typedef mem_element_list::iterator mem_element_list_it;
      
      mutable mem_element_list mem_elements; ///< list of subelements
      
      MemElement() : Element(){}     
      
      MemElement( const Element& e )  ///< copy contructor for Elements
	: Element() 
      { *this = e; }
      
      void operator=( const Element& e ); ///< copy en Element
      void clear(); ///< clear it
      
      Element get_element(); ///< returns en Element
    };
    
    MemElement::mem_element_list elements; ///< list of MemElements
    line_list comments; ///< comment list
    
    int openmode;          ///< mode how we opened the file
    std::string file_name; ///< remember the filename
    std::fstream file;          ///< fstream for accessing the file
    bool is_open;          ///< true if a file is opened
    bool valid;            ///< true if system is valid
    bool file_readed;      ///< true if we already read the file
    
    bool eof_reached;      ///< true if we reached eof
    int line_number;       ///< the current line number
    
    bool changed;          ///< true if something has changed and we have to write it to the file
  public:
    Ini() : is_open( false ), valid( false ), eof_reached( false ), changed( false ) {}
    Ini( std::string filename, int mode = std::ios::in | std::ios::out);
    
    /// destructor
    /** if a file is still open the buffer will be flushed and the file closed */
    ~Ini();
    
    /// open a ini file
    /** returns false if we already opened a file or file opening failed */
    bool open( std::string filename, int mode = std::ios::in | std::ios::out );
    
    
    /// closes the file
    /** if data had changed the buffer will be flushed */
    void close(); 
    void flush();  ///< flushes the buffer
    
    /// read the ini file
    /** returns false if no file is opened and if the file is not already read */
    bool read(); 
    
    /// read an Element
    /** If the file wasn't read, it will be read now */
    bool read( Element& element );
    
    /// same as flush
    /** but return false if no file is opened, or the file was opened in readonly mode */
    bool write();
    
    /// writes an Element into the ini file
    /** returns false if no file is opened, 
	if file was opend in readonly mode,
	if the element is not a correct element.
	
	If you write a whole section, the old elements of the section 
	won't be destroyed. If you wan't to destroy a whole section,
	you have to erase it.
	
	If the you wan't to write a key into a section that does not exists,
	its section will be created automatically.
    */
    bool write( Element element );
    
    /// clears the file
    /** returns false if no file is opened, or file is open in readonly mode  */
    bool erase(); 
    
    /// erases one element 
    /** returns false if no file is open, the element is not correct or the element
	does not exist 
	
	If you wan't to erase a whole section or section list, only the elements
	you are listed within the list will be destroyed. If you wan't to
	erase a whole section you will have to read it first, that you have all
	elements of it, and then erase it by calling this function.
	
	If the last key of a section was detroyed the section will be destroyed.
    */
    bool erase( Element element ); 
    
    bool is_valid() const { return valid; } ///< returns true if the system is valid
    bool operator!() const { return !valid; } 
    
#ifdef DEBUG
    void print_mem();
#endif

    friend bool operator == ( const Ini::MemElement& a, const Ini::MemElement& b );
  
    std::string get_file_name() const { return file_name; }

  private:
    Line read_line(); ///< reads one line
    std::string strip( std::string str, std::string what = " \t\0\n" ); ///< strips a string
    std::string::size_type find_comment( const std::string& str ); ///< finds a comment within a string
    
    /// finds the tag
    bool find_tag( std::string::size_type& start, std::string::size_type& end, const std::string& str ); 
    bool is_section( const std::string& str ); ///< detects a section
    bool is_key( const std::string& str ); ///< checks if the string is a key
    std::string extract_section_name( const std::string& str ); 
    std::string extract_key_name( const std::string& str );
    std::string extract_key_data( const std::string& str );
    
    bool is_good_element( Element& element ); ///< checks if the element is sane
    bool is_good_element_rec( Element& element ); ///< checks all elements
    
    void clear(); //clears the memory
    bool write_line( const Line& line, int last_line ); ///< write a line to file
    
#ifndef DEBUG
    void print_mem();
#endif
    
    bool is_section_empty( MemElement& element );
  }; // class Ini
  
  bool operator == ( const Ini::MemElement& a, const Ini::MemElement& b );

} // namspace Leo


/// print an element
std::ostream& operator<<( std::ostream& out, const Leo::Ini::Element& e );


#ifndef NO_STRSTREAM

#include "string_utils.h"

namespace Leo
{

  /// generates an indexed string
  template <class A, class B> std::string gen_index( const A a, const B b ) 
  {
    std::string s = x2s( a ) + '[' + x2s( b ) + ']';
    return s;
  }

  /// returns the index of a string
  template <class A> A get_index( const std::string& s )
  {
    std::string::size_type start = s.find( '[' );
    std::string::size_type end = s.find( ']', start );

    if( start == std::string::npos ||
	end == std::string::npos )
      s = "";
    else
      s = s.substr( start+1, start-end -1 );

    return s2x<A>(s);
  }
} // namespace Leo

#endif // NO_STRSTREAM

#endif

#endif