summaryrefslogtreecommitdiff
path: root/ndb/src/common/util/BaseString.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/src/common/util/BaseString.cpp')
-rw-r--r--ndb/src/common/util/BaseString.cpp418
1 files changed, 418 insertions, 0 deletions
diff --git a/ndb/src/common/util/BaseString.cpp b/ndb/src/common/util/BaseString.cpp
new file mode 100644
index 00000000000..1b0eaa1b83c
--- /dev/null
+++ b/ndb/src/common/util/BaseString.cpp
@@ -0,0 +1,418 @@
+/* Copyright (C) 2003 MySQL AB
+
+ 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 */
+
+/* -*- c-basic-offset: 4; -*- */
+#include <string.h>
+#include <NdbStdio.h>
+#include <stdarg.h>
+#include "BaseString.hpp"
+#include <stdlib.h>
+
+BaseString::BaseString()
+{
+ m_chr = new char[1];
+ m_chr[0] = 0;
+ m_len = 0;
+}
+
+BaseString::BaseString(const char* s)
+{
+ const size_t n = strlen(s);
+ m_chr = new char[n + 1];
+ memcpy(m_chr, s, n + 1);
+ m_len = n;
+}
+
+BaseString::BaseString(const BaseString& str)
+{
+ const char* const s = str.m_chr;
+ const size_t n = str.m_len;
+ char* t = new char[n + 1];
+ memcpy(t, s, n + 1);
+ m_chr = t;
+ m_len = n;
+}
+
+BaseString::~BaseString()
+{
+ delete[] m_chr;
+}
+
+BaseString&
+BaseString::assign(const char* s)
+{
+ const size_t n = strlen(s);
+ char* t = new char[n + 1];
+ memcpy(t, s, n + 1);
+ delete[] m_chr;
+ m_chr = t;
+ m_len = n;
+ return *this;
+}
+
+BaseString&
+BaseString::assign(const char* s, size_t n)
+{
+ char* t = new char[n + 1];
+ memcpy(t, s, n);
+ t[n] = 0;
+ delete[] m_chr;
+ m_chr = t;
+ m_len = n;
+ return *this;
+}
+
+BaseString&
+BaseString::assign(const BaseString& str, size_t n)
+{
+ if (n > str.m_len)
+ n = str.m_len;
+ return assign(str.m_chr, n);
+}
+
+BaseString&
+BaseString::append(const char* s)
+{
+ const size_t n = strlen(s);
+ char* t = new char[m_len + n + 1];
+ memcpy(t, m_chr, m_len);
+ memcpy(t + m_len, s, n + 1);
+ delete[] m_chr;
+ m_chr = t;
+ m_len += n;
+ return *this;
+}
+
+BaseString&
+BaseString::append(char c) {
+ return appfmt("%c", c);
+}
+
+BaseString&
+BaseString::append(const BaseString& str)
+{
+ return append(str.m_chr);
+}
+
+BaseString&
+BaseString::append(const Vector<BaseString> &vector,
+ const BaseString &separator) {
+ for(size_t i=0;i<vector.size(); i++) {
+ append(vector[i]);
+ if(i<vector.size()-1)
+ append(separator);
+ }
+ return *this;
+}
+
+BaseString&
+BaseString::assfmt(const char *fmt, ...)
+{
+ char buf[1];
+ va_list ap;
+ int l;
+
+ /* Figure out how long the formatted string will be. A small temporary
+ * buffer is used, because I don't trust all implementations to work
+ * when called as vsnprintf(NULL, 0, ...).
+ */
+ va_start(ap, fmt);
+ l = vsnprintf(buf, sizeof(buf), fmt, ap) + 1;
+ va_end(ap);
+ if(l > (int)m_len) {
+ delete[] m_chr;
+ m_chr = new char[l];
+ }
+ va_start(ap, fmt);
+ vsnprintf(m_chr, l, fmt, ap);
+ va_end(ap);
+ m_len = strlen(m_chr);
+ return *this;
+}
+
+BaseString&
+BaseString::appfmt(const char *fmt, ...)
+{
+ char buf[1];
+ va_list ap;
+ int l;
+
+ /* Figure out how long the formatted string will be. A small temporary
+ * buffer is used, because I don't trust all implementations to work
+ * when called as vsnprintf(NULL, 0, ...).
+ */
+ va_start(ap, fmt);
+ l = vsnprintf(buf, sizeof(buf), fmt, ap) + 1;
+ va_end(ap);
+ char *tmp = new char[l];
+ va_start(ap, fmt);
+ vsnprintf(tmp, l, fmt, ap);
+ va_end(ap);
+ append(tmp);
+ delete[] tmp;
+ return *this;
+}
+
+BaseString&
+BaseString::operator=(const BaseString& str)
+{
+ if (this != &str) {
+ this->assign(str);
+ }
+ return *this;
+}
+
+int
+BaseString::split(Vector<BaseString> &v,
+ const BaseString &separator,
+ int maxSize) const {
+ char *str = strdup(m_chr);
+ int i, start, len, num = 0;
+ len = strlen(str);
+ for(start = i = 0;
+ (i <= len) && ( (maxSize<0) || ((int)v.size()<=maxSize-1) );
+ i++) {
+ if(strchr(separator.c_str(), str[i]) || i == len) {
+ if(maxSize < 0 || (int)v.size() < maxSize-1)
+ str[i] = '\0';
+ v.push_back(BaseString(str+start));
+ num++;
+ start = i+1;
+ }
+ }
+ free(str);
+
+ return num;
+}
+
+ssize_t
+BaseString::indexOf(char c) {
+ char *p;
+ p = strchr(m_chr, c);
+ if(p == NULL)
+ return -1;
+ return (ssize_t)(p-m_chr);
+}
+
+ssize_t
+BaseString::lastIndexOf(char c) {
+ char *p;
+ p = strrchr(m_chr, c);
+ if(p == NULL)
+ return -1;
+ return (ssize_t)(p-m_chr);
+}
+
+BaseString
+BaseString::substr(ssize_t start, ssize_t stop) {
+ if(stop < 0)
+ stop = length();
+ ssize_t len = stop-start;
+ if(len <= 0)
+ return BaseString("");
+ BaseString s;
+ s.assign(m_chr+start, len);
+ return s;
+}
+
+static bool
+iswhite(char c) {
+ switch(c) {
+ case ' ':
+ case '\t':
+ return true;
+ default:
+ return false;
+ }
+ /* NOTREACHED */
+}
+
+char **
+BaseString::argify(const char *argv0, const char *src) {
+ Vector<char *> vargv;
+
+ if(argv0 != NULL)
+ vargv.push_back(strdup(argv0));
+
+ char *tmp = new char[strlen(src)+1];
+ char *dst = tmp;
+ const char *end = src + strlen(src);
+ /* Copy characters from src to destination, while compacting them
+ * so that all whitespace is compacted and replaced by a NUL-byte.
+ * At the same time, add pointers to strings in the vargv vector.
+ * When whitespace is detected, the characters '"' and '\' are honored,
+ * to make it possible to give arguments containing whitespace.
+ * The semantics of '"' and '\' match that of most Unix shells.
+ */
+ while(src < end && *src) {
+ /* Skip initial whitespace */
+ while(src < end && *src && iswhite(*src))
+ src++;
+
+ char *begin = dst;
+ while(src < end && *src) {
+ /* Handle '"' quotation */
+ if(*src == '"') {
+ src++;
+ while(src < end && *src && *src != '"') {
+ if(*src == '\\')
+ src++;
+ *dst++ = *src++;
+ }
+ src++;
+ if(src >= end)
+ goto end;
+ }
+
+ /* Handle '\' */
+ if(*src == '\\')
+ src++;
+ else if(iswhite(*src))
+ break;
+
+ /* Actually copy characters */
+ *dst++ = *src++;
+ }
+
+ /* Make sure the string is properly terminated */
+ *dst++ = '\0';
+ src++;
+
+ vargv.push_back(strdup(begin));
+ }
+ end:
+
+ delete[] tmp;
+ vargv.push_back(NULL);
+
+ /* Convert the C++ Vector into a C-vector of strings, suitable for
+ * calling execv().
+ */
+ char **argv = (char **)malloc(sizeof(*argv) * (vargv.size()));
+ if(argv == NULL)
+ return NULL;
+
+ for(size_t i = 0; i < vargv.size(); i++){
+ argv[i] = vargv[i];
+ }
+
+ return argv;
+}
+
+BaseString&
+BaseString::trim(const char * delim){
+ trim(m_chr, delim);
+ m_len = strlen(m_chr);
+ return * this;
+}
+
+char*
+BaseString::trim(char * str, const char * delim){
+ int len = strlen(str) - 1;
+ for(; len > 0 && strchr(delim, str[len]); len--);
+
+ int pos = 0;
+ for(; pos <= len && strchr(delim, str[pos]); pos++);
+
+ if(pos > len){
+ str[0] = 0;
+ return 0;
+ } else {
+ memmove(str, &str[pos], len - pos + 1);
+ str[len-pos+1] = 0;
+ }
+
+ return str;
+}
+
+
+#ifdef TEST_BASE_STRING
+#include <assert.h>
+
+/*
+g++ -g -Wall -o tbs -DTEST_BASE_STRING -I$NDB_TOP/include/util \
+ -I$NDB_TOP/include/portlib BaseString.cpp
+valgrind ./tbs
+*/
+
+int main()
+{
+ BaseString s("abc");
+ BaseString t(s);
+ s.assign("def");
+ t.append("123");
+ assert(s == "def");
+ assert(t == "abc123");
+ s.assign("");
+ t.assign("");
+ for (unsigned i = 0; i < 1000; i++) {
+ s.append("xyz");
+ t.assign(s);
+ assert(strlen(t.c_str()) % 3 == 0);
+ }
+
+ {
+ BaseString s(":123:abc:;:foo:");
+ Vector<BaseString> v;
+ assert(s.split(v, ":;") == 7);
+
+ assert(v[0] == "");
+ assert(v[1] == "123");
+ assert(v[2] == "abc");
+ assert(v[3] == "");
+ assert(v[4] == "");
+ assert(v[5] == "foo");
+ assert(v[6] == "");
+ }
+
+ {
+ BaseString s(":123:abc:foo:bar");
+ Vector<BaseString> v;
+ assert(s.split(v, ":;", 4) == 4);
+
+ assert(v[0] == "");
+ assert(v[1] == "123");
+ assert(v[2] == "abc");
+ assert(v[3] == "foo:bar");
+
+ BaseString n;
+ n.append(v, "()");
+ assert(n == "()123()abc()foo:bar");
+ n = "";
+ n.append(v);
+ assert(n == " 123 abc foo:bar");
+ }
+
+ {
+ assert(BaseString("hamburger").substr(4,2) == "");
+ assert(BaseString("hamburger").substr(3) == "burger");
+ assert(BaseString("hamburger").substr(4,8) == "urge");
+ assert(BaseString("smiles").substr(1,5) == "mile");
+ assert(BaseString("012345").indexOf('2') == 2);
+ assert(BaseString("hej").indexOf('X') == -1);
+ }
+
+ {
+ assert(BaseString(" 1").trim(" ") == "1");
+ assert(BaseString("1 ").trim(" ") == "1");
+ assert(BaseString(" 1 ").trim(" ") == "1");
+ assert(BaseString("abc\t\n\r kalleabc\t\r\n").trim("abc\t\r\n ") == "kalle");
+ assert(BaseString(" ").trim(" ") == "");
+ }
+ return 0;
+}
+
+#endif