Switch to unified view

a/src/utils/conftree.h b/src/utils/conftree.h
...
...
14
 *   Free Software Foundation, Inc.,
14
 *   Free Software Foundation, Inc.,
15
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16
 */
16
 */
17
#ifndef _CONFTREE_H_
17
#ifndef _CONFTREE_H_
18
#define  _CONFTREE_H_
18
#define  _CONFTREE_H_
19
19
/**
20
/**
20
 * A simple configuration file implementation.
21
 * A simple configuration file implementation.
21
 *
22
 *
22
 * Configuration files have lines like 'name = value', and/or like '[subkey]'
23
 * Configuration files have lines like 'name = value', and/or like '[subkey]'
23
 *
24
 *
...
...
29
 * Values can be queried for, or set. (the file is then rewritten).
30
 * Values can be queried for, or set. (the file is then rewritten).
30
 * The names are case-sensitive but don't count on it either.
31
 * The names are case-sensitive but don't count on it either.
31
 * Any line without a '=' is discarded when rewriting the file.
32
 * Any line without a '=' is discarded when rewriting the file.
32
 * All 'set' calls currently cause an immediate file rewrite.
33
 * All 'set' calls currently cause an immediate file rewrite.
33
 */
34
 */
35
34
#include <string>
36
#include <string>
35
#include <map>
37
#include <map>
36
#include <list>
38
#include <list>
37
// rh7.3 likes iostream better...
39
// rh7.3 likes iostream better...
38
#if defined(__GNUC__) && __GNUC__ < 3
40
#if defined(__GNUC__) && __GNUC__ < 3
...
...
75
    /** 
77
    /** 
76
     * Get value for named parameter, from specified subsection (looks in 
78
     * Get value for named parameter, from specified subsection (looks in 
77
     * global space if sk is empty).
79
     * global space if sk is empty).
78
     * @return 0 if name not found, 1 else
80
     * @return 0 if name not found, 1 else
79
     */
81
     */
80
    virtual int get(const std::string &name, string &value, const string &sk);
81
    virtual int get(const std::string &name, string &value) {
82
    virtual int get(const std::string &name, string &value, 
82
  return get(name, value, string(""));
83
          const string &sk = string(""));
83
    }
84
    /* Note: the version returning char* was buggy and has been removed */
84
    /*
85
     * See comments for std::string variant
86
     * @return 0 if name not found, const C string else
87
     */
88
    virtual const char *get(const char *name, const char *sk = 0);
89
85
90
    /** 
86
    /** 
91
     * Set value for named parameter in specified subsection (or global)
87
     * Set value for named parameter in specified subsection (or global)
92
     * @return 0 for error, 1 else
88
     * @return 0 for error, 1 else
93
     */
89
     */
...
...
153
    return *this;
149
    return *this;
154
    }
150
    }
155
151
156
 protected:
152
 protected:
157
    bool dotildexpand;
153
    bool dotildexpand;
154
    StatusCode status;
158
 private:
155
 private:
159
    StatusCode status;
160
    string filename; // set if we're working with a file
156
    string filename; // set if we're working with a file
161
    string *data;    // set if we're working with an in-memory string
157
    string *data;    // set if we're working with an in-memory string
162
    map<string, map<string, string> > submaps;
158
    map<string, map<string, string> > submaps;
163
159
164
    void parseinput(std::istream &input);
160
    void parseinput(std::istream &input);
...
...
177
 * NOTE: contrary to common behaviour, the global or root space is NOT
173
 * NOTE: contrary to common behaviour, the global or root space is NOT
178
 * designated by '/' but by '' (empty subkey). A '/' subkey will not
174
 * designated by '/' but by '' (empty subkey). A '/' subkey will not
179
 * be searched at all.
175
 * be searched at all.
180
 */
176
 */
