added toupper and simpleregexp utils

This commit is contained in:
Jean-Francois Dockes 2016-06-18 19:37:41 +02:00
parent 9a61c47467
commit c2e7708035
2 changed files with 197 additions and 2 deletions

View file

@ -31,6 +31,16 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
// Older compilers don't support stdc++ regex, but Windows does not
// have the Linux one. Have a simple class to solve the simple cases.
#if defined(_WIN32)
#define USE_STD_REGEX
#include <regex>
#else
#define USE_LINUX_REGEX
#include <regex.h>
#endif
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <list> #include <list>
@ -87,6 +97,23 @@ string stringtolower(const string& i)
stringtolower(o); stringtolower(o);
return o; return o;
} }
void stringtoupper(string& io)
{
string::iterator it = io.begin();
string::iterator ite = io.end();
while (it != ite) {
*it = ::toupper(*it);
it++;
}
}
string stringtoupper(const string& i)
{
string o = i;
stringtoupper(o);
return o;
}
extern int stringisuffcmp(const string& s1, const string& s2) extern int stringisuffcmp(const string& s1, const string& s2)
{ {
string::const_reverse_iterator r1 = s1.rbegin(), re1 = s1.rend(), string::const_reverse_iterator r1 = s1.rbegin(), re1 = s1.rend(),
@ -541,6 +568,34 @@ string escapeShell(const string& in)
return out; return out;
} }
// Escape value to be suitable as C++ source double-quoted string (for
// generating a c++ program
string makeCString(const string& in)
{
string out;
out += "\"";
for (string::size_type pos = 0; pos < in.length(); pos++) {
switch (in.at(pos)) {
case '"':
out += "\\\"";
break;
case '\n':
out += "\\n";
break;
case '\r':
out += "\\r";
break;
case '\\':
out += "\\\\";
break;
default:
out += in.at(pos);
}
}
out += "\"";
return out;
}
// Substitute printf-like percent cmds inside a string // Substitute printf-like percent cmds inside a string
bool pcSubst(const string& in, string& out, const map<char, string>& subs) bool pcSubst(const string& in, string& out, const map<char, string>& subs)
@ -1107,6 +1162,7 @@ void catstrerror(string *reason, const char *what, int _errno)
errbuf[0] = 0; errbuf[0] = 0;
// We don't use ret, it's there to silence a cc warning // We don't use ret, it's there to silence a cc warning
char *ret = (char *)strerror_r(_errno, errbuf, ERRBUFSZ); char *ret = (char *)strerror_r(_errno, errbuf, ERRBUFSZ);
(void)ret;
reason->append(errbuf); reason->append(errbuf);
#endif #endif
} }
@ -1175,6 +1231,100 @@ string localelang()
return locale.substr(0, under); return locale.substr(0, under);
} }
#ifdef USE_STD_REGEX
class SimpleRegexp::Internal {
public:
Internal(const string& exp, int flags, int nm)
: expr(exp,
basic_regex<char>::flag_type(regex_constants::extended |
((flags&SRE_ICASE) ? regex_constants::icase : 0) |
((flags&SRE_NOSUB) ? regex_constants::nosubs : 0)
)), ok(true), nmatch(nm) {
}
bool ok;
std::regex expr;
std::smatch res;
int nmatch;
};
bool SimpleRegexp::simpleMatch(const string& val) const
{
if (!ok())
return false;
return regex_match(val, m->res, m->expr);
}
string SimpleRegexp::getMatch(const string& val, int i) const
{
return m->res.str(i);
}
#else // -> !WIN32
class SimpleRegexp::Internal {
public:
Internal(const string& exp, int flags, int nm) : nmatch(nm) {
if (regcomp(&expr, exp.c_str(), REG_EXTENDED |
((flags&SRE_ICASE) ? REG_ICASE : 0) |
((flags&SRE_NOSUB) ? REG_NOSUB : 0)) == 0) {
ok = true;
} else {
ok = false;
}
matches.reserve(nmatch+1);
}
~Internal() {
regfree(&expr);
}
bool ok;
regex_t expr;
int nmatch;
vector<regmatch_t> matches;
};
bool SimpleRegexp::simpleMatch(const string& val) const
{
if (!ok())
return false;
if (regexec(&m->expr, val.c_str(), m->nmatch+1, &m->matches[0], 0) == 0) {
return true;
} else {
return false;
}
}
string SimpleRegexp::getMatch(const string& val, int i) const
{
if (i > m->nmatch) {
return string();
}
return val.substr(m->matches[i].rm_so,
m->matches[i].rm_eo - m->matches[i].rm_so);
}
#endif // win/notwinf
SimpleRegexp::SimpleRegexp(const string& exp, int flags, int nmatch)
: m(new Internal(exp, flags, nmatch))
{
}
SimpleRegexp::~SimpleRegexp()
{
delete m;
}
bool SimpleRegexp::ok() const
{
return m->ok;
}
bool SimpleRegexp::operator() (const string& val) const
{
return simpleMatch(val);
}
// Initialization for static stuff to be called from main thread before going // Initialization for static stuff to be called from main thread before going
// multiple // multiple
void smallut_init_mt() void smallut_init_mt()
@ -1249,7 +1399,7 @@ int main(int argc, char **argv)
thisprog = *argv++; thisprog = *argv++;
argc--; argc--;
#if 1 #if 0
if (argc <= 0) { if (argc <= 0) {
cerr << "Usage: smallut <stringtosplit>" << endl; cerr << "Usage: smallut <stringtosplit>" << endl;
exit(1); exit(1);
@ -1400,7 +1550,23 @@ int main(int argc, char **argv)
cout << it->first << " " << it->second << " " << cout << it->first << " " << it->second << " " <<
stringuppercmp(it->first, it->second) << endl; stringuppercmp(it->first, it->second) << endl;
} }
#elif 0
SimpleRegexp exp("[ \t]*#[ \t]*([a-zA-Z0-9]+)[ \t]*=.*", 0, 1);
//SimpleRegexp exp(" # ([a-zA-Z0-9]+) =.*", 0, 10);
//SimpleRegexp exp(" # (varnm) = sdf sdf sdf ", 0, 10);
//SimpleRegexp exp(".*", 0);
string tomatch(" # varnm = sdf sdf sdf ");
if (exp.simpleMatch(tomatch)) {
cout << "Match !\n";
cout << "Submatch[0]: [" << exp.getMatch(tomatch, 0) << "]\n";
cout << "Submatch[1]: [" << exp.getMatch(tomatch, 1) << "]\n";
return 0;
} else {
cerr << "No match\n";
return 1;
}
#elif 1
cout << makeCString("\"hello\" world\n2nd line") << endl;
#endif #endif
} }

