summaryrefslogtreecommitdiffstats
path: root/src/util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.cpp')
-rw-r--r--src/util.cpp765
1 files changed, 765 insertions, 0 deletions
diff --git a/src/util.cpp b/src/util.cpp
new file mode 100644
index 0000000..a88e85d
--- /dev/null
+++ b/src/util.cpp
@@ -0,0 +1,765 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ 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 <iostream>
+#include <iomanip>
+#include <sstream>
+#include <locale>
+#include <cassert>
+#include <cctype>
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <sys/time.h>
+
+#include "util.h"
+
+#include "twinkle_config.h"
+
+string month_abbrv[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
+ "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+string month_full[] = {"January", "February", "March", "April", "May", "June", "July",
+ "August", "September", "October", "November", "December"};
+
+string day_abbrv[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+
+string random_token(int length) {
+ string s;
+
+ for (int i = 0; i < length; i++) {
+ s += char(rand() % 26 + 97);
+ }
+
+ return s;
+}
+
+string random_hexstr(int length) {
+ string s;
+ int x;
+
+ for (int i = 0; i < length; i++) {
+ x = rand() % 16;
+ if (x <= 9)
+ s += '0' + x;
+ else
+ s += 'a' + x - 10;
+ }
+
+ return s;
+}
+
+string float2str(float f, int precision) {
+ ostringstream s;
+
+ // Force the locale to POSIX, such that a dot is used for
+ // the decimal point.
+ s.imbue(locale("POSIX"));
+ s.setf(ios::fixed,ios::floatfield);
+ s.precision(precision);
+ s << f;
+
+ return s.str();
+}
+
+string int2str(int i, const char *format) {
+ char buf[32];
+
+ snprintf(buf, 32, format, i);
+ return string(buf);
+}
+
+string int2str(int i) {
+ return int2str(i, "%d");
+}
+
+string ulong2str(unsigned long i, const char *format) {
+ char buf[32];
+
+ snprintf(buf, 32, format, i);
+ return string(buf);
+}
+
+string ulong2str(unsigned long i) {
+ return ulong2str(i, "%u");
+}
+
+string ptr2str(void *p) {
+ char buf[32];
+
+ snprintf(buf, 32, "%p", p);
+ return string(buf);
+}
+
+string bool2str(bool b) {
+ return (b ? "true" : "false");
+}
+
+string time2str(time_t t, const char *format) {
+ struct tm tm;
+ char buf[64];
+
+ localtime_r(&t, &tm);
+ strftime(buf, 64, format, &tm);
+ return string(buf);
+}
+
+string current_time2str(const char *format) {
+ struct timeval t;
+
+ gettimeofday(&t, NULL);
+ return time2str(t.tv_sec, format);
+}
+
+string weekday2str(int wkday) {
+ if (wkday >= 0 && wkday <= 6) return day_abbrv[wkday];
+ return "XXX";
+}
+
+string month2str(int month) {
+ if (month >= 0 && month <= 11) return month_abbrv[month];
+ return "XXX";
+}
+
+int str2month_full(const string &month) {
+ for (int i = 0; i < 12; i++) {
+ if (cmp_nocase(month_full[i], month) == 0) {
+ return i;
+ }
+ }
+
+ return 0;
+}
+
+string duration2str(unsigned long seconds) {
+ string result;
+ long remainder, h, m, s;
+
+ h = seconds / 3600;
+ remainder = seconds % 3600;
+ m = remainder / 60;
+ s = remainder % 60;
+
+ if (h > 0) {
+ result = ulong2str(h);
+ result += "h ";
+ }
+
+ if (!result.empty() || m > 0) {
+ result += ulong2str(m);
+ result += "m ";
+ }
+
+ result += ulong2str(s);
+ result += "s";
+
+ return result;
+}
+
+string timer2str(unsigned long seconds) {
+ string result;
+ unsigned long remainder, h, m, s;
+
+ h = seconds / 3600;
+ remainder = seconds % 3600;
+ m = remainder / 60;
+ s = remainder % 60;
+
+ char buf[16];
+ snprintf(buf, 16, "%01lu:%02lu:%02lu", h, m, s);
+ return string(buf);
+}
+
+static uint8 hexdig2value(char hexdig) {
+ uint8 val = 0;
+
+ if (hexdig >= '0' && hexdig <= '9')
+ val = hexdig - '0';
+ else if (hexdig >= 'a' && hexdig <= 'f')
+ val = hexdig - 'a' + 10;
+ else if (hexdig >= 'A' && hexdig <= 'F')
+ val = hexdig - 'A' + 10;
+
+ return val;
+}
+
+static char value2hexdig(uint8 val) {
+ char c = '0';
+
+ if (val <= 9) {
+ c = '0' + val;
+ } else if (val <= 15) {
+ c = 'a' + val - 10;
+ }
+
+ return c;
+}
+
+unsigned long hex2int(const string &h) {
+ unsigned long u = 0;
+
+ int power = 1;
+ for (string::const_reverse_iterator i = h.rbegin(); i != h.rend(); ++i) {
+ u += hexdig2value(*i) * power;
+ power = power * 16;
+ }
+
+ return u;
+}
+
+void hex2binary(const string &h, uint8 *buf) {
+ uint8 *p = buf;
+
+ bool hi_nibble = true;
+ for (string::const_iterator i = h.begin() ; i != h.end(); ++i) {
+ if (hi_nibble) {
+ *p = hexdig2value(*i) << 4;
+ } else {
+ *(p++) |= hexdig2value(*i);
+ }
+
+ hi_nibble = !hi_nibble;
+ }
+}
+
+string binary2hex(uint8 *buf, unsigned long len) {
+ string s;
+
+ for (uint8 *p = buf; p < buf + len; ++p) {
+ s += value2hexdig((*p >> 4) & 0xf);
+ s += value2hexdig(*p & 0xf);
+ }
+
+ return s;
+}
+
+string tolower(const string &s) {
+ string result;
+
+ for (string::const_iterator i = s.begin(); i != s.end(); ++i) {
+ result += tolower(*i);
+ }
+
+ return result;
+}
+
+string toupper(const string &s) {
+ string result;
+
+ for (string::const_iterator i = s.begin(); i != s.end(); ++i) {
+ result += toupper(*i);
+ }
+
+ return result;
+}
+
+string rtrim(const string &s) {
+ string::size_type i;
+
+ i = s.find_last_not_of(' ');
+ if (i == string::npos) return "";
+ if (i == s.size()-1) return s;
+ return s.substr(0, i+1);
+}
+
+string ltrim(const string &s) {
+ string::size_type i;
+
+ i = s.find_first_not_of(' ');
+ if (i == string::npos) return "";
+ if (i == 0) return s;
+ return s.substr(i, s.size()-i+1);
+}
+
+string trim(const string &s) {
+ return ltrim(rtrim(s));
+}
+
+string padleft(const string &s, char c, unsigned long len) {
+ string result(c, len);
+ result += s;
+ return result.substr(result.size() - len);
+}
+
+int cmp_nocase(const string &s1, const string &s2) {
+ string::const_iterator i1 = s1.begin();
+ string::const_iterator i2 = s2.begin();
+
+ while (i1 != s1.end() && i2 != s2.end()) {
+ if (toupper(*i1) != toupper(*i2)) {
+ return (toupper(*i1) < toupper(*i2)) ? -1 : 1;
+ }
+ ++i1;
+ ++i2;
+ }
+
+ if (s1.size() == s2.size()) return 0;
+ if (s1.size() < s2.size()) return -1;
+ return 1;
+}
+
+bool must_quote(const string &s) {
+ string special("()<>@,;:\\\"/[]?={} \t");
+
+ if (s.size() == 0) return true;
+ return (s.find_first_of(special) != string::npos);
+}
+
+string escape(const string &s, char c) {
+ string result;
+
+ for (string::size_type i = 0; i < s.size(); i++) {
+ if (s[i] == '\\' || s[i] == c) {
+ result += '\\';
+ }
+
+ result += s[i];
+ }
+
+ return result;
+}
+
+string unescape(const string &s) {
+ string result;
+
+ for (string::size_type i = 0; i < s.size(); i++) {
+ if (s[i] == '\\' && i < s.size() - 1) {
+ i++;
+ }
+
+ result += s[i];
+ }
+
+ return result;
+}
+
+string escape_hex(const string &s, const string &unreserved) {
+ string result;
+
+ for (string::size_type i = 0; i < s.size(); i++) {
+ if (unreserved.find(s[i], 0) != string::npos) {
+ // Unreserved symbol
+ result += s[i];
+ } else {
+ // Reserved symbol
+ result += int2str((int)s[i], "%%%02x");
+ }
+ }
+
+ return result;
+}
+string unescape_hex(const string &s) {
+ string result;
+
+ for (string::size_type i = 0; i < s.size(); i++) {
+ if (s[i] == '%' && i < s.size() - 2 &&
+ isxdigit(s[i+1]) && isxdigit(s[i+2]))
+ {
+ // Escaped hex-value
+ string hexval = s.substr(i+1, 2);
+ result += static_cast<char>(hex2int(hexval));
+ i += 2;
+ } else {
+ result += s[i];
+ }
+ }
+
+ return result;
+}
+
+string replace_char(const string &s, char from, char to) {
+ string result = s;
+
+ for (string::size_type i = 0; i < result.size(); i++) {
+ if (result[i] == from) result[i] = to;
+ }
+
+ return result;
+}
+
+string replace_first(const string &s, const string &from, const string &to) {
+ string result = s;
+
+ string::size_type i = result.find(from, 0);
+ if (i != string::npos) {
+ result.replace(i, from.size(), to);
+ }
+
+ return result;
+}
+
+vector<string> split(const string &s, char c) {
+ string::size_type i;
+ string::size_type j = 0;
+ vector<string> l;
+
+ while (true) {
+ i = s.find(c, j);
+ if (i == string::npos) {
+ l.push_back(s.substr(j));
+ return l;
+ }
+
+ if (i == j)
+ l.push_back("");
+ else
+ l.push_back(s.substr(j, i-j));
+
+ j = i+1;
+
+ if (j == s.size()) {
+ l.push_back("");
+ return l;
+ }
+ }
+}
+
+vector<string> split(const string &s, const string& separator) {
+ string::size_type i;
+ string::size_type j = 0;
+ vector<string> l;
+
+ while (true) {
+ i = s.find(separator, j);
+ if (i == string::npos) {
+ l.push_back(s.substr(j));
+ return l;
+ }
+
+ if (i == j)
+ l.push_back("");
+ else
+ l.push_back(s.substr(j, i-j));
+
+ j = i + separator.size();
+
+ if (j == s.size()) {
+ l.push_back("");
+ return l;
+ }
+ }
+}
+
+vector<string> split_linebreak(const string &s) {
+ if (s.find("\r\n") != string::npos) {
+ return split(s, "\r\n");
+ } else if (s.find("\r") != string::npos) {
+ return split(s, "\r");
+ }
+
+ return split(s, "\n");
+}
+
+vector<string> split_on_first(const string &s, char c) {
+ vector<string> l;
+ string::size_type i = s.find(c);
+ if (i == string::npos) {
+ l.push_back(s);
+ } else {
+ if (i == 0) {
+ l.push_back("");
+ } else {
+ l.push_back(s.substr(0, i));
+ }
+
+ if (i == s.size() - 1) {
+ l.push_back("");
+ } else {
+ l.push_back(s.substr(i + 1));
+ }
+ }
+
+ return l;
+}
+
+vector<string> split_on_last(const string &s, char c) {
+ vector<string> l;
+ string::size_type i = s.find_last_of(c);
+ if (i == string::npos) {
+ l.push_back(s);
+ } else {
+ if (i == 0) {
+ l.push_back("");
+ } else {
+ l.push_back(s.substr(0, i));
+ }
+
+ if (i == s.size() - 1) {
+ l.push_back("");
+ } else {
+ l.push_back(s.substr(i + 1));
+ }
+ }
+
+ return l;
+}
+
+vector<string> split_escaped(const string &s, char c) {
+ vector<string> l;
+
+ string::size_type start_pos = 0;
+ for (string::size_type i = 0; i < s.size(); i++) {
+ if (s[i] == '\\') {
+ // Skip escaped character
+ if (i < s.size()) i++;
+ continue;
+ }
+
+ if (s[i] == c) {
+ l.push_back(unescape(s.substr(start_pos, i - start_pos)));
+ start_pos = i + 1;
+ }
+ }
+
+ if (start_pos < s.size()) {
+ l.push_back(unescape(s.substr(start_pos, s.size() - start_pos)));
+ } else if (start_pos == s.size()) {
+ l.push_back("");
+ }
+
+ return l;
+}
+
+vector<string> split_ws(const string &s, bool quote_sensitive) {
+ vector<string> l;
+ bool in_quotes = false;
+
+ string::size_type start_pos = 0;
+ for (string::size_type i = 0; i < s.size(); i++ ) {
+ if (quote_sensitive && s[i] == '"') {
+ in_quotes = !in_quotes;
+ continue;
+ }
+
+ if (in_quotes) continue;
+
+ if (s[i] == ' ' || s[i] == '\t') {
+ // Skip consecutive white space
+ if (start_pos != i) {
+ l.push_back(s.substr(start_pos, i - start_pos));
+ }
+ start_pos = i + 1;
+ }
+ }
+
+ if (start_pos < s.size()) {
+ l.push_back(s.substr(start_pos, s.size() - start_pos));
+ }
+
+ return l;
+}
+
+string join_strings(const vector<string> &v, const string &separator) {
+ string text;
+ for (vector<string>::const_iterator it = v.begin(); it != v.end(); ++it)
+ {
+ if (it != v.begin()) {
+ text += separator;
+ }
+ text += *it;
+ }
+
+ return text;
+}
+
+string unquote(const string &s) {
+ if (s.size() <= 1) return s;
+
+ if (s[0] == '"' && s[s.size() - 1] == '"')
+ return s.substr(1, s.size() - 2);
+
+ return s;
+}
+
+bool is_number(const string &s) {
+ if (s.empty()) return false;
+
+ for (string::size_type i = 0; i < s.size(); i++ ) {
+ if (!isdigit(s[i])) return false;
+ }
+
+ return true;
+}
+
+bool is_ipaddr(const string &s) {
+ vector<string> l = split(s, '.');
+ if (l.size() != 4) return false;
+
+ for (vector<string>::iterator i = l.begin(); i != l.end(); ++i) {
+ if (!is_number(*i) || atoi(i->c_str()) > 255) return false;
+ }
+
+ return true;
+}
+
+bool yesno2bool(const string &yesno) {
+ return (yesno == "yes" ? true : false);
+}
+string bool2yesno(bool b) {
+ return (b ? "yes" : "no");
+}
+
+string str2dtmf(const string &s) {
+ string result;
+ string to_convert = tolower(s);
+
+ for (string::size_type i = 0; i < to_convert.size(); i++) {
+ switch (to_convert[i]) {
+ case '1':
+ result += '1';
+ break;
+ case '2':
+ case 'a':
+ case 'b':
+ case 'c':
+ result += '2';
+ break;
+ case '3':
+ case 'd':
+ case 'e':
+ case 'f':
+ result += '3';
+ break;
+ case '4':
+ case 'g':
+ case 'h':
+ case 'i':
+ result += '4';
+ break;
+ case '5':
+ case 'j':
+ case 'k':
+ case 'l':
+ result += '5';
+ break;
+ case '6':
+ case 'm':
+ case 'n':
+ case 'o':
+ result += '6';
+ break;
+ case '7':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ result += '7';
+ break;
+ case '8':
+ case 't':
+ case 'u':
+ case 'v':
+ result += '8';
+ break;
+ case '9':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ result += '9';
+ break;
+ case '0':
+ case ' ':
+ result += '0';
+ break;
+ case '#':
+ case '*':
+ result += to_convert[i];
+ break;
+ }
+ }
+
+ return result;
+}
+
+bool looks_like_phone(const string &s, const string &special_symbols) {
+ string phone_symbols= special_symbols + "0123456789*#+ \t";
+ string t;
+
+ for (string::const_iterator i = s.begin(); i != s.end(); ++i) {
+ if (phone_symbols.find(*i) == string::npos) return false;
+ }
+
+ return true;
+}
+
+string remove_symbols(const string &s, const string &special_symbols) {
+ string result;
+
+ for (string::const_iterator i = s.begin(); i != s.end(); ++i) {
+ if (special_symbols.find(*i) == string::npos) {
+ result += *i;
+ }
+ }
+
+ return result;
+}
+
+string remove_white_space(const string &s) {
+ string result;
+
+ for (string::const_iterator i = s.begin(); i != s.end(); ++i) {
+ if (*i != ' ' && *i != '\t') {
+ result += *i;
+ }
+ }
+
+ return result;
+}
+
+string dotted_truncate(const string &s, string::size_type len) {
+ if (len >= s.size()) return s;
+
+ return s.substr(0, len) + "...";
+}
+
+string to_printable(const string &s) {
+ string result;
+
+ for (string::const_iterator i = s.begin(); i != s.end(); ++i) {
+ if (isprint(*i) || *i == '\n' || *i == '\r') {
+ result += *i;
+ } else {
+ result += '.';
+ }
+ }
+
+ return result;
+}
+
+string get_error_str(int errnum) {
+#if HAVE_STRERROR_R
+ char buf[81];
+ memset(buf, 0, sizeof(buf));
+#if STRERROR_R_CHAR_P
+ string errmsg(strerror_r(errnum, buf, sizeof(buf)-1));
+#else
+ string errmsg;
+ if (strerror_r(errnum, buf, sizeof(buf)-1) == 0) {
+ errmsg = buf;
+ } else {
+ errmsg = "unknown error: ";
+ errmsg += int2str(errnum);
+ }
+#endif
+#else
+ string errmsg("strerror_r is not available: ");
+ errmsg += int2str(errnum);
+#endif
+ return errmsg;
+}