00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "autoconfig.h"
00034 #endif
00035
00036 #include <ctype.h>
00037
00038 #include "memory.h"
00039 #include "strings.h"
00040
00041 using namespace zmm;
00042
00043 StringBase::StringBase(int capacity) : Object()
00044 {
00045 len = capacity;
00046 data = (char *)MALLOC((len + 1) * sizeof(char));
00047 store = true;
00048 }
00049 StringBase::StringBase(const char *str) : Object()
00050 {
00051 len = (int)strlen(str);
00052 data = (char *)MALLOC((len + 1) * sizeof(char));
00053 strcpy(data, str);
00054 store = true;
00055 }
00056 StringBase::StringBase(const char *str, int len) : Object()
00057 {
00058 this->len = len;
00059 data = (char *)MALLOC((len + 1) * sizeof(char));
00060 memcpy(data, str, len);
00061 data[len] = 0;
00062 store = true;
00063 }
00064
00065 StringBase::~StringBase()
00066 {
00067 if (store)
00068 FREE(data);
00069 }
00070
00071 bool StringBase::startsWith(StringBase *other)
00072 {
00073 return (!strncmp(data, other->data, other->len));
00074 }
00075
00076 String::String()
00077 {
00078 base = NULL;
00079 }
00080 String::String(int capacity)
00081 {
00082 base = new StringBase(capacity);
00083 base->retain();
00084 }
00085 String::String(const char *str)
00086 {
00087 if(str)
00088 {
00089 base = new StringBase(str);
00090 base->retain();
00091 }
00092 else
00093 base = NULL;
00094 }
00095 String::String(const char *str, int len)
00096 {
00097 if(str)
00098 {
00099 base = new StringBase(str, len);
00100 base->retain();
00101 }
00102 else
00103 base = NULL;
00104 }
00105 String::String(char ch)
00106 {
00107 base = new StringBase(&ch, 1);
00108 base->retain();
00109 }
00110
00111 String::String(const String &other)
00112 {
00113 base = other.base;
00114 if(base)
00115 base->retain();
00116 }
00117 String::String(StringBase *other)
00118 {
00119 base = other;
00120 if(base)
00121 base->retain();
00122 }
00123 String::String(Ref<StringBase> other)
00124 {
00125 base = other.getPtr();
00126 if(base)
00127 base->retain();
00128 }
00129 String::~String()
00130 {
00131 if(base)
00132 base->release();
00133 }
00134
00135 int String::length()
00136 {
00137 if(base)
00138 return base->len;
00139 else
00140 return 0;
00141 }
00142 char *String::c_str()
00143 {
00144 if(base)
00145 return base->data;
00146 else
00147 return NULL;
00148 }
00149 String String::operator+(String other)
00150 {
00151 if(! other.base)
00152 return *this;
00153 if(! base)
00154 return other;
00155 int len = base->len;
00156 int otherLen = other.base->len;
00157
00158 String res(len + otherLen);
00159 strcpy(res.base->data, base->data);
00160 strcpy(res.base->data + len, other.base->data);
00161 return res;
00162 }
00163 String String::operator+(const char *other)
00164 {
00165 if(! other)
00166 return *this;
00167 if(! base)
00168 return String::copy(other);
00169 int len = base->len;
00170 int otherLen = (int)strlen(other);
00171 String res(len + otherLen);
00172 strcpy(res.base->data, base->data);
00173 strcpy(res.base->data + len, other);
00174 return res;
00175 }
00176 String String::operator+(char chr)
00177 {
00178 char str[2];
00179 str[0] = chr;
00180 str[1] = 0;
00181 return operator+(str);
00182 }
00183
00184 String String::operator+(int x)
00185 {
00186 return operator+(from(x));
00187 }
00188 String String::operator+(unsigned int x)
00189 {
00190 return operator+(from(x));
00191 }
00192 String String::operator+(double x)
00193 {
00194 return operator+(from(x));
00195 }
00196
00197 String String::from(int x)
00198 {
00199 StringBase *b = new StringBase(MAX_INT_STRING_LENGTH);
00200 b->len = sprintf(b->data, "%d", x);
00201 return (String(b));
00202 }
00203 String String::from(unsigned int x)
00204 {
00205 StringBase *b = new StringBase(MAX_INT_STRING_LENGTH);
00206 b->len = sprintf(b->data, "%u", x);
00207 return (String(b));
00208 }
00209 String String::from(long x)
00210 {
00211 StringBase *b = new StringBase(MAX_LONG_STRING_LENGTH);
00212 b->len = sprintf(b->data, "%ld", x);
00213 return (String(b));
00214 }
00215 String String::from(unsigned long x)
00216 {
00217 StringBase *b = new StringBase(MAX_LONG_STRING_LENGTH);
00218 b->len = sprintf(b->data, "%ld", x);
00219 return (String(b));
00220 }
00221 String String::from(double x)
00222 {
00223 StringBase *b = new StringBase(MAX_DOUBLE_STRING_LENGTH);
00224 b->len = sprintf(b->data, "%lf", x);
00225 return (String(b));
00226 }
00227 String String::from(long long x)
00228 {
00229 StringBase *b = new StringBase(MAX_LONG_LONG_STRING_LENGTH);
00230 b->len = sprintf(b->data, "%lld", x);
00231 return (String(b));
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241 String String::allocate(int size)
00242 {
00243 return String(new StringBase(size));
00244 }
00245 String String::take(const char *data)
00246 {
00247 StringBase *base = new StringBase();
00248 base->data = (char *)data;
00249 base->len = strlen(data);
00250 base->store = true;
00251 return String(base);
00252 }
00253 String String::take(const char *data, int length)
00254 {
00255 StringBase *base = new StringBase();
00256 base->data = (char *)data;
00257 base->len = length;
00258 base->store = true;
00259 return String(base);
00260 }
00261 String String::refer(const char *data)
00262 {
00263 StringBase *base = new StringBase();
00264 base->data = (char *)data;
00265 base->len = strlen(data);
00266 base->store = false;
00267 return String(base);
00268 }
00269 String String::refer(const char *data, int len)
00270 {
00271 StringBase *base = new StringBase();
00272 base->data = (char *)data;
00273 base->len = len;
00274 base->store = false;
00275 return String(base);
00276 }
00277 String String::copy(const char *data)
00278 {
00279 if (data)
00280 {
00281 StringBase *base = new StringBase(data);
00282 return String(base);
00283 }
00284 else
00285 return String();
00286 }
00287 int String::operator==(String other)
00288 {
00289 if(! base && ! other.base)
00290 return 1;
00291 if(base && other.base)
00292 return ( ! strcmp(base->data, other.base->data) );
00293 return 0;
00294 }
00295 int String::operator==(const char *other)
00296 {
00297 if(! base && ! other)
00298 return 1;
00299 if(base && other)
00300 return ( ! strcmp(base->data, other ) );
00301 return 0;
00302 }
00303 int String::operator==(char c)
00304 {
00305 if(! base || base->len != 1)
00306 return 0;
00307 return (c == *(base->data));
00308 }
00309 String& String::operator=(const char *str)
00310 {
00311 if (base)
00312 base->release();
00313 if (str)
00314 {
00315 base = new StringBase(str);
00316 base->retain();
00317 }
00318 else
00319 base = NULL;
00320 return *this;
00321 }
00322 String& String::operator=(String other)
00323 {
00324 if (this == &other)
00325 return *this;
00326 if(base)
00327 base->release();
00328 base = other.base;
00329 if(base)
00330 base->retain();
00331 return *this;
00332 }
00333
00334 int String::equals(String other, bool ignoreCase)
00335 {
00336 if(! base && ! other.base)
00337 return 1;
00338
00339 if (ignoreCase)
00340 {
00341 if(base && other.base)
00342 return ( ! strcasecmp(base->data, other.base->data) );
00343 }
00344 else
00345 return (operator==(other));
00346
00347 return 0;
00348 }
00349
00350 String String::toLower()
00351 {
00352 if (!base)
00353 return nil;
00354
00355 String result = String(base->data, base->len);
00356 for (int i = 0; i < result.base->len; i++)
00357 {
00358 result.base->data[i] = tolower(result.base->data[i]);
00359 }
00360 return result;
00361 }
00362
00363 String String::toUpper()
00364 {
00365 if (!base)
00366 return nil;
00367
00368 String result = String(base->data, base->len);
00369 for (int i = 0; i < base->len; i++)
00370 {
00371 result.base->data[i] = toupper(result.base->data[i]);
00372 }
00373
00374 return result;
00375 }
00376
00377 long String::toLong()
00378 {
00379 if(! base)
00380 return 0;
00381 char *endptr;
00382 long res = (int)strtol(base->data, &endptr, 10);
00383 if(*endptr)
00384 return 0;
00385
00386 return res;
00387 }
00388 double String::toDouble()
00389 {
00390 if(! base)
00391 return 0;
00392 char *endptr;
00393 double res = strtod(base->data, &endptr);
00394 if(*endptr)
00395 return 0;
00396
00397 return res;
00398 }
00399
00400
00401 off_t String::toOFF_T()
00402 {
00403 if(! base)
00404 return 0;
00405
00406 #if SIZEOF_OFF_T > 4
00407 char *endptr;
00408 off_t res = strtoll(base->data, &endptr, 10);
00409 if(*endptr)
00410 return 0;
00411
00412 return res;
00413
00414 #else
00415 return toLong();
00416 #endif
00417
00418 }
00419
00420
00421 String String::substring(int from)
00422 {
00423 if(! base)
00424 return nil;
00425 int count = base->len - from;
00426 return substring(from, count);
00427 }
00428 String String::substring(int from, int count)
00429 {
00430 if(! base || count < 0)
00431 return nil;
00432 if(count == 0)
00433 return _("");
00434 if(from + count > base->len)
00435 count = base->len - from;
00436 String res(count);
00437 strncpy(res.base->data, base->data + from, count);
00438 *(res.base->data + count) = 0;
00439 return res;
00440 }
00441 int String::index(int start, char ch)
00442 {
00443 if(! base)
00444 return -1;
00445 if (start < 0 || start + 1 > base->len)
00446 return -1;
00447 char *pos = ::strchr(base->data + start, ch);
00448 if (pos)
00449 return pos - base->data;
00450 else
00451 return -1;
00452 }
00453 int String::rindex(char ch)
00454 {
00455 if(! base)
00456 return -1;
00457 char *pos = ::strrchr(base->data, ch);
00458 if (pos)
00459 return pos - base->data;
00460 else
00461 return -1;
00462 }
00463 int String::rindex(int end, char ch)
00464 {
00465 if(! base)
00466 return -1;
00467 if (end < 0 || end + 1 > base->len)
00468 return -1;
00469 for (char *pos = base->data + end; pos >= base->data; pos--)
00470 {
00471 if (*pos == ch)
00472 return pos - base->data;
00473 }
00474 return -1;
00475 }
00476 String String::reduce(char ch)
00477 {
00478 if (!base)
00479 return nil;
00480
00481 char *pos = ::strchr(base->data, ch);
00482 if (!pos)
00483 return *this;
00484
00485 String res(base->len);
00486
00487 char *pos2 = res.base->data;
00488 char *pos3 = base->data;
00489 do
00490 {
00491 if (*(pos + 1) == ch)
00492 {
00493 if (pos-pos3 == 0)
00494 {
00495 *pos2 = ch;
00496 pos2++;
00497 }
00498 else
00499 {
00500 strncpy(pos2, pos3, (pos-pos3)+1);
00501 pos2 = pos2 + ((pos-pos3)+1);
00502 }
00503 while (*pos == ch) pos++;
00504 pos3 = pos;
00505 if (*pos == '\0')
00506 {
00507 *pos2 = '\0';
00508 break;
00509 }
00510 pos = ::strchr(pos, ch);
00511 }
00512 else
00513 {
00514 pos++;
00515 if (*pos == '\0')
00516 break;
00517 pos = ::strchr(pos, ch);
00518 }
00519 } while (pos);
00520 if ((base->data)+(base->len)-pos3)
00521 strncpy(pos2, pos3, (base->data)+(base->len)-pos3);
00522 pos2[(base->data)+(base->len)-pos3] = 0;
00523 res.updateLength();
00524 return res;
00525 }
00526
00527 int String::find(const char *needle)
00528 {
00529 if (!base)
00530 return -1;
00531
00532 char *pos = strstr(base->data, needle);
00533 if (pos)
00534 {
00535 return (pos-(base->data));
00536 }
00537 else
00538 return -1;
00539
00540 }
00541 int String::find(String needle)
00542 {
00543 return find(needle.base->data);
00544 }
00545
00546 String String::replace(String needle, String replacement)
00547 {
00548 if (! replacement.base || ! needle.base)
00549 return nil;
00550 int pos = find(needle);
00551 if (pos < 0)
00552 return *this;
00553 String res(base->len + replacement.base->len - needle.base->len);
00554 strncpy(res.base->data, base->data, pos);
00555 strncpy(res.base->data + pos, replacement.base->data, replacement.base->len);
00556 strncpy(res.base->data + pos + replacement.base->len, base->data + pos + needle.base->len, base->len - pos - needle.base->len);
00557 res.base->data[res.base->len] = 0;
00558 return res;
00559 }
00560
00561 String String::replaceChar(char needle, char replacement)
00562 {
00563 if ((needle == '\0') || (replacement == '\0'))
00564 return *this;
00565
00566 String res(base->len);
00567 for (int i = 0; i < res.base->len; i++)
00568 {
00569 if (base->data[i] == needle)
00570 res.base->data[i] = replacement;
00571 else
00572 res.base->data[i] = base->data[i];
00573 }
00574 res.base->data[res.base->len] = 0;
00575 return res;
00576 }