181
class ConfTree : public ConfSimple {
177
class ConfTree : public ConfSimple {
182
183
    /* Dont want this to be accessible: keep only the string-based one */
184
    virtual const char *get(const char *, const char *) {return 0;}
185
178
186
 public:
179
 public:
187
    /**
180
    /**
188
     * Build the object by reading content from file.
181
     * Build the object by reading content from file.
189
     */
182
     */
...
...
206
    virtual int get(const char *name, string &value, const char *sk) {
199
    virtual int get(const char *name, string &value, const char *sk) {
207
    return get(string(name), value, sk ? string(sk) : string(""));
200
    return get(string(name), value, sk ? string(sk) : string(""));
208
    }
201
    }
209
};
202
};
210
203
204
/** 
205
 * Use several config files, trying to get values from each in order. Used to
206
 * have a central config, with possible overrides from more specific
207
 * (ie personal) ones.
208
 *
209
 * Notes: it's ok for some of the files in the list to not exist, but the last
210
 * one must or we generate an error. We open all trees readonly.
211
 */
212
template <class T> class ConfStack {
213
 public:
214
    ConfStack(const std::list<string> &fns, bool ro = true) {
215
  construct(fns, ro);
216
    }
217
218
    ConfStack(const char *nm, bool ro = true) {
219
  std::list<string> fns;
220
  fns.push_back(string(nm));
221
  construct(fns, ro);
222
    }
223
224
    ~ConfStack() {
225
  erase();
226
  m_ok = false;
227
    }
228
229
    ConfStack(const ConfStack &rhs) {
230
  init_from(rhs);
231
    }
232
233
    ConfStack& operator=(const ConfStack &rhs) {
234
  if (this != &rhs){
235
      erase();
236
      m_ok = rhs.m_ok;
237
      if (m_ok)
238
      init_from(rhs);
239
  }
240
  return *this;
241
    }
242
243
    int get(const std::string &name, string &value, const string &sk) {
244
  typename std::list<T*>::iterator it;
245
  for (it = m_confs.begin();it != m_confs.end();it++) {
246
      if ((*it)->get(name, value, sk))
247
      return true;
248
  }
249
  return false;
250
    }
251
252
    int get(const char *name, string &value, const char *sk) {
253
  return get(string(name), value, sk ? string(sk) : string(""));
254
    }
255
256
    std::list<string> getNames(const string &sk) {
257
  std::list<string> nms;
258
  typename std::list<T*>::iterator it;
259
  for (it = m_confs.begin();it != m_confs.end();it++) {
260
      std::list<string> lst;
261
      lst = (*it)->getNames(sk);
262
      nms.splice(nms.end(), lst);
263
  }
264
  return nms;
265
    }
266
267
    bool ok() {return m_ok;}
268
269
 private:
270
    bool m_ok;
271
    std::list<T*> m_confs;
272
    
273
    void erase() {
274
  typename std::list<T*>::iterator it;
275
  for (it = m_confs.begin();it != m_confs.end();it++) {
276
      delete (*it);
277
  }
278
  m_confs.clear();
279
    }
280
281
    /// Common code to initialize from existing object
282
    void init_from(const ConfStack &rhs) {
283
  if ((m_ok = rhs.m_ok)) {
284
      typename std::list<T*>::const_iterator it;
285
      for (it = rhs.m_confs.begin();it != rhs.m_confs.end();it++) {
286
      m_confs.push_back(new T(**it));
287
      }
288
  }
289
    }
290
291
    /// Common constructor code
292
    void construct(const std::list<string> &fns, bool ro) {
293
  if (!ro) {
294
      m_ok = false;
295
      return;
296
  }
297
  std::list<std::string>::const_iterator it;
298
  bool lastok = false;
299
  for (it = fns.begin();it != fns.end();it++) {
300
      T* p = new T(it->c_str(), true);
301
      if (p && p->ok()) {
302
      m_confs.push_back(p);
303
      lastok = true;
304
      } else
305
      lastok = false;
306
  }
307
  m_ok = lastok;
308
    }
309
};
310
211
#endif /*_CONFTREE_H_ */
311
#endif /*_CONFTREE_H_ */