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
00030
00031
00038 #ifndef COLLECTIONS_STRING_H
00039 #define COLLECTIONS_STRING_H
00040
00041 #include "fastlib/base/base.h"
00042 #include "fastlib/col/arraylist.h"
00043
00044
00045 #include <cstring>
00046
00059 class String {
00060 private:
00061 ArrayList<char> array_;
00062
00063 OBJECT_TRAVERSAL(String) {
00064 OT_OBJ(array_);
00065 }
00066
00067 OT_CUSTOM_PRINT(String) {
00068 const char *c_str = this->c_str();
00069 OT_OBJ(c_str);
00070 }
00071
00072 public:
00076 String(const char *s) {
00077 Copy(s);
00078 }
00079
00083 void Init() {
00084 array_.Init(1);
00085 array_[0] = 0;
00086 }
00087
00092 void Init(int finalLength) {
00093 array_.Init(finalLength + 1);
00094 }
00095
00101 COMPILER_PRINTF(2, 3)
00102 const String& InitSprintf(const char *format, ...);
00103
00108 void Copy(const char *str_region_begin, index_t len) {
00109 array_.Init(len + 1);
00110 mem::Copy(array_.begin(), str_region_begin, len);
00111 Terminate();
00112 }
00113
00117 void Copy(const char *str) {
00118 array_.InitCopy(str, index_t(strlen(str) + 1));
00119 }
00120
00124 void Destruct() {
00125 array_.Renew();
00126 }
00127
00131 void Swap(String* other) {
00132 array_.Swap(&other->array_);
00133 }
00134
00139 void StealDestruct(String *other) {
00140 array_.InitSteal(&other->array_);
00141 other->Destruct();
00142 }
00143
00147 void Steal(ArrayList<char> *null_terminated_char_list) {
00148 array_.InitSteal(null_terminated_char_list);
00149 }
00150
00151 void Steal(char *str, index_t len, index_t capacity) {
00152 array_.InitSteal(str, len + 1, capacity);
00153 }
00154
00155 void Steal(char *str, index_t len) {
00156 array_.InitSteal(str, len + 1, len + 1);
00157 }
00158
00159 void Steal(char *str) {
00160 Steal(str, strlen(str));
00161 }
00162
00164 operator const char * () const
00165 { return array_.begin(); }
00166
00168 const char* c_str() const
00169 { return array_.begin(); }
00171 char* c_str()
00172 { return array_.begin(); }
00173
00175 char* begin()
00176 { return array_.begin(); }
00178 const char* begin() const
00179 { return array_.begin(); }
00181 const char *end() const {
00182 return array_.end() - 1;
00183 }
00185 char *end() {
00186 return array_.end() - 1;
00187 }
00188
00190 index_t length() const
00191 { return array_.size() - 1; }
00192
00199 void Truncate(const char *s) {
00200 array_.Resize(s - begin() + 1);
00201 Terminate();
00202 }
00203
00209 void Truncate(index_t newlen) {
00210 array_.Resize(newlen + 1);
00211 Terminate();
00212 }
00213
00218 void SetLength(index_t newlen) {
00219 array_.Resize(newlen + 1);
00220 Terminate();
00221 }
00222
00227 void FixLength()
00228 { array_.Resize(strlen(array_.begin()) + 1); }
00229
00233 void Terminate() {
00234 array_.back() = 0;
00235 }
00236
00240 void Trim()
00241 { array_.Trim(); }
00242
00243 index_t Find(char c) const {
00244 return IndexFromPtr(strchr(array_.begin(), c));
00245 }
00246 index_t FindR(char c) const {
00247 return IndexFromPtr(strrchr(array_.begin(), c));
00248 }
00249 index_t Find(const char* s) const {
00250 return IndexFromPtr(strstr(array_.begin(), s));
00251 }
00252 index_t FindAny(const char *char_set, index_t skip_initial = 0) const;
00253
00254 index_t IndexFromPtr(const char *position) const {
00255 if (unlikely(!position)) {
00256 return -1;
00257 } else {
00258 return index_t(position - begin());
00259 }
00260 }
00261
00263 bool is_empty() const
00264 { return array_.size() == 1; }
00265
00275 void Append(const char *add_str, index_t add_length) {
00276 index_t mysize = array_.size();
00277 array_.Resize(mysize + add_length);
00278 strcpy(array_.begin() + mysize - 1, add_str);
00279 }
00280
00285 void Append(const char *add_str) {
00286 Append(add_str, strlen(add_str));
00287 }
00288
00293 void Append(char c) {
00294 array_.back() = c;
00295 array_.PushBackCopy('\0');
00296 }
00297
00302 void Append(const String& str) {
00303 Append(str.array_.begin(), str.length());
00304 }
00305
00306
00311 const String& operator += (const String& o) {
00312 Append(o);
00313 return *this;
00314 }
00315
00320 const String& operator += (char c) {
00321 Append(c);
00322 return *this;
00323 }
00324
00329 const String& operator += (const char *s) {
00330 Append(s);
00331 return *this;
00332 }
00333
00337 char operator [] (index_t index) const
00338 { return array_[index]; }
00342 char& operator [] (index_t index)
00343 { return array_[index]; }
00344
00371 index_t Split(index_t start_index, const char *delimeters,
00372 const char *donechars, index_t max_portions,
00373 ArrayList<String> *result) const;
00374
00393 index_t Split(const char *delimeters, ArrayList<String> *result) const {
00394 return Split(0, delimeters, "", 0, result);
00395 }
00396
00401 void TrimLeft(const char *delimeters, String *result) const;
00402
00407 void TrimRight(const char *delimeters, String *result) const;
00408
00413 void Trim(const char *delimeters, String *result) const;
00414
00418 int CompareNoCase(const char *s) const {
00419 return strcasecmp(array_.begin(), s);
00420 }
00424 bool EqualsNoCase(const char *s) const {
00425 return CompareNoCase(s) == 0;
00426 }
00427
00431 bool StartsWith(const char *s) const {
00432 return strncmp(array_.begin(), s, strlen(s)) == 0;
00433 }
00434
00440 int CompareTo(const String& other) const
00441 { return strcmp(begin(), other.begin()); }
00447 int CompareTo(const char* s) const
00448 { return strcmp(begin(), s); }
00449
00450 friend bool operator < (const String& a, const String& b) {
00451 return strcmp(a.begin(), b.begin()) < 0;
00452 }
00453 EXPAND_LESS_THAN(String);
00454 friend bool operator == (const String& a, const String& b) {
00455 return strcmp(a.begin(), b.begin()) == 0;
00456 }
00457 EXPAND_EQUALS(String);
00458
00459 friend bool operator < (const char *a, const String& b) {
00460
00461 return strcmp(a, b.begin()) < 0;
00462 }
00463 EXPAND_HETERO_LESS_THAN(const char *, String);
00464 friend bool operator < (const String& a, const char *b) {
00465
00466 return strcmp(a.begin(), b) < 0;
00467 }
00468 EXPAND_HETERO_LESS_THAN(String, const char *);
00469 friend bool operator == (const String& a, const char *b) {
00470 return strcmp(a.begin(), b) == 0;
00471 }
00472 EXPAND_HETERO_EQUALS(String, const char *);
00473
00474 friend bool operator < (char a, const String& b) {
00475
00476 DEBUG_ASSERT(b != '\0');
00477 return a < b[0] || (unlikely(a == b[0]) && b[1] != '\0');
00478 }
00479 EXPAND_HETERO_LESS_THAN(char, String);
00480 friend bool operator < (const String& a, char b) {
00481
00482 DEBUG_ASSERT(b != '\0');
00483 return a[0] < b;
00484 }
00485 EXPAND_HETERO_LESS_THAN(String, char);
00486 friend bool operator == (const String& a, char b) {
00487 DEBUG_ASSERT(b != '\0');
00488 return a[0] == b && a[1] == '\0';
00489 }
00490 EXPAND_HETERO_EQUALS(String, char);
00491 };
00492
00493 #endif