BaseString.cpp

Go to the documentation of this file.
00001 /* Copyright (C) 2003 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; either version 2 of the License, or
00006    (at your option) any later version.
00007 
00008    This program is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011    GNU General Public License for more details.
00012 
00013    You should have received a copy of the GNU General Public License
00014    along with this program; if not, write to the Free Software
00015    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
00016 
00017 /* -*- c-basic-offset: 4; -*- */
00018 #include <ndb_global.h>
00019 #include <BaseString.hpp>
00020 #include <basestring_vsnprintf.h>
00021 
00022 BaseString::BaseString()
00023 {
00024     m_chr = new char[1];
00025     m_chr[0] = 0;
00026     m_len = 0;
00027 }
00028 
00029 BaseString::BaseString(const char* s)
00030 {
00031     const size_t n = strlen(s);
00032     m_chr = new char[n + 1];
00033     memcpy(m_chr, s, n + 1);
00034     m_len = n;
00035 }
00036 
00037 BaseString::BaseString(const BaseString& str)
00038 {
00039     const char* const s = str.m_chr;
00040     const size_t n = str.m_len;
00041     char* t = new char[n + 1];
00042     memcpy(t, s, n + 1);
00043     m_chr = t;
00044     m_len = n;
00045 }
00046 
00047 BaseString::~BaseString()
00048 {
00049     delete[] m_chr;
00050 }
00051 
00052 BaseString&
00053 BaseString::assign(const char* s)
00054 {
00055     const size_t n = strlen(s);
00056     char* t = new char[n + 1];
00057     memcpy(t, s, n + 1);
00058     delete[] m_chr;
00059     m_chr = t;
00060     m_len = n;
00061     return *this;
00062 }
00063 
00064 BaseString&
00065 BaseString::assign(const char* s, size_t n)
00066 {
00067     char* t = new char[n + 1];
00068     memcpy(t, s, n);
00069     t[n] = 0;
00070     delete[] m_chr;
00071     m_chr = t;
00072     m_len = n;
00073     return *this;
00074 }
00075 
00076 BaseString&
00077 BaseString::assign(const BaseString& str, size_t n)
00078 {
00079     if (n > str.m_len)
00080         n = str.m_len;
00081     return assign(str.m_chr, n);
00082 }
00083 
00084 BaseString&
00085 BaseString::append(const char* s)
00086 {
00087     const size_t n = strlen(s);
00088     char* t = new char[m_len + n + 1];
00089     memcpy(t, m_chr, m_len);
00090     memcpy(t + m_len, s, n + 1);
00091     delete[] m_chr;
00092     m_chr = t;
00093     m_len += n;
00094     return *this;
00095 }
00096 
00097 BaseString&
00098 BaseString::append(char c) {
00099     return appfmt("%c", c);
00100 }
00101 
00102 BaseString&
00103 BaseString::append(const BaseString& str)
00104 {
00105     return append(str.m_chr);
00106 }
00107 
00108 BaseString&
00109 BaseString::append(const Vector<BaseString> &vector,
00110                    const BaseString &separator) {
00111     for(size_t i=0;i<vector.size(); i++) {
00112         append(vector[i]);
00113         if(i<vector.size()-1)
00114             append(separator);
00115     }
00116     return *this;
00117 }
00118 
00119 BaseString&
00120 BaseString::assfmt(const char *fmt, ...)
00121 {
00122     char buf[1];
00123     va_list ap;
00124     int l;
00125 
00126     /* Figure out how long the formatted string will be. A small temporary
00127      * buffer is used, because I don't trust all implementations to work
00128      * when called as vsnprintf(NULL, 0, ...).
00129      */
00130     va_start(ap, fmt);
00131     l = basestring_vsnprintf(buf, sizeof(buf), fmt, ap) + 1;
00132     va_end(ap);
00133     if(l > (int)m_len) {
00134         delete[] m_chr;
00135         m_chr = new char[l];
00136     }
00137     va_start(ap, fmt);
00138     basestring_vsnprintf(m_chr, l, fmt, ap);
00139     va_end(ap);
00140     m_len = strlen(m_chr);
00141     return *this;
00142 }
00143 
00144 BaseString&
00145 BaseString::appfmt(const char *fmt, ...)
00146 {
00147     char buf[1];
00148     va_list ap;
00149     int l;
00150 
00151     /* Figure out how long the formatted string will be. A small temporary
00152      * buffer is used, because I don't trust all implementations to work
00153      * when called as vsnprintf(NULL, 0, ...).
00154      */
00155     va_start(ap, fmt);
00156     l = basestring_vsnprintf(buf, sizeof(buf), fmt, ap) + 1;
00157     va_end(ap);
00158     char *tmp = new char[l];
00159     va_start(ap, fmt);
00160     basestring_vsnprintf(tmp, l, fmt, ap);
00161     va_end(ap);
00162     append(tmp);
00163     delete[] tmp;
00164     return *this;
00165 }
00166 
00167 BaseString&
00168 BaseString::operator=(const BaseString& str)
00169 {
00170     if (this != &str) {
00171         this->assign(str);
00172     }
00173     return *this;
00174 }
00175 
00176 int
00177 BaseString::split(Vector<BaseString> &v,
00178                   const BaseString &separator,
00179                   int maxSize) const {
00180     char *str = strdup(m_chr);
00181     int i, start, len, num = 0;
00182     len = strlen(str);
00183     for(start = i = 0;
00184         (i <= len) && ( (maxSize<0) || ((int)v.size()<=maxSize-1) );
00185         i++) {
00186         if(strchr(separator.c_str(), str[i]) || i == len) {
00187             if(maxSize < 0 || (int)v.size() < maxSize-1)
00188                 str[i] = '\0';
00189             v.push_back(BaseString(str+start));
00190             num++;
00191             start = i+1;
00192         }
00193     }
00194     free(str);
00195 
00196     return num;
00197 }
00198 
00199 ssize_t
00200 BaseString::indexOf(char c) {
00201     char *p;
00202     p = strchr(m_chr, c);
00203     if(p == NULL)
00204         return -1;
00205     return (ssize_t)(p-m_chr);
00206 }
00207 
00208 ssize_t
00209 BaseString::lastIndexOf(char c) {
00210     char *p;
00211     p = strrchr(m_chr, c);
00212     if(p == NULL)
00213         return -1;
00214     return (ssize_t)(p-m_chr);
00215 }
00216 
00217 BaseString
00218 BaseString::substr(ssize_t start, ssize_t stop) {
00219     if(stop < 0)
00220         stop = length();
00221     ssize_t len = stop-start;
00222     if(len <= 0)
00223         return BaseString("");
00224     BaseString s;
00225     s.assign(m_chr+start, len);
00226     return s;
00227 }
00228 
00229 static bool
00230 iswhite(char c) {
00231   switch(c) {
00232   case ' ':
00233   case '\t':
00234     return true;
00235   default:
00236     return false;
00237   }
00238   /* NOTREACHED */
00239 }
00240 
00241 char **
00242 BaseString::argify(const char *argv0, const char *src) {
00243     Vector<char *> vargv;
00244     
00245     if(argv0 != NULL)
00246         vargv.push_back(strdup(argv0));
00247     
00248     char *tmp = new char[strlen(src)+1];
00249     char *dst = tmp;
00250     const char *end = src + strlen(src);
00251     /* Copy characters from src to destination, while compacting them
00252      * so that all whitespace is compacted and replaced by a NUL-byte.
00253      * At the same time, add pointers to strings in the vargv vector.
00254      * When whitespace is detected, the characters '"' and '\' are honored,
00255      * to make it possible to give arguments containing whitespace.
00256      * The semantics of '"' and '\' match that of most Unix shells.
00257      */
00258     while(src < end && *src) {
00259         /* Skip initial whitespace */
00260         while(src < end && *src && iswhite(*src))
00261             src++;
00262         
00263         char *begin = dst;
00264         while(src < end && *src) {
00265             /* Handle '"' quotation */
00266             if(*src == '"') {
00267                 src++;
00268                 while(src < end && *src && *src != '"') {
00269                     if(*src == '\\')
00270                         src++;
00271                     *dst++ = *src++;
00272                 }
00273                 src++;
00274                 if(src >= end)
00275                     goto end;
00276             }
00277             
00278             /* Handle '\' */
00279             if(*src == '\\')
00280                 src++;
00281             else if(iswhite(*src))
00282                 break;
00283 
00284             /* Actually copy characters */
00285             *dst++ = *src++;
00286         }
00287         
00288         /* Make sure the string is properly terminated */
00289         *dst++ = '\0';
00290         src++;
00291         
00292         vargv.push_back(strdup(begin));
00293     }
00294  end:
00295     
00296     delete[] tmp;
00297     vargv.push_back(NULL);
00298     
00299     /* Convert the C++ Vector into a C-vector of strings, suitable for
00300      * calling execv().
00301      */
00302     char **argv = (char **)malloc(sizeof(*argv) * (vargv.size()));
00303     if(argv == NULL)
00304         return NULL;
00305     
00306     for(size_t i = 0; i < vargv.size(); i++){
00307         argv[i] = vargv[i];
00308     }
00309     
00310     return argv;
00311 }
00312 
00313 BaseString&
00314 BaseString::trim(const char * delim){
00315     trim(m_chr, delim);
00316     m_len = strlen(m_chr);
00317     return * this;
00318 }
00319 
00320 char*
00321 BaseString::trim(char * str, const char * delim){
00322     int len = strlen(str) - 1;
00323     for(; len > 0 && strchr(delim, str[len]); len--);
00324     
00325     int pos = 0;
00326     for(; pos <= len && strchr(delim, str[pos]); pos++);
00327     
00328     if(pos > len){
00329         str[0] = 0;
00330         return 0;
00331     } else {
00332         memmove(str, &str[pos], len - pos + 1);
00333         str[len-pos+1] = 0;
00334     }
00335     
00336     return str;
00337 }
00338 
00339 int
00340 BaseString::vsnprintf(char *str, size_t size, const char *format, va_list ap)
00341 {
00342   return(basestring_vsnprintf(str, size, format, ap));
00343 }
00344 
00345 int
00346 BaseString::snprintf(char *str, size_t size, const char *format, ...)
00347 {
00348   va_list ap;
00349   va_start(ap, format);
00350   int ret= basestring_vsnprintf(str, size, format, ap);
00351   va_end(ap);
00352   return(ret);
00353 }
00354 
00355 
00356 #ifdef TEST_BASE_STRING
00357 
00358 /*
00359 g++ -g -Wall -o tbs -DTEST_BASE_STRING -I$NDB_TOP/include/util \
00360         -I$NDB_TOP/include/portlib BaseString.cpp
00361 valgrind ./tbs
00362 */
00363 
00364 int main()
00365 {
00366     BaseString s("abc");
00367     BaseString t(s);
00368     s.assign("def");
00369     t.append("123");
00370     assert(s == "def");
00371     assert(t == "abc123");
00372     s.assign("");
00373     t.assign("");
00374     for (unsigned i = 0; i < 1000; i++) {
00375         s.append("xyz");
00376         t.assign(s);
00377         assert(strlen(t.c_str()) % 3 == 0);
00378     }
00379 
00380     {
00381         BaseString s(":123:abc:;:foo:");
00382         Vector<BaseString> v;
00383         assert(s.split(v, ":;") == 7);
00384 
00385         assert(v[0] == "");
00386         assert(v[1] == "123");
00387         assert(v[2] == "abc");
00388         assert(v[3] == "");
00389         assert(v[4] == "");
00390         assert(v[5] == "foo");
00391         assert(v[6] == "");
00392     }
00393 
00394     {
00395         BaseString s(":123:abc:foo:bar");
00396         Vector<BaseString> v;
00397         assert(s.split(v, ":;", 4) == 4);
00398 
00399         assert(v[0] == "");
00400         assert(v[1] == "123");
00401         assert(v[2] == "abc");
00402         assert(v[3] == "foo:bar");
00403 
00404         BaseString n;
00405         n.append(v, "()");
00406         assert(n == "()123()abc()foo:bar");
00407         n = "";
00408         n.append(v);
00409         assert(n == " 123 abc foo:bar");
00410     }
00411 
00412     {
00413         assert(BaseString("hamburger").substr(4,2) == "");
00414         assert(BaseString("hamburger").substr(3) == "burger");
00415         assert(BaseString("hamburger").substr(4,8) == "urge");
00416         assert(BaseString("smiles").substr(1,5) == "mile");
00417         assert(BaseString("012345").indexOf('2') == 2);
00418         assert(BaseString("hej").indexOf('X') == -1);
00419     }
00420 
00421     {
00422         assert(BaseString(" 1").trim(" ") == "1");
00423         assert(BaseString("1 ").trim(" ") == "1");
00424         assert(BaseString(" 1 ").trim(" ") == "1");
00425         assert(BaseString("abc\t\n\r kalleabc\t\r\n").trim("abc\t\r\n ") == "kalle");
00426         assert(BaseString(" ").trim(" ") == "");
00427     }
00428     return 0;
00429 }
00430 
00431 #endif
00432 
00433 template class Vector<char *>;
00434 template class Vector<BaseString>;

Generated on Wed Jul 20 21:05:12 2005 for MySQL 5.0.9 Beta by  doxygen 1.4.3