summaryrefslogtreecommitdiffstats
path: root/src/translators/pilotdb/strop.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/translators/pilotdb/strop.cpp')
-rw-r--r--src/translators/pilotdb/strop.cpp589
1 files changed, 589 insertions, 0 deletions
diff --git a/src/translators/pilotdb/strop.cpp b/src/translators/pilotdb/strop.cpp
new file mode 100644
index 0000000..b8c7f55
--- /dev/null
+++ b/src/translators/pilotdb/strop.cpp
@@ -0,0 +1,589 @@
+/*
+ * palm-db-tools: Support Library: String Parsing Utility Functions
+ * Copyright (C) 1999-2000 by Tom Dyas (tdyas@users.sourceforge.net)
+ *
+ * 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., 51 Franklin Street, Fifh Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <cctype>
+#include <sstream>
+
+#include "strop.h"
+#include <kdebug.h>
+
+extern std::ostream* err;
+
+void StrOps::lower(std::string& str)
+{
+ for (std::string::iterator p = str.begin(); p != str.end(); ++p) {
+ if (isupper(*p))
+ *p = tolower(*p);
+ }
+}
+
+bool StrOps::string2boolean(const std::string& str)
+{
+ std::string value(str);
+
+ StrOps::lower(value);
+
+ if (value == "on") return true;
+ else if (str == "off") return false;
+ else if (str == "true") return true;
+ else if (str == "t") return true;
+ else if (str == "false") return false;
+ else if (str == "f") return false;
+ else {
+ int num = 0;
+
+ std::istringstream(str.c_str()) >> num;
+ return num != 0 ? true : false;
+ }
+}
+
+std::string StrOps::type2string(PalmLib::FlatFile::Field::FieldType t)
+{
+ switch (t) {
+ case PalmLib::FlatFile::Field::STRING:
+ return "string";
+
+ case PalmLib::FlatFile::Field::BOOLEAN:
+ return "boolean";
+
+ case PalmLib::FlatFile::Field::INTEGER:
+ return "integer";
+
+ case PalmLib::FlatFile::Field::FLOAT:
+ return "float";
+
+ case PalmLib::FlatFile::Field::DATE:
+ return "date";
+
+ case PalmLib::FlatFile::Field::TIME:
+ return "time";
+
+ case PalmLib::FlatFile::Field::DATETIME:
+ return "datetime";
+
+ case PalmLib::FlatFile::Field::NOTE:
+ return "note";
+
+ case PalmLib::FlatFile::Field::LIST:
+ return "list";
+
+ case PalmLib::FlatFile::Field::LINK:
+ return "link";
+
+ case PalmLib::FlatFile::Field::CALCULATED:
+ return "calculated";
+
+ case PalmLib::FlatFile::Field::LINKED:
+ return "linked";
+
+ default:
+ // If we don't support the field type, then fake it as a string.
+ return "string";
+ }
+}
+
+PalmLib::FlatFile::Field::FieldType StrOps::string2type(std::string typestr)
+{
+ StrOps::lower(typestr);
+ if (typestr == "string")
+ return PalmLib::FlatFile::Field::STRING;
+ else if (typestr == "str")
+ return PalmLib::FlatFile::Field::STRING;
+ else if (typestr == "note")
+ return PalmLib::FlatFile::Field::NOTE;
+ else if (typestr == "bool")
+ return PalmLib::FlatFile::Field::BOOLEAN;
+ else if (typestr == "boolean")
+ return PalmLib::FlatFile::Field::BOOLEAN;
+ else if (typestr == "integer")
+ return PalmLib::FlatFile::Field::INTEGER;
+ else if (typestr == "int")
+ return PalmLib::FlatFile::Field::INTEGER;
+ else if (typestr == "float")
+ return PalmLib::FlatFile::Field::FLOAT;
+ else if (typestr == "date")
+ return PalmLib::FlatFile::Field::DATE;
+ else if (typestr == "time")
+ return PalmLib::FlatFile::Field::TIME;
+ else if (typestr == "datetime")
+ return PalmLib::FlatFile::Field::DATETIME;
+ else if (typestr == "list")
+ return PalmLib::FlatFile::Field::LIST;
+ else if (typestr == "link")
+ return PalmLib::FlatFile::Field::LINK;
+ else if (typestr == "linked")
+ return PalmLib::FlatFile::Field::LINKED;
+ else if (typestr == "calculated")
+ return PalmLib::FlatFile::Field::CALCULATED;
+ else
+ kdDebug() << "unknown field type" << endl;
+ return PalmLib::FlatFile::Field::STRING;
+}
+
+std::string StrOps::strip_back(const std::string& str, const std::string& what)
+{
+ std::string result(str);
+ std::string::reverse_iterator p = result.rbegin();
+
+ while (p != result.rend()
+ && (std::find(what.begin(), what.end(), *p) != what.end())) ++p;
+
+ result.erase(p.base(), result.end());
+
+ return result;
+}
+
+std::string StrOps::strip_front(const std::string& str,const std::string& what)
+{
+ std::string result(str);
+ std::string::iterator p = result.begin();
+
+ while (p != result.end()
+ && (std::find(what.begin(), what.end(), *p) != what.end())) ++p;
+
+ result.erase(result.begin(), p);
+
+ return result;
+}
+
+StrOps::string_list_t StrOps::csv_to_array(const std::string& str, char delim, bool quoted_string)
+{
+ enum { STATE_NORMAL, STATE_QUOTES } state;
+ StrOps::string_list_t result;
+ std::string elem;
+
+ state = STATE_NORMAL;
+ for (std::string::const_iterator p = str.begin(); p != str.end(); ++p) {
+ switch (state) {
+ case STATE_NORMAL:
+ if (quoted_string && *p == '"') {
+ state = STATE_QUOTES;
+ } else if (*p == delim) {
+ result.push_back(elem);
+ elem = "";
+ } else {
+ elem += *p;
+ }
+ break;
+
+ case STATE_QUOTES:
+ if (quoted_string && *p == '"') {
+ if ((p + 1) != str.end() && *(p+1) == '"') {
+ ++p;
+ elem += '"';
+ } else {
+ state = STATE_NORMAL;
+ }
+ } else {
+ elem += *p;
+ }
+ break;
+ }
+ }
+
+ switch (state) {
+ case STATE_NORMAL:
+ result.push_back(elem);
+ break;
+ case STATE_QUOTES:
+ kdDebug() << "unterminated quotes" << endl;
+ break;
+ }
+
+ return result;
+}
+
+StrOps::string_list_t
+StrOps::str_to_array(const std::string& str, const std::string& delim,
+ bool multiple_delim, bool handle_comments)
+{
+ enum { STATE_NORMAL, STATE_COMMENT, STATE_QUOTE_DOUBLE, STATE_QUOTE_SINGLE,
+ STATE_BACKSLASH, STATE_BACKSLASH_DOUBLEQUOTE } state;
+ StrOps::string_list_t result;
+ std::string elem;
+
+ state = STATE_NORMAL;
+ for (std::string::const_iterator p = str.begin(); p != str.end(); ++p) {
+ switch (state) {
+ case STATE_NORMAL:
+ if (*p == '"') {
+ state = STATE_QUOTE_DOUBLE;
+ } else if (*p == '\'') {
+ state = STATE_QUOTE_SINGLE;
+ } else if (std::find(delim.begin(), delim.end(), *p) != delim.end()) {
+ if (multiple_delim) {
+ ++p;
+ while (p != str.end()
+ && std::find(delim.begin(), delim.end(), *p) != delim.end()) {
+ ++p;
+ }
+ --p;
+ }
+ result.push_back(elem);
+ elem = "";
+ } else if (*p == '\\') {
+ state = STATE_BACKSLASH;
+ } else if (handle_comments && *p == '#') {
+ state = STATE_COMMENT;
+ } else {
+ elem += *p;
+ }
+ break;
+
+ case STATE_COMMENT:
+ break;
+
+ case STATE_QUOTE_DOUBLE:
+ if (*p == '"')
+ state = STATE_NORMAL;
+ else if (*p == '\\')
+ state = STATE_BACKSLASH_DOUBLEQUOTE;
+ else
+ elem += *p;
+ break;
+
+ case STATE_QUOTE_SINGLE:
+ if (*p == '\'')
+ state = STATE_NORMAL;
+ else
+ elem += *p;
+ break;
+
+ case STATE_BACKSLASH:
+ elem += *p;
+ state = STATE_NORMAL;
+ break;
+
+ case STATE_BACKSLASH_DOUBLEQUOTE:
+ switch (*p) {
+ case '\\':
+ elem += '\\';
+ break;
+
+ case 'n':
+ elem += '\n';
+ break;
+
+ case 'r':
+ elem += '\r';
+ break;
+
+ case 't':
+ elem += '\t';
+ break;
+
+ case 'v':
+ elem += '\v';
+ break;
+
+ case '"':
+ elem += '"';
+ break;
+
+ case 'x':
+ {
+ char buf[3];
+
+ // Extract and check the first hexadecimal character.
+ if ((p + 1) == str.end())
+ kdDebug() << "truncated escape" << endl;
+ if (! isxdigit(*(p + 1)))
+ kdDebug() << "invalid hex character" << endl;
+ buf[0] = *++p;
+
+ // Extract and check the second (if any) hex character.
+ if ((p + 1) != str.end() && isxdigit(*(p + 1))) {
+ buf[1] = *++p;
+ buf[2] = '\0';
+ } else {
+ buf[1] = buf[2] = '\0';
+ }
+
+ std::istringstream stream(buf);
+ stream.setf(std::ios::hex, std::ios::basefield);
+ unsigned value;
+ stream >> value;
+
+ elem += static_cast<char> (value & 0xFFu);
+ }
+ break;
+ }
+
+ // Escape is done. Go back to the normal double quote state.
+ state = STATE_QUOTE_DOUBLE;
+ break;
+ }
+ }
+
+ switch (state) {
+ case STATE_NORMAL:
+ result.push_back(elem);
+ break;
+
+ case STATE_QUOTE_DOUBLE:
+ kdDebug() << "unterminated double quotes" << endl;
+ break;
+
+ case STATE_QUOTE_SINGLE:
+ kdDebug() << "unterminated single quotes" << endl;
+ break;
+
+ case STATE_BACKSLASH:
+ case STATE_BACKSLASH_DOUBLEQUOTE:
+ kdDebug() << "an escape character must follow a backslash" << endl;
+ break;
+
+ default:
+ break;
+ }
+
+ return result;
+}
+
+PalmLib::pi_uint32_t
+StrOps::get_current_time(void)
+{
+ time_t now;
+
+ time(&now);
+ return static_cast<PalmLib::pi_uint32_t> (now) + PalmLib::pi_uint32_t(2082844800);
+}
+
+char *
+StrOps::strptime(const char *s, const char *format, struct tm *tm)
+{
+ char *data = (char *)s;
+ char option = false;
+
+ while (*format != 0) {
+ if (*data == 0)
+ return NULL;
+ switch (*format) {
+ case '%':
+ option = true;
+ format++;
+ break;
+ case 'd':
+ if (option) {
+ tm->tm_mday = strtol(data, &data, 10);
+ if (tm->tm_mday < 1 || tm->tm_mday > 31)
+ return NULL;
+ } else if (*data != 'd') {
+ return data;
+ }
+ option = false;
+ format++;
+ break;
+ case 'm':
+ if (option) {
+ /* tm_mon between 0 and 11 */
+ tm->tm_mon = strtol(data, &data, 10) - 1;
+ if (tm->tm_mon < 0 || tm->tm_mon > 11)
+ return NULL;
+ } else if (*data != 'm') {
+ return data;
+ }
+ option = false;
+ format++;
+ break;
+ case 'y':
+ if (option) {
+ tm->tm_year = strtol(data, &data, 10);
+ if (tm->tm_year < 60) tm->tm_year += 100;
+ } else if (*data != 'y') {
+ return data;
+ }
+ option = false;
+ format++;
+ break;
+ case 'Y':
+ if (option) {
+ tm->tm_year = strtol(data, &data, 10) - 1900;
+ } else if (*data != 'Y') {
+ return data;
+ }
+ option = false;
+ format++;
+ break;
+ case 'H':
+ if (option) {
+ tm->tm_hour = strtol(data, &data, 10);
+ if (tm->tm_hour < 0 || tm->tm_hour > 23)
+ return NULL;
+ } else if (*data != 'H') {
+ return data;
+ }
+ option = false;
+ format++;
+ break;
+ case 'M':
+ if (option) {
+ tm->tm_min = strtol(data, &data, 10);
+ if (tm->tm_min < 0 || tm->tm_min > 59)
+ return NULL;
+ } else if (*data != 'M') {
+ return data;
+ }
+ option = false;
+ format++;
+ break;
+ default:
+ if (option)
+ return data;
+ if (*data != *format)
+ return data;
+ format++;
+ data++;
+ }
+ }
+ return data;
+}
+
+// Read a line from an istream w/o concern for buffer limitations.
+std::string
+StrOps::readline(std::istream& stream)
+{
+ std::string line;
+ char buf[1024];
+
+ while (1) {
+ // Read the next line (or part thereof) from the stream.
+ stream.getline(buf, sizeof(buf));
+ // Bail out of the loop if the stream has reached end-of-file.
+ if ((stream.eof() && !buf[0]) || stream.bad())
+ break;
+
+ // Append the data read to the result string.
+ line.append(buf);
+
+ // If the stream is good, then stop. Otherwise, clear the
+ // error indicator so that getline will work again.
+ if ((stream.eof() && buf[0]) || stream.good())
+ break;
+ stream.clear();
+ }
+
+ return line;
+}
+
+std::string
+StrOps::quote_string(std::string str, bool extended_mode)
+{
+ std::string result;
+ std::ostringstream error;
+
+ if (extended_mode) {
+ result += '"';
+ for (std::string::iterator c = str.begin(); c != str.end(); ++c) {
+ switch (*c) {
+ case '\\':
+ result += '\\';
+ result += '\\';
+ break;
+
+ case '\r':
+ result += '\\';
+ result += 'r';
+ break;
+
+ case '\n':
+ result += '\\';
+ result += 'n';
+ break;
+
+ case '\t':
+ result += '\\';
+ result += 't';
+ break;
+
+ case '\v':
+ result += '\\';
+ result += 'v';
+ break;
+
+ case '"':
+ result += '\\';
+ result += '"';
+ break;
+
+ default:
+ if (isprint(*c)) {
+ result += *c;
+ } else {
+ std::ostringstream buf;
+ buf.width(2);
+ buf.setf(std::ios::hex, std::ios::basefield);
+ buf.setf(std::ios::left);
+ buf << ((static_cast<unsigned> (*c)) & 0xFF) << std::ends;
+
+ result += "\\x";
+ result += buf.str();
+ }
+ break;
+ }
+ }
+ result += '"';
+ } else {
+ result += '"';
+ for (std::string::iterator c = str.begin(); c != str.end(); ++c) {
+ if (*c == '"') {
+ result += "\"\"";
+ } else if (*c == '\n' || *c == '\r') {
+ error << "use extended csv mode for newlines\n";
+ *err << error.str();
+ kdDebug() << error.str().c_str() << endl;
+ } else {
+ result += *c;
+ }
+ }
+ result += '"';
+ }
+
+ return result;
+}
+
+std::string
+StrOps::concatenatepath(std::string p_Path,
+ std::string p_FileName, std::string p_Ext)
+{
+ std::string l_FilePath;
+#ifdef WIN32
+ if (p_FileName[1] == ':' || p_FileName[0] == '\\')
+ return p_FileName;
+ else if (p_Path.empty())
+ l_FilePath = p_FileName;
+ else
+ l_FilePath = p_Path + std::string("\\") + p_FileName;
+#else
+ if (p_FileName[0] == '/')
+ return p_FileName;
+ else if (p_Path.empty())
+ l_FilePath = p_FileName;
+ else
+ l_FilePath = p_Path + std::string("/") + p_FileName;
+
+#endif
+ if (!p_Ext.empty() && (p_FileName.rfind(p_Ext) == std::string::npos))
+ l_FilePath += p_Ext;
+
+ return l_FilePath;
+}