00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif
00017
00018 #include "htString.h"
00019 #include "Object.h"
00020
00021 #include <unistd.h>
00022 #include <stream.h>
00023 #include <ctype.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026
00027
00028 const int MinimumAllocationSize = 4;
00029
00030 #ifdef NOINLINE
00031 String::String()
00032 {
00033 Length = Allocated = 0;
00034 Data = 0;
00035 }
00036 #endif
00037
00038 String::String(int init)
00039 {
00040 Length = 0;
00041 Allocated = init >= MinimumAllocationSize ? init : MinimumAllocationSize;
00042 Data = new char[Allocated];
00043 }
00044
00045 String::String(const char *s)
00046 {
00047 Allocated = Length = 0;
00048 Data = 0;
00049
00050 int len;
00051 if (s)
00052 {
00053 len = strlen(s);
00054 copy(s, len, len);
00055 }
00056 }
00057
00058 String::String(const char *s, int len)
00059 {
00060 Allocated = Length = 0;
00061 Data = 0;
00062 if (s && len != 0)
00063 copy(s, len, len);
00064 }
00065
00066 String::String(const String &s) : Object()
00067 {
00068 Allocated = Length = 0;
00069 Data = 0;
00070
00071 if (s.length() != 0)
00072 copy(s.Data, s.length(), s.length());
00073 }
00074
00075
00076
00077
00078
00079 String::String(const String &s, int allocation_hint)
00080 {
00081 Allocated = Length = 0;
00082 Data = 0;
00083
00084 if (s.length() != 0)
00085 {
00086 if (allocation_hint < s.length())
00087 allocation_hint = s.length();
00088 copy(s.Data, s.length(), allocation_hint);
00089 }
00090 }
00091
00092 String::~String()
00093 {
00094 if (Allocated)
00095 delete [] Data;
00096 }
00097
00098 void String::operator = (const String &s)
00099 {
00100 allocate_space(s.length());
00101 Length = s.length();
00102 copy_data_from(s.Data, Length);
00103 }
00104
00105 void String::operator = (const char *s)
00106 {
00107 if (s)
00108 {
00109 int len = strlen(s);
00110 allocate_fix_space(len);
00111 Length = len;
00112 copy_data_from(s, Length);
00113 }
00114 else
00115 Length = 0;
00116 }
00117
00118 void String::append(const String &s)
00119 {
00120 if (s.length() == 0)
00121 return;
00122 int new_len = Length + s.length();
00123
00124 reallocate_space(new_len);
00125 copy_data_from(s.Data, s.length(), Length);
00126 Length = new_len;
00127 }
00128
00129 void String::append(const char *s)
00130 {
00131 if (!s)
00132 return;
00133
00134 append(s,strlen(s));
00135 }
00136
00137 void String::append(const char *s, int slen)
00138 {
00139 if (!s || !slen)
00140 return;
00141
00142
00143
00144
00145
00146
00147 int new_len = Length + slen;
00148
00149 if (new_len + 1 > Allocated)
00150 reallocate_space(new_len);
00151 copy_data_from(s, slen, Length);
00152 Length = new_len;
00153 }
00154
00155 void String::append(char ch)
00156 {
00157 int new_len = Length +1;
00158 if (new_len + 1 > Allocated)
00159 reallocate_space(new_len);
00160 Data[Length] = ch;
00161 Length = new_len;
00162 }
00163
00164 int String::compare(const String& obj) const
00165 {
00166 int len;
00167 int result;
00168 const char *p1 = Data;
00169 const char *p2 = obj.Data;
00170
00171 len = Length;
00172 result = 0;
00173
00174 if (Length > obj.Length)
00175 {
00176 result = 1;
00177 len = obj.Length;
00178 }
00179 else if (Length < obj.Length)
00180 result = -1;
00181
00182 while (len)
00183 {
00184 if (*p1 > *p2)
00185 return 1;
00186 if (*p1 < *p2)
00187 return -1;
00188 p1++;
00189 p2++;
00190 len--;
00191 }
00192
00193
00194
00195
00196 return result;
00197 }
00198
00199 int String::nocase_compare(const String &s) const
00200 {
00201 const char *p1 = get();
00202 const char *p2 = s.get();
00203
00204 return strcasecmp(p1, p2);
00205 }
00206
00207 int String::Write(int fd) const
00208 {
00209 int left = Length;
00210 char *wptr = Data;
00211
00212 while (left)
00213 {
00214 int result = write(fd, wptr, left);
00215
00216 if (result < 0)
00217 return result;
00218
00219 left -= result;
00220 wptr += result;
00221 }
00222 return left;
00223 }
00224
00225 const char *String::get() const
00226 {
00227 static const char *null = "";
00228 if (!Allocated)
00229 return null;
00230 Data[Length] = '\0';
00231 return Data;
00232 }
00233
00234 char *String::get()
00235 {
00236 static char *null = "";
00237 if (!Allocated)
00238 return null;
00239 Data[Length] = '\0';
00240 return Data;
00241 }
00242
00243 String::operator int () const
00244 {
00245 fprintf(stderr, "String: int(): either use empty() or as_integer()\n");
00246 abort();
00247 }
00248
00249 char *String::new_char() const
00250 {
00251 char *r;
00252 if (!Allocated)
00253 {
00254 r = new char[1];
00255 *r = '\0';
00256 return r;
00257 }
00258 Data[Length] = '\0';
00259 r = new char[Length + 1];
00260 strcpy(r, Data);
00261 return r;
00262 }
00263
00264
00265 int String::as_integer(int def) const
00266 {
00267 if (Length <= 0)
00268 return def;
00269 Data[Length] = '\0';
00270 return atoi(Data);
00271 }
00272
00273 double String::as_double(double def) const
00274 {
00275 if (Length <= 0)
00276 return def;
00277 Data[Length] = '\0';
00278 return atof(Data);
00279 }
00280
00281 String String::sub(int start, int len) const
00282 {
00283 if (start > Length)
00284 return 0;
00285
00286 if (len > Length - start)
00287 len = Length - start;
00288
00289 return String(Data + start, len);
00290 }
00291
00292 String String::sub(int start) const
00293 {
00294 return sub(start, Length - start);
00295 }
00296
00297 int String::indexOf(const char *str) const
00298 {
00299 char *c;
00300
00301
00302
00303
00304 if (!Allocated)
00305 return -1;
00306 Data[Length] = '\0';
00307
00308
00309 #ifdef HAVE_STRSTR
00310 if ((c = strstr(Data, str)) != NULL)
00311 return(c -Data);
00312 #else
00313 int len = strlen(str);
00314 int i;
00315 for (i = 0; i <= Length-len; i++)
00316 {
00317 if (strncmp(&Data[i], str, len) == 0)
00318 return i;
00319 }
00320 #endif
00321 return -1;
00322 }
00323
00324 int String::indexOf(char ch) const
00325 {
00326 int i;
00327 for (i = 0; i < Length; i++)
00328 {
00329 if (Data[i] == ch)
00330 return i;
00331 }
00332 return -1;
00333 }
00334
00335 int String::indexOf(char ch, int pos) const
00336 {
00337 if (pos >= Length)
00338 return -1;
00339 for (int i = pos; i < Length; i++)
00340 {
00341 if (Data[i] == ch)
00342 return i;
00343 }
00344 return -1;
00345 }
00346
00347 int String::lastIndexOf(char ch, int pos) const
00348 {
00349 if (pos >= Length)
00350 return -1;
00351 while (pos >= 0)
00352 {
00353 if (Data[pos] == ch)
00354 return pos;
00355 pos--;
00356 }
00357 return -1;
00358 }
00359
00360 int String::lastIndexOf(char ch) const
00361 {
00362 return lastIndexOf(ch, Length - 1);
00363 }
00364 #ifdef NOINLINE
00365 String &String::operator << (const char *str)
00366 {
00367 append(str);
00368 return *this;
00369 }
00370
00371 String &String::operator << (char ch)
00372 {
00373 append(&ch, 1);
00374 return *this;
00375 }
00376 #endif
00377
00378 String &String::operator << (int i)
00379 {
00380 char str[20];
00381 sprintf(str, "%d", i);
00382 append(str);
00383 return *this;
00384 }
00385
00386 String &String::operator << (unsigned int i)
00387 {
00388 char str[20];
00389 sprintf(str, "%u", i);
00390 append(str);
00391 return *this;
00392 }
00393
00394 String &String::operator << (long l)
00395 {
00396 char str[20];
00397 sprintf(str, "%ld", l);
00398 append(str);
00399 return *this;
00400 }
00401
00402 String &String::operator << (const String &s)
00403 {
00404 append(s.get(), s.length());
00405 return *this;
00406 }
00407
00408 char String::operator >> (char c)
00409 {
00410 c = '\0';
00411
00412 if (Allocated && Length)
00413 {
00414 c = Data[Length - 1];
00415 Data[Length - 1] = '\0';
00416 Length--;
00417 }
00418
00419 return c;
00420 }
00421
00422 int String::lowercase()
00423 {
00424 int converted = 0;
00425 for (int i = 0; i < Length; i++)
00426 {
00427 if (isupper((unsigned char)Data[i])) {
00428 Data[i] = tolower((unsigned char)Data[i]);
00429 converted++;
00430 }
00431 }
00432 return converted;
00433 }
00434
00435
00436 int String::uppercase()
00437 {
00438 int converted = 0;
00439 for (int i = 0; i < Length; i++)
00440 {
00441 if (islower((unsigned char)Data[i])) {
00442 Data[i] = toupper((unsigned char)Data[i]);
00443 converted++;
00444 }
00445 }
00446 return converted;
00447 }
00448
00449
00450 void String::replace(char c1, char c2)
00451 {
00452 for (int i = 0; i < Length; i++)
00453 if (Data[i] == c1)
00454 Data[i] = c2;
00455 }
00456
00457
00458 int String::remove(const char *chars)
00459 {
00460 if (Length <= 0)
00461 return 0;
00462
00463 char *good, *bad;
00464 int skipped = 0;
00465
00466 good = bad = Data;
00467 for (int i = 0; i < Length; i++)
00468 {
00469 if (strchr(chars, *bad))
00470 skipped++;
00471 else
00472 *good++ = *bad;
00473 bad++;
00474 }
00475 Length -= skipped;
00476
00477 return skipped;
00478 }
00479
00480 String &String::chop(int n)
00481 {
00482 Length -= n;
00483 if (Length < 0)
00484 Length = 0;
00485 return *this;
00486 }
00487
00488
00489 String &String::chop(char ch)
00490 {
00491 while (Length > 0 && Data[Length - 1] == ch)
00492 Length--;
00493 return *this;
00494 }
00495
00496
00497 String &String::chop(const char *str)
00498 {
00499 while (Length > 0 && strchr(str, Data[Length - 1]))
00500 Length--;
00501 return *this;
00502 }
00503
00504
00505 void String::Serialize(String &dest)
00506 {
00507 dest.append((char *) &Length, sizeof(Length));
00508 dest.append(get(), Length);
00509 }
00510
00511
00512 void String::Deserialize(String &source, int &index)
00513 {
00514 memcpy((char *) &Length, (char *) source.get() + index, sizeof(Length));
00515 index += sizeof(Length);
00516 allocate_fix_space(Length);
00517 copy_data_from(source.get() + index, Length);
00518 index += Length;
00519 }
00520
00521
00522
00523
00524
00525 String operator + (const String &a, const String &b)
00526 {
00527 String result(a, a.length() + b.length());
00528
00529 result.append(b);
00530 return result;
00531 }
00532
00533 int operator == (const String &a, const String &b)
00534 {
00535 if (a.Length != b.Length)
00536 return 0;
00537
00538 return a.compare(b) == 0;
00539 }
00540
00541 int operator != (const String &a, const String &b)
00542 {
00543 return a.compare(b) != 0;
00544 }
00545
00546 int operator < (const String &a, const String &b)
00547 {
00548 return a.compare(b) == -1;
00549 }
00550
00551 int operator > (const String &a, const String &b)
00552 {
00553 return a.compare(b) == 1;
00554 }
00555
00556 int operator <= (const String &a, const String &b)
00557 {
00558 return a.compare(b) <= 0;
00559 }
00560
00561 int operator >= (const String &a, const String &b)
00562 {
00563 return a.compare(b) >= 0;
00564 }
00565
00566 #ifndef NOSTREAM
00567 ostream &operator << (ostream &o, const String &s)
00568 {
00569 o.write(s.Data, s.length());
00570 return o;
00571 }
00572 #endif
00573
00574
00575
00576
00577
00578 void String::copy_data_from(const char *s, int len, int dest_offset)
00579 {
00580 memcpy(Data + dest_offset, s, len);
00581 }
00582
00583 void String::allocate_space(int len)
00584 {
00585 len++;
00586
00587 if (len <= Allocated)
00588 return;
00589
00590 if (Allocated)
00591 delete [] Data;
00592
00593 Allocated = MinimumAllocationSize;
00594 while (Allocated < len)
00595 Allocated <<= 1;
00596
00597 Data = new char[Allocated];
00598 }
00599
00600 void String::allocate_fix_space(int len)
00601 {
00602 len++;
00603
00604 if (len <= Allocated)
00605 return;
00606
00607 if (Allocated)
00608 delete [] Data;
00609
00610 Allocated = len;
00611 if (Allocated < MinimumAllocationSize)
00612 Allocated = MinimumAllocationSize;
00613 Data = new char[Allocated];
00614 }
00615
00616 void String::reallocate_space(int len)
00617 {
00618 char *old_data = 0;
00619 int old_data_len = 0;
00620
00621 if (Allocated)
00622 {
00623 old_data = Data;
00624 old_data_len = Length;
00625 Allocated = 0;
00626 }
00627 allocate_space(len);
00628 if (old_data)
00629 {
00630 copy_data_from(old_data, old_data_len);
00631 delete [] old_data;
00632 }
00633 }
00634
00635 void String::copy(const char *s, int len, int allocation_hint)
00636 {
00637 if (len == 0 || allocation_hint == 0)
00638 return;
00639 allocate_fix_space(allocation_hint);
00640 Length = len;
00641 copy_data_from(s, len);
00642 }
00643
00644 #ifndef NOSTREAM
00645 void String::debug(ostream &o)
00646 {
00647 o << "Length: " << Length << " Allocated: " << Allocated <<
00648 " Data: " << ((void*) Data) << " '" << *this << "'\n";
00649 }
00650 #endif
00651
00652 int String::readLine(FILE *in)
00653 {
00654 Length = 0;
00655 allocate_fix_space(2048);
00656
00657 while (fgets(Data + Length, Allocated - Length, in))
00658 {
00659 Length += strlen(Data + Length);
00660 if (Length == 0)
00661 continue;
00662 if (Data[Length - 1] == '\n')
00663 {
00664
00665
00666
00667 chop('\n');
00668 return 1;
00669 }
00670 if (Allocated > Length + 1)
00671 {
00672
00673
00674
00675 continue;
00676 }
00677
00678
00679
00680
00681 reallocate_space(Allocated << 1);
00682 }
00683 chop('\n');
00684
00685 return Length > 0;
00686 }
00687
00688 #ifndef NOSTREAM
00689 istream &operator >> (istream &in, String &line)
00690 {
00691 line.Length = 0;
00692 line.allocate_fix_space(2048);
00693
00694 while (in.get(line.Data + line.Length, line.Allocated - line.Length))
00695 {
00696 line.Length += strlen(line.Data + line.Length);
00697 int c = in.get();
00698 if (c == '\n' || c == EOF)
00699 {
00700
00701
00702
00703 break;
00704 }
00705 if (line.Allocated > line.Length + 2)
00706 {
00707
00708
00709
00710 line.Data[line.Length++] = char(c);
00711 continue;
00712 }
00713
00714
00715
00716
00717 line.reallocate_space(line.Allocated << 1);
00718 line.Data[line.Length++] = char(c);
00719 }
00720
00721 return in;
00722 }
00723 #endif