config update enabling functions
This commit is contained in:
parent
2456f5a0a4
commit
569d96c43f
@ -1 +1 @@
|
|||||||
1.9.1cjk
|
1.9.1cjk1
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char rcsid[] = "@(#$Id: rclconfig.cpp,v 1.49 2007-06-22 06:14:04 dockes Exp $ (C) 2004 J.F.Dockes";
|
static char rcsid[] = "@(#$Id: rclconfig.cpp,v 1.50 2007-10-01 06:19:21 dockes Exp $ (C) 2004 J.F.Dockes";
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -107,7 +107,7 @@ RclConfig::RclConfig(const string *argcnf)
|
|||||||
cdirs.push_back(path_cat(m_datadir, "examples"));
|
cdirs.push_back(path_cat(m_datadir, "examples"));
|
||||||
string cnferrloc = m_confdir + " or " + path_cat(m_datadir, "examples");
|
string cnferrloc = m_confdir + " or " + path_cat(m_datadir, "examples");
|
||||||
|
|
||||||
m_conf = new ConfStack<ConfTree>("recoll.conf", cdirs, true);
|
m_conf = new ConfStack<ConfTree>("recoll.conf", cdirs, false);
|
||||||
if (m_conf == 0 || !m_conf->ok()) {
|
if (m_conf == 0 || !m_conf->ok()) {
|
||||||
m_reason = string("No/bad main configuration file in: ") + cnferrloc;
|
m_reason = string("No/bad main configuration file in: ") + cnferrloc;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef _RCLCONFIG_H_INCLUDED_
|
#ifndef _RCLCONFIG_H_INCLUDED_
|
||||||
#define _RCLCONFIG_H_INCLUDED_
|
#define _RCLCONFIG_H_INCLUDED_
|
||||||
/* @(#$Id: rclconfig.h,v 1.36 2007-06-22 06:14:04 dockes Exp $ (C) 2004 J.F.Dockes */
|
/* @(#$Id: rclconfig.h,v 1.37 2007-10-01 06:19:21 dockes Exp $ (C) 2004 J.F.Dockes */
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -63,6 +63,8 @@ class RclConfig {
|
|||||||
guesscharset = stringToBool(str);
|
guesscharset = stringToBool(str);
|
||||||
}
|
}
|
||||||
string getKeyDir() const {return m_keydir;}
|
string getKeyDir() const {return m_keydir;}
|
||||||
|
/** Get all defined key directories in configuration */
|
||||||
|
list<string> getKeyDirs() {return m_conf->getSubKeys();}
|
||||||
|
|
||||||
/** Get generic configuration parameter according to current keydir */
|
/** Get generic configuration parameter according to current keydir */
|
||||||
bool getConfParam(const string &name, string &value)
|
bool getConfParam(const string &name, string &value)
|
||||||
@ -71,6 +73,28 @@ class RclConfig {
|
|||||||
return false;
|
return false;
|
||||||
return m_conf->get(name, value, m_keydir);
|
return m_conf->get(name, value, m_keydir);
|
||||||
}
|
}
|
||||||
|
/** Set generic configuration parameter according to current keydir */
|
||||||
|
bool setConfParam(const string &name, const string &value)
|
||||||
|
{
|
||||||
|
if (m_conf == 0)
|
||||||
|
return false;
|
||||||
|
return m_conf->set(name, value, m_keydir);
|
||||||
|
}
|
||||||
|
/** Remove parameter from configuration */
|
||||||
|
bool eraseConfParam(const string &name)
|
||||||
|
{
|
||||||
|
if (m_conf == 0)
|
||||||
|
return false;
|
||||||
|
return m_conf->erase(name, m_keydir);
|
||||||
|
}
|
||||||
|
/** Remove parameter from configuration */
|
||||||
|
bool eraseKeyDir()
|
||||||
|
{
|
||||||
|
if (m_conf == 0)
|
||||||
|
return false;
|
||||||
|
return m_conf->eraseKey(m_keydir);
|
||||||
|
}
|
||||||
|
|
||||||
/** Variant with autoconversion to int */
|
/** Variant with autoconversion to int */
|
||||||
bool getConfParam(const std::string &name, int *value);
|
bool getConfParam(const std::string &name, int *value);
|
||||||
/** Variant with autoconversion to bool */
|
/** Variant with autoconversion to bool */
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char rcsid[] = "@(#$Id: confgui.cpp,v 1.3 2007-09-29 09:06:53 dockes Exp $ (C) 2005 J.F.Dockes";
|
static char rcsid[] = "@(#$Id: confgui.cpp,v 1.4 2007-10-01 06:19:21 dockes Exp $ (C) 2005 J.F.Dockes";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -415,6 +415,9 @@ void ConfParamDNLW::showInputDialog()
|
|||||||
if (m_lb->findItem(s, Qt::ExactMatch) == 0) {
|
if (m_lb->findItem(s, Qt::ExactMatch) == 0) {
|
||||||
m_lb->insertItem(s);
|
m_lb->insertItem(s);
|
||||||
m_lb->sort();
|
m_lb->sort();
|
||||||
|
QListBoxItem *item = m_lb->findItem(s, Qt::ExactMatch);
|
||||||
|
if (m_lb->selectionMode() == QListBox::Single && item)
|
||||||
|
m_lb->setSelected(item, true);
|
||||||
listToConf();
|
listToConf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char rcsid [] = "@(#$Id: conftree.cpp,v 1.11 2007-09-27 11:02:13 dockes Exp $ (C) 2003 J.F.Dockes";
|
static char rcsid [] = "@(#$Id: conftree.cpp,v 1.12 2007-10-01 06:19:21 dockes Exp $ (C) 2003 J.F.Dockes";
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -44,6 +44,13 @@ using std::list;
|
|||||||
#define MIN(A,B) ((A)<(B) ? (A) : (B))
|
#define MIN(A,B) ((A)<(B) ? (A) : (B))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//#define DEBUG
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define LOGDEB(X) fprintf X
|
||||||
|
#else
|
||||||
|
#define LOGDEB(X)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LL 1024
|
#define LL 1024
|
||||||
void ConfSimple::parseinput(istream &input)
|
void ConfSimple::parseinput(istream &input)
|
||||||
{
|
{
|
||||||
@ -54,7 +61,7 @@ void ConfSimple::parseinput(istream &input)
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
input.getline(cline, LL-1);
|
input.getline(cline, LL-1);
|
||||||
// fprintf(stderr, "Line: '%s' status %d\n", cline, int(status));
|
LOGDEB((stderr, "Parse:line: [%s] status %d\n", cline, int(status)));
|
||||||
if (!input.good()) {
|
if (!input.good()) {
|
||||||
if (input.bad()) {
|
if (input.bad()) {
|
||||||
status = STATUS_ERROR;
|
status = STATUS_ERROR;
|
||||||
@ -127,13 +134,13 @@ void ConfSimple::parseinput(istream &input)
|
|||||||
|
|
||||||
|
|
||||||
ConfSimple::ConfSimple(int readonly, bool tildexp)
|
ConfSimple::ConfSimple(int readonly, bool tildexp)
|
||||||
: dotildexpand(tildexp), m_data(0)
|
: dotildexpand(tildexp), m_data(0), m_holdWrites(false)
|
||||||
{
|
{
|
||||||
status = readonly ? STATUS_RO : STATUS_RW;
|
status = readonly ? STATUS_RO : STATUS_RW;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfSimple::ConfSimple(string *d, int readonly, bool tildexp)
|
ConfSimple::ConfSimple(string *d, int readonly, bool tildexp)
|
||||||
: dotildexpand(tildexp), m_data(d)
|
: dotildexpand(tildexp), m_data(d), m_holdWrites(false)
|
||||||
{
|
{
|
||||||
status = readonly ? STATUS_RO : STATUS_RW;
|
status = readonly ? STATUS_RO : STATUS_RW;
|
||||||
|
|
||||||
@ -142,7 +149,7 @@ ConfSimple::ConfSimple(string *d, int readonly, bool tildexp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ConfSimple::ConfSimple(const char *fname, int readonly, bool tildexp)
|
ConfSimple::ConfSimple(const char *fname, int readonly, bool tildexp)
|
||||||
: dotildexpand(tildexp), m_filename(fname), m_data(0)
|
: dotildexpand(tildexp), m_filename(fname), m_data(0), m_holdWrites(false)
|
||||||
{
|
{
|
||||||
status = readonly ? STATUS_RO : STATUS_RW;
|
status = readonly ? STATUS_RO : STATUS_RW;
|
||||||
|
|
||||||
@ -204,7 +211,7 @@ int ConfSimple::get(const string &nm, string &value, const string &sk)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Code to appropriately output a subkey (nm=="") or variable line
|
// Appropriately output a subkey (nm=="") or variable line.
|
||||||
// Splits long lines
|
// Splits long lines
|
||||||
static ConfSimple::WalkerCode varprinter(void *f, const string &nm,
|
static ConfSimple::WalkerCode varprinter(void *f, const string &nm,
|
||||||
const string &value)
|
const string &value)
|
||||||
@ -249,22 +256,34 @@ int ConfSimple::set(const std::string &nm, const std::string &value,
|
|||||||
int ConfSimple::i_set(const std::string &nm, const std::string &value,
|
int ConfSimple::i_set(const std::string &nm, const std::string &value,
|
||||||
const string &sk, bool init)
|
const string &sk, bool init)
|
||||||
{
|
{
|
||||||
|
LOGDEB((stderr, "ConfSimple::i_set: nm[%s] val[%s] key[%s], init %d\n",
|
||||||
|
nm.c_str(), value.c_str(), sk.c_str(), init));
|
||||||
// Values must not have embedded newlines
|
// Values must not have embedded newlines
|
||||||
if (value.find_first_of("\n\r") != string::npos) {
|
if (value.find_first_of("\n\r") != string::npos) {
|
||||||
|
LOGDEB((stderr, "ConfSimple::i_set: LF in value\n"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
bool existing = false;
|
bool existing = false;
|
||||||
map<string, map<string, string> >::iterator ss;
|
map<string, map<string, string> >::iterator ss;
|
||||||
|
// Test if submap already exists, else create it, and insert variable:
|
||||||
if ((ss = m_submaps.find(sk)) == m_submaps.end()) {
|
if ((ss = m_submaps.find(sk)) == m_submaps.end()) {
|
||||||
|
LOGDEB((stderr, "ConfSimple::i_set: new submap\n"));
|
||||||
map<string, string> submap;
|
map<string, string> submap;
|
||||||
submap[nm] = value;
|
submap[nm] = value;
|
||||||
m_submaps[sk] = submap;
|
m_submaps[sk] = submap;
|
||||||
if (!sk.empty())
|
|
||||||
m_order.push_back(ConfLine(ConfLine::CFL_SK, sk));
|
// Maybe add sk entry to m_order data:
|
||||||
// The var insert will be at the end, need not search for the
|
if (!sk.empty()) {
|
||||||
// right place
|
ConfLine nl(ConfLine::CFL_SK, sk);
|
||||||
init = true;
|
// Append SK entry only if it's not already there (erase
|
||||||
|
// does not remove entries from the order data, adn it may
|
||||||
|
// be being recreated after deletion)
|
||||||
|
if (find(m_order.begin(), m_order.end(), nl) == m_order.end()) {
|
||||||
|
m_order.push_back(nl);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Insert or update variable in existing map.
|
||||||
map<string, string>::iterator it;
|
map<string, string>::iterator it;
|
||||||
it = ss->second.find(nm);
|
it = ss->second.find(nm);
|
||||||
if (it == ss->second.end()) {
|
if (it == ss->second.end()) {
|
||||||
@ -275,21 +294,29 @@ int ConfSimple::i_set(const std::string &nm, const std::string &value,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the variable already existed, no need to change the order data
|
// If the variable already existed, no need to change the m_order data
|
||||||
if (existing)
|
if (existing) {
|
||||||
|
LOGDEB((stderr, "ConfSimple::i_set: existing var: no order update\n"));
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Add the new variable at the end of its submap in the order data.
|
// Add the new variable at the end of its submap in the order data.
|
||||||
|
|
||||||
if (init) {
|
if (init) {
|
||||||
// During the initial construction, insert at end
|
// During the initial construction, just append:
|
||||||
|
LOGDEB((stderr, "ConfSimple::i_set: init true: append\n"));
|
||||||
m_order.push_back(ConfLine(ConfLine::CFL_VAR, nm));
|
m_order.push_back(ConfLine(ConfLine::CFL_VAR, nm));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Look for the start and end of the subkey zone. Start is either
|
||||||
|
// at begin() for a null subkey, or just behind the subkey
|
||||||
|
// entry. End is either the next subkey entry, or the end of
|
||||||
|
// list. We insert the new entry just before end.
|
||||||
list<ConfLine>::iterator start, fin;
|
list<ConfLine>::iterator start, fin;
|
||||||
if (sk.empty()) {
|
if (sk.empty()) {
|
||||||
start = m_order.begin();
|
start = m_order.begin();
|
||||||
|
LOGDEB((stderr,"ConfSimple::i_set: null sk, start at top of order\n"));
|
||||||
} else {
|
} else {
|
||||||
start = find(m_order.begin(), m_order.end(),
|
start = find(m_order.begin(), m_order.end(),
|
||||||
ConfLine(ConfLine::CFL_SK, sk));
|
ConfLine(ConfLine::CFL_SK, sk));
|
||||||
@ -304,7 +331,9 @@ int ConfSimple::i_set(const std::string &nm, const std::string &value,
|
|||||||
|
|
||||||
fin = m_order.end();
|
fin = m_order.end();
|
||||||
if (start != m_order.end()) {
|
if (start != m_order.end()) {
|
||||||
start++;
|
// The null subkey has no entry (maybe it should)
|
||||||
|
if (!sk.empty())
|
||||||
|
start++;
|
||||||
for (list<ConfLine>::iterator it = start; it != m_order.end(); it++) {
|
for (list<ConfLine>::iterator it = start; it != m_order.end(); it++) {
|
||||||
if (it->m_kind == ConfLine::CFL_SK) {
|
if (it->m_kind == ConfLine::CFL_SK) {
|
||||||
fin = it;
|
fin = it;
|
||||||
@ -314,10 +343,10 @@ int ConfSimple::i_set(const std::string &nm, const std::string &value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// It may happen that the order entry already exists because erase doesnt
|
// It may happen that the order entry already exists because erase doesnt
|
||||||
// update m_order (fix it ?)
|
// update m_order
|
||||||
if (find(start, fin, ConfLine(ConfLine::CFL_VAR, nm)) == fin)
|
if (find(start, fin, ConfLine(ConfLine::CFL_VAR, nm)) == fin) {
|
||||||
m_order.insert(fin, ConfLine(ConfLine::CFL_VAR, nm));
|
m_order.insert(fin, ConfLine(ConfLine::CFL_VAR, nm));
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,10 +361,22 @@ int ConfSimple::erase(const string &nm, const string &sk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ss->second.erase(nm);
|
ss->second.erase(nm);
|
||||||
|
if (ss->second.empty()) {
|
||||||
|
m_submaps.erase(ss);
|
||||||
|
}
|
||||||
return write();
|
return write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ConfSimple::eraseKey(const string &sk)
|
||||||
|
{
|
||||||
|
list<string>nms = getNames(sk);
|
||||||
|
for (list<string>::iterator it = nms.begin(); it != nms.end(); it++) {
|
||||||
|
erase(*it, sk);
|
||||||
|
}
|
||||||
|
return write();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk the tree, calling user function at each node
|
||||||
ConfSimple::WalkerCode
|
ConfSimple::WalkerCode
|
||||||
ConfSimple::sortwalk(WalkerCode (*walker)(void *,const string&,const string&),
|
ConfSimple::sortwalk(WalkerCode (*walker)(void *,const string&,const string&),
|
||||||
void *clidata)
|
void *clidata)
|
||||||
@ -362,8 +403,13 @@ ConfSimple::sortwalk(WalkerCode (*walker)(void *,const string&,const string&),
|
|||||||
return WALK_CONTINUE;
|
return WALK_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write to default output:
|
||||||
bool ConfSimple::write()
|
bool ConfSimple::write()
|
||||||
{
|
{
|
||||||
|
if (!ok())
|
||||||
|
return false;
|
||||||
|
if (m_holdWrites)
|
||||||
|
return true;
|
||||||
if (m_filename.length()) {
|
if (m_filename.length()) {
|
||||||
ofstream output(m_filename.c_str(), ios::out|ios::trunc);
|
ofstream output(m_filename.c_str(), ios::out|ios::trunc);
|
||||||
if (!output.is_open())
|
if (!output.is_open())
|
||||||
@ -378,6 +424,9 @@ bool ConfSimple::write()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write out the tree in configuration file format:
|
||||||
|
// This does not check holdWrites, this is done by write(void), which
|
||||||
|
// lets ie: listall work even when holdWrites is set
|
||||||
bool ConfSimple::write(ostream& out)
|
bool ConfSimple::write(ostream& out)
|
||||||
{
|
{
|
||||||
if (!ok())
|
if (!ok())
|
||||||
@ -393,19 +442,34 @@ bool ConfSimple::write(ostream& out)
|
|||||||
break;
|
break;
|
||||||
case ConfLine::CFL_SK:
|
case ConfLine::CFL_SK:
|
||||||
sk = it->m_data;
|
sk = it->m_data;
|
||||||
out << "[" << it->m_data << "]" << endl;
|
LOGDEB((stderr, "ConfSimple::write: SK [%s]\n", sk.c_str()));
|
||||||
if (!out.good())
|
// Check that the submap still exists, and only output it if it
|
||||||
return false;
|
// does
|
||||||
break;
|
if (m_submaps.find(sk) != m_submaps.end()) {
|
||||||
case ConfLine::CFL_VAR:
|
out << "[" << it->m_data << "]" << endl;
|
||||||
string value;
|
|
||||||
// As erase() doesnt update m_order we can find unexisting
|
|
||||||
// variables, and must not output anything for them
|
|
||||||
if (get(it->m_data, value, sk)) {
|
|
||||||
varprinter(&out, it->m_data, value);
|
|
||||||
if (!out.good())
|
if (!out.good())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case ConfLine::CFL_VAR:
|
||||||
|
string nm = it->m_data;
|
||||||
|
LOGDEB((stderr, "ConfSimple::write: VAR [%s], sk [%s]\n",
|
||||||
|
nm.c_str(), sk.c_str()));
|
||||||
|
// As erase() doesnt update m_order we can find unexisting
|
||||||
|
// variables, and must not output anything for them. Have
|
||||||
|
// to use a ConfSimple::get() to check here, because
|
||||||
|
// ConfTree's could retrieve from an ancestor even if the
|
||||||
|
// local var is gone.
|
||||||
|
string value;
|
||||||
|
if (ConfSimple::get(nm, value, sk)) {
|
||||||
|
varprinter(&out, nm, value);
|
||||||
|
if (!out.good())
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LOGDEB((stderr, "ConfSimple::write: no value: nm[%s] sk[%s]\n",
|
||||||
|
nm.c_str(), sk.c_str()));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -455,7 +519,7 @@ list<string> ConfSimple::getSubKeys()
|
|||||||
int ConfTree::get(const std::string &name, string &value, const string &sk)
|
int ConfTree::get(const std::string &name, string &value, const string &sk)
|
||||||
{
|
{
|
||||||
if (sk.empty() || sk[0] != '/') {
|
if (sk.empty() || sk[0] != '/') {
|
||||||
// fprintf(stderr, "Looking in global space");
|
// LOGDEB((stderr, "ConfTree::get: looking in global space\n"));
|
||||||
return ConfSimple::get(name, value, sk);
|
return ConfSimple::get(name, value, sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,8 +532,8 @@ int ConfTree::get(const std::string &name, string &value, const string &sk)
|
|||||||
|
|
||||||
// Look in subkey and up its parents until root ('')
|
// Look in subkey and up its parents until root ('')
|
||||||
for (;;) {
|
for (;;) {
|
||||||
//fprintf(stderr,"Looking for '%s' in '%s'\n",
|
// LOGDEB((stderr,"ConfTree::get: looking for '%s' in '%s'\n",
|
||||||
//name.c_str(), msk.c_str());
|
// name.c_str(), msk.c_str()));
|
||||||
if (ConfSimple::get(name, value, msk))
|
if (ConfSimple::get(name, value, msk))
|
||||||
return 1;
|
return 1;
|
||||||
string::size_type pos = msk.rfind("/");
|
string::size_type pos = msk.rfind("/");
|
||||||
@ -600,6 +664,20 @@ bool erase(ConfNull *conf, const string& nm, const string& sub)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool eraseKey(ConfNull *conf, const string& sub)
|
||||||
|
{
|
||||||
|
if (!conf->ok()) {
|
||||||
|
cerr << "Error opening or parsing file\n" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conf->eraseKey(sub)) {
|
||||||
|
cerr << "delete key [" << sub << "] failed" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool setvar(ConfNull *conf, const string& nm, const string& value,
|
bool setvar(ConfNull *conf, const string& nm, const string& value,
|
||||||
const string& sub)
|
const string& sub)
|
||||||
{
|
{
|
||||||
@ -618,9 +696,10 @@ static char usage [] =
|
|||||||
"testconftree [opts] filename\n"
|
"testconftree [opts] filename\n"
|
||||||
"[-w] : read/write test.\n"
|
"[-w] : read/write test.\n"
|
||||||
"[-s] : string parsing test. Filename must hold parm 'strings'\n"
|
"[-s] : string parsing test. Filename must hold parm 'strings'\n"
|
||||||
"[-a] nm value sect : add/set nm,value in 'sect' which can be ''\n"
|
"-a nm value sect : add/set nm,value in 'sect' which can be ''\n"
|
||||||
"[-q] nm sect : subsection test: look for nm in 'sect' which can be ''\n"
|
"-q nm sect : subsection test: look for nm in 'sect' which can be ''\n"
|
||||||
"[-d] nm sect : delete nm in 'sect' which can be ''\n"
|
"-d nm sect : delete nm in 'sect' which can be ''\n"
|
||||||
|
"-E sect : erase key (and all its names)\n"
|
||||||
"[-S] : string io test. No filename in this case\n"
|
"[-S] : string io test. No filename in this case\n"
|
||||||
"[-V] : volatile config test. No filename in this case\n"
|
"[-V] : volatile config test. No filename in this case\n"
|
||||||
;
|
;
|
||||||
@ -639,6 +718,7 @@ static int op_flags;
|
|||||||
#define OPT_V 0x40
|
#define OPT_V 0x40
|
||||||
#define OPT_a 0x80
|
#define OPT_a 0x80
|
||||||
#define OPT_k 0x100
|
#define OPT_k 0x100
|
||||||
|
#define OPT_E 0x200
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -656,13 +736,6 @@ int main(int argc, char **argv)
|
|||||||
Usage();
|
Usage();
|
||||||
while (**argv)
|
while (**argv)
|
||||||
switch (*(*argv)++) {
|
switch (*(*argv)++) {
|
||||||
case 'd':
|
|
||||||
op_flags |= OPT_d;
|
|
||||||
if (argc < 3)
|
|
||||||
Usage();
|
|
||||||
nm = *(++argv);argc--;
|
|
||||||
sub = *(++argv);argc--;
|
|
||||||
goto b1;
|
|
||||||
case 'a':
|
case 'a':
|
||||||
op_flags |= OPT_a;
|
op_flags |= OPT_a;
|
||||||
if (argc < 4)
|
if (argc < 4)
|
||||||
@ -671,6 +744,20 @@ int main(int argc, char **argv)
|
|||||||
value = *(++argv);argc--;
|
value = *(++argv);argc--;
|
||||||
sub = *(++argv);argc--;
|
sub = *(++argv);argc--;
|
||||||
goto b1;
|
goto b1;
|
||||||
|
case 'd':
|
||||||
|
op_flags |= OPT_d;
|
||||||
|
if (argc < 3)
|
||||||
|
Usage();
|
||||||
|
nm = *(++argv);argc--;
|
||||||
|
sub = *(++argv);argc--;
|
||||||
|
goto b1;
|
||||||
|
case 'E':
|
||||||
|
op_flags |= OPT_E;
|
||||||
|
if (argc < 2)
|
||||||
|
Usage();
|
||||||
|
sub = *(++argv);argc--;
|
||||||
|
goto b1;
|
||||||
|
case 'k': op_flags |= OPT_k; break;
|
||||||
case 'q':
|
case 'q':
|
||||||
op_flags |= OPT_q;
|
op_flags |= OPT_q;
|
||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
@ -679,7 +766,6 @@ int main(int argc, char **argv)
|
|||||||
sub = *(++argv);argc--;
|
sub = *(++argv);argc--;
|
||||||
goto b1;
|
goto b1;
|
||||||
case 's': op_flags |= OPT_s; break;
|
case 's': op_flags |= OPT_s; break;
|
||||||
case 'k': op_flags |= OPT_k; break;
|
|
||||||
case 'S': op_flags |= OPT_S; break;
|
case 'S': op_flags |= OPT_S; break;
|
||||||
case 'V': op_flags |= OPT_S; break;
|
case 'V': op_flags |= OPT_S; break;
|
||||||
case 'w': op_flags |= OPT_w; break;
|
case 'w': op_flags |= OPT_w; break;
|
||||||
@ -714,7 +800,7 @@ int main(int argc, char **argv)
|
|||||||
while (argc--) {
|
while (argc--) {
|
||||||
flist.push_back(*argv++);
|
flist.push_back(*argv++);
|
||||||
}
|
}
|
||||||
bool ro = !(op_flags & (OPT_w|OPT_a|OPT_d));
|
bool ro = !(op_flags & (OPT_w|OPT_a|OPT_d|OPT_E));
|
||||||
ConfNull *conf = 0;
|
ConfNull *conf = 0;
|
||||||
switch (flist.size()) {
|
switch (flist.size()) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -747,6 +833,8 @@ int main(int argc, char **argv)
|
|||||||
exit(!setvar(conf, nm, value, sub));
|
exit(!setvar(conf, nm, value, sub));
|
||||||
} else if (op_flags & OPT_d) {
|
} else if (op_flags & OPT_d) {
|
||||||
exit(!erase(conf, nm, sub));
|
exit(!erase(conf, nm, sub));
|
||||||
|
} else if (op_flags & OPT_E) {
|
||||||
|
exit(!eraseKey(conf, sub));
|
||||||
} else if (op_flags & OPT_s) {
|
} else if (op_flags & OPT_s) {
|
||||||
if (!conf->ok()) {
|
if (!conf->ok()) {
|
||||||
cerr << "Cant open /parse conf file " << endl;
|
cerr << "Cant open /parse conf file " << endl;
|
||||||
|
|||||||
@ -85,7 +85,6 @@ public:
|
|||||||
{
|
{
|
||||||
return o.m_kind == m_kind && o.m_data == m_data;
|
return o.m_kind == m_kind && o.m_data == m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,8 +101,10 @@ public:
|
|||||||
virtual bool ok() = 0;
|
virtual bool ok() = 0;
|
||||||
virtual list<string> getNames(const string &sk) = 0;
|
virtual list<string> getNames(const string &sk) = 0;
|
||||||
virtual int erase(const string &, const string &) {return 0;}
|
virtual int erase(const string &, const string &) {return 0;}
|
||||||
|
virtual int eraseKey(const string &) {return 0;}
|
||||||
virtual void listall() {}
|
virtual void listall() {}
|
||||||
virtual list<string> getSubKeys() = 0;
|
virtual list<string> getSubKeys() = 0;
|
||||||
|
virtual bool holdWrites(bool) {return true;}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,13 +138,24 @@ public:
|
|||||||
|
|
||||||
virtual ~ConfSimple() {};
|
virtual ~ConfSimple() {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decide if we actually rewrite the backing-store after modifying the
|
||||||
|
* tree. (Re-)Enabling writes causes a flush.
|
||||||
|
*/
|
||||||
|
virtual bool holdWrites(bool on)
|
||||||
|
{
|
||||||
|
m_holdWrites = on;
|
||||||
|
if (m_holdWrites == false)
|
||||||
|
return write();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get value for named parameter, from specified subsection (looks in
|
* Get value for named parameter, from specified subsection (looks in
|
||||||
* global space if sk is empty).
|
* global space if sk is empty).
|
||||||
* @return 0 if name not found, 1 else
|
* @return 0 if name not found, 1 else
|
||||||
*/
|
*/
|
||||||
virtual int get(const string &name, string &value, const string &sk = "");
|
virtual int get(const string &name, string &value, const string &sk = "");
|
||||||
/* Note: the version returning char* was buggy and has been removed */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set value for named parameter in specified subsection (or global)
|
* Set value for named parameter in specified subsection (or global)
|
||||||
@ -156,6 +168,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual int erase(const string &name, const string &sk);
|
virtual int erase(const string &name, const string &sk);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erase all names under given subkey (and subkey itself)
|
||||||
|
*/
|
||||||
|
virtual int eraseKey(const string &sk);
|
||||||
|
|
||||||
virtual StatusCode getStatus();
|
virtual StatusCode getStatus();
|
||||||
virtual bool ok() {return getStatus() != STATUS_ERROR;}
|
virtual bool ok() {return getStatus() != STATUS_ERROR;}
|
||||||
|
|
||||||
@ -171,6 +188,8 @@ public:
|
|||||||
(*wlkr)(void *cldata, const string &nm,
|
(*wlkr)(void *cldata, const string &nm,
|
||||||
const string &val),
|
const string &val),
|
||||||
void *clidata);
|
void *clidata);
|
||||||
|
|
||||||
|
/** List all values to stdout */
|
||||||
virtual void listall();
|
virtual void listall();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -228,6 +247,8 @@ private:
|
|||||||
// variable and subkey ordering information in there (for
|
// variable and subkey ordering information in there (for
|
||||||
// rewriting the file while keeping hand-edited information)
|
// rewriting the file while keeping hand-edited information)
|
||||||
list<ConfLine> m_order;
|
list<ConfLine> m_order;
|
||||||
|
// Control if we're writing to the backing store
|
||||||
|
bool m_holdWrites;
|
||||||
|
|
||||||
void parseinput(istream& input);
|
void parseinput(istream& input);
|
||||||
bool write();
|
bool write();
|
||||||
@ -254,11 +275,14 @@ private:
|
|||||||
class ConfTree : public ConfSimple {
|
class ConfTree : public ConfSimple {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/* The constructors just call ConfSimple's, asking for key tilde
|
||||||
* Build the object by reading content from file.
|
* expansion */
|
||||||
*/
|
|
||||||
ConfTree(const char *fname, int readonly = 0)
|
ConfTree(const char *fname, int readonly = 0)
|
||||||
: ConfSimple(fname, readonly, true) {}
|
: ConfSimple(fname, readonly, true) {}
|
||||||
|
ConfTree(string *data, int readonly = 0)
|
||||||
|
: ConfSimple(data, readonly, true) {}
|
||||||
|
ConfTree(int readonly = 0)
|
||||||
|
: ConfSimple(readonly, true) {}
|
||||||
virtual ~ConfTree() {};
|
virtual ~ConfTree() {};
|
||||||
ConfTree(const ConfTree& r) : ConfSimple(r) {};
|
ConfTree(const ConfTree& r) : ConfSimple(r) {};
|
||||||
ConfTree& operator=(const ConfTree& r) {
|
ConfTree& operator=(const ConfTree& r) {
|
||||||
@ -282,13 +306,14 @@ public:
|
|||||||
* Notes: it's ok for some of the files in the list to not exist, but the last
|
* Notes: it's ok for some of the files in the list to not exist, but the last
|
||||||
* one must or we generate an error. We open all trees readonly, except the
|
* one must or we generate an error. We open all trees readonly, except the
|
||||||
* topmost one if requested. All writes go to the topmost file. Note that
|
* topmost one if requested. All writes go to the topmost file. Note that
|
||||||
* erase() won't work.
|
* erase() won't work except for parameters only defined in the topmost
|
||||||
|
* file (it erases only from there).
|
||||||
*/
|
*/
|
||||||
template <class T> class ConfStack : public ConfNull {
|
template <class T> class ConfStack : public ConfNull {
|
||||||
public:
|
public:
|
||||||
/// Construct from list of configuration file names. The earler files in
|
/// Construct from list of configuration file names. The earler
|
||||||
/// have priority when fetching values. Only the first file will be updated
|
/// files in have priority when fetching values. Only the first
|
||||||
/// if ro is false and set() is used.
|
/// file will be updated if ro is false and set() is used.
|
||||||
ConfStack(const list<string> &fns, bool ro = true)
|
ConfStack(const list<string> &fns, bool ro = true)
|
||||||
{
|
{
|
||||||
construct(fns, ro);
|
construct(fns, ro);
|
||||||
@ -366,6 +391,19 @@ public:
|
|||||||
return m_confs.front()->set(nm, val, sk);
|
return m_confs.front()->set(nm, val, sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int erase(const string &nm, const string &sk)
|
||||||
|
{
|
||||||
|
return m_confs.front()->erase(nm, sk);
|
||||||
|
}
|
||||||
|
virtual int eraseKey(const string &sk)
|
||||||
|
{
|
||||||
|
return m_confs.front()->eraseKey(sk);
|
||||||
|
}
|
||||||
|
virtual bool holdWrites(bool on)
|
||||||
|
{
|
||||||
|
return m_confs.front()->holdWrites(on);
|
||||||
|
}
|
||||||
|
|
||||||
virtual list<string> getNames(const string &sk)
|
virtual list<string> getNames(const string &sk)
|
||||||
{
|
{
|
||||||
list<string> nms;
|
list<string> nms;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user