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>;
1.4.7

