/* -*- mona-c++ -*-
* Copyright (c) 2004 - 2006
* Max-Planck-Institute for Human Cognitive and Brain Science
*
* Copyright (c) 2007 Gert Wollny
*
* 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
*
*/
// $Id: monaUtils.cc 670 2005-06-29 13:22:23Z wollny $
/*! \brief Some easy cache, string, and file manipulation tools
\file monaUtils.hh
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#pragma implementation "utils.hh"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#else
extern char *getcwd(char* buf, int size);
#endif
#include <limits.h>
#include <cstdio>
#include <cstdlib>
#include <errno.h>
#include <regex.h>
#include <dirent.h>
#include <iostream>
#include <stdexcept>
#include <iomanip>
// MONA specific
#include <ph/utils.hh>
NS_PH_BEGIN
CCWDSaver::CCWDSaver():
cwd(new char[PATH_MAX])
{
if (!getcwd(cwd, PATH_MAX)) {
delete[] cwd;
throw strerror(errno);
}
}
CCWDSaver::~CCWDSaver()
{
chdir(cwd);
delete[] cwd;
}
static bool scan_dir(const std::string& path, const std::string& pattern, std::list<std::string>& list)
{
class TFindRegExp {
regex_t preg;
public:
TFindRegExp(const std::string& pattern) {
char buf[1024];
int status = regcomp (&preg, pattern.c_str(), REG_EXTENDED |REG_NOSUB);
if (status) {
regerror(status, &preg, buf, 1024);
std::cerr << buf << std::endl;
}
}
~TFindRegExp() {
regfree(&preg);
}
bool check(const char *s) {
return !regexec(&preg, s,0, NULL, 0);
}
};
CCWDSaver __saver;
if (chdir(path.c_str())) {
//std::cerr << path << ":" << strerror(errno) << std::endl;
return false;
}
struct dirent **namelist;
int nfiles = scandir(".", &namelist, NULL , NULL);
TFindRegExp searcher(pattern);
for (int i = 0; i < nfiles; i++) {
if (searcher.check(namelist[i]->d_name))
list.push_back(path + std::string("/") + std::string(namelist[i]->d_name));
free(namelist[i]);
}
free(namelist);
return true;
}
FSearchFiles::FSearchFiles(std::list<std::string>& __result, const std::string& __pattern):
result(__result),
pattern(__pattern)
{
}
void FSearchFiles::operator()(const std::string& path) {
try {
scan_dir(path, pattern, result);
}
catch (std::exception& e) {
std::cerr << e.what();
}
}
std::string erase_to_last_of(std::string const & str, char chr)
{
std::string result = str;
std::string::size_type pos = result.find_last_of(chr);
if (pos != std::string::npos)
result.erase(0, pos + 1);
return result;
}
std::string split(std::string & str, char chr)
{
std::string::size_type i = str.find_first_of(chr);
if (i == std::string::npos)
return std::string();
std::string const tail = str.substr(i + 1);
str = str.substr(0, i);
return tail;
}
bool is_prefix(std::string const & str, std::string const & prefix)
{
// gcc 2.95 and below don't have this
// return str.compare(0, prefix.length(), prefix) == 0;
return str.find(prefix) == 0;
}
std::vector<std::string> separate_token(const std::string & str, char sep)
{
std::vector<std::string> result;
std::string next;
for (size_t pos = 0 ; pos != str.length() ; ++pos) {
char ch = str[pos];
if (ch == '\\') {
if (pos < str.length() - 1 && str[pos + 1] == sep) {
++pos;
next += sep;
} else {
next += '\\';
}
} else if (ch == sep) {
result.push_back(next);
// some stl lacks std::string::clear()
next.erase(next.begin(), next.end());
} else {
next += ch;
}
}
if (!next.empty())
result.push_back(next);
return result;
}
std::string ltrim(std::string const & str, std::string const & totrim)
{
std::string result(str);
return result.erase(0, result.find_first_not_of(totrim));
}
std::string rtrim(std::string const & str, std::string const & totrim)
{
std::string result(str);
return result.erase(result.find_last_not_of(totrim) + 1);
}
std::string trim(std::string const & str, std::string const & totrim)
{
return rtrim(ltrim(str, totrim), totrim);
}
std::string const format_percent(double value, size_t int_width, size_t fract_width)
{
std::ostringstream os;
if (value > .001) {
// os << fixed << value unsupported by gcc 2.95
os.setf(std::ios::fixed, std::ios::floatfield);
os << std::setw(int_width + fract_width + 1)
<< std::setprecision(fract_width) << value;
} else {
// os << scientific << value unsupported by gcc 2.95
os.setf(std::ios::scientific, std::ios::floatfield);
os << std::setw(int_width + fract_width + 1)
// - 3 to count exponent part
<< std::setprecision(fract_width - 3) << value;
}
std::string formatted = os.str();
if (is_prefix(formatted, "100."))
formatted.erase(formatted.size() - 1);
return formatted;
}
template <>
unsigned int op_lexical_cast<unsigned int, std::string>(std::string const & str)
{
char* endptr;
// 2.91.66 fix
unsigned long ret = 0;
ret = strtoul(str.c_str(), &endptr, 0);
if (*endptr) {
throw std::invalid_argument("op_lexical_cast(\""+ str +"\")");
}
return ret;
}
NS_PH_END