From 414222c003a025d33e2eb33545b1091a87cac1ba Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Mon, 2 Dec 2019 09:37:34 +0100 Subject: [PATCH] use conftree conversions --- src/common/rclconfig.cpp | 19 +- src/index/idxstatus.cpp | 18 +- src/qtgui/spell_w.cpp | 8 +- src/rcldb/rclquery.cpp | 1 - src/testmains/Makefile.am | 6 +- src/testmains/trcircache.cpp | 245 ++++++++++++++++++++++ src/utils/circache.cpp | 396 +++++++---------------------------- src/utils/conftree.cpp | 151 +++++++------ src/utils/conftree.h | 65 +++--- 9 files changed, 456 insertions(+), 453 deletions(-) create mode 100644 src/testmains/trcircache.cpp diff --git a/src/common/rclconfig.cpp b/src/common/rclconfig.cpp index 3612ddc0..09e60028 100644 --- a/src/common/rclconfig.cpp +++ b/src/common/rclconfig.cpp @@ -970,15 +970,10 @@ bool RclConfig::readFieldsConfig(const string& cnferrloc) "]: [" << val << "]\n"); return 0; } - string tval; - if (attrs.get("wdfinc", tval)) - ft.wdfinc = atoi(tval.c_str()); - if (attrs.get("boost", tval)) - ft.boost = atof(tval.c_str()); - if (attrs.get("pfxonly", tval)) - ft.pfxonly = stringToBool(tval); - if (attrs.get("noterms", tval)) - ft.noterms = stringToBool(tval); + ft.wdfinc = attrs.getInt("wdfinc", 1); + ft.boost = attrs.getFloat("boost", 1.0); + ft.pfxonly = attrs.getBool("pfxonly", false); + ft.noterms = attrs.getBool("noterms", false); m_fldtotraits[stringtolower(fieldname)] = ft; LOGDEB2("readFieldsConfig: [" << fieldname << "] -> [" << ft.pfx << "] " << ft.wdfinc << " " << ft.boost << "\n"); @@ -1018,11 +1013,7 @@ bool RclConfig::readFieldsConfig(const string& cnferrloc) return 0; } } - int valuelen{0}; - if (attrs.get("len", tval)) { - valuelen = atoi(tval.c_str()); - } - + int valuelen = attrs.getInt("len", 0); // Find or insert traits entry const auto pit = m_fldtotraits.insert( diff --git a/src/index/idxstatus.cpp b/src/index/idxstatus.cpp index 9e04692e..d798b122 100644 --- a/src/index/idxstatus.cpp +++ b/src/index/idxstatus.cpp @@ -24,16 +24,12 @@ void readIdxStatus(RclConfig *config, DbIxStatus &status) { ConfSimple cs(config->getIdxStatusFile().c_str(), 1); - string val; - cs.get("phase", val); - status.phase = DbIxStatus::Phase(atoi(val.c_str())); + status.phase = DbIxStatus::Phase(cs.getInt("phase", 0)); cs.get("fn", status.fn); - cs.get("docsdone", &status.docsdone); - cs.get("filesdone", &status.filesdone); - cs.get("fileerrors", &status.fileerrors); - cs.get("dbtotdocs", &status.dbtotdocs); - cs.get("totfiles", &status.totfiles); - string shm("0"); - cs.get("hasmonitor", shm); - status.hasmonitor = stringToBool(shm); + status.docsdone = cs.getInt("docsdone", 0); + status.filesdone = cs.getInt("filesdone", 0); + status.fileerrors = cs.getInt("fileerrors", 0); + status.dbtotdocs = cs.getInt("dbtotdocs", 0); + status.totfiles = cs.getInt("totfiles", 0); + status.hasmonitor = cs.getBool("hasmonitor", false); } diff --git a/src/qtgui/spell_w.cpp b/src/qtgui/spell_w.cpp index 80b5e358..7fb824b2 100644 --- a/src/qtgui/spell_w.cpp +++ b/src/qtgui/spell_w.cpp @@ -289,14 +289,8 @@ void SpellW::showStats() if (!theconfig) return; - ConfSimple cs(theconfig->getIdxStatusFile().c_str(), 1); DbIxStatus st; - cs.get("fn", st.fn); - cs.get("docsdone", &st.docsdone); - cs.get("filesdone", &st.filesdone); - cs.get("fileerrors", &st.fileerrors); - cs.get("dbtotdocs", &st.dbtotdocs); - cs.get("totfiles", &st.totfiles); + readIdxStatus(theconfig, st); resTW->setRowCount(row+1); resTW->setItem(row, 0, diff --git a/src/rcldb/rclquery.cpp b/src/rcldb/rclquery.cpp index 9052853c..4f5eecd3 100644 --- a/src/rcldb/rclquery.cpp +++ b/src/rcldb/rclquery.cpp @@ -32,7 +32,6 @@ #include "rcldb_p.h" #include "rclquery.h" #include "rclquery_p.h" -#include "conftree.h" #include "smallut.h" #include "chrono.h" #include "searchdata.h" diff --git a/src/testmains/Makefile.am b/src/testmains/Makefile.am index fb3f79d3..b54e16be 100644 --- a/src/testmains/Makefile.am +++ b/src/testmains/Makefile.am @@ -37,7 +37,8 @@ AM_CPPFLAGS = -Wall -Wno-unused -std=c++11 \ -D_GNU_SOURCE \ $(DEFS) -noinst_PROGRAMS = textsplit utf8iter fstreewalk rclconfig hldata unac mbox +noinst_PROGRAMS = textsplit utf8iter fstreewalk rclconfig hldata unac mbox \ + circache textsplit_SOURCES = trtextsplit.cpp textsplit_LDADD = ../librecoll.la @@ -59,3 +60,6 @@ unac_LDADD = ../librecoll.la mbox_SOURCES = trmbox.cpp mbox_LDADD = ../librecoll.la + +circache_SOURCES = trcircache.cpp +circache_LDADD = ../librecoll.la diff --git a/src/testmains/trcircache.cpp b/src/testmains/trcircache.cpp new file mode 100644 index 00000000..58c71729 --- /dev/null +++ b/src/testmains/trcircache.cpp @@ -0,0 +1,245 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "circache.h" +#include "fileudi.h" +#include "conftree.h" +#include "readfile.h" +#include "log.h" + +#include "smallut.h" + +using namespace std; + +static char *thisprog; + +static char usage [] = + " -c [-u] : create\n" + " -p [apath ...] : put files\n" + " -d : dump\n" + " -g [-i instance] [-D] : get\n" + " -D: also dump data\n" + " -e : erase\n" + " -a [ ...]: append old content to target\n" + " The target should be first resized to hold all the data, else only\n" + " as many entries as capacity permit will be retained\n" + ; + +static void +Usage(FILE *fp = stderr) +{ + fprintf(fp, "%s: usage:\n%s", thisprog, usage); + exit(1); +} + +static int op_flags; +#define OPT_MOINS 0x1 +#define OPT_c 0x2 +#define OPT_p 0x8 +#define OPT_g 0x10 +#define OPT_d 0x20 +#define OPT_i 0x40 +#define OPT_D 0x80 +#define OPT_u 0x100 +#define OPT_e 0x200 +#define OPT_a 0x800 + +int main(int argc, char **argv) +{ + int instance = -1; + + thisprog = argv[0]; + argc--; + argv++; + + while (argc > 0 && **argv == '-') { + (*argv)++; + if (!(**argv)) + /* Cas du "adb - core" */ + { + Usage(); + } + while (**argv) + switch (*(*argv)++) { + case 'a': + op_flags |= OPT_a; + break; + case 'c': + op_flags |= OPT_c; + break; + case 'D': + op_flags |= OPT_D; + break; + case 'd': + op_flags |= OPT_d; + break; + case 'e': + op_flags |= OPT_e; + break; + case 'g': + op_flags |= OPT_g; + break; + case 'i': + op_flags |= OPT_i; + if (argc < 2) { + Usage(); + } + if ((sscanf(*(++argv), "%d", &instance)) != 1) { + Usage(); + } + argc--; + goto b1; + case 'p': + op_flags |= OPT_p; + break; + case 'u': + op_flags |= OPT_u; + break; + default: + Usage(); + break; + } +b1: + argc--; + argv++; + } + + Logger::getTheLog("")->setLogLevel(Logger::LLDEB1); + + if (argc < 1) { + Usage(); + } + string dir = *argv++; + argc--; + + CirCache cc(dir); + + if (op_flags & OPT_c) { + if (argc != 1) { + Usage(); + } + int64_t sizekb = atoi(*argv++); + argc--; + int flags = 0; + if (op_flags & OPT_u) { + flags |= CirCache::CC_CRUNIQUE; + } + if (!cc.create(sizekb * 1024, flags)) { + cerr << "Create failed:" << cc.getReason() << endl; + exit(1); + } + } else if (op_flags & OPT_a) { + if (argc < 1) { + Usage(); + } + while (argc) { + string reason; + if (CirCache::append(dir, *argv++, &reason) < 0) { + cerr << reason << endl; + return 1; + } + argc--; + } + } else if (op_flags & OPT_p) { + if (argc < 1) { + Usage(); + } + if (!cc.open(CirCache::CC_OPWRITE)) { + cerr << "Open failed: " << cc.getReason() << endl; + exit(1); + } + while (argc) { + string fn = *argv++; + argc--; + char dic[1000]; + string data, reason; + if (!file_to_string(fn, data, &reason)) { + cerr << "File_to_string: " << reason << endl; + exit(1); + } + string udi; + make_udi(fn, "", udi); + string cmd("xdg-mime query filetype "); + // Should do more quoting here... + cmd += "'" + fn + "'"; + FILE *fp = popen(cmd.c_str(), "r"); + char* buf=0; + size_t sz = 0; + if (::getline(&buf, &sz, fp) -1) { + cerr << "Could not read from xdg-mime output\n"; + exit(1); + } + pclose(fp); + string mimetype(buf); + free(buf); + trimstring(mimetype, "\n\r"); + cout << "Got [" << mimetype << "]\n"; + + string s; + ConfSimple conf(s); + conf.set("udi", udi); + conf.set("mimetype", mimetype); + //ostringstream str; conf.write(str); cout << str.str() << endl; + + if (!cc.put(udi, &conf, data, 0)) { + cerr << "Put failed: " << cc.getReason() << endl; + cerr << "conf: ["; + conf.write(cerr); + cerr << "]" << endl; + exit(1); + } + } + cc.open(CirCache::CC_OPREAD); + } else if (op_flags & OPT_g) { + if (!cc.open(CirCache::CC_OPREAD)) { + cerr << "Open failed: " << cc.getReason() << endl; + exit(1); + } + while (argc) { + string udi = *argv++; + argc--; + string dic, data; + if (!cc.get(udi, dic, &data, instance)) { + cerr << "Get failed: " << cc.getReason() << endl; + exit(1); + } + cout << "Dict: [" << dic << "]" << endl; + if (op_flags & OPT_D) { + cout << "Data: [" << data << "]" << endl; + } + } + } else if (op_flags & OPT_e) { + if (!cc.open(CirCache::CC_OPWRITE)) { + cerr << "Open failed: " << cc.getReason() << endl; + exit(1); + } + while (argc) { + string udi = *argv++; + argc--; + string dic, data; + if (!cc.erase(udi)) { + cerr << "Erase failed: " << cc.getReason() << endl; + exit(1); + } + } + } else if (op_flags & OPT_d) { + if (!cc.open(CirCache::CC_OPREAD)) { + cerr << "Open failed: " << cc.getReason() << endl; + exit(1); + } + cc.dump(); + } else { + Usage(); + } + + exit(0); +} diff --git a/src/utils/circache.cpp b/src/utils/circache.cpp index 371c307f..bbb35eb4 100644 --- a/src/utils/circache.cpp +++ b/src/utils/circache.cpp @@ -15,7 +15,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef TEST_CIRCACHE #include "autoconfig.h" #include "circache.h" @@ -235,13 +234,15 @@ public: bool khEnter(const string& udi, int64_t ofs) { UdiH h(udi); - LOGDEB2("Circache::khEnter: h " << h.asHexString() << " offs " << ofs << " udi [" << udi << "]\n"); + LOGDEB2("Circache::khEnter: h " << h.asHexString() << " offs " << + ofs << " udi [" << udi << "]\n"); pair p = m_ofskh.equal_range(h); if (p.first != m_ofskh.end() && p.first->first == h) { for (kh_type::iterator it = p.first; it != p.second; it++) { - LOGDEB2("Circache::khEnter: col h " << it->first.asHexString() << ", ofs " << it->second << "\n"); + LOGDEB2("Circache::khEnter: col h " << it->first.asHexString() << + ", ofs " << it->second << "\n"); if (it->second == ofs) { // (h,offs) already there. Happens LOGDEB2("Circache::khEnter: already there\n"); @@ -255,8 +256,9 @@ public: } void khDump() { for (kh_type::const_iterator it = m_ofskh.begin(); - it != m_ofskh.end(); it++) { - LOGDEB("Circache::KHDUMP: " << it->first.asHexString() << " " << it->second << "\n"); + it != m_ofskh.end(); it++) { + LOGDEB("Circache::KHDUMP: " << it->first.asHexString() << " " << + it->second << "\n"); } } @@ -268,7 +270,8 @@ public: UdiH h(udi); - LOGDEB2("Circache::khFind: h " << h.asHexString() << " udi [" << udi << "]\n"); + LOGDEB2("Circache::khFind: h " << h.asHexString() << " udi [" << udi << + "]\n"); pair p = m_ofskh.equal_range(h); @@ -280,7 +283,8 @@ public: LOGDEB("KHFIND: SECOND END()\n"); } if (!(p.first->first == h)) - LOGDEB("KHFIND: NOKEY: " << p.first->first.asHexString() << " " << p.second->first.asHexString() << "\n"); + LOGDEB("KHFIND: NOKEY: " << p.first->first.asHexString() << " " << + p.second->first.asHexString() << "\n"); #endif if (p.first == m_ofskh.end() || !(p.first->first == h)) { @@ -309,7 +313,7 @@ public: // Clear entries for vector of udi/offs bool khClear(const vector >& udis) { for (vector >::const_iterator it = udis.begin(); - it != udis.end(); it++) { + it != udis.end(); it++) { khClear(*it); } return true; @@ -367,15 +371,15 @@ public: ostringstream s; s << - "maxsize = " << m_maxsize << "\n" << - "oheadoffs = " << m_oheadoffs << "\n" << - "nheadoffs = " << m_nheadoffs << "\n" << - "npadsize = " << m_npadsize << "\n" << - "unient = " << m_uniquentries << "\n" << - " " << - " " << - " " << - "\0"; + "maxsize = " << m_maxsize << "\n" << + "oheadoffs = " << m_oheadoffs << "\n" << + "nheadoffs = " << m_nheadoffs << "\n" << + "npadsize = " << m_npadsize << "\n" << + "unient = " << m_uniquentries << "\n" << + " " << + " " << + " " << + "\0"; int sz = int(s.str().size()); assert(sz < CIRCACHE_FIRSTBLOCK_SIZE); @@ -397,38 +401,33 @@ public: lseek(m_fd, 0, 0); if (read(m_fd, bf, CIRCACHE_FIRSTBLOCK_SIZE) != - CIRCACHE_FIRSTBLOCK_SIZE) { + CIRCACHE_FIRSTBLOCK_SIZE) { m_reason << "readfirstblock: read() failed: errno " << errno; return false; } string s(bf, CIRCACHE_FIRSTBLOCK_SIZE); ConfSimple conf(s, 1); - string value; - if (!conf.get("maxsize", value, cstr_null)) { + m_maxsize = conf.getInt("maxsize", -1); + if (m_maxsize == -1) { m_reason << "readfirstblock: conf get maxsize failed"; return false; } - m_maxsize = atoll(value.c_str()); - if (!conf.get("oheadoffs", value, cstr_null)) { + m_oheadoffs = conf.getInt("oheadoffs", -1); + if (m_oheadoffs == -1) { m_reason << "readfirstblock: conf get oheadoffs failed"; return false; } - m_oheadoffs = atoll(value.c_str()); - if (!conf.get("nheadoffs", value, cstr_null)) { + m_nheadoffs = conf.getInt("nheadoffs", -1); + if (m_nheadoffs == -1) { m_reason << "readfirstblock: conf get nheadoffs failed"; return false; } - m_nheadoffs = atoll(value.c_str()); - if (!conf.get("npadsize", value, cstr_null)) { + m_npadsize = conf.getInt("npadsize", -1); + if (m_npadsize == -1) { m_reason << "readfirstblock: conf get npadsize failed"; return false; } - m_npadsize = atoll(value.c_str()); - if (!conf.get("unient", value, cstr_null)) { - m_uniquentries = false; - } else { - m_uniquentries = stringToBool(value); - } + m_uniquentries = conf.getBool("unient", false); return true; } @@ -444,7 +443,7 @@ public: headerformat, d.dicsize, d.datasize, d.padsize, d.flags); if (lseek(m_fd, offset, 0) != offset) { m_reason << "CirCache::weh: lseek(" << offset << - ") failed: errno " << errno; + ") failed: errno " << errno; return false; } if (write(m_fd, bf, CIRCACHE_HEADER_SIZE) != CIRCACHE_HEADER_SIZE) { @@ -473,7 +472,7 @@ public: if (lseek(m_fd, offset, 0) != offset) { m_reason << "readEntryHeader: lseek(" << offset << - ") failed: errno " << errno; + ") failed: errno " << errno; return CCScanHook::Error; } char bf[CIRCACHE_HEADER_SIZE]; @@ -491,11 +490,11 @@ public: if (sscanf(bf, headerformat, &d.dicsize, &d.datasize, &d.padsize, &d.flags) != 4) { m_reason << " readEntryHeader: bad header at " << - offset << " [" << bf << "]"; + offset << " [" << bf << "]"; return CCScanHook::Error; } - LOGDEB2("Circache:readEntryHeader: dcsz " << d.dicsize << " dtsz " << d.datasize << " pdsz " << d.padsize << - " flgs " << d.flags << "\n"); + LOGDEB2("Circache:readEntryHeader: dcsz " << d.dicsize << " dtsz " << + d.datasize << " pdsz " << d.padsize << " flgs " <m_reason << "CirCache::create: mkdir(" << m_dir << - ") failed" << " errno " << errno; + ") failed" << " errno " << errno; return false; } } else { // If the file exists too, and truncate is not set, switch // to open-mode. Still may need to update header params. if (access(m_d->datafn(m_dir).c_str(), 0) >= 0 && - !(flags & CC_CRTRUNCATE)) { + !(flags & CC_CRTRUNCATE)) { if (!open(CC_OPWRITE)) { return false; } if (maxsize == m_d->m_maxsize && - ((flags & CC_CRUNIQUE) != 0) == m_d->m_uniquentries) { + ((flags & CC_CRUNIQUE) != 0) == m_d->m_uniquentries) { LOGDEB("Header unchanged, no rewrite\n"); return true; } @@ -733,9 +734,10 @@ bool CirCache::create(int64_t maxsize, int flags) } m_d->m_maxsize = maxsize; m_d->m_uniquentries = ((flags & CC_CRUNIQUE) != 0); - LOGDEB2("CirCache::create: rewriting header with maxsize " << m_d->m_maxsize << " oheadoffs " << - m_d->m_oheadoffs << " nheadoffs " << m_d->m_nheadoffs << " npadsize " << m_d->m_npadsize << - " unient " << m_d->m_uniquentries << "\n"); + LOGDEB2("CirCache::create: rewriting header with maxsize " << + m_d->m_maxsize << " oheadoffs " << m_d->m_oheadoffs << + " nheadoffs " << m_d->m_nheadoffs << " npadsize " << + m_d->m_npadsize << " unient " << m_d->m_uniquentries <<"\n"); return m_d->writefirstblock(); } // Else fallthrough to create file @@ -744,7 +746,7 @@ bool CirCache::create(int64_t maxsize, int flags) if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(), O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0666)) < 0) { m_d->m_reason << "CirCache::create: open/creat(" << - m_d->datafn(m_dir) << ") failed " << "errno " << errno; + m_d->datafn(m_dir) << ") failed " << "errno " << errno; return false; } @@ -755,9 +757,9 @@ bool CirCache::create(int64_t maxsize, int flags) char buf[CIRCACHE_FIRSTBLOCK_SIZE]; memset(buf, 0, CIRCACHE_FIRSTBLOCK_SIZE); if (::write(m_d->m_fd, buf, CIRCACHE_FIRSTBLOCK_SIZE) != - CIRCACHE_FIRSTBLOCK_SIZE) { + CIRCACHE_FIRSTBLOCK_SIZE) { m_d->m_reason << "CirCache::create: write header failed, errno " - << errno; + << errno; return false; } return m_d->writefirstblock(); @@ -778,7 +780,7 @@ bool CirCache::open(OpMode mode) mode == CC_OPREAD ? O_RDONLY | O_BINARY : O_RDWR | O_BINARY)) < 0) { m_d->m_reason << "CirCache::open: open(" << m_d->datafn(m_dir) << - ") failed " << "errno " << errno; + ") failed " << "errno " << errno; return false; } return m_d->readfirstblock(); @@ -789,9 +791,9 @@ public: virtual status takeone(int64_t offs, const string& udi, const EntryHeaderData& d) { cout << "Scan: offs " << offs << " dicsize " << d.dicsize - << " datasize " << d.datasize << " padsize " << d.padsize << - " flags " << d.flags << - " udi [" << udi << "]" << endl; + << " datasize " << d.datasize << " padsize " << d.padsize << + " flags " << d.flags << + " udi [" << udi << "]" << endl; return Continue; } }; @@ -810,7 +812,7 @@ bool CirCache::dump() return false; case CCScanHook::Continue: cout << "Scan returns Continue ?? " << CCScanHook::Continue << " " << - getReason() << endl; + getReason() << endl; return false; case CCScanHook::Error: cout << "Scan returns Error: " << getReason() << endl; @@ -837,7 +839,8 @@ public: virtual status takeone(int64_t offs, const string& udi, const EntryHeaderData& d) { - LOGDEB2("Circache:Scan: off " << offs << " udi [" << udi << "] dcsz " << d.dicsize << " dtsz " << d.datasize << + LOGDEB2("Circache:Scan: off " << offs << " udi [" << udi << "] dcsz " << + d.dicsize << " dtsz " << d.datasize << " pdsz " << d.padsize << " flgs " << d.flags << "\n"); if (!m_udi.compare(udi)) { m_instance++; @@ -873,7 +876,7 @@ bool CirCache::get(const string& udi, string& dic, string *data, int instance) EntryHeaderData d_good; int64_t o_good = 0; for (vector::iterator it = ofss.begin(); - it != ofss.end(); it++) { + it != ofss.end(); it++) { LOGDEB1("Circache::get: trying offs " << *it << "\n"); EntryHeaderData d; string fudi; @@ -989,7 +992,8 @@ public: virtual status takeone(int64_t offs, const string& udi, const EntryHeaderData& d) { - LOGDEB2("Circache:ScanSpacer:off " << offs << " dcsz " << d.dicsize << " dtsz " << d.datasize << + LOGDEB2("Circache:ScanSpacer:off " << offs << " dcsz " << d.dicsize << + " dtsz " << d.datasize << " pdsz " << d.padsize << " udi[" << udi << "]\n"); sizeseen += CIRCACHE_HEADER_SIZE + d.dicsize + d.datasize + d.padsize; squashed_udis.push_back(make_pair(udi, offs)); @@ -1016,7 +1020,8 @@ bool CirCache::put(const string& udi, const ConfSimple *iconf, string dic; if (!iconf || !iconf->get("udi", dic) || dic.empty() || dic.compare(udi)) { m_d->m_reason << "No/bad 'udi' entry in input dic"; - LOGERR("Circache::put: no/bad udi: DIC:[" << dic << "] UDI [" << udi << "]\n"); + LOGERR("Circache::put: no/bad udi: DIC:[" << dic << "] UDI [" << udi << + "]\n"); return false; } @@ -1060,12 +1065,13 @@ bool CirCache::put(const string& udi, const ConfSimple *iconf, int64_t npadsize = 0; bool extending = false; - LOGDEB("CirCache::put: nsz " << nsize << " oheadoffs " << m_d->m_oheadoffs << "\n"); + LOGDEB("CirCache::put: nsz " << nsize << " oheadoffs " << + m_d->m_oheadoffs << "\n"); // Check if we can recover some pad space from the (physically) previous // entry. int64_t recovpadsize = m_d->m_oheadoffs == CIRCACHE_FIRSTBLOCK_SIZE ? - 0 : m_d->m_npadsize; + 0 : m_d->m_npadsize; if (recovpadsize != 0) { // Need to read the latest entry's header, to rewrite it with a // zero pad size @@ -1095,7 +1101,7 @@ bool CirCache::put(const string& udi, const ConfSimple *iconf, if (nsize <= recovpadsize) { // If the new entry fits entirely in the pad area from the // latest one, no need to recycle stuff - LOGDEB("CirCache::put: new fits in old padsize " << recovpadsize << "\n"); + LOGDEB("CirCache::put: new fits in old padsize " << recovpadsize <<"\n"); npadsize = recovpadsize - nsize; } else if (st.st_size < m_d->m_maxsize) { // Still growing the file. @@ -1105,11 +1111,12 @@ bool CirCache::put(const string& udi, const ConfSimple *iconf, // Scan the file until we have enough space for the new entry, // and determine the pad size up to the 1st preserved entry int64_t scansize = nsize - recovpadsize; - LOGDEB("CirCache::put: scanning for size " << scansize << " from offs " << m_d->m_oheadoffs << "\n"); + LOGDEB("CirCache::put: scanning for size " << scansize << + " from offs " << m_d->m_oheadoffs << "\n"); CCScanHookSpacer spacer(scansize); switch (m_d->scan(m_d->m_oheadoffs, &spacer)) { case CCScanHook::Stop: - LOGDEB("CirCache::put: Scan ok, sizeseen " << spacer.sizeseen << "\n"); + LOGDEB("CirCache::put: Scan ok, sizeseen " << spacer.sizeseen<<"\n"); npadsize = spacer.sizeseen - scansize; break; case CCScanHook::Eof: @@ -1124,7 +1131,8 @@ bool CirCache::put(const string& udi, const ConfSimple *iconf, m_d->khClear(spacer.squashed_udis); } - LOGDEB("CirCache::put: writing " << nsize << " at " << nwriteoffs << " padsize " << npadsize << "\n"); + LOGDEB("CirCache::put: writing " << nsize << " at " << nwriteoffs << + " padsize " << npadsize << "\n"); if (lseek(m_d->m_fd, nwriteoffs, 0) != nwriteoffs) { m_d->m_reason << "CirCache::put: lseek failed: " << errno; @@ -1211,7 +1219,7 @@ bool CirCache::next(bool& eof) // Skip to next header, using values stored from previous one m_d->m_itoffs += CIRCACHE_HEADER_SIZE + m_d->m_ithd.dicsize + - m_d->m_ithd.datasize + m_d->m_ithd.padsize; + m_d->m_ithd.datasize + m_d->m_ithd.padsize; // Looped back ? if (m_d->m_itoffs == m_d->m_oheadoffs) { @@ -1268,7 +1276,7 @@ bool CirCache::getCurrent(string& udi, string& dic, string *data) // Copy all entries from occ to ncc. Both are already open. static bool copyall(std::shared_ptr occ, std::shared_ptr ncc, int& nentries, - ostringstream& msg) + ostringstream& msg) { bool eof = false; if (!occ->rewind(eof)) { @@ -1298,7 +1306,7 @@ static bool copyall(std::shared_ptr occ, //cerr << "UDI: " << udi << endl; if (!ncc->put(udi, &dic, data)) { msg << "put failed: " << ncc->getReason() << " sdic [" << sdic << - "]" << endl; + "]" << endl; return false; } nentries++; @@ -1342,253 +1350,3 @@ int CirCache::append(const string ddir, const string& sdir, string *reason) return nentries; } - - -#else // TEST -> -#include "autoconfig.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "circache.h" -#include "fileudi.h" -#include "conftree.h" -#include "readfile.h" -#include "log.h" - -#include "smallut.h" - -using namespace std; - -static char *thisprog; - -static char usage [] = - " -c [-u] : create\n" - " -p [apath ...] : put files\n" - " -d : dump\n" - " -g [-i instance] [-D] : get\n" - " -D: also dump data\n" - " -e : erase\n" - " -a [ ...]: append old content to target\n" - " The target should be first resized to hold all the data, else only\n" - " as many entries as capacity permit will be retained\n" - ; - -static void -Usage(FILE *fp = stderr) -{ - fprintf(fp, "%s: usage:\n%s", thisprog, usage); - exit(1); -} - -static int op_flags; -#define OPT_MOINS 0x1 -#define OPT_c 0x2 -#define OPT_p 0x8 -#define OPT_g 0x10 -#define OPT_d 0x20 -#define OPT_i 0x40 -#define OPT_D 0x80 -#define OPT_u 0x100 -#define OPT_e 0x200 -#define OPT_a 0x800 - -int main(int argc, char **argv) -{ - int instance = -1; - - thisprog = argv[0]; - argc--; - argv++; - - while (argc > 0 && **argv == '-') { - (*argv)++; - if (!(**argv)) - /* Cas du "adb - core" */ - { - Usage(); - } - while (**argv) - switch (*(*argv)++) { - case 'a': - op_flags |= OPT_a; - break; - case 'c': - op_flags |= OPT_c; - break; - case 'D': - op_flags |= OPT_D; - break; - case 'd': - op_flags |= OPT_d; - break; - case 'e': - op_flags |= OPT_e; - break; - case 'g': - op_flags |= OPT_g; - break; - case 'i': - op_flags |= OPT_i; - if (argc < 2) { - Usage(); - } - if ((sscanf(*(++argv), "%d", &instance)) != 1) { - Usage(); - } - argc--; - goto b1; - case 'p': - op_flags |= OPT_p; - break; - case 'u': - op_flags |= OPT_u; - break; - default: - Usage(); - break; - } -b1: - argc--; - argv++; - } - - Logger::getTheLog("")->setLogLevel(Logger::LLDEB1); - - if (argc < 1) { - Usage(); - } - string dir = *argv++; - argc--; - - CirCache cc(dir); - - if (op_flags & OPT_c) { - if (argc != 1) { - Usage(); - } - int64_t sizekb = atoi(*argv++); - argc--; - int flags = 0; - if (op_flags & OPT_u) { - flags |= CirCache::CC_CRUNIQUE; - } - if (!cc.create(sizekb * 1024, flags)) { - cerr << "Create failed:" << cc.getReason() << endl; - exit(1); - } - } else if (op_flags & OPT_a) { - if (argc < 1) { - Usage(); - } - while (argc) { - string reason; - if (CirCache::append(dir, *argv++, &reason) < 0) { - cerr << reason << endl; - return 1; - } - argc--; - } - } else if (op_flags & OPT_p) { - if (argc < 1) { - Usage(); - } - if (!cc.open(CirCache::CC_OPWRITE)) { - cerr << "Open failed: " << cc.getReason() << endl; - exit(1); - } - while (argc) { - string fn = *argv++; - argc--; - char dic[1000]; - string data, reason; - if (!file_to_string(fn, data, &reason)) { - cerr << "File_to_string: " << reason << endl; - exit(1); - } - string udi; - make_udi(fn, "", udi); - string cmd("xdg-mime query filetype "); - // Should do more quoting here... - cmd += "'" + fn + "'"; - FILE *fp = popen(cmd.c_str(), "r"); - char* buf=0; - size_t sz = 0; - ::getline(&buf, &sz, fp); - pclose(fp); - string mimetype(buf); - free(buf); - trimstring(mimetype, "\n\r"); - cout << "Got [" << mimetype << "]\n"; - - string s; - ConfSimple conf(s); - conf.set("udi", udi); - conf.set("mimetype", mimetype); - //ostringstream str; conf.write(str); cout << str.str() << endl; - - if (!cc.put(udi, &conf, data, 0)) { - cerr << "Put failed: " << cc.getReason() << endl; - cerr << "conf: ["; - conf.write(cerr); - cerr << "]" << endl; - exit(1); - } - } - cc.open(CirCache::CC_OPREAD); - } else if (op_flags & OPT_g) { - if (!cc.open(CirCache::CC_OPREAD)) { - cerr << "Open failed: " << cc.getReason() << endl; - exit(1); - } - while (argc) { - string udi = *argv++; - argc--; - string dic, data; - if (!cc.get(udi, dic, &data, instance)) { - cerr << "Get failed: " << cc.getReason() << endl; - exit(1); - } - cout << "Dict: [" << dic << "]" << endl; - if (op_flags & OPT_D) { - cout << "Data: [" << data << "]" << endl; - } - } - } else if (op_flags & OPT_e) { - if (!cc.open(CirCache::CC_OPWRITE)) { - cerr << "Open failed: " << cc.getReason() << endl; - exit(1); - } - while (argc) { - string udi = *argv++; - argc--; - string dic, data; - if (!cc.erase(udi)) { - cerr << "Erase failed: " << cc.getReason() << endl; - exit(1); - } - } - } else if (op_flags & OPT_d) { - if (!cc.open(CirCache::CC_OPREAD)) { - cerr << "Open failed: " << cc.getReason() << endl; - exit(1); - } - cc.dump(); - } else { - Usage(); - } - - exit(0); -} - -#endif - diff --git a/src/utils/conftree.cpp b/src/utils/conftree.cpp index 54cddee5..0a70093e 100644 --- a/src/utils/conftree.cpp +++ b/src/utils/conftree.cpp @@ -57,6 +57,47 @@ using namespace std; #define CONFDEB LOGDEB2 #endif + +long long ConfNull::getInt(const std::string& name, long long dflt, + const std::string& sk) +{ + string val; + if (!get(name, val, sk)) { + return dflt; + } + char *endptr; + long long ret = strtoll(val.c_str(), &endptr, 0); + if (endptr == val.c_str()) { + return dflt; + } + return ret; +} + +double ConfNull::getFloat(const std::string& name, double dflt, + const std::string& sk) +{ + string val; + if (!get(name, val, sk)) { + return dflt; + } + char *endptr; + double ret = strtod(val.c_str(), &endptr); + if (endptr == val.c_str()) { + return dflt; + } + return ret; +} + +bool ConfNull::getBool(const std::string& name, bool dflt, + const std::string& sk) +{ + string val; + if (!get(name, val, sk)) { + return dflt; + } + return stringToBool(val); +} + static const SimpleRegexp varcomment_rx("[ \t]*#[ \t]*([a-zA-Z0-9]+)[ \t]*=", 0, 1); @@ -275,30 +316,20 @@ int ConfSimple::get(const string& nm, string& value, const string& sk) const } // Find submap - map >::const_iterator ss; - if ((ss = m_submaps.find(sk)) == m_submaps.end()) { + const auto ss = m_submaps.find(sk); + if (ss == m_submaps.end()) { return 0; } // Find named value - map::const_iterator s; - if ((s = ss->second.find(nm)) == ss->second.end()) { + const auto s = ss->second.find(nm); + if (s == ss->second.end()) { return 0; } value = s->second; return 1; } -int ConfSimple::get(const string& nm, int *value, const string& sk) const -{ - string sval; - if (!get(nm, sval, sk)) { - return 0; - } - *value = atoi(sval.c_str()); - return 1; -} - // Appropriately output a subkey (nm=="") or variable line. // We can't make any assumption about the data except that it does not // contain line breaks. @@ -314,7 +345,7 @@ int ConfSimple::get(const string& nm, int *value, const string& sk) const // the file data (when read back by conftree), only its ease of // editing with a normal editor. static ConfSimple::WalkerCode varprinter(void *f, const string& nm, - const string& value) + const string& value) { ostream& output = *((ostream *)f); if (nm.empty()) { @@ -332,7 +363,7 @@ static ConfSimple::WalkerCode varprinter(void *f, const string& nm, // Break at whitespace if line too long and "a lot" of // remaining data if (ll > 50 && (value.length() - pos) > 10 && - (c == ' ' || c == '\t')) { + (c == ' ' || c == '\t')) { ll = 0; output << "\\\n"; } @@ -356,13 +387,13 @@ int ConfSimple::set(const std::string& nm, const std::string& value, } return write(); } + int ConfSimple::set(const string& nm, long long val, const string& sk) { return this->set(nm, lltodecstr(val), sk); } - // Internal set variable: no rw checking or file rewriting. If init is // set, we're doing initial parsing, else we are changing a parsed // tree (changes the way we update the order data) @@ -377,9 +408,9 @@ int ConfSimple::i_set(const std::string& nm, const std::string& value, return 0; } bool existing = false; - map >::iterator ss; + auto ss = m_submaps.find(sk); // Test if submap already exists, else create it, and insert variable: - if ((ss = m_submaps.find(sk)) == m_submaps.end()) { + if (ss == m_submaps.end()) { CONFDEB("ConfSimple::i_set: new submap\n"); map submap; submap[nm] = value; @@ -397,8 +428,7 @@ int ConfSimple::i_set(const std::string& nm, const std::string& value, } } else { // Insert or update variable in existing map. - map::iterator it; - it = ss->second.find(nm); + auto it = ss->second.find(nm); if (it == ss->second.end()) { ss->second.insert(pair(nm, value)); } else { @@ -438,7 +468,7 @@ int ConfSimple::i_set(const std::string& nm, const std::string& value, // This is not logically possible. The subkey must // exist. We're doomed std::cerr << "Logical failure during configuration variable " - "insertion" << endl; + "insertion" << endl; abort(); } } @@ -486,8 +516,8 @@ int ConfSimple::erase(const string& nm, const string& sk) return 0; } - map >::iterator ss; - if ((ss = m_submaps.find(sk)) == m_submaps.end()) { + auto ss = m_submaps.find(sk); + if (ss == m_submaps.end()) { return 0; } @@ -501,8 +531,8 @@ int ConfSimple::erase(const string& nm, const string& sk) int ConfSimple::eraseKey(const string& sk) { vector nms = getNames(sk); - for (vector::iterator it = nms.begin(); it != nms.end(); it++) { - erase(*it, sk); + for (const auto& nm : nms) { + erase(nm, sk); } return write(); } @@ -523,21 +553,16 @@ ConfSimple::sortwalk(WalkerCode(*walker)(void *, const string&, const string&), return WALK_STOP; } // For all submaps: - for (map >::const_iterator sit = - m_submaps.begin(); - sit != m_submaps.end(); sit++) { - + for (const auto& submap : m_submaps) { // Possibly emit submap name: - if (!sit->first.empty() && walker(clidata, string(), sit->first.c_str()) - == WALK_STOP) { + if (!submap.first.empty() && + walker(clidata, string(), submap.first.c_str()) == WALK_STOP) { return WALK_STOP; } // Walk submap - const map& sm = sit->second; - for (map::const_iterator it = sm.begin(); it != sm.end(); - it++) { - if (walker(clidata, it->first, it->second) == WALK_STOP) { + for (const auto& item : submap.second) { + if (walker(clidata, item.first, item.second) == WALK_STOP) { return WALK_STOP; } } @@ -579,30 +604,29 @@ bool ConfSimple::write(ostream& out) const return false; } string sk; - for (vector::const_iterator it = m_order.begin(); - it != m_order.end(); it++) { - switch (it->m_kind) { + for (const auto& confline : m_order) { + switch (confline.m_kind) { case ConfLine::CFL_COMMENT: case ConfLine::CFL_VARCOMMENT: - out << it->m_data << endl; + out << confline.m_data << endl; if (!out.good()) { return false; } break; case ConfLine::CFL_SK: - sk = it->m_data; + sk = confline.m_data; CONFDEB("ConfSimple::write: SK [" << sk << "]\n"); // Check that the submap still exists, and only output it if it // does if (m_submaps.find(sk) != m_submaps.end()) { - out << "[" << it->m_data << "]" << endl; + out << "[" << confline.m_data << "]" << endl; if (!out.good()) { return false; } } break; case ConfLine::CFL_VAR: - string nm = it->m_data; + string nm = confline.m_data; CONFDEB("ConfSimple::write: VAR [" << nm << "], sk [" < ConfSimple::getNames(const string& sk, const char *pattern) const if (!ok()) { return mylist; } - map >::const_iterator ss; - if ((ss = m_submaps.find(sk)) == m_submaps.end()) { + const auto ss = m_submaps.find(sk); + if (ss == m_submaps.end()) { return mylist; } mylist.reserve(ss->second.size()); - map::const_iterator it; - for (it = ss->second.begin(); it != ss->second.end(); it++) { - if (pattern && 0 != fnmatch(pattern, it->first.c_str(), 0)) { + for (const auto& item : ss->second) { + if (pattern && 0 != fnmatch(pattern, item.first.c_str(), 0)) { continue; } - mylist.push_back(it->first); + mylist.push_back(item.first); } return mylist; } @@ -660,9 +683,8 @@ vector ConfSimple::getSubKeys() const return mylist; } mylist.reserve(m_submaps.size()); - map >::const_iterator ss; - for (ss = m_submaps.begin(); ss != m_submaps.end(); ss++) { - mylist.push_back(ss->first); + for (const auto& submap : m_submaps) { + mylist.push_back(submap.first); } return mylist; } @@ -670,10 +692,9 @@ vector ConfSimple::getSubKeys() const bool ConfSimple::hasNameAnywhere(const string& nm) const { vectorkeys = getSubKeys(); - for (vector::const_iterator it = keys.begin(); - it != keys.end(); it++) { + for (const auto& key : keys) { string val; - if (get(nm, val, *it)) { + if (get(nm, val, key)) { return true; } } @@ -687,24 +708,23 @@ bool ConfSimple::commentsAsXML(ostream& out) out << "\n"; string sk; - for (vector::const_iterator it = lines.begin(); - it != lines.end(); it++) { - switch (it->m_kind) { + for (const auto& line : lines) { + switch (line.m_kind) { case ConfLine::CFL_COMMENT: case ConfLine::CFL_VARCOMMENT: { - string::size_type pos = it->m_data.find_first_not_of("# "); + string::size_type pos = line.m_data.find_first_not_of("# "); if (pos != string::npos) { - out << it->m_data.substr(pos) << endl; + out << line.m_data.substr(pos) << endl; } break; } case ConfLine::CFL_SK: - out << "" << it->m_data << "" << endl; + out << "" << line.m_data << "" << endl; break; case ConfLine::CFL_VAR: - out << "" << it->m_data << " = " << - it->m_value << "" << endl; + out << "" << line.m_data << " = " << + line.m_value << "" << endl; break; default: break; @@ -721,7 +741,7 @@ bool ConfSimple::commentsAsXML(ostream& out) // ////////////////////////////////////////////////////////////////////////// int ConfTree::get(const std::string& name, string& value, const string& sk) -const + const { if (sk.empty() || !path_isabsolute(sk)) { LOGDEB2("ConfTree::get: looking in global space for [" << @@ -757,4 +777,3 @@ const } return 0; } - diff --git a/src/utils/conftree.h b/src/utils/conftree.h index b91a8743..e12b9d75 100644 --- a/src/utils/conftree.h +++ b/src/utils/conftree.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 J.F.Dockes +/* Copyright (C) 2006-2019 J.F.Dockes * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or @@ -24,21 +24,21 @@ * * Lines like '[subkey]' in the file define subsections, with independant * configuration namespaces. Only subsections holding at least one variable are - * significant (empty subsections may be deleted during an update, or not) + * significant (empty subsections may be deleted during an update, or not). * - * Whitespace around name and value is insignificant. + * Whitespace around name and value is ignored. * - * The names are case-sensitive but don't depend on it, this might change + * The names are case-sensitive but don't depend on it, this might change. * * Values can be queried for, or set. * - * Any line without a '=' is a comment (a line like #var = value - * actually assigns a variable named '#var', which is not a big issue) + * Any line without a '=', or beginning with '[ \t]*#' is a comment. * * A configuration object can be created empty or by reading from a file or * a string. - * All 'set' calls cause an immediate rewrite of the backing object if any - * (file or string) + * + * All 'set' calls normally cause an immediate rewrite of the backing + * object if any (file or string). This can be prevented with holdWrites(). * * The ConfTree derived class interprets the subkeys as file paths and * lets subdir keys hierarchically inherit the properties from @@ -46,7 +46,7 @@ * * The ConfStack class stacks several Con(Simple/Tree) objects so that * parameters from the top of the stack override the values from lower - * (useful to have central/personal config files) + * (useful to have central/personal config files). */ #include @@ -62,7 +62,6 @@ #include #include #endif -#include #include "pathut.h" @@ -83,7 +82,7 @@ public: }; /** - * Virtual base class used to define an interface mostly useful for testing + * Virtual base class used to define the interface, and a few helper methods. */ class ConfNull { public: @@ -93,9 +92,15 @@ public: const std::string& sk = std::string()) const = 0; virtual int set(const std::string& nm, const std::string& val, const std::string& sk = std::string()) = 0; + virtual long long getInt(const std::string& name, long long dflt, + const std::string& sk = std::string()); + virtual double getFloat(const std::string& name, double dflt, + const std::string& sk = std::string()); + virtual bool getBool(const std::string& name, bool dflt, + const std::string& sk = std::string()); virtual bool ok() const = 0; virtual std::vector getNames(const std::string& sk, - const char* = 0)const = 0; + const char* = 0) const = 0; virtual bool hasNameAnywhere(const std::string& nm) const = 0; virtual int erase(const std::string&, const std::string&) = 0; virtual int eraseKey(const std::string&) = 0; @@ -167,15 +172,6 @@ public: virtual int get(const std::string& name, std::string& value, const std::string& sk = std::string()) const override; - /** - * Get integer value for named parameter, from specified subsection (looks - * in global space if sk is empty). - * @return 0 if name not found, 1 else - */ - virtual int get(const std::string& name, int* value, - const std::string& sk = std::string()) const; - - /** * Set value for named string parameter in specified subsection (or global) * @return 0 for error, 1 else @@ -302,8 +298,8 @@ protected: StatusCode status; private: // Set if we're working with a file - std::string m_filename; - time_t m_fmtime; + std::string m_filename; + time_t m_fmtime; // Configuration data submaps (one per subkey, the main data has a // null subkey) std::map > m_submaps; @@ -311,9 +307,9 @@ private: // Presentation data. We keep the comments, empty lines and // variable and subkey ordering information in there (for // rewriting the file while keeping hand-edited information) - std::vector m_order; + std::vector m_order; // Control if we're writing to the backing store - bool m_holdWrites; + bool m_holdWrites; void parseinput(std::istream& input); bool write(); @@ -369,15 +365,16 @@ public: }; /** - * Use several config files, trying to get values from each in order. Used to - * have a central config, with possible overrides from more specific - * (ie personal) ones. + * Use several config files, trying to get values from each in order. + * + * Enables having a central/default config, with possible overrides + * from more specific (e.g. personal) ones. * * Notes: it's ok for some of the files not to exist, but the last - * 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 - * erase() won't work except for parameters only defined in the topmost - * file (it erases only from there). + * (bottom) 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 erase() won't work except for parameters + * only defined in the topmost file (it erases only from there). */ template class ConfStack : public ConfNull { public: @@ -418,7 +415,7 @@ public: return *this; } - virtual bool sourceChanged() const override { + virtual bool sourceChanged() const override { for (const auto& conf : m_confs) { if (conf->sourceChanged()) { return true; @@ -500,7 +497,7 @@ public: return getNames1(sk, pattern, false); } virtual std::vector getNamesShallow(const std::string& sk, - const char *patt = 0) const { + const char *patt = 0) const { return getNames1(sk, patt, true); }