View file

@ -63,6 +63,8 @@ extern int stringuppercmp(const std::string& alreadyupper,
extern void stringtolower(std::string& io); extern void stringtolower(std::string& io);
extern std::string stringtolower(const std::string& io); extern std::string stringtolower(const std::string& io);
extern void stringtoupper(std::string& io);
extern std::string stringtoupper(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 std::string& s1, const std::string& s2); extern int stringisuffcmp(const std::string& s1, const std::string& s2);
@ -141,6 +143,9 @@ 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 std::string escapeHtml(const std::string& in); extern std::string escapeHtml(const std::string& in);
/** Double-quote and escape to produce C source code string (prog generation) */
extern std::string makeCString(const std::string& in);
/** Replace some chars with spaces (ie: newline chars). */ /** Replace some chars with spaces (ie: newline chars). */
extern std::string neutchars(const std::string& str, const std::string& chars); extern std::string neutchars(const std::string& str, const std::string& chars);
extern void neutchars(const std::string& str, std::string& out, extern void neutchars(const std::string& str, std::string& out,
@ -189,6 +194,30 @@ inline void leftzeropad(std::string& s, unsigned len)
} }
} }
// A class to solve platorm/compiler issues for simple regex
// matches. Uses the appropriate native lib under the hood.
// This always uses extended regexp syntax.
class SimpleRegexp {
public:
enum Flags {SRE_NONE = 0, SRE_ICASE = 1, SRE_NOSUB = 2};
/// @param nmatch must be >= the number of parenthesed subexp in exp
SimpleRegexp(const std::string& exp, int flags, int nmatch = 0);
~SimpleRegexp();
/// Match input against exp, return true if matches
bool simpleMatch(const std::string& val) const;
/// After simpleMatch success, get nth submatch, 0 is the whole
/// match, 1 first parentheses, etc.
std::string getMatch(const std::string& val, int matchidx) const;
/// Calls simpleMatch()
bool operator() (const std::string& val) const;
/// Check after construction
bool ok() const;
class Internal;
private:
Internal *m;
};
// 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);