moved code around to make smallut and pathut less recoll-specific and reusable. No actual changes
This commit is contained in:
parent
7b2a455b80
commit
35de51985b
26 changed files with 1821 additions and 1493 deletions
|
@ -207,6 +207,7 @@ utils/fileudi.h \
|
||||||
utils/fstreewalk.cpp \
|
utils/fstreewalk.cpp \
|
||||||
utils/fstreewalk.h \
|
utils/fstreewalk.h \
|
||||||
utils/hldata.h \
|
utils/hldata.h \
|
||||||
|
utils/hldata.cpp \
|
||||||
utils/idfile.cpp \
|
utils/idfile.cpp \
|
||||||
utils/idfile.h \
|
utils/idfile.h \
|
||||||
utils/md5.cpp \
|
utils/md5.cpp \
|
||||||
|
@ -224,6 +225,8 @@ utils/pxattr.cpp \
|
||||||
utils/pxattr.h \
|
utils/pxattr.h \
|
||||||
utils/rclionice.cpp \
|
utils/rclionice.cpp \
|
||||||
utils/rclionice.h \
|
utils/rclionice.h \
|
||||||
|
utils/rclutil.h \
|
||||||
|
utils/rclutil.cpp \
|
||||||
utils/readfile.cpp \
|
utils/readfile.cpp \
|
||||||
utils/readfile.h \
|
utils/readfile.h \
|
||||||
utils/refcntr.h \
|
utils/refcntr.h \
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
#include "cstr.h"
|
#include "cstr.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
#include "conftree.h"
|
#include "conftree.h"
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
|
@ -144,7 +145,7 @@ RclConfig::RclConfig(const string *argcnf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute our data dir name, typically /usr/local/share/recoll
|
// Compute our data dir name, typically /usr/local/share/recoll
|
||||||
m_datadir = path_sharedatadir();
|
m_datadir = path_pkgdatadir();
|
||||||
// We only do the automatic configuration creation thing for the default
|
// We only do the automatic configuration creation thing for the default
|
||||||
// config dir, not if it was specified through -c or RECOLL_CONFDIR
|
// config dir, not if it was specified through -c or RECOLL_CONFDIR
|
||||||
bool autoconfdir = false;
|
bool autoconfdir = false;
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
#include "rclinit.h"
|
#include "rclinit.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "unac.h"
|
#include "unac.h"
|
||||||
#include "smallut.h"
|
#include "smallut.h"
|
||||||
#include "execmd.h"
|
#include "execmd.h"
|
||||||
|
@ -318,6 +319,8 @@ RclConfig *recollinit(RclInitFlags flags,
|
||||||
// Init smallut and pathut static values
|
// Init smallut and pathut static values
|
||||||
pathut_init_mt();
|
pathut_init_mt();
|
||||||
smallut_init_mt();
|
smallut_init_mt();
|
||||||
|
rclutil_init_mt();
|
||||||
|
|
||||||
// Init execmd.h static PATH and PATHELT splitting
|
// Init execmd.h static PATH and PATHELT splitting
|
||||||
{string bogus;
|
{string bogus;
|
||||||
ExecCmd::which("nosuchcmd", bogus);
|
ExecCmd::which("nosuchcmd", bogus);
|
||||||
|
@ -389,4 +392,3 @@ bool recoll_ismainthread()
|
||||||
return pthread_equal(pthread_self(), mainthread_id);
|
return pthread_equal(pthread_self(), mainthread_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
#define _RCLINIT_H_INCLUDED_
|
#define _RCLINIT_H_INCLUDED_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#ifndef NO_NAMESPACES
|
|
||||||
using std::string;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class RclConfig;
|
class RclConfig;
|
||||||
/**
|
/**
|
||||||
|
@ -45,9 +42,11 @@ class RclConfig;
|
||||||
enum RclInitFlags {RCLINIT_NONE = 0, RCLINIT_DAEMON = 1, RCLINIT_IDX = 2};
|
enum RclInitFlags {RCLINIT_NONE = 0, RCLINIT_DAEMON = 1, RCLINIT_IDX = 2};
|
||||||
extern RclConfig *recollinit(RclInitFlags flags,
|
extern RclConfig *recollinit(RclInitFlags flags,
|
||||||
void (*cleanup)(void), void (*sigcleanup)(int),
|
void (*cleanup)(void), void (*sigcleanup)(int),
|
||||||
string &reason, const string *argcnf = 0);
|
std::string& reason, const string *argcnf = 0);
|
||||||
inline RclConfig *recollinit(void (*cleanup)(void), void (*sigcleanup)(int),
|
inline RclConfig *recollinit(void (*cleanup)(void), void (*sigcleanup)(int),
|
||||||
string &reason, const string *argcnf = 0) {
|
std::string& reason,
|
||||||
|
const std::string *argcnf = 0)
|
||||||
|
{
|
||||||
return recollinit(RCLINIT_NONE, cleanup, sigcleanup, reason, argcnf);
|
return recollinit(RCLINIT_NONE, cleanup, sigcleanup, reason, argcnf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "cstr.h"
|
#include "cstr.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
#include "fstreewalk.h"
|
#include "fstreewalk.h"
|
||||||
#include "beaglequeue.h"
|
#include "beaglequeue.h"
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "cstr.h"
|
#include "cstr.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "conftree.h"
|
#include "conftree.h"
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
#include "fstreewalk.h"
|
#include "fstreewalk.h"
|
||||||
|
|
|
@ -42,6 +42,7 @@ using namespace std;
|
||||||
#include "smallut.h"
|
#include "smallut.h"
|
||||||
#include "chrono.h"
|
#include "chrono.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "rclmon.h"
|
#include "rclmon.h"
|
||||||
#include "x11mon.h"
|
#include "x11mon.h"
|
||||||
#include "cancelcheck.h"
|
#include "cancelcheck.h"
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "ptmutex.h"
|
#include "ptmutex.h"
|
||||||
|
|
||||||
/// Uncompression script interface.
|
/// Uncompression script interface.
|
||||||
|
|
|
@ -32,6 +32,7 @@ using namespace std;
|
||||||
#include "searchdata.h"
|
#include "searchdata.h"
|
||||||
#include "rclquery.h"
|
#include "rclquery.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "wasatorcl.h"
|
#include "wasatorcl.h"
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "rcldoc.h"
|
#include "rcldoc.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
#include "rcldb.h"
|
#include "rcldb.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "ptmutex.h"
|
#include "ptmutex.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
|
@ -34,6 +34,7 @@ using std::list;
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
#include "smallut.h"
|
#include "smallut.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "plaintorich.h"
|
#include "plaintorich.h"
|
||||||
#include "mimehandler.h"
|
#include "mimehandler.h"
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ using namespace std;
|
||||||
#include "unacpp.h"
|
#include "unacpp.h"
|
||||||
#include "conftree.h"
|
#include "conftree.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
|
#include "rclutil.h"
|
||||||
#include "smallut.h"
|
#include "smallut.h"
|
||||||
#include "chrono.h"
|
#include "chrono.h"
|
||||||
#include "utf8iter.h"
|
#include "utf8iter.h"
|
||||||
|
@ -126,6 +127,21 @@ static inline string make_parentterm(const string& udi)
|
||||||
return pterm;
|
return pterm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void utf8truncate(string& s, int maxlen)
|
||||||
|
{
|
||||||
|
if (s.size() <= string::size_type(maxlen)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Utf8Iter iter(s);
|
||||||
|
string::size_type pos = 0;
|
||||||
|
while (iter++ != string::npos)
|
||||||
|
if (iter.getBpos() < string::size_type(maxlen)) {
|
||||||
|
pos = iter.getBpos();
|
||||||
|
}
|
||||||
|
|
||||||
|
s.erase(pos);
|
||||||
|
}
|
||||||
|
|
||||||
Db::Native::Native(Db *db)
|
Db::Native::Native(Db *db)
|
||||||
: m_rcldb(db), m_isopen(false), m_iswritable(false),
|
: m_rcldb(db), m_isopen(false), m_iswritable(false),
|
||||||
m_noversionwrite(false)
|
m_noversionwrite(false)
|
||||||
|
|
|
@ -14,9 +14,11 @@
|
||||||
* Free Software Foundation, Inc.,
|
* Free Software Foundation, Inc.,
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
#include "autoconfig.h"
|
||||||
|
|
||||||
#include "rcldoc.h"
|
#include "rcldoc.h"
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
|
#include "rclutil.h"
|
||||||
|
|
||||||
namespace Rcl {
|
namespace Rcl {
|
||||||
const string Doc::keyabs("abstract");
|
const string Doc::keyabs("abstract");
|
||||||
|
@ -70,5 +72,31 @@ namespace Rcl {
|
||||||
if (dotext)
|
if (dotext)
|
||||||
LOGDEB(("Rcl::Doc::dump: text: \n[%s]\n", text.c_str()));
|
LOGDEB(("Rcl::Doc::dump: text: \n[%s]\n", text.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy ensuring no shared string data, for threading issues.
|
||||||
|
void Doc::copyto(Doc *d) const
|
||||||
|
{
|
||||||
|
d->url.assign(url.begin(), url.end());
|
||||||
|
d->idxurl.assign(idxurl.begin(), idxurl.end());
|
||||||
|
d->idxi = idxi;
|
||||||
|
d->ipath.assign(ipath.begin(), ipath.end());
|
||||||
|
d->mimetype.assign(mimetype.begin(), mimetype.end());
|
||||||
|
d->fmtime.assign(fmtime.begin(), fmtime.end());
|
||||||
|
d->dmtime.assign(dmtime.begin(), dmtime.end());
|
||||||
|
d->origcharset.assign(origcharset.begin(), origcharset.end());
|
||||||
|
map_ss_cp_noshr(meta, &d->meta);
|
||||||
|
d->syntabs = syntabs;
|
||||||
|
d->pcbytes.assign(pcbytes.begin(), pcbytes.end());
|
||||||
|
d->fbytes.assign(fbytes.begin(), fbytes.end());
|
||||||
|
d->dbytes.assign(dbytes.begin(), dbytes.end());
|
||||||
|
d->sig.assign(sig.begin(), sig.end());
|
||||||
|
d->text.assign(text.begin(), text.end());
|
||||||
|
d->pc = pc;
|
||||||
|
d->xdocid = xdocid;
|
||||||
|
d->idxi = idxi;
|
||||||
|
d->haspages = haspages;
|
||||||
|
d->haschildren = haschildren;
|
||||||
|
d->onlyxattr = onlyxattr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,33 +163,11 @@ class Doc {
|
||||||
onlyxattr = false;
|
onlyxattr = false;
|
||||||
}
|
}
|
||||||
// Copy ensuring no shared string data, for threading issues.
|
// Copy ensuring no shared string data, for threading issues.
|
||||||
void copyto(Doc *d) const {
|
void copyto(Doc *d) const;
|
||||||
d->url.assign(url.begin(), url.end());
|
|
||||||
d->idxurl.assign(idxurl.begin(), idxurl.end());
|
|
||||||
d->idxi = idxi;
|
|
||||||
d->ipath.assign(ipath.begin(), ipath.end());
|
|
||||||
d->mimetype.assign(mimetype.begin(), mimetype.end());
|
|
||||||
d->fmtime.assign(fmtime.begin(), fmtime.end());
|
|
||||||
d->dmtime.assign(dmtime.begin(), dmtime.end());
|
|
||||||
d->origcharset.assign(origcharset.begin(), origcharset.end());
|
|
||||||
map_ss_cp_noshr(meta, &d->meta);
|
|
||||||
d->syntabs = syntabs;
|
|
||||||
d->pcbytes.assign(pcbytes.begin(), pcbytes.end());
|
|
||||||
d->fbytes.assign(fbytes.begin(), fbytes.end());
|
|
||||||
d->dbytes.assign(dbytes.begin(), dbytes.end());
|
|
||||||
d->sig.assign(sig.begin(), sig.end());
|
|
||||||
d->text.assign(text.begin(), text.end());
|
|
||||||
d->pc = pc;
|
|
||||||
d->xdocid = xdocid;
|
|
||||||
d->idxi = idxi;
|
|
||||||
d->haspages = haspages;
|
|
||||||
d->haschildren = haschildren;
|
|
||||||
d->onlyxattr = onlyxattr;
|
|
||||||
}
|
|
||||||
Doc()
|
Doc()
|
||||||
: idxi(0), syntabs(false), pc(0), xdocid(0),
|
: idxi(0), syntabs(false), pc(0), xdocid(0),
|
||||||
haspages(false), haschildren(false), onlyxattr(false)
|
haspages(false), haschildren(false), onlyxattr(false) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
/** Get value for named field. If value pointer is 0, just test existence */
|
/** Get value for named field. If value pointer is 0, just test existence */
|
||||||
bool getmeta(const string& nm, string *value = 0) const
|
bool getmeta(const string& nm, string *value = 0) const
|
||||||
|
|
|
@ -32,10 +32,12 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include UNORDERED_MAP_INCLUDE
|
#include UNORDERED_MAP_INCLUDE
|
||||||
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
#include "smallut.h"
|
#include "smallut.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Storage for the exception translations. These are chars which
|
Storage for the exception translations. These are chars which
|
||||||
should not be translated according to what UnicodeData says, but
|
should not be translated according to what UnicodeData says, but
|
||||||
|
|
|
@ -71,6 +71,28 @@ typedef unsigned char UCHAR;
|
||||||
typedef unsigned int UINT;
|
typedef unsigned int UINT;
|
||||||
typedef unsigned long ULONG;
|
typedef unsigned long ULONG;
|
||||||
|
|
||||||
|
/** Temp buffer with automatic deallocation */
|
||||||
|
struct TempBuf {
|
||||||
|
TempBuf()
|
||||||
|
: m_buf(0) {
|
||||||
|
}
|
||||||
|
TempBuf(int n) {
|
||||||
|
m_buf = (char *)malloc(n);
|
||||||
|
}
|
||||||
|
~TempBuf() {
|
||||||
|
if (m_buf) {
|
||||||
|
free(m_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char *setsize(int n) {
|
||||||
|
return (m_buf = (char *)realloc(m_buf, n));
|
||||||
|
}
|
||||||
|
char *buf() {
|
||||||
|
return m_buf;
|
||||||
|
}
|
||||||
|
char *m_buf;
|
||||||
|
};
|
||||||
|
|
||||||
static bool inflateToDynBuf(void *inp, UINT inlen, void **outpp, UINT *outlenp);
|
static bool inflateToDynBuf(void *inp, UINT inlen, void **outpp, UINT *outlenp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -18,10 +18,16 @@
|
||||||
#ifndef TEST_CPUCONF
|
#ifndef TEST_CPUCONF
|
||||||
|
|
||||||
#include "autoconfig.h"
|
#include "autoconfig.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "cpuconf.h"
|
#include "cpuconf.h"
|
||||||
#include "execmd.h"
|
#include "execmd.h"
|
||||||
#include "smallut.h"
|
#include "smallut.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
#if defined(__gnu_linux__)
|
#if defined(__gnu_linux__)
|
||||||
bool getCpuConf(CpuConf& conf)
|
bool getCpuConf(CpuConf& conf)
|
||||||
{
|
{
|
||||||
|
|
78
src/utils/hldata.cpp
Normal file
78
src/utils/hldata.cpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/* Copyright (C) 2016 J.F.Dockes
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the
|
||||||
|
* Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
#include "autoconfig.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "hldata.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::map;
|
||||||
|
|
||||||
|
void HighlightData::toString(string& out)
|
||||||
|
{
|
||||||
|
out.append("\nUser terms (orthograph): ");
|
||||||
|
for (std::set<string>::const_iterator it = uterms.begin();
|
||||||
|
it != uterms.end(); it++) {
|
||||||
|
out.append(" [").append(*it).append("]");
|
||||||
|
}
|
||||||
|
out.append("\nUser terms to Query terms:");
|
||||||
|
for (map<string, string>::const_iterator it = terms.begin();
|
||||||
|
it != terms.end(); it++) {
|
||||||
|
out.append("[").append(it->first).append("]->[");
|
||||||
|
out.append(it->second).append("] ");
|
||||||
|
}
|
||||||
|
out.append("\nGroups: ");
|
||||||
|
char cbuf[200];
|
||||||
|
sprintf(cbuf, "Groups size %d grpsugidx size %d ugroups size %d",
|
||||||
|
int(groups.size()), int(grpsugidx.size()), int(ugroups.size()));
|
||||||
|
out.append(cbuf);
|
||||||
|
|
||||||
|
size_t ugidx = (size_t) - 1;
|
||||||
|
for (unsigned int i = 0; i < groups.size(); i++) {
|
||||||
|
if (ugidx != grpsugidx[i]) {
|
||||||
|
ugidx = grpsugidx[i];
|
||||||
|
out.append("\n(");
|
||||||
|
for (unsigned int j = 0; j < ugroups[ugidx].size(); j++) {
|
||||||
|
out.append("[").append(ugroups[ugidx][j]).append("] ");
|
||||||
|
}
|
||||||
|
out.append(") ->");
|
||||||
|
}
|
||||||
|
out.append(" {");
|
||||||
|
for (unsigned int j = 0; j < groups[i].size(); j++) {
|
||||||
|
out.append("[").append(groups[i][j]).append("]");
|
||||||
|
}
|
||||||
|
sprintf(cbuf, "%d", slacks[i]);
|
||||||
|
out.append("}").append(cbuf);
|
||||||
|
}
|
||||||
|
out.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void HighlightData::append(const HighlightData& hl)
|
||||||
|
{
|
||||||
|
uterms.insert(hl.uterms.begin(), hl.uterms.end());
|
||||||
|
terms.insert(hl.terms.begin(), hl.terms.end());
|
||||||
|
size_t ugsz0 = ugroups.size();
|
||||||
|
ugroups.insert(ugroups.end(), hl.ugroups.begin(), hl.ugroups.end());
|
||||||
|
|
||||||
|
groups.insert(groups.end(), hl.groups.begin(), hl.groups.end());
|
||||||
|
slacks.insert(slacks.end(), hl.slacks.begin(), hl.slacks.end());
|
||||||
|
for (std::vector<size_t>::const_iterator it = hl.grpsugidx.begin();
|
||||||
|
it != hl.grpsugidx.end(); it++) {
|
||||||
|
grpsugidx.push_back(*it + ugsz0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
/** Store data about user search terms and their expansions. This is used
|
/** Store data about user search terms and their expansions. This is used
|
||||||
* mostly for highlighting result text and walking the matches, generating
|
* mostly for highlighting result text and walking the matches, generating
|
||||||
|
|
|
@ -16,25 +16,31 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TEST_PATHUT
|
#ifndef TEST_PATHUT
|
||||||
|
#ifdef BUILDING_RECOLL
|
||||||
#include "autoconfig.h"
|
#include "autoconfig.h"
|
||||||
|
#else
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "dirent.h"
|
||||||
#include "safefcntl.h"
|
#include "safefcntl.h"
|
||||||
#include "safeunistd.h"
|
#include "safeunistd.h"
|
||||||
#include "dirent.h"
|
|
||||||
#include "cstr.h"
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include "safewindows.h"
|
#include "safewindows.h"
|
||||||
|
#include "safesysstat.h"
|
||||||
#else
|
#else
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <dirent.h>
|
||||||
#endif
|
#endif
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include "safesysstat.h"
|
|
||||||
#include "ptmutex.h"
|
|
||||||
|
|
||||||
// Let's include all files where statfs can be defined and hope for no
|
// Let's include all files where statfs can be defined and hope for no
|
||||||
// conflict...
|
// conflict...
|
||||||
|
@ -60,9 +66,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
#include "transcode.h"
|
|
||||||
#include "wipedir.h"
|
|
||||||
#include "md5ut.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -71,10 +74,11 @@ using namespace std;
|
||||||
void path_slashize(string& s)
|
void path_slashize(string& s)
|
||||||
{
|
{
|
||||||
for (string::size_type i = 0; i < s.size(); i++) {
|
for (string::size_type i = 0; i < s.size(); i++) {
|
||||||
if (s[i] == '\\')
|
if (s[i] == '\\') {
|
||||||
s[i] = '/';
|
s[i] = '/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
static bool path_strlookslikedrive(const string& s)
|
static bool path_strlookslikedrive(const string& s)
|
||||||
{
|
{
|
||||||
return s.size() == 2 && isalpha(s[0]) && s[1] == ':';
|
return s.size() == 2 && isalpha(s[0]) && s[1] == ':';
|
||||||
|
@ -82,14 +86,16 @@ static bool path_strlookslikedrive(const string& s)
|
||||||
|
|
||||||
static bool path_hasdrive(const string& s)
|
static bool path_hasdrive(const string& s)
|
||||||
{
|
{
|
||||||
if (s.size() >= 2 && isalpha(s[0]) && s[1] == ':')
|
if (s.size() >= 2 && isalpha(s[0]) && s[1] == ':') {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool path_isdriveabs(const string& s)
|
static bool path_isdriveabs(const string& s)
|
||||||
{
|
{
|
||||||
if (s.size() >= 3 && isalpha(s[0]) && s[1] == ':' && s[2] == '/')
|
if (s.size() >= 3 && isalpha(s[0]) && s[1] == ':' && s[2] == '/') {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,8 +136,9 @@ string path_thisexecpath()
|
||||||
PathRemoveFileSpec(text);
|
PathRemoveFileSpec(text);
|
||||||
#endif
|
#endif
|
||||||
string path = path_tchartoutf8(text);
|
string path = path_tchartoutf8(text);
|
||||||
if (path.empty())
|
if (path.empty()) {
|
||||||
path = "c:/";
|
path = "c:/";
|
||||||
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
@ -150,7 +157,8 @@ string path_wingettempfilename(TCHAR *pref)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_SYS_MOUNT_H) || defined(HAVE_SYS_STATFS_H) || \
|
||||||
|
defined(HAVE_SYS_STATVFS_H) || defined(HAVE_SYS_VFS_H)
|
||||||
bool fsocc(const string& path, int *pc, long long *avmbs)
|
bool fsocc(const string& path, int *pc, long long *avmbs)
|
||||||
{
|
{
|
||||||
static const int FSOCC_MB = 1024 * 1024;
|
static const int FSOCC_MB = 1024 * 1024;
|
||||||
|
@ -161,10 +169,12 @@ bool fsocc(const string &path, int *pc, long long *avmbs)
|
||||||
&totalbytes, NULL)) {
|
&totalbytes, NULL)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (pc)
|
if (pc) {
|
||||||
*pc = int((100 * freebytesavail.QuadPart) / totalbytes.QuadPart);
|
*pc = int((100 * freebytesavail.QuadPart) / totalbytes.QuadPart);
|
||||||
if (avmbs)
|
}
|
||||||
|
if (avmbs) {
|
||||||
*avmbs = int(totalbytes.QuadPart / FSOCC_MB);
|
*avmbs = int(totalbytes.QuadPart / FSOCC_MB);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
#ifdef sun
|
#ifdef sun
|
||||||
|
@ -186,8 +196,9 @@ bool fsocc(const string &path, int *pc, long long *avmbs)
|
||||||
if (FSOCC_TOTAVAIL > 0) {
|
if (FSOCC_TOTAVAIL > 0) {
|
||||||
fpc = 100.0 * FSOCC_USED / FSOCC_TOTAVAIL;
|
fpc = 100.0 * FSOCC_USED / FSOCC_TOTAVAIL;
|
||||||
}
|
}
|
||||||
if (pc)
|
if (pc) {
|
||||||
*pc = int(fpc);
|
*pc = int(fpc);
|
||||||
|
}
|
||||||
if (avmbs) {
|
if (avmbs) {
|
||||||
*avmbs = 0;
|
*avmbs = 0;
|
||||||
if (buf.f_bsize > 0) {
|
if (buf.f_bsize > 0) {
|
||||||
|
@ -202,54 +213,7 @@ bool fsocc(const string &path, int *pc, long long *avmbs)
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif // we have found an appropriate include file
|
||||||
const string& tmplocation()
|
|
||||||
{
|
|
||||||
static string stmpdir;
|
|
||||||
if (stmpdir.empty()) {
|
|
||||||
const char *tmpdir = getenv("RECOLL_TMPDIR");
|
|
||||||
if (tmpdir == 0)
|
|
||||||
tmpdir = getenv("TMPDIR");
|
|
||||||
if (tmpdir == 0)
|
|
||||||
tmpdir = getenv("TMP");
|
|
||||||
if (tmpdir == 0)
|
|
||||||
tmpdir = getenv("TEMP");
|
|
||||||
if (tmpdir == 0) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
TCHAR bufw[(MAX_PATH+1)*sizeof(TCHAR)];
|
|
||||||
GetTempPath(MAX_PATH+1, bufw);
|
|
||||||
stmpdir = path_tchartoutf8(bufw);
|
|
||||||
#else
|
|
||||||
stmpdir = "/tmp";
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
stmpdir = tmpdir;
|
|
||||||
}
|
|
||||||
stmpdir = path_canon(stmpdir);
|
|
||||||
}
|
|
||||||
|
|
||||||
return stmpdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Location for sample config, filters, etc. (e.g. /usr/share/recoll/)
|
|
||||||
const string& path_sharedatadir()
|
|
||||||
{
|
|
||||||
static string datadir;
|
|
||||||
if (datadir.empty()) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
datadir = path_cat(path_thisexecpath(), "Share");
|
|
||||||
#else
|
|
||||||
const char *cdatadir = getenv("RECOLL_DATADIR");
|
|
||||||
if (cdatadir == 0) {
|
|
||||||
// If not in environment, use the compiled-in constant.
|
|
||||||
datadir = RECOLL_DATADIR;
|
|
||||||
} else {
|
|
||||||
datadir = cdatadir;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return datadir;
|
|
||||||
}
|
|
||||||
|
|
||||||
string path_PATHsep()
|
string path_PATHsep()
|
||||||
{
|
{
|
||||||
|
@ -262,148 +226,15 @@ string path_PATHsep()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool maketmpdir(string& tdir, string& reason)
|
|
||||||
{
|
|
||||||
#ifndef _WIN32
|
|
||||||
tdir = path_cat(tmplocation(), "rcltmpXXXXXX");
|
|
||||||
|
|
||||||
char *cp = strdup(tdir.c_str());
|
|
||||||
if (!cp) {
|
|
||||||
reason = "maketmpdir: out of memory (for file name !)\n";
|
|
||||||
tdir.erase();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There is a race condition between name computation and
|
|
||||||
// mkdir. try to make sure that we at least don't shoot ourselves
|
|
||||||
// in the foot
|
|
||||||
#if !defined(HAVE_MKDTEMP) || defined(_WIN32)
|
|
||||||
static PTMutexInit mlock;
|
|
||||||
PTMutexLocker lock(mlock);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!
|
|
||||||
#ifdef HAVE_MKDTEMP
|
|
||||||
mkdtemp(cp)
|
|
||||||
#else
|
|
||||||
mktemp(cp)
|
|
||||||
#endif // HAVE_MKDTEMP
|
|
||||||
) {
|
|
||||||
free(cp);
|
|
||||||
reason = "maketmpdir: mktemp failed for [" + tdir + "] : " +
|
|
||||||
strerror(errno);
|
|
||||||
tdir.erase();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
tdir = cp;
|
|
||||||
free(cp);
|
|
||||||
#else // _WIN32
|
|
||||||
// There is a race condition between name computation and
|
|
||||||
// mkdir. try to make sure that we at least don't shoot ourselves
|
|
||||||
// in the foot
|
|
||||||
static PTMutexInit mlock;
|
|
||||||
PTMutexLocker lock(mlock);
|
|
||||||
tdir = path_wingettempfilename(TEXT("rcltmp"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// At this point the directory does not exist yet except if we used
|
|
||||||
// mkdtemp
|
|
||||||
|
|
||||||
#if !defined(HAVE_MKDTEMP) || defined(_WIN32)
|
|
||||||
if (mkdir(tdir.c_str(), 0700) < 0) {
|
|
||||||
reason = string("maketmpdir: mkdir ") + tdir + " failed";
|
|
||||||
tdir.erase();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TempFileInternal::TempFileInternal(const string& suffix)
|
|
||||||
: m_noremove(false)
|
|
||||||
{
|
|
||||||
// Because we need a specific suffix, can't use mkstemp
|
|
||||||
// well. There is a race condition between name computation and
|
|
||||||
// file creation. try to make sure that we at least don't shoot
|
|
||||||
// our own selves in the foot. maybe we'll use mkstemps one day.
|
|
||||||
static PTMutexInit mlock;
|
|
||||||
PTMutexLocker lock(mlock);
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
string filename = path_cat(tmplocation(), "rcltmpfXXXXXX");
|
|
||||||
char *cp = strdup(filename.c_str());
|
|
||||||
if (!cp) {
|
|
||||||
m_reason = "Out of memory (for file name !)\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using mkstemp this way is awful (bot the suffix adding and
|
|
||||||
// using mkstemp() instead of mktemp just to avoid the warnings)
|
|
||||||
int fd;
|
|
||||||
if ((fd = mkstemp(cp)) < 0) {
|
|
||||||
free(cp);
|
|
||||||
m_reason = "TempFileInternal: mkstemp failed\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
unlink(cp);
|
|
||||||
filename = cp;
|
|
||||||
free(cp);
|
|
||||||
#else
|
|
||||||
string filename = path_wingettempfilename(TEXT("recoll"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_filename = filename + suffix;
|
|
||||||
if (close(open(m_filename.c_str(), O_CREAT|O_EXCL, 0600)) != 0) {
|
|
||||||
m_reason = string("Could not open/create") + m_filename;
|
|
||||||
m_filename.erase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TempFileInternal::~TempFileInternal()
|
|
||||||
{
|
|
||||||
if (!m_filename.empty() && !m_noremove)
|
|
||||||
unlink(m_filename.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
TempDir::TempDir()
|
|
||||||
{
|
|
||||||
if (!maketmpdir(m_dirname, m_reason)) {
|
|
||||||
m_dirname.erase();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TempDir::~TempDir()
|
|
||||||
{
|
|
||||||
if (!m_dirname.empty()) {
|
|
||||||
(void)wipedir(m_dirname, true, true);
|
|
||||||
m_dirname.erase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TempDir::wipe()
|
|
||||||
{
|
|
||||||
if (m_dirname.empty()) {
|
|
||||||
m_reason = "TempDir::wipe: no directory !\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (wipedir(m_dirname, false, true)) {
|
|
||||||
m_reason = "TempDir::wipe: wipedir failed\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void path_catslash(string& s)
|
void path_catslash(string& s)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
path_slashize(s);
|
path_slashize(s);
|
||||||
#endif
|
#endif
|
||||||
if (s.empty() || s[s.length() - 1] != '/')
|
if (s.empty() || s[s.length() - 1] != '/') {
|
||||||
s += '/';
|
s += '/';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string path_cat(const string& s1, const string& s2)
|
string path_cat(const string& s1, const string& s2)
|
||||||
{
|
{
|
||||||
|
@ -421,11 +252,13 @@ string path_getfather(const string &s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ??
|
// ??
|
||||||
if (father.empty())
|
if (father.empty()) {
|
||||||
return "./";
|
return "./";
|
||||||
|
}
|
||||||
|
|
||||||
if (path_isroot(father))
|
if (path_isroot(father)) {
|
||||||
return father;
|
return father;
|
||||||
|
}
|
||||||
|
|
||||||
if (father[father.length() - 1] == '/') {
|
if (father[father.length() - 1] == '/') {
|
||||||
// Input ends with /. Strip it, root special case was tested above
|
// Input ends with /. Strip it, root special case was tested above
|
||||||
|
@ -433,8 +266,9 @@ string path_getfather(const string &s)
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type slp = father.rfind('/');
|
string::size_type slp = father.rfind('/');
|
||||||
if (slp == string::npos)
|
if (slp == string::npos) {
|
||||||
return "./";
|
return "./";
|
||||||
|
}
|
||||||
|
|
||||||
father.erase(slp);
|
father.erase(slp);
|
||||||
path_catslash(father);
|
path_catslash(father);
|
||||||
|
@ -448,12 +282,14 @@ string path_getsimple(const string &s)
|
||||||
path_slashize(simple);
|
path_slashize(simple);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (simple.empty())
|
if (simple.empty()) {
|
||||||
return simple;
|
return simple;
|
||||||
|
}
|
||||||
|
|
||||||
string::size_type slp = simple.rfind('/');
|
string::size_type slp = simple.rfind('/');
|
||||||
if (slp == string::npos)
|
if (slp == string::npos) {
|
||||||
return simple;
|
return simple;
|
||||||
|
}
|
||||||
|
|
||||||
simple.erase(0, slp + 1);
|
simple.erase(0, slp + 1);
|
||||||
return simple;
|
return simple;
|
||||||
|
@ -465,17 +301,19 @@ string path_basename(const string &s, const string &suff)
|
||||||
string::size_type pos = string::npos;
|
string::size_type pos = string::npos;
|
||||||
if (suff.length() && simple.length() > suff.length()) {
|
if (suff.length() && simple.length() > suff.length()) {
|
||||||
pos = simple.rfind(suff);
|
pos = simple.rfind(suff);
|
||||||
if (pos != string::npos && pos + suff.length() == simple.length())
|
if (pos != string::npos && pos + suff.length() == simple.length()) {
|
||||||
return simple.substr(0, pos);
|
return simple.substr(0, pos);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return simple;
|
return simple;
|
||||||
}
|
}
|
||||||
|
|
||||||
string path_suffix(const string& s)
|
string path_suffix(const string& s)
|
||||||
{
|
{
|
||||||
string::size_type dotp = s.rfind('.');
|
string::size_type dotp = s.rfind('.');
|
||||||
if (dotp == string::npos)
|
if (dotp == string::npos) {
|
||||||
return string();
|
return string();
|
||||||
|
}
|
||||||
return s.substr(dotp + 1);
|
return s.substr(dotp + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,11 +346,12 @@ string path_home()
|
||||||
struct passwd *entry = getpwuid(uid);
|
struct passwd *entry = getpwuid(uid);
|
||||||
if (entry == 0) {
|
if (entry == 0) {
|
||||||
const char *cp = getenv("HOME");
|
const char *cp = getenv("HOME");
|
||||||
if (cp)
|
if (cp) {
|
||||||
return cp;
|
return cp;
|
||||||
else
|
} else {
|
||||||
return "/";
|
return "/";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string homedir = entry->pw_dir;
|
string homedir = entry->pw_dir;
|
||||||
path_catslash(homedir);
|
path_catslash(homedir);
|
||||||
|
@ -541,8 +380,9 @@ string path_homedata()
|
||||||
|
|
||||||
string path_tildexpand(const string& s)
|
string path_tildexpand(const string& s)
|
||||||
{
|
{
|
||||||
if (s.empty() || s[0] != '~')
|
if (s.empty() || s[0] != '~') {
|
||||||
return s;
|
return s;
|
||||||
|
}
|
||||||
string o = s;
|
string o = s;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
path_slashize(o);
|
path_slashize(o);
|
||||||
|
@ -560,8 +400,9 @@ string path_tildexpand(const string &s)
|
||||||
o.replace(0, l + 1, path_home());
|
o.replace(0, l + 1, path_home());
|
||||||
#else
|
#else
|
||||||
struct passwd *entry = getpwnam(s.substr(1, l).c_str());
|
struct passwd *entry = getpwnam(s.substr(1, l).c_str());
|
||||||
if (entry)
|
if (entry) {
|
||||||
o.replace(0, l + 1, entry->pw_dir);
|
o.replace(0, l + 1, entry->pw_dir);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
|
@ -569,12 +410,14 @@ string path_tildexpand(const string &s)
|
||||||
|
|
||||||
bool path_isroot(const string& path)
|
bool path_isroot(const string& path)
|
||||||
{
|
{
|
||||||
if (path.size() == 1 && path[0] == '/')
|
if (path.size() == 1 && path[0] == '/') {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (path.size() == 3 && isalpha(path[0]) && path[1] == ':' &&
|
if (path.size() == 3 && isalpha(path[0]) && path[1] == ':' &&
|
||||||
(path[2] == '/' || path[2] == '\\'))
|
(path[2] == '/' || path[2] == '\\')) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -593,8 +436,9 @@ bool path_isabsolute(const string &path)
|
||||||
|
|
||||||
string path_absolute(const string& is)
|
string path_absolute(const string& is)
|
||||||
{
|
{
|
||||||
if (is.length() == 0)
|
if (is.length() == 0) {
|
||||||
return is;
|
return is;
|
||||||
|
}
|
||||||
string s = is;
|
string s = is;
|
||||||
if (!path_isabsolute(s)) {
|
if (!path_isabsolute(s)) {
|
||||||
char buf[MAXPATHLEN];
|
char buf[MAXPATHLEN];
|
||||||
|
@ -612,8 +456,9 @@ string path_absolute(const string &is)
|
||||||
#include <smallut.h>
|
#include <smallut.h>
|
||||||
string path_canon(const string& is, const string* cwd)
|
string path_canon(const string& is, const string* cwd)
|
||||||
{
|
{
|
||||||
if (is.length() == 0)
|
if (is.length() == 0) {
|
||||||
return is;
|
return is;
|
||||||
|
}
|
||||||
string s = is;
|
string s = is;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
path_slashize(s);
|
path_slashize(s);
|
||||||
|
@ -641,8 +486,9 @@ string path_canon(const string &is, const string* cwd)
|
||||||
for (vector<string>::const_iterator it = elems.begin();
|
for (vector<string>::const_iterator it = elems.begin();
|
||||||
it != elems.end(); it++) {
|
it != elems.end(); it++) {
|
||||||
if (*it == "..") {
|
if (*it == "..") {
|
||||||
if (!cleaned.empty())
|
if (!cleaned.empty()) {
|
||||||
cleaned.pop_back();
|
cleaned.pop_back();
|
||||||
|
}
|
||||||
} else if (it->empty() || *it == ".") {
|
} else if (it->empty() || *it == ".") {
|
||||||
} else {
|
} else {
|
||||||
cleaned.push_back(*it);
|
cleaned.push_back(*it);
|
||||||
|
@ -676,8 +522,9 @@ bool makepath(const string& ipath)
|
||||||
for (vector<string>::const_iterator it = elems.begin();
|
for (vector<string>::const_iterator it = elems.begin();
|
||||||
it != elems.end(); it++) {
|
it != elems.end(); it++) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (it == elems.begin() && path_strlookslikedrive(*it))
|
if (it == elems.begin() && path_strlookslikedrive(*it)) {
|
||||||
path = "";
|
path = "";
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
path += *it;
|
path += *it;
|
||||||
// Not using path_isdir() here, because this cant grok symlinks
|
// Not using path_isdir() here, because this cant grok symlinks
|
||||||
|
@ -695,30 +542,35 @@ bool makepath(const string& ipath)
|
||||||
bool path_isdir(const string& path)
|
bool path_isdir(const string& path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (lstat(path.c_str(), &st) < 0)
|
if (lstat(path.c_str(), &st) < 0) {
|
||||||
return false;
|
return false;
|
||||||
if (S_ISDIR(st.st_mode))
|
}
|
||||||
|
if (S_ISDIR(st.st_mode)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long path_filesize(const string& path)
|
long long path_filesize(const string& path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(path.c_str(), &st) < 0)
|
if (stat(path.c_str(), &st) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
return (long long)st.st_size;
|
return (long long)st.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int path_fileprops(const std::string path, struct stat *stp, bool follow)
|
int path_fileprops(const std::string path, struct stat *stp, bool follow)
|
||||||
{
|
{
|
||||||
if (!stp)
|
if (!stp) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
memset(stp, 0, sizeof(struct stat));
|
memset(stp, 0, sizeof(struct stat));
|
||||||
struct stat mst;
|
struct stat mst;
|
||||||
int ret = follow ? stat(path.c_str(), &mst) : lstat(path.c_str(), &mst);
|
int ret = follow ? stat(path.c_str(), &mst) : lstat(path.c_str(), &mst);
|
||||||
if (ret != 0)
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
stp->st_size = mst.st_size;
|
stp->st_size = mst.st_size;
|
||||||
stp->st_mode = mst.st_mode;
|
stp->st_mode = mst.st_mode;
|
||||||
stp->st_mtime = mst.st_mtime;
|
stp->st_mtime = mst.st_mtime;
|
||||||
|
@ -822,14 +674,16 @@ string url_gpath(const string& url)
|
||||||
{
|
{
|
||||||
// Remove the access schema part (or whatever it's called)
|
// Remove the access schema part (or whatever it's called)
|
||||||
string::size_type colon = url.find_first_of(":");
|
string::size_type colon = url.find_first_of(":");
|
||||||
if (colon == string::npos || colon == url.size() - 1)
|
if (colon == string::npos || colon == url.size() - 1) {
|
||||||
return url;
|
return url;
|
||||||
|
}
|
||||||
// If there are non-alphanum chars before the ':', then there
|
// If there are non-alphanum chars before the ':', then there
|
||||||
// probably is no scheme. Whatever...
|
// probably is no scheme. Whatever...
|
||||||
for (string::size_type i = 0; i < colon; i++) {
|
for (string::size_type i = 0; i < colon; i++) {
|
||||||
if (!isalnum(url.at(i)))
|
if (!isalnum(url.at(i))) {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// In addition we canonize the path to remove empty host parts
|
// In addition we canonize the path to remove empty host parts
|
||||||
// (for compatibility with older versions of recoll where file://
|
// (for compatibility with older versions of recoll where file://
|
||||||
|
@ -838,29 +692,6 @@ string url_gpath(const string& url)
|
||||||
return path_canon(url.substr(colon + 1));
|
return path_canon(url.substr(colon + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
string url_gpathS(const string& url)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
string u = url_gpath(url);
|
|
||||||
string nu;
|
|
||||||
if (path_hasdrive(u)) {
|
|
||||||
nu.append(1, '/');
|
|
||||||
nu.append(1, u[0]);
|
|
||||||
if (path_isdriveabs(u)) {
|
|
||||||
nu.append(u.substr(2));
|
|
||||||
} else {
|
|
||||||
// This should be an error really
|
|
||||||
nu.append(1, '/');
|
|
||||||
nu.append(u.substr(2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nu;
|
|
||||||
#else
|
|
||||||
return url_gpath(url);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
string url_parentfolder(const string& url)
|
string url_parentfolder(const string& url)
|
||||||
{
|
{
|
||||||
// In general, the parent is the directory above the full path
|
// In general, the parent is the directory above the full path
|
||||||
|
@ -876,24 +707,16 @@ string url_parentfolder(const string& url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string path_defaultrecollconfsubdir()
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
return "Recoll";
|
|
||||||
#else
|
|
||||||
return ".recoll";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert to file path if url is like file:
|
// Convert to file path if url is like file:
|
||||||
// Note: this only works with our internal pseudo-urls which are not
|
// Note: this only works with our internal pseudo-urls which are not
|
||||||
// encoded/escaped
|
// encoded/escaped
|
||||||
string fileurltolocalpath(string url)
|
string fileurltolocalpath(string url)
|
||||||
{
|
{
|
||||||
if (url.find("file://") == 0)
|
if (url.find("file://") == 0) {
|
||||||
url = url.substr(7, string::npos);
|
url = url.substr(7, string::npos);
|
||||||
else
|
} else {
|
||||||
return string();
|
return string();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Absolute file urls are like: file:///c:/mydir/...
|
// Absolute file urls are like: file:///c:/mydir/...
|
||||||
|
@ -916,13 +739,16 @@ string fileurltolocalpath(string url)
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const string cstr_fileu("file://");
|
||||||
|
|
||||||
string path_pathtofileurl(const string& path)
|
string path_pathtofileurl(const string& path)
|
||||||
{
|
{
|
||||||
// We're supposed to receive a canonic absolute path, but on windows we
|
// We're supposed to receive a canonic absolute path, but on windows we
|
||||||
// may need to add a '/' in front of the drive spec
|
// may need to add a '/' in front of the drive spec
|
||||||
string url(cstr_fileu);
|
string url(cstr_fileu);
|
||||||
if (path.empty() || path[0] != '/')
|
if (path.empty() || path[0] != '/') {
|
||||||
url.push_back('/');
|
url.push_back('/');
|
||||||
|
}
|
||||||
url += path;
|
url += path;
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
@ -932,17 +758,6 @@ bool urlisfileurl(const string& url)
|
||||||
return url.find("file://") == 0;
|
return url.find("file://") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Printable url: this is used to transcode from the system charset
|
|
||||||
// into either utf-8 if transcoding succeeds, or url-encoded
|
|
||||||
bool printableUrl(const string &fcharset, const string &in, string &out)
|
|
||||||
{
|
|
||||||
int ecnt = 0;
|
|
||||||
if (!transcode(in, out, fcharset, "UTF-8", &ecnt) || ecnt) {
|
|
||||||
out = url_encode(in, 7);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool readdir(const string& dir, string& reason, set<string>& entries)
|
bool readdir(const string& dir, string& reason, set<string>& entries)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -971,17 +786,20 @@ bool readdir(const string& dir, string& reason, set<string>& entries)
|
||||||
|
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
while ((ent = readdir(d)) != 0) {
|
while ((ent = readdir(d)) != 0) {
|
||||||
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
|
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
entries.insert(ent->d_name);
|
entries.insert(ent->d_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (d)
|
if (d) {
|
||||||
closedir(d);
|
closedir(d);
|
||||||
|
}
|
||||||
reason = msg.str();
|
reason = msg.str();
|
||||||
if (reason.empty())
|
if (reason.empty()) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -992,27 +810,31 @@ out:
|
||||||
// alone.
|
// alone.
|
||||||
Pidfile::~Pidfile()
|
Pidfile::~Pidfile()
|
||||||
{
|
{
|
||||||
if (m_fd >= 0)
|
if (m_fd >= 0) {
|
||||||
::close(m_fd);
|
::close(m_fd);
|
||||||
|
}
|
||||||
m_fd = -1;
|
m_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t Pidfile::read_pid()
|
pid_t Pidfile::read_pid()
|
||||||
{
|
{
|
||||||
int fd = ::open(m_path.c_str(), O_RDONLY);
|
int fd = ::open(m_path.c_str(), O_RDONLY);
|
||||||
if (fd == -1)
|
if (fd == -1) {
|
||||||
return (pid_t) - 1;
|
return (pid_t) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
char buf[16];
|
char buf[16];
|
||||||
int i = read(fd, buf, sizeof(buf) - 1);
|
int i = read(fd, buf, sizeof(buf) - 1);
|
||||||
::close(fd);
|
::close(fd);
|
||||||
if (i <= 0)
|
if (i <= 0) {
|
||||||
return (pid_t) - 1;
|
return (pid_t) - 1;
|
||||||
|
}
|
||||||
buf[i] = '\0';
|
buf[i] = '\0';
|
||||||
char *endptr;
|
char *endptr;
|
||||||
pid_t pid = strtol(buf, &endptr, 10);
|
pid_t pid = strtol(buf, &endptr, 10);
|
||||||
if (endptr != &buf[i])
|
if (endptr != &buf[i]) {
|
||||||
return (pid_t) - 1;
|
return (pid_t) - 1;
|
||||||
|
}
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1098,79 +920,10 @@ int Pidfile::remove()
|
||||||
return unlink(m_path.c_str());
|
return unlink(m_path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Freedesktop standard paths for cache directory (thumbnails are now in there)
|
|
||||||
static const string& xdgcachedir()
|
|
||||||
{
|
|
||||||
static string xdgcache;
|
|
||||||
if (xdgcache.empty()) {
|
|
||||||
const char *cp = getenv("XDG_CACHE_HOME");
|
|
||||||
if (cp == 0)
|
|
||||||
xdgcache = path_cat(path_home(), ".cache");
|
|
||||||
else
|
|
||||||
xdgcache = string(cp);
|
|
||||||
}
|
|
||||||
return xdgcache;
|
|
||||||
}
|
|
||||||
static const string& thumbnailsdir()
|
|
||||||
{
|
|
||||||
static string thumbnailsd;
|
|
||||||
if (thumbnailsd.empty()) {
|
|
||||||
thumbnailsd = path_cat(xdgcachedir(), "thumbnails");
|
|
||||||
if (access(thumbnailsd.c_str(), 0) != 0) {
|
|
||||||
thumbnailsd = path_cat(path_home(), ".thumbnails");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return thumbnailsd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Place for 256x256 files
|
|
||||||
static const string thmbdirlarge = "large";
|
|
||||||
// 128x128
|
|
||||||
static const string thmbdirnormal = "normal";
|
|
||||||
|
|
||||||
static void thumbname(const string& url, string& name)
|
|
||||||
{
|
|
||||||
string digest;
|
|
||||||
string l_url = url_encode(url);
|
|
||||||
MD5String(l_url, digest);
|
|
||||||
MD5HexPrint(digest, name);
|
|
||||||
name += ".png";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool thumbPathForUrl(const string& url, int size, string& path)
|
|
||||||
{
|
|
||||||
string name;
|
|
||||||
thumbname(url, name);
|
|
||||||
if (size <= 128) {
|
|
||||||
path = path_cat(thumbnailsdir(), thmbdirnormal);
|
|
||||||
path = path_cat(path, name);
|
|
||||||
if (access(path.c_str(), R_OK) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
path = path_cat(thumbnailsdir(), thmbdirlarge);
|
|
||||||
path = path_cat(path, name);
|
|
||||||
if (access(path.c_str(), R_OK) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// File does not exist. Path corresponds to the large version at this point,
|
|
||||||
// fix it if needed.
|
|
||||||
if (size <= 128) {
|
|
||||||
path = path_cat(path_home(), thmbdirnormal);
|
|
||||||
path = path_cat(path, name);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call funcs that need static init (not initially reentrant)
|
// Call funcs that need static init (not initially reentrant)
|
||||||
void pathut_init_mt()
|
void pathut_init_mt()
|
||||||
{
|
{
|
||||||
path_home();
|
path_home();
|
||||||
tmplocation();
|
|
||||||
thumbnailsdir();
|
|
||||||
path_sharedatadir();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1185,8 +938,9 @@ void path_to_thumb(const string& _input)
|
||||||
{
|
{
|
||||||
string input(_input);
|
string input(_input);
|
||||||
// Make absolute path if needed
|
// Make absolute path if needed
|
||||||
if (input[0] != '/')
|
if (input[0] != '/') {
|
||||||
input = path_absolute(input);
|
input = path_absolute(input);
|
||||||
|
}
|
||||||
|
|
||||||
input = string("file://") + path_canon(input);
|
input = string("file://") + path_canon(input);
|
||||||
|
|
||||||
|
@ -1203,14 +957,16 @@ const char *tstvec[] = {"", "/", "/dir", "/dir/", "/dir1/dir2",
|
||||||
};
|
};
|
||||||
|
|
||||||
const string ttvec[] = {"/dir", "", "~", "~/sub", "~root", "~root/sub",
|
const string ttvec[] = {"/dir", "", "~", "~/sub", "~root", "~root/sub",
|
||||||
"~nosuch", "~nosuch/sub"};
|
"~nosuch", "~nosuch/sub"
|
||||||
|
};
|
||||||
int nttvec = sizeof(ttvec) / sizeof(string);
|
int nttvec = sizeof(ttvec) / sizeof(string);
|
||||||
|
|
||||||
const char *thisprog;
|
const char *thisprog;
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
thisprog = *argv++;argc--;
|
thisprog = *argv++;
|
||||||
|
argc--;
|
||||||
|
|
||||||
string s;
|
string s;
|
||||||
vector<string>::const_iterator it;
|
vector<string>::const_iterator it;
|
||||||
|
@ -1251,8 +1007,10 @@ int main(int argc, const char **argv)
|
||||||
cerr << "Usage: trpathut <dir> <pattern>" << endl;
|
cerr << "Usage: trpathut <dir> <pattern>" << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
string dir = *argv++;argc--;
|
string dir = *argv++;
|
||||||
string pattern = *argv++;argc--;
|
argc--;
|
||||||
|
string pattern = *argv++;
|
||||||
|
argc--;
|
||||||
vector<string> matched = path_dirglob(dir, pattern);
|
vector<string> matched = path_dirglob(dir, pattern);
|
||||||
for (it = matched.begin(); it != matched.end(); it++) {
|
for (it = matched.begin(); it != matched.end(); it++) {
|
||||||
cout << *it << endl;
|
cout << *it << endl;
|
||||||
|
@ -1264,7 +1022,8 @@ int main(int argc, const char **argv)
|
||||||
fprintf(stderr, "Usage: fsocc: trpathut <path>\n");
|
fprintf(stderr, "Usage: fsocc: trpathut <path>\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
string path = *argv++;argc--;
|
string path = *argv++;
|
||||||
|
argc--;
|
||||||
|
|
||||||
int pc;
|
int pc;
|
||||||
long long blocks;
|
long long blocks;
|
||||||
|
@ -1303,9 +1062,10 @@ int main(int argc, const char **argv)
|
||||||
}
|
}
|
||||||
path_to_thumb(input);
|
path_to_thumb(input);
|
||||||
} else {
|
} else {
|
||||||
while (getline(cin, input))
|
while (getline(cin, input)) {
|
||||||
path_to_thumb(input);
|
path_to_thumb(input);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -1316,7 +1076,8 @@ int main(int argc, const char **argv)
|
||||||
cerr << "Usage: trpathut <filename>" << endl;
|
cerr << "Usage: trpathut <filename>" << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
string fn = *argv++;argc--;
|
string fn = *argv++;
|
||||||
|
argc--;
|
||||||
string ext = path_suffix(fn);
|
string ext = path_suffix(fn);
|
||||||
cout << "Suffix: [" << ext << "]" << endl;
|
cout << "Suffix: [" << ext << "]" << endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1327,7 +1088,8 @@ int main(int argc, const char **argv)
|
||||||
cerr << "Usage: trpathut url" << endl;
|
cerr << "Usage: trpathut url" << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
string url = *argv++;argc--;
|
string url = *argv++;
|
||||||
|
argc--;
|
||||||
|
|
||||||
cout << "File: [" << fileurltolocalpath(url) << "]\n";
|
cout << "File: [" << fileurltolocalpath(url) << "]\n";
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
*/
|
*/
|
||||||
#ifndef _PATHUT_H_INCLUDED_
|
#ifndef _PATHUT_H_INCLUDED_
|
||||||
#define _PATHUT_H_INCLUDED_
|
#define _PATHUT_H_INCLUDED_
|
||||||
#include "autoconfig.h"
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include MEMORY_INCLUDE
|
// Must be called in main thread before starting other threads
|
||||||
|
extern void pathut_init_mt();
|
||||||
|
|
||||||
/// Add a / at the end if none there yet.
|
/// Add a / at the end if none there yet.
|
||||||
extern void path_catslash(std::string& s);
|
extern void path_catslash(std::string& s);
|
||||||
|
@ -52,9 +52,6 @@ extern std::vector<std::string> path_dirglob(const std::string &dir,
|
||||||
/// Encode according to rfc 1738
|
/// Encode according to rfc 1738
|
||||||
extern std::string url_encode(const std::string& url,
|
extern std::string url_encode(const std::string& url,
|
||||||
std::string::size_type offs = 0);
|
std::string::size_type offs = 0);
|
||||||
/// Transcode to utf-8 if possible or url encoding, for display.
|
|
||||||
extern bool printableUrl(const std::string &fcharset,
|
|
||||||
const std::string &in, std::string &out);
|
|
||||||
//// Convert to file path if url is like file://. This modifies the
|
//// Convert to file path if url is like file://. This modifies the
|
||||||
//// input (and returns a copy for convenience)
|
//// input (and returns a copy for convenience)
|
||||||
extern std::string fileurltolocalpath(std::string url);
|
extern std::string fileurltolocalpath(std::string url);
|
||||||
|
@ -67,12 +64,6 @@ extern std::string url_parentfolder(const std::string& url);
|
||||||
/// routine, it does the right thing only in the recoll context
|
/// routine, it does the right thing only in the recoll context
|
||||||
extern std::string url_gpath(const std::string& url);
|
extern std::string url_gpath(const std::string& url);
|
||||||
|
|
||||||
/// Same but, in the case of a Windows local path, also turn "c:/" into
|
|
||||||
/// "/c/" This should be used only for splitting the path in rcldb, it
|
|
||||||
/// would better be local in there, but I prefer to keep all the
|
|
||||||
/// system-specific path stuff in pathut
|
|
||||||
extern std::string url_gpathS(const std::string& url);
|
|
||||||
|
|
||||||
/// Stat parameter and check if it's a directory
|
/// Stat parameter and check if it's a directory
|
||||||
extern bool path_isdir(const std::string& path);
|
extern bool path_isdir(const std::string& path);
|
||||||
|
|
||||||
|
@ -103,26 +94,17 @@ extern bool readdir(const std::string& dir, std::string& reason,
|
||||||
std::set<std::string>& entries);
|
std::set<std::string>& entries);
|
||||||
|
|
||||||
/** A small wrapper around statfs et al, to return percentage of disk
|
/** A small wrapper around statfs et al, to return percentage of disk
|
||||||
occupation */
|
occupation
|
||||||
bool fsocc(const std::string &path, int *pc, // Percent occupied
|
@param[output] pc percent occupied
|
||||||
long long *avmbs = 0 // Mbs available to non-superuser. Mb=1024*1024
|
@param[output] avmbs Mbs available to non-superuser. Mb=1024*1024
|
||||||
);
|
*/
|
||||||
|
bool fsocc(const std::string& path, int *pc, long long *avmbs = 0);
|
||||||
/// Retrieve the temp dir location: $RECOLL_TMPDIR else $TMPDIR else /tmp
|
|
||||||
extern const std::string& tmplocation();
|
|
||||||
|
|
||||||
/// Create temporary directory (inside the temp location)
|
|
||||||
extern bool maketmpdir(std::string& tdir, std::string& reason);
|
|
||||||
|
|
||||||
/// mkdir -p
|
/// mkdir -p
|
||||||
extern bool makepath(const std::string& path);
|
extern bool makepath(const std::string& path);
|
||||||
|
|
||||||
/// Sub-directory for default recoll config (e.g: .recoll)
|
|
||||||
extern std::string path_defaultrecollconfsubdir();
|
|
||||||
/// Where we create the user data subdirs
|
/// Where we create the user data subdirs
|
||||||
extern std::string path_homedata();
|
extern std::string path_homedata();
|
||||||
/// e.g. /usr/share/recoll. Depends on OS and config
|
|
||||||
extern const std::string& path_sharedatadir();
|
|
||||||
/// Test if path is absolute
|
/// Test if path is absolute
|
||||||
extern bool path_isabsolute(const std::string& s);
|
extern bool path_isabsolute(const std::string& s);
|
||||||
|
|
||||||
|
@ -137,52 +119,6 @@ extern std::string path_pathtofileurl(const std::string& path);
|
||||||
void path_slashize(std::string& s);
|
void path_slashize(std::string& s);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Temporary file class
|
|
||||||
class TempFileInternal {
|
|
||||||
public:
|
|
||||||
TempFileInternal(const std::string& suffix);
|
|
||||||
~TempFileInternal();
|
|
||||||
const char *filename()
|
|
||||||
{
|
|
||||||
return m_filename.c_str();
|
|
||||||
}
|
|
||||||
const std::string &getreason()
|
|
||||||
{
|
|
||||||
return m_reason;
|
|
||||||
}
|
|
||||||
void setnoremove(bool onoff)
|
|
||||||
{
|
|
||||||
m_noremove = onoff;
|
|
||||||
}
|
|
||||||
bool ok()
|
|
||||||
{
|
|
||||||
return !m_filename.empty();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::string m_filename;
|
|
||||||
std::string m_reason;
|
|
||||||
bool m_noremove;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef STD_SHARED_PTR<TempFileInternal> TempFile;
|
|
||||||
|
|
||||||
/// Temporary directory class. Recursively deleted by destructor.
|
|
||||||
class TempDir {
|
|
||||||
public:
|
|
||||||
TempDir();
|
|
||||||
~TempDir();
|
|
||||||
const char *dirname() {return m_dirname.c_str();}
|
|
||||||
const std::string &getreason() {return m_reason;}
|
|
||||||
bool ok() {return !m_dirname.empty();}
|
|
||||||
/// Recursively delete contents but not self.
|
|
||||||
bool wipe();
|
|
||||||
private:
|
|
||||||
std::string m_dirname;
|
|
||||||
std::string m_reason;
|
|
||||||
TempDir(const TempDir &) {}
|
|
||||||
TempDir& operator=(const TempDir &) {return *this;};
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Lock/pid file class. This is quite close to the pidfile_xxx
|
/// Lock/pid file class. This is quite close to the pidfile_xxx
|
||||||
/// utilities in FreeBSD with a bit more encapsulation. I'd have used
|
/// utilities in FreeBSD with a bit more encapsulation. I'd have used
|
||||||
/// the freebsd code if it was available elsewhere
|
/// the freebsd code if it was available elsewhere
|
||||||
|
@ -200,7 +136,9 @@ public:
|
||||||
int close();
|
int close();
|
||||||
/// Delete the pid file
|
/// Delete the pid file
|
||||||
int remove();
|
int remove();
|
||||||
const std::string& getreason() {return m_reason;}
|
const std::string& getreason() {
|
||||||
|
return m_reason;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
int m_fd;
|
int m_fd;
|
||||||
|
@ -209,14 +147,4 @@ private:
|
||||||
int flopen();
|
int flopen();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Freedesktop thumbnail standard path routine
|
|
||||||
// On return, path will have the appropriate value in all cases,
|
|
||||||
// returns true if the file already exists
|
|
||||||
extern bool thumbPathForUrl(const std::string& url, int size, std::string& path);
|
|
||||||
|
|
||||||
// Must be called in main thread before starting other threads
|
|
||||||
extern void pathut_init_mt();
|
|
||||||
|
|
||||||
#endif /* _PATHUT_H_INCLUDED_ */
|
#endif /* _PATHUT_H_INCLUDED_ */
|
||||||
|
|
411
src/utils/rclutil.cpp
Normal file
411
src/utils/rclutil.cpp
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
/* Copyright (C) 2016 J.F.Dockes
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the
|
||||||
|
* Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
#ifndef TEST_RCLUTIL
|
||||||
|
#include "autoconfig.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "safefcntl.h"
|
||||||
|
#include "safeunistd.h"
|
||||||
|
#include "dirent.h"
|
||||||
|
#include "cstr.h"
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "safewindows.h"
|
||||||
|
#else
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#endif
|
||||||
|
#include <math.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "safesysstat.h"
|
||||||
|
#include "ptmutex.h"
|
||||||
|
|
||||||
|
#include "rclutil.h"
|
||||||
|
#include "pathut.h"
|
||||||
|
#include "wipedir.h"
|
||||||
|
#include "transcode.h"
|
||||||
|
#include "md5ut.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
void map_ss_cp_noshr(const map<string, string> s, map<string, string> *d)
|
||||||
|
{
|
||||||
|
for (map<string, string>::const_iterator it = s.begin();
|
||||||
|
it != s.end(); it++) {
|
||||||
|
d->insert(
|
||||||
|
pair<string, string>(string(it->first.begin(), it->first.end()),
|
||||||
|
string(it->second.begin(), it->second.end())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string path_defaultrecollconfsubdir()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return "Recoll";
|
||||||
|
#else
|
||||||
|
return ".recoll";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Location for sample config, filters, etc. (e.g. /usr/share/recoll/)
|
||||||
|
const string& path_pkgdatadir()
|
||||||
|
{
|
||||||
|
static string datadir;
|
||||||
|
if (datadir.empty()) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
datadir = path_cat(path_thisexecpath(), "Share");
|
||||||
|
#else
|
||||||
|
const char *cdatadir = getenv("RECOLL_DATADIR");
|
||||||
|
if (cdatadir == 0) {
|
||||||
|
// If not in environment, use the compiled-in constant.
|
||||||
|
datadir = RECOLL_DATADIR;
|
||||||
|
} else {
|
||||||
|
datadir = cdatadir;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return datadir;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printable url: this is used to transcode from the system charset
|
||||||
|
// into either utf-8 if transcoding succeeds, or url-encoded
|
||||||
|
bool printableUrl(const string& fcharset, const string& in, string& out)
|
||||||
|
{
|
||||||
|
int ecnt = 0;
|
||||||
|
if (!transcode(in, out, fcharset, "UTF-8", &ecnt) || ecnt) {
|
||||||
|
out = url_encode(in, 7);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string url_gpathS(const string& url)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
string u = url_gpath(url);
|
||||||
|
string nu;
|
||||||
|
if (path_hasdrive(u)) {
|
||||||
|
nu.append(1, '/');
|
||||||
|
nu.append(1, u[0]);
|
||||||
|
if (path_isdriveabs(u)) {
|
||||||
|
nu.append(u.substr(2));
|
||||||
|
} else {
|
||||||
|
// This should be an error really
|
||||||
|
nu.append(1, '/');
|
||||||
|
nu.append(u.substr(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nu;
|
||||||
|
#else
|
||||||
|
return url_gpath(url);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const string& tmplocation()
|
||||||
|
{
|
||||||
|
static string stmpdir;
|
||||||
|
if (stmpdir.empty()) {
|
||||||
|
const char *tmpdir = getenv("RECOLL_TMPDIR");
|
||||||
|
if (tmpdir == 0) {
|
||||||
|
tmpdir = getenv("TMPDIR");
|
||||||
|
}
|
||||||
|
if (tmpdir == 0) {
|
||||||
|
tmpdir = getenv("TMP");
|
||||||
|
}
|
||||||
|
if (tmpdir == 0) {
|
||||||
|
tmpdir = getenv("TEMP");
|
||||||
|
}
|
||||||
|
if (tmpdir == 0) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
TCHAR bufw[(MAX_PATH + 1)*sizeof(TCHAR)];
|
||||||
|
GetTempPath(MAX_PATH + 1, bufw);
|
||||||
|
stmpdir = path_tchartoutf8(bufw);
|
||||||
|
#else
|
||||||
|
stmpdir = "/tmp";
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
stmpdir = tmpdir;
|
||||||
|
}
|
||||||
|
stmpdir = path_canon(stmpdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stmpdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool maketmpdir(string& tdir, string& reason)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
tdir = path_cat(tmplocation(), "rcltmpXXXXXX");
|
||||||
|
|
||||||
|
char *cp = strdup(tdir.c_str());
|
||||||
|
if (!cp) {
|
||||||
|
reason = "maketmpdir: out of memory (for file name !)\n";
|
||||||
|
tdir.erase();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is a race condition between name computation and
|
||||||
|
// mkdir. try to make sure that we at least don't shoot ourselves
|
||||||
|
// in the foot
|
||||||
|
#if !defined(HAVE_MKDTEMP) || defined(_WIN32)
|
||||||
|
static PTMutexInit mlock;
|
||||||
|
PTMutexLocker lock(mlock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!
|
||||||
|
#ifdef HAVE_MKDTEMP
|
||||||
|
mkdtemp(cp)
|
||||||
|
#else
|
||||||
|
mktemp(cp)
|
||||||
|
#endif // HAVE_MKDTEMP
|
||||||
|
) {
|
||||||
|
free(cp);
|
||||||
|
reason = "maketmpdir: mktemp failed for [" + tdir + "] : " +
|
||||||
|
strerror(errno);
|
||||||
|
tdir.erase();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tdir = cp;
|
||||||
|
free(cp);
|
||||||
|
#else // _WIN32
|
||||||
|
// There is a race condition between name computation and
|
||||||
|
// mkdir. try to make sure that we at least don't shoot ourselves
|
||||||
|
// in the foot
|
||||||
|
static PTMutexInit mlock;
|
||||||
|
PTMutexLocker lock(mlock);
|
||||||
|
tdir = path_wingettempfilename(TEXT("rcltmp"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// At this point the directory does not exist yet except if we used
|
||||||
|
// mkdtemp
|
||||||
|
|
||||||
|
#if !defined(HAVE_MKDTEMP) || defined(_WIN32)
|
||||||
|
if (mkdir(tdir.c_str(), 0700) < 0) {
|
||||||
|
reason = string("maketmpdir: mkdir ") + tdir + " failed";
|
||||||
|
tdir.erase();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TempFileInternal::TempFileInternal(const string& suffix)
|
||||||
|
: m_noremove(false)
|
||||||
|
{
|
||||||
|
// Because we need a specific suffix, can't use mkstemp
|
||||||
|
// well. There is a race condition between name computation and
|
||||||
|
// file creation. try to make sure that we at least don't shoot
|
||||||
|
// our own selves in the foot. maybe we'll use mkstemps one day.
|
||||||
|
static PTMutexInit mlock;
|
||||||
|
PTMutexLocker lock(mlock);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
string filename = path_cat(tmplocation(), "rcltmpfXXXXXX");
|
||||||
|
char *cp = strdup(filename.c_str());
|
||||||
|
if (!cp) {
|
||||||
|
m_reason = "Out of memory (for file name !)\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using mkstemp this way is awful (bot the suffix adding and
|
||||||
|
// using mkstemp() instead of mktemp just to avoid the warnings)
|
||||||
|
int fd;
|
||||||
|
if ((fd = mkstemp(cp)) < 0) {
|
||||||
|
free(cp);
|
||||||
|
m_reason = "TempFileInternal: mkstemp failed\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
unlink(cp);
|
||||||
|
filename = cp;
|
||||||
|
free(cp);
|
||||||
|
#else
|
||||||
|
string filename = path_wingettempfilename(TEXT("recoll"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_filename = filename + suffix;
|
||||||
|
if (close(open(m_filename.c_str(), O_CREAT | O_EXCL, 0600)) != 0) {
|
||||||
|
m_reason = string("Could not open/create") + m_filename;
|
||||||
|
m_filename.erase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TempFileInternal::~TempFileInternal()
|
||||||
|
{
|
||||||
|
if (!m_filename.empty() && !m_noremove) {
|
||||||
|
unlink(m_filename.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TempDir::TempDir()
|
||||||
|
{
|
||||||
|
if (!maketmpdir(m_dirname, m_reason)) {
|
||||||
|
m_dirname.erase();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TempDir::~TempDir()
|
||||||
|
{
|
||||||
|
if (!m_dirname.empty()) {
|
||||||
|
(void)wipedir(m_dirname, true, true);
|
||||||
|
m_dirname.erase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TempDir::wipe()
|
||||||
|
{
|
||||||
|
if (m_dirname.empty()) {
|
||||||
|
m_reason = "TempDir::wipe: no directory !\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (wipedir(m_dirname, false, true)) {
|
||||||
|
m_reason = "TempDir::wipe: wipedir failed\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Freedesktop standard paths for cache directory (thumbnails are now in there)
|
||||||
|
static const string& xdgcachedir()
|
||||||
|
{
|
||||||
|
static string xdgcache;
|
||||||
|
if (xdgcache.empty()) {
|
||||||
|
const char *cp = getenv("XDG_CACHE_HOME");
|
||||||
|
if (cp == 0) {
|
||||||
|
xdgcache = path_cat(path_home(), ".cache");
|
||||||
|
} else {
|
||||||
|
xdgcache = string(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return xdgcache;
|
||||||
|
}
|
||||||
|
static const string& thumbnailsdir()
|
||||||
|
{
|
||||||
|
static string thumbnailsd;
|
||||||
|
if (thumbnailsd.empty()) {
|
||||||
|
thumbnailsd = path_cat(xdgcachedir(), "thumbnails");
|
||||||
|
if (access(thumbnailsd.c_str(), 0) != 0) {
|
||||||
|
thumbnailsd = path_cat(path_home(), ".thumbnails");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return thumbnailsd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place for 256x256 files
|
||||||
|
static const string thmbdirlarge = "large";
|
||||||
|
// 128x128
|
||||||
|
static const string thmbdirnormal = "normal";
|
||||||
|
|
||||||
|
static void thumbname(const string& url, string& name)
|
||||||
|
{
|
||||||
|
string digest;
|
||||||
|
string l_url = url_encode(url);
|
||||||
|
MD5String(l_url, digest);
|
||||||
|
MD5HexPrint(digest, name);
|
||||||
|
name += ".png";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool thumbPathForUrl(const string& url, int size, string& path)
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
thumbname(url, name);
|
||||||
|
if (size <= 128) {
|
||||||
|
path = path_cat(thumbnailsdir(), thmbdirnormal);
|
||||||
|
path = path_cat(path, name);
|
||||||
|
if (access(path.c_str(), R_OK) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path = path_cat(thumbnailsdir(), thmbdirlarge);
|
||||||
|
path = path_cat(path, name);
|
||||||
|
if (access(path.c_str(), R_OK) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// File does not exist. Path corresponds to the large version at this point,
|
||||||
|
// fix it if needed.
|
||||||
|
if (size <= 128) {
|
||||||
|
path = path_cat(path_home(), thmbdirnormal);
|
||||||
|
path = path_cat(path, name);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rclutil_init_mt()
|
||||||
|
{
|
||||||
|
path_pkgdatadir();
|
||||||
|
tmplocation();
|
||||||
|
thumbnailsdir();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // TEST_RCLUTIL
|
||||||
|
|
||||||
|
void path_to_thumb(const string& _input)
|
||||||
|
{
|
||||||
|
string input(_input);
|
||||||
|
// Make absolute path if needed
|
||||||
|
if (input[0] != '/') {
|
||||||
|
input = path_absolute(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
input = string("file://") + path_canon(input);
|
||||||
|
|
||||||
|
string path;
|
||||||
|
//path = url_encode(input, 7);
|
||||||
|
thumbPathForUrl(input, 7, path);
|
||||||
|
cout << path << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *thisprog;
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
thisprog = *argv++;
|
||||||
|
argc--;
|
||||||
|
|
||||||
|
string s;
|
||||||
|
vector<string>::const_iterator it;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (argc > 1) {
|
||||||
|
cerr << "Usage: thumbpath <filepath>" << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
string input;
|
||||||
|
if (argc == 1) {
|
||||||
|
input = *argv++;
|
||||||
|
if (input.empty()) {
|
||||||
|
cerr << "Usage: thumbpath <filepath>" << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
path_to_thumb(input);
|
||||||
|
} else {
|
||||||
|
while (getline(cin, input)) {
|
||||||
|
path_to_thumb(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TEST_RCLUTIL
|
||||||
|
|
112
src/utils/rclutil.h
Normal file
112
src/utils/rclutil.h
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/* Copyright (C) 2016 J.F.Dockes
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the
|
||||||
|
* Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _RCLUTIL_H_INCLUDED_
|
||||||
|
#define _RCLUTIL_H_INCLUDED_
|
||||||
|
#include "autoconfig.h"
|
||||||
|
|
||||||
|
// Misc stuff not generic enough to get into smallut or pathut
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include MEMORY_INCLUDE
|
||||||
|
|
||||||
|
|
||||||
|
extern void rclutil_init_mt();
|
||||||
|
|
||||||
|
/// Sub-directory for default recoll config (e.g: .recoll)
|
||||||
|
extern std::string path_defaultrecollconfsubdir();
|
||||||
|
|
||||||
|
/// e.g. /usr/share/recoll. Depends on OS and config
|
||||||
|
extern const std::string& path_pkgdatadir();
|
||||||
|
|
||||||
|
/// Transcode to utf-8 if possible or url encoding, for display.
|
||||||
|
extern bool printableUrl(const std::string& fcharset,
|
||||||
|
const std::string& in, std::string& out);
|
||||||
|
/// Same but, in the case of a Windows local path, also turn "c:/" into
|
||||||
|
/// "/c/" This should be used only for splitting the path in rcldb.
|
||||||
|
extern std::string url_gpathS(const std::string& url);
|
||||||
|
|
||||||
|
/// Retrieve the temp dir location: $RECOLL_TMPDIR else $TMPDIR else /tmp
|
||||||
|
extern const std::string& tmplocation();
|
||||||
|
|
||||||
|
/// Create temporary directory (inside the temp location)
|
||||||
|
extern bool maketmpdir(std::string& tdir, std::string& reason);
|
||||||
|
|
||||||
|
/// Temporary file class
|
||||||
|
class TempFileInternal {
|
||||||
|
public:
|
||||||
|
TempFileInternal(const std::string& suffix);
|
||||||
|
~TempFileInternal();
|
||||||
|
const char *filename() {
|
||||||
|
return m_filename.c_str();
|
||||||
|
}
|
||||||
|
const std::string& getreason() {
|
||||||
|
return m_reason;
|
||||||
|
}
|
||||||
|
void setnoremove(bool onoff) {
|
||||||
|
m_noremove = onoff;
|
||||||
|
}
|
||||||
|
bool ok() {
|
||||||
|
return !m_filename.empty();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::string m_filename;
|
||||||
|
std::string m_reason;
|
||||||
|
bool m_noremove;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef STD_SHARED_PTR<TempFileInternal> TempFile;
|
||||||
|
|
||||||
|
/// Temporary directory class. Recursively deleted by destructor.
|
||||||
|
class TempDir {
|
||||||
|
public:
|
||||||
|
TempDir();
|
||||||
|
~TempDir();
|
||||||
|
const char *dirname() {
|
||||||
|
return m_dirname.c_str();
|
||||||
|
}
|
||||||
|
const std::string& getreason() {
|
||||||
|
return m_reason;
|
||||||
|
}
|
||||||
|
bool ok() {
|
||||||
|
return !m_dirname.empty();
|
||||||
|
}
|
||||||
|
/// Recursively delete contents but not self.
|
||||||
|
bool wipe();
|
||||||
|
private:
|
||||||
|
std::string m_dirname;
|
||||||
|
std::string m_reason;
|
||||||
|
TempDir(const TempDir&) {}
|
||||||
|
TempDir& operator=(const TempDir&) {
|
||||||
|
return *this;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Freedesktop thumbnail standard path routine
|
||||||
|
// On return, path will have the appropriate value in all cases,
|
||||||
|
// returns true if the file already exists
|
||||||
|
extern bool thumbPathForUrl(const std::string& url, int size,
|
||||||
|
std::string& path);
|
||||||
|
|
||||||
|
// Duplicate map<string,string> while ensuring no shared string data (to pass
|
||||||
|
// to other thread):
|
||||||
|
void map_ss_cp_noshr(const std::map<std::string, std::string> s,
|
||||||
|
std::map<std::string, std::string> *d);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _RCLUTIL_H_INCLUDED_ */
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2004 J.F.Dockes
|
/* Copyright (C) 2004-2016 J.F.Dockes
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
@ -16,7 +16,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TEST_SMALLUT
|
#ifndef TEST_SMALLUT
|
||||||
|
#ifdef BUILDING_RECOLL
|
||||||
#include "autoconfig.h"
|
#include "autoconfig.h"
|
||||||
|
#else
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -34,22 +38,9 @@
|
||||||
#include UNORDERED_SET_INCLUDE
|
#include UNORDERED_SET_INCLUDE
|
||||||
|
|
||||||
#include "smallut.h"
|
#include "smallut.h"
|
||||||
#include "utf8iter.h"
|
|
||||||
#include "hldata.h"
|
|
||||||
#include "cstr.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void map_ss_cp_noshr(const map<string,string> s, map<string,string> *d)
|
|
||||||
{
|
|
||||||
for (map<string,string>::const_iterator it= s.begin();
|
|
||||||
it != s.end(); it++) {
|
|
||||||
d->insert(
|
|
||||||
pair<string,string>(string(it->first.begin(), it->first.end()),
|
|
||||||
string(it->second.begin(), it->second.end())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int stringicmp(const string& s1, const string& s2)
|
int stringicmp(const string& s1, const string& s2)
|
||||||
{
|
{
|
||||||
string::const_iterator it1 = s1.begin();
|
string::const_iterator it1 = s1.begin();
|
||||||
|
@ -64,7 +55,8 @@ int stringicmp(const string & s1, const string& s2)
|
||||||
if (c1 != c2) {
|
if (c1 != c2) {
|
||||||
return c1 > c2 ? 1 : -1;
|
return c1 > c2 ? 1 : -1;
|
||||||
}
|
}
|
||||||
++it1; ++it2;
|
++it1;
|
||||||
|
++it2;
|
||||||
}
|
}
|
||||||
return size1 == size2 ? 0 : -1;
|
return size1 == size2 ? 0 : -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -74,7 +66,8 @@ int stringicmp(const string & s1, const string& s2)
|
||||||
if (c1 != c2) {
|
if (c1 != c2) {
|
||||||
return c1 > c2 ? 1 : -1;
|
return c1 > c2 ? 1 : -1;
|
||||||
}
|
}
|
||||||
++it1; ++it2;
|
++it1;
|
||||||
|
++it2;
|
||||||
}
|
}
|
||||||
return size1 == size2 ? 0 : 1;
|
return size1 == size2 ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +97,8 @@ extern int stringisuffcmp(const string& s1, const string& s2)
|
||||||
if (c1 != c2) {
|
if (c1 != c2) {
|
||||||
return c1 > c2 ? 1 : -1;
|
return c1 > c2 ? 1 : -1;
|
||||||
}
|
}
|
||||||
++r1; ++r2;
|
++r1;
|
||||||
|
++r2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +117,8 @@ int stringlowercmp(const string & s1, const string& s2)
|
||||||
if (*it1 != c2) {
|
if (*it1 != c2) {
|
||||||
return *it1 > c2 ? 1 : -1;
|
return *it1 > c2 ? 1 : -1;
|
||||||
}
|
}
|
||||||
++it1; ++it2;
|
++it1;
|
||||||
|
++it2;
|
||||||
}
|
}
|
||||||
return size1 == size2 ? 0 : -1;
|
return size1 == size2 ? 0 : -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -132,7 +127,8 @@ int stringlowercmp(const string & s1, const string& s2)
|
||||||
if (*it1 != c2) {
|
if (*it1 != c2) {
|
||||||
return *it1 > c2 ? 1 : -1;
|
return *it1 > c2 ? 1 : -1;
|
||||||
}
|
}
|
||||||
++it1; ++it2;
|
++it1;
|
||||||
|
++it2;
|
||||||
}
|
}
|
||||||
return size1 == size2 ? 0 : 1;
|
return size1 == size2 ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
@ -152,7 +148,8 @@ int stringuppercmp(const string & s1, const string& s2)
|
||||||
if (*it1 != c2) {
|
if (*it1 != c2) {
|
||||||
return *it1 > c2 ? 1 : -1;
|
return *it1 > c2 ? 1 : -1;
|
||||||
}
|
}
|
||||||
++it1; ++it2;
|
++it1;
|
||||||
|
++it2;
|
||||||
}
|
}
|
||||||
return size1 == size2 ? 0 : -1;
|
return size1 == size2 ? 0 : -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -161,7 +158,8 @@ int stringuppercmp(const string & s1, const string& s2)
|
||||||
if (*it1 != c2) {
|
if (*it1 != c2) {
|
||||||
return *it1 > c2 ? 1 : -1;
|
return *it1 > c2 ? 1 : -1;
|
||||||
}
|
}
|
||||||
++it1; ++it2;
|
++it1;
|
||||||
|
++it2;
|
||||||
}
|
}
|
||||||
return size1 == size2 ? 0 : 1;
|
return size1 == size2 ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +195,8 @@ template <class T> bool stringToStrings(const string &s, T &tokens,
|
||||||
case '"':
|
case '"':
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case SPACE:
|
case SPACE:
|
||||||
state=INQUOTE; continue;
|
state = INQUOTE;
|
||||||
|
continue;
|
||||||
case TOKEN:
|
case TOKEN:
|
||||||
current += '"';
|
current += '"';
|
||||||
continue;
|
continue;
|
||||||
|
@ -307,12 +306,15 @@ template <class T> void stringsToString(const T &tokens, string &s)
|
||||||
for (typename T::const_iterator it = tokens.begin();
|
for (typename T::const_iterator it = tokens.begin();
|
||||||
it != tokens.end(); it++) {
|
it != tokens.end(); it++) {
|
||||||
bool hasblanks = false;
|
bool hasblanks = false;
|
||||||
if (it->find_first_of(" \t\n") != string::npos)
|
if (it->find_first_of(" \t\n") != string::npos) {
|
||||||
hasblanks = true;
|
hasblanks = true;
|
||||||
if (it != tokens.begin())
|
}
|
||||||
|
if (it != tokens.begin()) {
|
||||||
s.append(1, ' ');
|
s.append(1, ' ');
|
||||||
if (hasblanks)
|
}
|
||||||
|
if (hasblanks) {
|
||||||
s.append(1, '"');
|
s.append(1, '"');
|
||||||
|
}
|
||||||
for (unsigned int i = 0; i < it->length(); i++) {
|
for (unsigned int i = 0; i < it->length(); i++) {
|
||||||
char car = it->at(i);
|
char car = it->at(i);
|
||||||
if (car == '"') {
|
if (car == '"') {
|
||||||
|
@ -322,10 +324,11 @@ template <class T> void stringsToString(const T &tokens, string &s)
|
||||||
s.append(1, car);
|
s.append(1, car);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasblanks)
|
if (hasblanks) {
|
||||||
s.append(1, '"');
|
s.append(1, '"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
template void stringsToString<list<string> >(const list<string>&, string&);
|
template void stringsToString<list<string> >(const list<string>&, string&);
|
||||||
template void stringsToString<vector<string> >(const vector<string>&, string&);
|
template void stringsToString<vector<string> >(const vector<string>&, string&);
|
||||||
template void stringsToString<set<string> >(const set<string>&, string&);
|
template void stringsToString<set<string> >(const set<string>&, string&);
|
||||||
|
@ -347,12 +350,15 @@ template <class T> void stringsToCSV(const T &tokens, string &s,
|
||||||
it != tokens.end(); it++) {
|
it != tokens.end(); it++) {
|
||||||
bool needquotes = false;
|
bool needquotes = false;
|
||||||
if (it->empty() ||
|
if (it->empty() ||
|
||||||
it->find_first_of(string(1, sep) + "\"\n") != string::npos)
|
it->find_first_of(string(1, sep) + "\"\n") != string::npos) {
|
||||||
needquotes = true;
|
needquotes = true;
|
||||||
if (it != tokens.begin())
|
}
|
||||||
|
if (it != tokens.begin()) {
|
||||||
s.append(1, sep);
|
s.append(1, sep);
|
||||||
if (needquotes)
|
}
|
||||||
|
if (needquotes) {
|
||||||
s.append(1, '"');
|
s.append(1, '"');
|
||||||
|
}
|
||||||
for (unsigned int i = 0; i < it->length(); i++) {
|
for (unsigned int i = 0; i < it->length(); i++) {
|
||||||
char car = it->at(i);
|
char car = it->at(i);
|
||||||
if (car == '"') {
|
if (car == '"') {
|
||||||
|
@ -361,10 +367,11 @@ template <class T> void stringsToCSV(const T &tokens, string &s,
|
||||||
s.append(1, car);
|
s.append(1, car);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (needquotes)
|
if (needquotes) {
|
||||||
s.append(1, '"');
|
s.append(1, '"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
template void stringsToCSV<list<string> >(const list<string>&, string&, char);
|
template void stringsToCSV<list<string> >(const list<string>&, string&, char);
|
||||||
template void stringsToCSV<vector<string> >(const vector<string>&, string&,
|
template void stringsToCSV<vector<string> >(const vector<string>&, string&,
|
||||||
char);
|
char);
|
||||||
|
@ -389,8 +396,9 @@ void stringToTokens(const string& str, vector<string>& tokens,
|
||||||
break;
|
break;
|
||||||
} else if (pos == startPos) {
|
} else if (pos == startPos) {
|
||||||
// Dont' push empty tokens after first
|
// Dont' push empty tokens after first
|
||||||
if (tokens.empty())
|
if (tokens.empty()) {
|
||||||
tokens.push_back(string());
|
tokens.push_back(string());
|
||||||
|
}
|
||||||
startPos = ++pos;
|
startPos = ++pos;
|
||||||
} else {
|
} else {
|
||||||
tokens.push_back(str.substr(startPos, pos - startPos));
|
tokens.push_back(str.substr(startPos, pos - startPos));
|
||||||
|
@ -401,14 +409,16 @@ void stringToTokens(const string& str, vector<string>& tokens,
|
||||||
|
|
||||||
bool stringToBool(const string& s)
|
bool stringToBool(const string& s)
|
||||||
{
|
{
|
||||||
if (s.empty())
|
if (s.empty()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (isdigit(s[0])) {
|
if (isdigit(s[0])) {
|
||||||
int val = atoi(s.c_str());
|
int val = atoi(s.c_str());
|
||||||
return val ? true : false;
|
return val ? true : false;
|
||||||
}
|
}
|
||||||
if (s.find_first_of("yYtT") == 0)
|
if (s.find_first_of("yYtT") == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,9 +432,10 @@ void trimstring(string &s, const char *ws)
|
||||||
s.replace(0, pos, string());
|
s.replace(0, pos, string());
|
||||||
|
|
||||||
pos = s.find_last_not_of(ws);
|
pos = s.find_last_not_of(ws);
|
||||||
if (pos != string::npos && pos != s.length()-1)
|
if (pos != string::npos && pos != s.length() - 1) {
|
||||||
s.replace(pos + 1, string::npos, string());
|
s.replace(pos + 1, string::npos, string());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove some chars and replace them with spaces
|
// Remove some chars and replace them with spaces
|
||||||
string neutchars(const string& str, const string& chars)
|
string neutchars(const string& str, const string& chars)
|
||||||
|
@ -439,8 +450,9 @@ void neutchars(const string &str, string &out, const string& chars)
|
||||||
|
|
||||||
for (pos = 0;;) {
|
for (pos = 0;;) {
|
||||||
// Skip initial chars, break if this eats all.
|
// Skip initial chars, break if this eats all.
|
||||||
if ((startPos = str.find_first_not_of(chars, pos)) == string::npos)
|
if ((startPos = str.find_first_not_of(chars, pos)) == string::npos) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
// Find next delimiter or end of string (end of token)
|
// Find next delimiter or end of string (end of token)
|
||||||
pos = str.find_first_of(chars, startPos);
|
pos = str.find_first_of(chars, startPos);
|
||||||
// Add token to the output. Note: token cant be empty here
|
// Add token to the output. Note: token cant be empty here
|
||||||
|
@ -481,19 +493,6 @@ string truncate_to_word(const string &input, string::size_type maxlen)
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void utf8truncate(string &s, int maxlen)
|
|
||||||
{
|
|
||||||
if (s.size() <= string::size_type(maxlen))
|
|
||||||
return;
|
|
||||||
Utf8Iter iter(s);
|
|
||||||
string::size_type pos = 0;
|
|
||||||
while (iter++ != string::npos)
|
|
||||||
if (iter.getBpos() < string::size_type(maxlen))
|
|
||||||
pos = iter.getBpos();
|
|
||||||
|
|
||||||
s.erase(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escape things that would look like markup
|
// Escape things that would look like markup
|
||||||
string escapeHtml(const string& in)
|
string escapeHtml(const string& in)
|
||||||
{
|
{
|
||||||
|
@ -622,7 +621,8 @@ inline static int ulltorbuf(unsigned long long val, char *rbuf)
|
||||||
for (idx = 0; val; idx++) {
|
for (idx = 0; val; idx++) {
|
||||||
rbuf[idx] = '0' + val % 10;
|
rbuf[idx] = '0' + val % 10;
|
||||||
val /= 10;
|
val /= 10;
|
||||||
} while (val);
|
}
|
||||||
|
while (val);
|
||||||
rbuf[idx] = 0;
|
rbuf[idx] = 0;
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
@ -659,14 +659,16 @@ void lltodecstr(long long val, string& buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool neg = val < 0;
|
bool neg = val < 0;
|
||||||
if (neg)
|
if (neg) {
|
||||||
val = -val;
|
val = -val;
|
||||||
|
}
|
||||||
|
|
||||||
char rbuf[30];
|
char rbuf[30];
|
||||||
int idx = ulltorbuf(val, rbuf);
|
int idx = ulltorbuf(val, rbuf);
|
||||||
|
|
||||||
if (neg)
|
if (neg) {
|
||||||
rbuf[idx++] = '-';
|
rbuf[idx++] = '-';
|
||||||
|
}
|
||||||
rbuf[idx] = 0;
|
rbuf[idx] = 0;
|
||||||
|
|
||||||
ullcopyreverse(rbuf, buf, idx);
|
ullcopyreverse(rbuf, buf, idx);
|
||||||
|
@ -722,10 +724,11 @@ string breakIntoLines(const string& in, unsigned int ll,
|
||||||
string::size_type pos = ss.find_last_of(" ");
|
string::size_type pos = ss.find_last_of(" ");
|
||||||
if (pos == string::npos) {
|
if (pos == string::npos) {
|
||||||
pos = query.find_first_of(" ");
|
pos = query.find_first_of(" ");
|
||||||
if (pos != string::npos)
|
if (pos != string::npos) {
|
||||||
ss = query.substr(0, pos + 1);
|
ss = query.substr(0, pos + 1);
|
||||||
else
|
} else {
|
||||||
ss = query;
|
ss = query;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ss = ss.substr(0, pos + 1);
|
ss = ss.substr(0, pos + 1);
|
||||||
}
|
}
|
||||||
|
@ -757,8 +760,9 @@ static bool parsedate(vector<string>::const_iterator& it,
|
||||||
if (it == end || sscanf(it++->c_str(), "%d", &dip->y1) != 1) {
|
if (it == end || sscanf(it++->c_str(), "%d", &dip->y1) != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (it == end || *it == "/")
|
if (it == end || *it == "/") {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
if (*it++ != "-") {
|
if (*it++ != "-") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -770,8 +774,9 @@ static bool parsedate(vector<string>::const_iterator& it,
|
||||||
if (it == end || sscanf(it++->c_str(), "%d", &dip->m1) != 1) {
|
if (it == end || sscanf(it++->c_str(), "%d", &dip->m1) != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (it == end || *it == "/")
|
if (it == end || *it == "/") {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
if (*it++ != "-") {
|
if (*it++ != "-") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -802,17 +807,29 @@ static bool parseperiod(vector<string>::const_iterator& it,
|
||||||
if (sscanf(it++->c_str(), "%d", &value) != 1) {
|
if (sscanf(it++->c_str(), "%d", &value) != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (it == end || it->empty())
|
if (it == end || it->empty()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
switch (it->at(0)) {
|
switch (it->at(0)) {
|
||||||
case 'Y': case 'y': dip->y1 = value;break;
|
case 'Y':
|
||||||
case 'M': case 'm': dip->m1 = value;break;
|
case 'y':
|
||||||
case 'D': case 'd': dip->d1 = value;break;
|
dip->y1 = value;
|
||||||
default: return false;
|
break;
|
||||||
|
case 'M':
|
||||||
|
case 'm':
|
||||||
|
dip->m1 = value;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
case 'd':
|
||||||
|
dip->d1 = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
it++;
|
it++;
|
||||||
if (it == end)
|
if (it == end) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
if (*it == "/") {
|
if (*it == "/") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -825,9 +842,10 @@ int setenv(const char *name, const char *value, int overwrite)
|
||||||
{
|
{
|
||||||
if (!overwrite) {
|
if (!overwrite) {
|
||||||
const char *cp = getenv(name);
|
const char *cp = getenv(name);
|
||||||
if (cp)
|
if (cp) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return _putenv_s(name, value);
|
return _putenv_s(name, value);
|
||||||
}
|
}
|
||||||
void unsetenv(const char *name)
|
void unsetenv(const char *name)
|
||||||
|
@ -845,10 +863,11 @@ time_t portable_timegm(struct tm *tm)
|
||||||
setenv("TZ", "", 1);
|
setenv("TZ", "", 1);
|
||||||
tzset();
|
tzset();
|
||||||
ret = mktime(tm);
|
ret = mktime(tm);
|
||||||
if (tz)
|
if (tz) {
|
||||||
setenv("TZ", tz, 1);
|
setenv("TZ", tz, 1);
|
||||||
else
|
} else {
|
||||||
unsetenv("TZ");
|
unsetenv("TZ");
|
||||||
|
}
|
||||||
tzset();
|
tzset();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -886,10 +905,19 @@ static bool addperiod(DateInterval *dp, DateInterval *pp)
|
||||||
int monthdays(int mon, int year)
|
int monthdays(int mon, int year)
|
||||||
{
|
{
|
||||||
switch (mon) {
|
switch (mon) {
|
||||||
// We are returning a few two many 29 days februaries, no problem
|
// We are returning a few too many 29 days februaries, no problem
|
||||||
case 2: return (year % 4) == 0 ? 29 : 28;
|
case 2:
|
||||||
case 1:case 3:case 5:case 7: case 8:case 10:case 12: return 31;
|
return (year % 4) == 0 ? 29 : 28;
|
||||||
default: return 30;
|
case 1:
|
||||||
|
case 3:
|
||||||
|
case 5:
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
case 10:
|
||||||
|
case 12:
|
||||||
|
return 31;
|
||||||
|
default:
|
||||||
|
return 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool parsedateinterval(const string& s, DateInterval *dip)
|
bool parsedateinterval(const string& s, DateInterval *dip)
|
||||||
|
@ -904,8 +932,9 @@ bool parsedateinterval(const string& s, DateInterval *dip)
|
||||||
if (!stringToStrings(s, vs, "PYMDpymd-/")) {
|
if (!stringToStrings(s, vs, "PYMDpymd-/")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (vs.empty())
|
if (vs.empty()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
vector<string>::const_iterator it = vs.begin();
|
vector<string>::const_iterator it = vs.begin();
|
||||||
if (*it == "P" || *it == "p") {
|
if (*it == "P" || *it == "p") {
|
||||||
|
@ -1042,10 +1071,12 @@ secondelt:
|
||||||
|
|
||||||
void catstrerror(string *reason, const char *what, int _errno)
|
void catstrerror(string *reason, const char *what, int _errno)
|
||||||
{
|
{
|
||||||
if (!reason)
|
if (!reason) {
|
||||||
return;
|
return;
|
||||||
if (what)
|
}
|
||||||
|
if (what) {
|
||||||
reason->append(what);
|
reason->append(what);
|
||||||
|
}
|
||||||
|
|
||||||
reason->append(": errno: ");
|
reason->append(": errno: ");
|
||||||
|
|
||||||
|
@ -1080,59 +1111,6 @@ void catstrerror(string *reason, const char *what, int _errno)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HighlightData::toString(std::string& out)
|
|
||||||
{
|
|
||||||
out.append("\nUser terms (orthograph): ");
|
|
||||||
for (std::set<std::string>::const_iterator it = uterms.begin();
|
|
||||||
it != uterms.end(); it++) {
|
|
||||||
out.append(" [").append(*it).append("]");
|
|
||||||
}
|
|
||||||
out.append("\nUser terms to Query terms:");
|
|
||||||
for (map<string, string>::const_iterator it = terms.begin();
|
|
||||||
it != terms.end(); it++) {
|
|
||||||
out.append("[").append(it->first).append("]->[");
|
|
||||||
out.append(it->second).append("] ");
|
|
||||||
}
|
|
||||||
out.append("\nGroups: ");
|
|
||||||
char cbuf[200];
|
|
||||||
sprintf(cbuf, "Groups size %d grpsugidx size %d ugroups size %d",
|
|
||||||
int(groups.size()), int(grpsugidx.size()), int(ugroups.size()));
|
|
||||||
out.append(cbuf);
|
|
||||||
|
|
||||||
size_t ugidx = (size_t)-1;
|
|
||||||
for (unsigned int i = 0; i < groups.size(); i++) {
|
|
||||||
if (ugidx != grpsugidx[i]) {
|
|
||||||
ugidx = grpsugidx[i];
|
|
||||||
out.append("\n(");
|
|
||||||
for (unsigned int j = 0; j < ugroups[ugidx].size(); j++) {
|
|
||||||
out.append("[").append(ugroups[ugidx][j]).append("] ");
|
|
||||||
}
|
|
||||||
out.append(") ->");
|
|
||||||
}
|
|
||||||
out.append(" {");
|
|
||||||
for (unsigned int j = 0; j < groups[i].size(); j++) {
|
|
||||||
out.append("[").append(groups[i][j]).append("]");
|
|
||||||
}
|
|
||||||
sprintf(cbuf, "%d", slacks[i]);
|
|
||||||
out.append("}").append(cbuf);
|
|
||||||
}
|
|
||||||
out.append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void HighlightData::append(const HighlightData& hl)
|
|
||||||
{
|
|
||||||
uterms.insert(hl.uterms.begin(), hl.uterms.end());
|
|
||||||
terms.insert(hl.terms.begin(), hl.terms.end());
|
|
||||||
size_t ugsz0 = ugroups.size();
|
|
||||||
ugroups.insert(ugroups.end(), hl.ugroups.begin(), hl.ugroups.end());
|
|
||||||
|
|
||||||
groups.insert(groups.end(), hl.groups.begin(), hl.groups.end());
|
|
||||||
slacks.insert(slacks.end(), hl.slacks.begin(), hl.slacks.end());
|
|
||||||
for (std::vector<size_t>::const_iterator it = hl.grpsugidx.begin();
|
|
||||||
it != hl.grpsugidx.end(); it++) {
|
|
||||||
grpsugidx.push_back(*it + ugsz0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *vlang_to_code[] = {
|
static const char *vlang_to_code[] = {
|
||||||
"be", "cp1251",
|
"be", "cp1251",
|
||||||
|
@ -1159,6 +1137,8 @@ static const char *vlang_to_code[] = {
|
||||||
"uk", "koi8-u",
|
"uk", "koi8-u",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const string cstr_cp1252("CP1252");
|
||||||
|
|
||||||
string langtocode(const string& lang)
|
string langtocode(const string& lang)
|
||||||
{
|
{
|
||||||
static STD_UNORDERED_MAP<string, string> lang_to_code;
|
static STD_UNORDERED_MAP<string, string> lang_to_code;
|
||||||
|
@ -1172,8 +1152,9 @@ string langtocode(const string& lang)
|
||||||
lang_to_code.find(lang);
|
lang_to_code.find(lang);
|
||||||
|
|
||||||
// Use cp1252 by default...
|
// Use cp1252 by default...
|
||||||
if (it == lang_to_code.end())
|
if (it == lang_to_code.end()) {
|
||||||
return cstr_cp1252;
|
return cstr_cp1252;
|
||||||
|
}
|
||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
@ -1182,12 +1163,15 @@ string localelang()
|
||||||
{
|
{
|
||||||
const char *lang = getenv("LANG");
|
const char *lang = getenv("LANG");
|
||||||
|
|
||||||
if (lang == 0 || *lang == 0 || !strcmp(lang, "C") || !strcmp(lang, "POSIX"))
|
if (lang == 0 || *lang == 0 || !strcmp(lang, "C") ||
|
||||||
|
!strcmp(lang, "POSIX")) {
|
||||||
return "en";
|
return "en";
|
||||||
|
}
|
||||||
string locale(lang);
|
string locale(lang);
|
||||||
string::size_type under = locale.find_first_of("_");
|
string::size_type under = locale.find_first_of("_");
|
||||||
if (under == string::npos)
|
if (under == string::npos) {
|
||||||
return locale;
|
return locale;
|
||||||
|
}
|
||||||
return locale.substr(0, under);
|
return locale.substr(0, under);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1262,18 +1246,21 @@ static void cerrdip(const string& s, DateInterval *dip)
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
thisprog = *argv++;argc--;
|
thisprog = *argv++;
|
||||||
|
argc--;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (argc <= 0) {
|
if (argc <= 0) {
|
||||||
cerr << "Usage: smallut <stringtosplit>" << endl;
|
cerr << "Usage: smallut <stringtosplit>" << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
string s = *argv++;argc--;
|
string s = *argv++;
|
||||||
|
argc--;
|
||||||
vector<string> vs;
|
vector<string> vs;
|
||||||
stringToTokens(s, vs, "/");
|
stringToTokens(s, vs, "/");
|
||||||
for (vector<string>::const_iterator it = vs.begin(); it != vs.end(); it++)
|
for (vector<string>::const_iterator it = vs.begin(); it != vs.end(); it++) {
|
||||||
cerr << "[" << *it << "] ";
|
cerr << "[" << *it << "] ";
|
||||||
|
}
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
#elif 0
|
#elif 0
|
||||||
|
@ -1281,14 +1268,16 @@ int main(int argc, char **argv)
|
||||||
cerr << "Usage: smallut <stringtosplit>" << endl;
|
cerr << "Usage: smallut <stringtosplit>" << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
string s = *argv++;argc--;
|
string s = *argv++;
|
||||||
|
argc--;
|
||||||
vector<string> vs;
|
vector<string> vs;
|
||||||
if (!stringToStrings(s, vs, ":-()")) {
|
if (!stringToStrings(s, vs, ":-()")) {
|
||||||
cerr << "Bad entry" << endl;
|
cerr << "Bad entry" << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
for (vector<string>::const_iterator it = vs.begin(); it != vs.end(); it++)
|
for (vector<string>::const_iterator it = vs.begin(); it != vs.end(); it++) {
|
||||||
cerr << "[" << *it << "] ";
|
cerr << "[" << *it << "] ";
|
||||||
|
}
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
#elif 0
|
#elif 0
|
||||||
|
@ -1296,7 +1285,8 @@ int main(int argc, char **argv)
|
||||||
cerr << "Usage: smallut <dateinterval>" << endl;
|
cerr << "Usage: smallut <dateinterval>" << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
string s = *argv++;argc--;
|
string s = *argv++;
|
||||||
|
argc--;
|
||||||
DateInterval di;
|
DateInterval di;
|
||||||
if (!parsedateinterval(s, &di)) {
|
if (!parsedateinterval(s, &di)) {
|
||||||
cerr << "Parse failed" << endl;
|
cerr << "Parse failed" << endl;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2004 J.F.Dockes
|
/* Copyright (C) 2004-2016 J.F.Dockes
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
@ -17,47 +17,63 @@
|
||||||
#ifndef _SMALLUT_H_INCLUDED_
|
#ifndef _SMALLUT_H_INCLUDED_
|
||||||
#define _SMALLUT_H_INCLUDED_
|
#define _SMALLUT_H_INCLUDED_
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
using std::string;
|
// Miscellaneous mostly string-oriented small utilities
|
||||||
using std::vector;
|
// Note that none of the following code knows about utf-8.
|
||||||
using std::map;
|
|
||||||
using std::set;
|
// Call this before going multithread.
|
||||||
|
void smallut_init_mt();
|
||||||
|
|
||||||
|
#ifndef SMALLUT_DISABLE_MACROS
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(A,B) (((A)<(B)) ? (A) : (B))
|
||||||
|
#endif
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(A,B) (((A)>(B)) ? (A) : (B))
|
||||||
|
#endif
|
||||||
|
#ifndef deleteZ
|
||||||
|
#define deleteZ(X) {delete X;X = 0;}
|
||||||
|
#endif
|
||||||
|
#endif /* SMALLUT_DISABLE_MACROS */
|
||||||
|
|
||||||
|
// Case-insensitive compare. ASCII ONLY !
|
||||||
|
extern int stringicmp(const std::string& s1, const std::string& s2);
|
||||||
|
|
||||||
// Note these are all ascii routines
|
|
||||||
extern int stringicmp(const string& s1, const string& s2);
|
|
||||||
// For find_if etc.
|
// For find_if etc.
|
||||||
struct StringIcmpPred {
|
struct StringIcmpPred {
|
||||||
StringIcmpPred(const string& s1)
|
StringIcmpPred(const std::string& s1)
|
||||||
: m_s1(s1)
|
: m_s1(s1) {
|
||||||
{}
|
}
|
||||||
bool operator()(const string& s2) {
|
bool operator()(const std::string& s2) {
|
||||||
return stringicmp(m_s1, s2) == 0;
|
return stringicmp(m_s1, s2) == 0;
|
||||||
}
|
}
|
||||||
const string& m_s1;
|
const std::string& m_s1;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int stringlowercmp(const string& alreadylower, const string& s2);
|
extern int stringlowercmp(const std::string& alreadylower,
|
||||||
extern int stringuppercmp(const string& alreadyupper, const string& s2);
|
const std::string& s2);
|
||||||
|
extern int stringuppercmp(const std::string& alreadyupper,
|
||||||
|
const std::string& s2);
|
||||||
|
|
||||||
extern void stringtolower(string& io);
|
extern void stringtolower(std::string& io);
|
||||||
extern string stringtolower(const string& io);
|
extern std::string stringtolower(const std::string& io);
|
||||||
|
|
||||||
// Is one string the end part of the other ?
|
// Is one string the end part of the other ?
|
||||||
extern int stringisuffcmp(const string& s1, const string& s2);
|
extern int stringisuffcmp(const std::string& s1, const std::string& s2);
|
||||||
|
|
||||||
// Divine language from locale
|
// Divine language from locale
|
||||||
extern std::string localelang();
|
extern std::string localelang();
|
||||||
// Divine 8bit charset from language
|
// Divine 8bit charset from language
|
||||||
extern std::string langtocode(const string& lang);
|
extern std::string langtocode(const std::string& lang);
|
||||||
|
|
||||||
// Compare charset names, removing the more common spelling variations
|
// Compare charset names, removing the more common spelling variations
|
||||||
extern bool samecharset(const string &cs1, const string &cs2);
|
extern bool samecharset(const std::string& cs1, const std::string& cs2);
|
||||||
|
|
||||||
// Parse date interval specifier into pair of y,m,d dates. The format
|
// Parse date interval specifier into pair of y,m,d dates. The format
|
||||||
// for the time interval is based on a subset of iso 8601 with
|
// for the time interval is based on a subset of iso 8601 with
|
||||||
|
@ -71,9 +87,14 @@ extern bool samecharset(const string &cs1, const string &cs2);
|
||||||
// YYYY/ (from YYYY) YYYY-MM-DD/P3Y (3 years after date) etc.
|
// YYYY/ (from YYYY) YYYY-MM-DD/P3Y (3 years after date) etc.
|
||||||
// This returns a pair of y,m,d dates.
|
// This returns a pair of y,m,d dates.
|
||||||
struct DateInterval {
|
struct DateInterval {
|
||||||
int y1;int m1;int d1; int y2;int m2;int d2;
|
int y1;
|
||||||
|
int m1;
|
||||||
|
int d1;
|
||||||
|
int y2;
|
||||||
|
int m2;
|
||||||
|
int d2;
|
||||||
};
|
};
|
||||||
extern bool parsedateinterval(const string&s, DateInterval *di);
|
extern bool parsedateinterval(const std::string& s, DateInterval *di);
|
||||||
extern int monthdays(int mon, int year);
|
extern int monthdays(int mon, int year);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,172 +102,132 @@ extern int monthdays(int mon, int year);
|
||||||
*
|
*
|
||||||
* Token delimiter is " \t\n" except inside dquotes. dquote inside
|
* Token delimiter is " \t\n" except inside dquotes. dquote inside
|
||||||
* dquotes can be escaped with \ etc...
|
* dquotes can be escaped with \ etc...
|
||||||
* Input is handled a byte at a time, things will work as long as space tab etc.
|
* Input is handled a byte at a time, things will work as long as
|
||||||
* have the ascii values and can't appear as part of a multibyte char. utf-8 ok
|
* space tab etc. have the ascii values and can't appear as part of a
|
||||||
* but so are the iso-8859-x and surely others. addseps do have to be
|
* multibyte char. utf-8 ok but so are the iso-8859-x and surely
|
||||||
* single-bytes
|
* others. addseps do have to be single-bytes
|
||||||
*/
|
*/
|
||||||
template <class T> bool stringToStrings(const string& s, T &tokens,
|
template <class T> bool stringToStrings(const std::string& s, T& tokens,
|
||||||
const string& addseps = "");
|
const std::string& addseps = "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inverse operation:
|
* Inverse operation:
|
||||||
*/
|
*/
|
||||||
template <class T> void stringsToString(const T &tokens, string &s);
|
template <class T> void stringsToString(const T& tokens, std::string& s);
|
||||||
template <class T> std::string stringsToString(const T& tokens);
|
template <class T> std::string stringsToString(const T& tokens);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strings to CSV string. tokens containing the separator are quoted (")
|
* Strings to CSV string. tokens containing the separator are quoted (")
|
||||||
* " inside tokens is escaped as "" ([word "quote"] =>["word ""quote"""]
|
* " inside tokens is escaped as "" ([word "quote"] =>["word ""quote"""]
|
||||||
*/
|
*/
|
||||||
template <class T> void stringsToCSV(const T &tokens, string &s,
|
template <class T> void stringsToCSV(const T& tokens, std::string& s,
|
||||||
char sep = ',');
|
char sep = ',');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split input string. No handling of quoting
|
* Split input string. No handling of quoting
|
||||||
*/
|
*/
|
||||||
extern void stringToTokens(const string &s, vector<string> &tokens,
|
extern void stringToTokens(const std::string& s,
|
||||||
const string &delims = " \t", bool skipinit=true);
|
std::vector<std::string>& tokens,
|
||||||
|
const std::string& delims = " \t",
|
||||||
|
bool skipinit = true);
|
||||||
|
|
||||||
/** Convert string to boolean */
|
/** Convert string to boolean */
|
||||||
extern bool stringToBool(const string &s);
|
extern bool stringToBool(const std::string& s);
|
||||||
|
|
||||||
/** Remove instances of characters belonging to set (default {space,
|
/** Remove instances of characters belonging to set (default {space,
|
||||||
tab}) at beginning and end of input string */
|
tab}) at beginning and end of input string */
|
||||||
extern void trimstring(string &s, const char *ws = " \t");
|
extern void trimstring(std::string& s, const char *ws = " \t");
|
||||||
|
|
||||||
/** Escape things like < or & by turning them into entities */
|
/** Escape things like < or & by turning them into entities */
|
||||||
extern string escapeHtml(const string &in);
|
extern std::string escapeHtml(const std::string& in);
|
||||||
|
|
||||||
/** Replace some chars with spaces (ie: newline chars). This is not utf8-aware
|
/** Replace some chars with spaces (ie: newline chars). */
|
||||||
* so chars should only contain ascii */
|
extern std::string neutchars(const std::string& str, const std::string& chars);
|
||||||
extern string neutchars(const string &str, const string &chars);
|
extern void neutchars(const std::string& str, std::string& out,
|
||||||
extern void neutchars(const string &str, string& out, const string &chars);
|
const std::string& chars);
|
||||||
|
|
||||||
/** Turn string into something that won't be expanded by a shell. In practise
|
/** Turn string into something that won't be expanded by a shell. In practise
|
||||||
* quote with double-quotes and escape $`\ */
|
* quote with double-quotes and escape $`\ */
|
||||||
extern string escapeShell(const string &str);
|
extern std::string escapeShell(const std::string& str);
|
||||||
|
|
||||||
/** Truncate a string to a given maxlength, avoiding cutting off midword
|
/** Truncate a string to a given maxlength, avoiding cutting off midword
|
||||||
* if reasonably possible. */
|
* if reasonably possible. */
|
||||||
extern string truncate_to_word(const string &input, string::size_type maxlen);
|
extern std::string truncate_to_word(const std::string& input,
|
||||||
|
std::string::size_type maxlen);
|
||||||
|
|
||||||
/** Truncate in place in an utf8-legal way */
|
void ulltodecstr(unsigned long long val, std::string& buf);
|
||||||
extern void utf8truncate(string &s, int maxlen);
|
void lltodecstr(long long val, std::string& buf);
|
||||||
|
std::string lltodecstr(long long val);
|
||||||
void ulltodecstr(unsigned long long val, string& buf);
|
std::string ulltodecstr(unsigned long long val);
|
||||||
void lltodecstr(long long val, string& buf);
|
|
||||||
string lltodecstr(long long val);
|
|
||||||
string ulltodecstr(unsigned long long val);
|
|
||||||
|
|
||||||
/** Convert byte count into unit (KB/MB...) appropriate for display */
|
/** Convert byte count into unit (KB/MB...) appropriate for display */
|
||||||
string displayableBytes(off_t size);
|
std::string displayableBytes(off_t size);
|
||||||
|
|
||||||
/** Break big string into lines */
|
/** Break big string into lines */
|
||||||
string breakIntoLines(const string& in, unsigned int ll = 100,
|
std::string breakIntoLines(const std::string& in, unsigned int ll = 100,
|
||||||
unsigned int maxlines = 50);
|
unsigned int maxlines = 50);
|
||||||
|
|
||||||
/** Small utility to substitute printf-like percents cmds in a string */
|
/** Small utility to substitute printf-like percents cmds in a string */
|
||||||
bool pcSubst(const string& in, string& out, const map<char, string>& subs);
|
bool pcSubst(const std::string& in, std::string& out,
|
||||||
|
const std::map<char, std::string>& subs);
|
||||||
/** Substitute printf-like percents and also %(key) */
|
/** Substitute printf-like percents and also %(key) */
|
||||||
bool pcSubst(const string& in, string& out, const map<string, string>& subs);
|
bool pcSubst(const std::string& in, std::string& out,
|
||||||
|
const std::map<std::string, std::string>& subs);
|
||||||
|
|
||||||
/** Append system error message */
|
/** Append system error message */
|
||||||
void catstrerror(string *reason, const char *what, int _errno);
|
void catstrerror(std::string *reason, const char *what, int _errno);
|
||||||
|
|
||||||
/** Portable timegm. MS C has _mkgmtime, but there is a bug in Gminw which
|
/** Portable timegm. MS C has _mkgmtime, but there is a bug in Gminw which
|
||||||
* makes it inaccessible */
|
* makes it inaccessible */
|
||||||
struct tm;
|
struct tm;
|
||||||
time_t portable_timegm(struct tm *tm);
|
time_t portable_timegm(struct tm *tm);
|
||||||
|
|
||||||
/** Temp buffer with automatic deallocation */
|
inline void leftzeropad(std::string& s, unsigned len)
|
||||||
struct TempBuf {
|
|
||||||
TempBuf()
|
|
||||||
: m_buf(0)
|
|
||||||
{}
|
|
||||||
TempBuf(int n)
|
|
||||||
{
|
{
|
||||||
m_buf = (char *)malloc(n);
|
if (s.length() && s.length() < len) {
|
||||||
}
|
|
||||||
~TempBuf()
|
|
||||||
{
|
|
||||||
if (m_buf)
|
|
||||||
free(m_buf);
|
|
||||||
}
|
|
||||||
char *setsize(int n) { return (m_buf = (char *)realloc(m_buf, n)); }
|
|
||||||
char *buf() {return m_buf;}
|
|
||||||
char *m_buf;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void leftzeropad(string& s, unsigned len)
|
|
||||||
{
|
|
||||||
if (s.length() && s.length() < len)
|
|
||||||
s = s.insert(0, len - s.length(), '0');
|
s = s.insert(0, len - s.length(), '0');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Duplicate map<string,string> while ensuring no shared string data (to pass
|
|
||||||
// to other thread):
|
|
||||||
void map_ss_cp_noshr(const std::map<std::string,std::string> s,
|
|
||||||
std::map<std::string,std::string> *d);
|
|
||||||
|
|
||||||
// Code for static initialization of an stl map. Somewhat like Boost.assign.
|
// Code for static initialization of an stl map. Somewhat like Boost.assign.
|
||||||
// Ref: http://stackoverflow.com/questions/138600/initializing-a-static-stdmapint-int-in-c
|
// Ref: http://stackoverflow.com/questions/138600/initializing-a-static-stdmapint-int-in-c
|
||||||
// Example use: map<int, int> m = create_map<int, int> (1,2) (3,4) (5,6) (7,8);
|
// Example use: map<int, int> m = create_map<int, int> (1,2) (3,4) (5,6) (7,8);
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
class create_map
|
class create_map {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
std::map<T, U> m_map;
|
std::map<T, U> m_map;
|
||||||
public:
|
public:
|
||||||
create_map(const T& key, const U& val)
|
create_map(const T& key, const U& val) {
|
||||||
{
|
|
||||||
m_map[key] = val;
|
m_map[key] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
create_map<T, U>& operator()(const T& key, const U& val)
|
create_map<T, U>& operator()(const T& key, const U& val) {
|
||||||
{
|
|
||||||
m_map[key] = val;
|
m_map[key] = val;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator std::map<T, U>()
|
operator std::map<T, U>() {
|
||||||
{
|
|
||||||
return m_map;
|
return m_map;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class create_vector
|
class create_vector {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
std::vector<T> m_vector;
|
std::vector<T> m_vector;
|
||||||
public:
|
public:
|
||||||
create_vector(const T& val)
|
create_vector(const T& val) {
|
||||||
{
|
|
||||||
m_vector.push_back(val);
|
m_vector.push_back(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
create_vector<T>& operator()(const T& val)
|
create_vector<T>& operator()(const T& val) {
|
||||||
{
|
|
||||||
m_vector.push_back(val);
|
m_vector.push_back(val);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator std::vector<T>()
|
operator std::vector<T>() {
|
||||||
{
|
|
||||||
return m_vector;
|
return m_vector;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef MIN
|
|
||||||
#define MIN(A,B) (((A)<(B)) ? (A) : (B))
|
|
||||||
#endif
|
|
||||||
#ifndef MAX
|
|
||||||
#define MAX(A,B) (((A)>(B)) ? (A) : (B))
|
|
||||||
#endif
|
|
||||||
#ifndef deleteZ
|
|
||||||
#define deleteZ(X) {delete X;X = 0;}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void smallut_init_mt();
|
|
||||||
|
|
||||||
#endif /* _SMALLUT_H_INCLUDED_ */
|
#endif /* _SMALLUT_H_INCLUDED_ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue