00001 #ifndef ISTRING_IMPLEMENTATION_FILE
00002 #define ISTRING_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "build_configuration.h"
00019 #include "function.h"
00020 #include "guards.h"
00021 #include "istring.h"
00022 #include "packable.h"
00023 #include "sequence.cpp"
00024
00025 #ifdef _MSC_VER
00026 #include <comdef.h>
00027 #undef strcasecmp
00028 #undef strncasecmp
00029 #define strcasecmp strcmpi
00030 #define strncasecmp strnicmp
00031 #endif
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035
00036
00037
00038
00039 const int LONGEST_SPRINTF = 600;
00040
00041 const char CASE_DIFFERENCE = char('A' - 'a');
00042
00043
00044
00045
00046 #ifdef EMBEDDED_BUILD
00047 const int MAX_FIELD_FUDGE_FACTOR = 16;
00048 #else
00049 const int MAX_FIELD_FUDGE_FACTOR = 64;
00050 #endif
00051
00052 const byte empty_char_star[] = "";
00053
00054
00055 const istring BASIS_EXTERN &__istring_empty_string();
00057
00059
00060 bool istring_comparator(const istring &a, const istring &b) { return a == b; }
00061
00063
00064 #undef static_class_name
00065 #define static_class_name() "istring"
00066
00067
00068 istring::istring()
00069 : _implementation(new byte_sequence(1, empty_char_star)),
00070 _held_string((char * const *)_implementation->internal_offset_mem())
00071 {}
00072
00073 istring::istring(char initial, int repeat)
00074 : _implementation(NIL)
00075 {
00076 FUNCDEF("constructor [char/repeat]");
00077 if (!initial) initial = ' ';
00078 int new_size = repeat;
00079 if (non_positive(repeat)) new_size = 0;
00080
00081 _implementation = new byte_sequence(new_size + 1);
00082 memset(_implementation->access(), initial, new_size);
00083 _implementation->put(new_size, '\0');
00084 _held_string = (char * const *)_implementation->internal_offset_mem();
00085 }
00086
00087 istring::istring(const istring &s1)
00088 : _implementation(new byte_sequence(*s1._implementation)),
00089 _held_string((char * const *)_implementation->internal_offset_mem())
00090 {
00091 }
00092
00093 istring::istring(const char *initial)
00094 : _implementation(NIL)
00095 {
00096 FUNCDEF("constructor [char *]");
00097
00098 int new_size = initial? int(strlen(initial)) : 0;
00099 _implementation = new byte_sequence(new_size + 1);
00100 _implementation->put(0, '\0');
00101 if (!initial) return;
00102 strcpy(access(), initial);
00103 _held_string = (char * const *)_implementation->internal_offset_mem();
00104 }
00105
00106 istring::istring(special_flag flag, const char *initial, ...)
00107 : _implementation(new byte_sequence(1, empty_char_star)),
00108 _held_string((char * const *)_implementation->internal_offset_mem())
00109 {
00110 FUNCDEF("constructor [special_flag]");
00111 if (!initial) return;
00112 if ( (flag != UNTERMINATED) && (flag != SPRINTF) ) {
00113 operator = (istring(istring::SPRINTF, "unknown flag %d", flag));
00114 return;
00115 }
00116
00117 va_list args;
00118 va_start(args, initial);
00119
00120 if (flag == UNTERMINATED) {
00121
00122 int length = va_arg(args, int);
00123 _implementation->reset(length, (byte *)initial);
00124 (*_implementation) += byte(0);
00125 va_end(args);
00126 return;
00127 }
00128
00129
00130 base_sprintf(initial, args);
00131 va_end(args);
00132 }
00133
00134 istring::~istring() { WHACK(_implementation); _held_string = NIL; }
00135
00136 const istring &istring::empty_string() { return __istring_empty_string(); }
00137
00138 const byte_sequence &istring::low_level() const { return *_implementation; }
00139
00140 int istring::length() const { return _implementation->length() - 1; }
00141
00142 byte_sequence &istring::get_implem() { return *_implementation; }
00143
00144 char *istring::access() { return (char *)_implementation->access(); }
00145
00146 char istring::get(int index) const { return (char)_implementation->get(index); }
00147
00148 const char *istring::observe() const
00149 { return (const char *)_implementation->observe(); }
00150
00151 bool istring::operator < (const istring &s2) const
00152 { return _implementation->operator < (*s2._implementation); }
00153
00154 bool istring::operator > (const istring &s2) const
00155 { return _implementation->operator > (*s2._implementation); }
00156
00157 bool istring::operator <= (const istring &s2) const
00158 { return _implementation->operator <= (*s2._implementation); }
00159
00160 bool istring::operator >= (const istring &s2) const
00161 { return _implementation->operator >= (*s2._implementation); }
00162
00163 bool istring::operator != (const istring &s2) const
00164 { return !(*this == s2); }
00165
00166 bool istring::operator == (const istring &s2) const
00167 { return strcmp(observe(), s2.observe()) == 0; }
00168
00169 bool istring::operator == (const char *that) const
00170 { return strcmp(observe(), that) == 0; }
00171
00172 bool istring::operator != (const char *that) const
00173 { return strcmp(observe(), that) != 0; }
00174
00175 bool istring::contains(const istring &to_find) const
00176 { return (find(to_find, 0) < 0) ? false : true; }
00177
00178 istring &istring::operator += (const istring &s1)
00179 { insert(length(), s1); return *this; }
00180
00181 void istring::shrink()
00182 {
00183 istring copy_of_this(observe());
00184 _implementation->swap_contents(*copy_of_this._implementation);
00185 }
00186
00187 istring &istring::sprintf(const char *initial, ...)
00188 {
00189 va_list args;
00190 va_start(args, initial);
00191 istring &to_return = base_sprintf(initial, args);
00192 va_end(args);
00193 return to_return;
00194 }
00195
00196 istring &istring::base_sprintf(const char *initial, va_list &args)
00197 {
00198 reset();
00199 if (!initial) return *this;
00200 if (!initial[0]) return *this;
00201
00202
00203 char flag_chars[23], width_chars[23], precision_chars[23], modifier_chars[23];
00204
00205
00206 for (const char *traverser = initial; *traverser; traverser++) {
00207 #ifdef DEBUG_STRING
00208 printf("index=%d, char=%c\n", traverser - initial, *traverser);
00209 #endif
00210
00211 if (*traverser != '%') {
00212
00213 *this += *traverser;
00214 continue;
00215 }
00216 traverser++;
00217 #ifdef DEBUG_STRING
00218 printf("index=%d, char=%c\n", traverser - initial, *traverser);
00219 #endif
00220 if (*traverser == '%') {
00221
00222 *this += *traverser;
00223 continue;
00224 }
00225 bool failure = false;
00226
00227
00228 seek_flag(traverser, flag_chars, failure);
00229 if (failure) {
00230 *this += '%';
00231 *this += flag_chars;
00232 continue;
00233 }
00234 seek_width(traverser, width_chars);
00235 seek_precision(traverser, precision_chars);
00236 seek_modifier(traverser, modifier_chars);
00237 get_type_character(traverser, args, *this, flag_chars,
00238 width_chars, precision_chars, modifier_chars);
00239 }
00240 return *this;
00241 }
00242
00243 void istring::seek_flag(const char *&traverser, char *flag_chars, bool &failure)
00244 {
00245 flag_chars[0] = '\0';
00246 failure = false;
00247 bool keep_going = true;
00248 while (!failure && keep_going) {
00249 switch (*traverser) {
00250 case '-': case '+': case ' ': case '\011': case '#':
00251 flag_chars[strlen(flag_chars) + 1] = '\0';
00252 flag_chars[strlen(flag_chars)] = *traverser++;
00253 break;
00254 default:
00255
00256 keep_going = false;
00257 break;
00258 }
00259 }
00260 #ifdef DEBUG_STRING
00261 if (strlen(flag_chars)) printf("[flag=%s]\n", flag_chars);
00262 else printf("no flags\n");
00263 #endif
00264 }
00265
00266 void istring::seek_width(const char *&traverser, char *width_chars)
00267 {
00268 width_chars[0] = '\0';
00269 bool no_more_nums = false;
00270 bool first_num = true;
00271 while (!no_more_nums) {
00272 char wideness[2] = { *traverser, '\0' };
00273 if (first_num && (wideness[0] == '0')) {
00274 strcpy(width_chars, wideness);
00275 traverser++;
00276 } else if (first_num && (wideness[0] == '*') ) {
00277 strcpy(width_chars, wideness);
00278 traverser++;
00279 no_more_nums = true;
00280 } else if ( (wideness[0] <= '9') && (wideness[0] >= '0') ) {
00281
00282 strcat(width_chars, wideness);
00283 traverser++;
00284 } else no_more_nums = true;
00285 first_num = false;
00286 }
00287 #ifdef DEBUG_STRING
00288 if (strlen(width_chars)) printf("[width=%s]\n", width_chars);
00289 else printf("no widths\n");
00290 #endif
00291 }
00292
00293 void istring::seek_precision(const char *&traverser, char *precision_chars)
00294 {
00295 precision_chars[0] = '\0';
00296 if (*traverser != '.') return;
00297 strcpy(precision_chars, ".");
00298 traverser++;
00299 bool no_more_nums = false;
00300 bool first_num = true;
00301 while (!no_more_nums) {
00302 char preciseness[2] = { *traverser, '\0' };
00303 if (first_num && (preciseness[0] == '0')) {
00304 strcat(precision_chars, preciseness);
00305 traverser++;
00306 no_more_nums = true;
00307 } else if (first_num && (preciseness[0] == '*') ) {
00308 strcat(precision_chars, preciseness);
00309 traverser++;
00310 no_more_nums = true;
00311 } else if ( (preciseness[0] <= '9') && (preciseness[0] >= '0') ) {
00312 strcat(precision_chars, preciseness);
00313 traverser++;
00314 } else no_more_nums = true;
00315 first_num = false;
00316 }
00317 #ifdef DEBUG_STRING
00318 if (strlen(precision_chars)) printf("[precis=%s]\n", precision_chars);
00319 else printf("no precision\n");
00320 #endif
00321 }
00322
00323 void istring::seek_modifier(const char *&traverser, char *modifier_chars)
00324 {
00325 modifier_chars[0] = '\0';
00326 switch (*traverser) {
00327 case 'F': case 'N': case 'h': case 'l': case 'L': {
00328 modifier_chars[strlen(modifier_chars) + 1] = '\0';
00329 modifier_chars[strlen(modifier_chars)] = *traverser++;
00330 break;
00331 }
00332 }
00333 #ifdef DEBUG_STRING
00334 if (strlen(modifier_chars)) printf("[mod=%s]\n", modifier_chars);
00335 else printf("no modifiers\n");
00336 #endif
00337 }
00338
00339 void istring::get_type_character(const char * &traverser, va_list &args,
00340 istring &output_string, const char *flag_chars, const char *width_chars,
00341 const char *precision_chars, const char *modifier_chars)
00342 {
00343 char formatting[120];
00344 strcpy(formatting, "%");
00345 strcat(formatting, flag_chars);
00346 strcat(formatting, width_chars);
00347 strcat(formatting, precision_chars);
00348 strcat(formatting, modifier_chars);
00349 char tmposh[2] = { *traverser, '\0' };
00350 strcat(formatting, tmposh);
00351 #ifdef DEBUG_STRING
00352 printf("format: %s\n", formatting);
00353 #endif
00354
00355 enum argument_size { bits_8, bits_16, bits_32, bits_64, bits_80 };
00356 bool ints_are_32_bits;
00357 #ifdef __WIN32__
00358 ints_are_32_bits = true;
00359 #elif defined(__OS2__)
00360 ints_are_32_bits = true;
00361 #elif defined(__MSDOS__)
00362 ints_are_32_bits = false;
00363 #elif defined(__WIN32__)
00364 ints_are_32_bits = false;
00365 #else
00366 ints_are_32_bits = true;
00367 #endif
00368 argument_size next_argument;
00369 bool use_dynamic_sprintf = false;
00370
00371 switch (*traverser) {
00372 case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
00373 next_argument = bits_16;
00374 if (ints_are_32_bits) next_argument = bits_32;
00375 break;
00376 case 'f': case 'e': case 'g': case 'E': case 'G':
00377 next_argument = bits_64;
00378 break;
00379 case 'c':
00380 next_argument = bits_8;
00381 break;
00382 case 's':
00383 next_argument = bits_32;
00384 use_dynamic_sprintf = true;
00385 break;
00386 case 'n':
00387 next_argument = bits_32;
00388 break;
00389 case 'p':
00390 next_argument = bits_32;
00391 break;
00392 default:
00393
00394
00395 #ifdef DEBUG_STRING
00396 printf("failure in type char: %c\n", *traverser);
00397 #endif
00398 output_string += formatting;
00399 return;
00400 }
00401
00402
00403
00404
00405
00406
00407 if (strlen(modifier_chars)) {
00408 switch (modifier_chars[0]) {
00409 case 'N':
00410 next_argument = bits_16;
00411 if (ints_are_32_bits) next_argument = bits_32;
00412 break;
00413 case 'F':
00414 next_argument = bits_32;
00415 break;
00416 case 'h':
00417 next_argument = bits_16;
00418 break;
00419 case 'l':
00420 next_argument = bits_32;
00421 break;
00422 case 'L':
00423 next_argument = bits_80;
00424 break;
00425 default:
00426
00427
00428 #ifdef DEBUG_STRING
00429 printf("failure in modifier: %s\n", modifier_chars);
00430 #endif
00431 output_string += formatting;
00432 return;
00433 }
00434 }
00435
00436 char temp[LONGEST_SPRINTF];
00437 char *temp2 = NIL;
00438 switch (next_argument) {
00439
00440
00441 case bits_8: case bits_16:
00442 if (ints_are_32_bits) ::sprintf(temp, formatting, va_arg(args, long));
00443 else ::sprintf(temp, formatting, va_arg(args, int));
00444 break;
00445 case bits_32:
00446 if (use_dynamic_sprintf) {
00447
00448 char *to_print = va_arg(args, char *);
00449
00450 if (!to_print) {
00451
00452 use_dynamic_sprintf = false;
00453 ::sprintf(temp, "{error:parm=NIL}");
00454 } else if (strlen(to_print) < LONGEST_SPRINTF - 2) {
00455
00456
00457 use_dynamic_sprintf = false;
00458 ::sprintf(temp, formatting, to_print);
00459 } else {
00460
00461 temp2 = new char[strlen(to_print) + MAX_FIELD_FUDGE_FACTOR];
00462 ::sprintf(temp2, formatting, to_print);
00463 }
00464 } else ::sprintf(temp, formatting, va_arg(args, void *));
00465 break;
00466 case bits_64:
00467 ::sprintf(temp, formatting, va_arg(args, double));
00468 break;
00469 case bits_80:
00470 ::sprintf(temp, formatting, va_arg(args, long double));
00471 break;
00472 }
00473 if (use_dynamic_sprintf) {
00474 output_string += temp2;
00475 delete [] temp2;
00476 } else output_string += temp;
00477 }
00478
00479
00480 void istring::reset(special_flag flag, const char *initial, ...)
00481 {
00482 reset();
00483 if (!initial) return;
00484 if ( (flag != UNTERMINATED) && (flag != SPRINTF) ) {
00485 operator = (istring(istring::SPRINTF, "unknown flag %d", flag));
00486 return;
00487 }
00488
00489 va_list args;
00490 va_start(args, initial);
00491
00492 if (flag == UNTERMINATED) {
00493
00494 int length = va_arg(args, int);
00495 _implementation->reset(length, (byte *)initial);
00496 (*_implementation) += byte(0);
00497 va_end(args);
00498 return;
00499 }
00500
00501
00502 base_sprintf(initial, args);
00503 va_end(args);
00504 }
00505
00506 void istring::pad(int len, char padding)
00507 {
00508 if (length() >= len) return;
00509 byte_sequence pad(len - length());
00510 memset(pad.access(), padding, pad.length());
00511 operator += (istring(UNTERMINATED, (char *)pad.observe(), pad.length()));
00512 }
00513
00514 void istring::trim(int len)
00515 {
00516 if (length() <= len) return;
00517 zap(len, end());
00518 }
00519
00520 istring &istring::operator = (const istring &s1)
00521 {
00522 if (this != &s1)
00523 _implementation->operator = (*s1._implementation);
00524 return *this;
00525 }
00526
00527 istring &istring::operator = (const char *s1)
00528 {
00529 reset();
00530 *this += s1;
00531 return *this;
00532 }
00533
00534 void istring::zap(int position1, int position2)
00535 {
00536 bounds_return(position1, 0, end(), );
00537 bounds_return(position2, 0, end(), );
00538 _implementation->zap(position1, position2);
00539 }
00540
00541 void istring::to_lower()
00542 {
00543 for (int i = 0; i < length(); i++)
00544 if ( (get(i) >= 'A') && (get(i) <= 'Z') )
00545 _implementation->put(i, char(get(i) - CASE_DIFFERENCE));
00546 }
00547
00548 void istring::to_upper()
00549 {
00550 for (int i = 0; i < length(); i++)
00551 if ( (get(i) >= 'a') && (get(i) <= 'z') )
00552 _implementation->put(i, char(get(i) + CASE_DIFFERENCE));
00553 }
00554
00555 istring istring::lower() const
00556 {
00557 istring to_return(*this);
00558 to_return.to_lower();
00559 return to_return;
00560 }
00561
00562 istring istring::upper() const
00563 {
00564 istring to_return(*this);
00565 to_return.to_upper();
00566 return to_return;
00567 }
00568
00569 void istring::copy(char *array_to_stuff, int how_many) const
00570 {
00571 if (!array_to_stuff) return;
00572 array_to_stuff[0] = '\0';
00573 if ( (how_many <= 0) || (length() <= 0) ) return;
00574 strncpy(array_to_stuff, observe(), minimum(how_many, int(length())));
00575 array_to_stuff[minimum(how_many, int(length()))] = '\0';
00576 }
00577
00578 bool istring::iequals(const istring &that) const
00579 { return strcasecmp(observe(), that.observe()) == 0; }
00580
00581 bool istring::iequals(const char *that) const
00582 { return strcasecmp(observe(), that) == 0; }
00583
00584 int istring::ifind(char to_find, int position, bool reverse) const
00585 { return char_find(to_find, position, reverse, false); }
00586
00587 int istring::find(char to_find, int position, bool reverse) const
00588 { return char_find(to_find, position, reverse, true); }
00589
00590 int istring::find_any(const istring &to_find, int position, bool reverse) const
00591 { return char_find_any(to_find, position, reverse, true); }
00592
00593 int istring::ifind_any(const istring &to_find, int position, bool reverse) const
00594 { return char_find_any(to_find, position, reverse, false); }
00595
00596 int istring::find_non_match(const istring &to_find, int position,
00597 bool reverse) const
00598 { return char_find_any(to_find, position, reverse, false, true); }
00599
00600 char simple_lower(char input)
00601 {
00602 if ( (input <= 'Z') && (input >= 'A') ) return input - CASE_DIFFERENCE;
00603 return input;
00604 }
00605
00606 int istring::char_find(char to_find, int position, bool reverse,
00607 bool case_sense) const
00608 {
00609 if (position < 0) return common::OUT_OF_RANGE;
00610 if (position > end()) return common::OUT_OF_RANGE;
00611 if (reverse) {
00612 for (int i = position; i >= 0; i--) {
00613 if (case_sense && (get(i) == to_find)) return i;
00614 else if (simple_lower(get(i)) == simple_lower(to_find)) return i;
00615 }
00616 } else {
00617 if (case_sense) {
00618 const char *const pos = strchr(observe() + position, to_find);
00619 if (pos) return int(pos - observe());
00620 } else {
00621 for (int i = position; i < length(); i++)
00622 if (simple_lower(get(i)) == simple_lower(to_find)) return i;
00623 }
00624 }
00625 return common::NOT_FOUND;
00626 }
00627
00628 bool imatches_any(char to_check, const istring &list)
00629 {
00630 for (int i = 0; i < list.length(); i++)
00631 if (simple_lower(to_check) == simple_lower(list[i])) return true;
00632 return false;
00633 }
00634
00635 bool matches_any(char to_check, const istring &list)
00636 {
00637 for (int i = 0; i < list.length(); i++)
00638 if (to_check == list[i]) return true;
00639 return false;
00640 }
00641
00642 bool matches_none(char to_check, const istring &list)
00643 {
00644 bool saw_match = false;
00645 for (int i = 0; i < list.length(); i++)
00646 if (to_check == list[i]) {
00647 saw_match = true;
00648 break;
00649 }
00650 return !saw_match;
00651 }
00652
00653 int istring::char_find_any(const istring &to_find, int position, bool reverse,
00654 bool case_sense, bool invert_find) const
00655 {
00656 if (position < 0) return common::OUT_OF_RANGE;
00657 if (position > end()) return common::OUT_OF_RANGE;
00658 if (reverse) {
00659 for (int i = position; i >= 0; i--) {
00660 if (!invert_find) {
00661 if (case_sense && matches_any(get(i), to_find)) return i;
00662 else if (imatches_any(get(i), to_find)) return i;
00663 } else {
00664
00665
00666 if (matches_none(get(i), to_find)) return i;
00667 }
00668 }
00669 } else {
00670 for (int i = position; i < length(); i++) {
00671 if (!invert_find) {
00672 if (case_sense && matches_any(get(i), to_find)) return i;
00673 else if (imatches_any(get(i), to_find)) return i;
00674 } else {
00675
00676
00677 if (matches_none(get(i), to_find)) return i;
00678 }
00679 }
00680 }
00681 return common::NOT_FOUND;
00682 }
00683
00684 int istring::find(const istring &to_find, int posn, bool reverse) const
00685 { return str_find(to_find, posn, reverse, true); }
00686
00687 int istring::ifind(const istring &to_find, int posn, bool reverse) const
00688 { return str_find(to_find, posn, reverse, false); }
00689
00690 int istring::str_find(const istring &to_find, int posn, bool reverse,
00691 bool case_sense) const
00692 {
00693 bounds_return(posn, 0, end(), common::OUT_OF_RANGE);
00694 if (!to_find.length()) return common::BAD_INPUT;
00695
00696
00697
00698 if (case_sense)
00699 posn = find(to_find[0], posn, reverse);
00700 else posn = ifind(to_find[0], posn, reverse);
00701 if (posn < 0) return common::NOT_FOUND;
00702
00703
00704
00705 if (case_sense) {
00706
00707 if (reverse) {
00708 if (posn > length() - to_find.length())
00709 posn = length() - to_find.length();
00710 for (int i = posn; i >= 0; i--)
00711 if (!memcmp((void *)&observe()[i], (void *)to_find.observe(),
00712 to_find.length()))
00713 return i;
00714 } else {
00715 const int find_len = to_find.length();
00716 const int str_len = length();
00717 const char first_char = to_find[0];
00718 bounds_return(posn, 0, str_len - find_len, common::OUT_OF_RANGE);
00719 for (int i = posn - 1;
00720 ( ( (i = find(first_char, i + 1)) >= 0)
00721 && (str_len - i >= find_len) ); ) {
00722 if (!memcmp((void *)&observe()[i], (void *)to_find.observe(),
00723 to_find.length()))
00724 return i;
00725 }
00726 }
00727 } else {
00728
00729 if (reverse) {
00730 if (posn > length() - to_find.length())
00731 posn = length() - to_find.length();
00732 for (int i = posn; i >= 0; i--)
00733 if (!strncasecmp(&observe()[i], to_find.observe(), to_find.length()))
00734 return i;
00735 } else {
00736 bounds_return(posn, 0, length() - to_find.length(), common::OUT_OF_RANGE);
00737 for (int i = posn; i < length() - to_find.length() + 1; i++)
00738 if (!strncasecmp(&observe()[i], to_find.observe(), to_find.length()))
00739 return i;
00740 }
00741 }
00742 return common::NOT_FOUND;
00743 }
00744
00745 istring istring::operator + (const istring &s1) const
00746 {
00747 istring to_return(*this);
00748 to_return += s1;
00749 return to_return;
00750 }
00751
00752 char &istring::operator [] (int position)
00753 {
00754 if (position < 0) position = 0;
00755 if (position > end()) position = 0;
00756 byte &found = _implementation->use(position);
00757 char &to_return = *((char *)(&found));
00758 return to_return;
00759 }
00760
00761 const char &istring::operator [] (int position) const
00762 {
00763 if (position < 0) position = 0;
00764 if (position > end()) position = 0;
00765 const byte &found = _implementation->get(position);
00766 const char &to_return = *((const char *)(&found));
00767 return to_return;
00768 }
00769
00770 int istring::convert(int default_value) const
00771 {
00772 if (!length()) return default_value;
00773 int to_return;
00774 int fields = sscanf(observe(), "%d", &to_return);
00775 if (fields < 1) return default_value;
00776 return to_return;
00777 }
00778
00779 long istring::convert(long default_value) const
00780 {
00781 if (!length()) return default_value;
00782 long to_return;
00783 int fields = sscanf(observe(), "%ld", &to_return);
00784 if (fields < 1) return default_value;
00785 return to_return;
00786 }
00787
00788 float istring::convert(float default_value) const
00789 {
00790 if (!length()) return default_value;
00791 float to_return;
00792 int fields = sscanf(observe(), "%f", &to_return);
00793 if (fields < 1) return default_value;
00794 return to_return;
00795 }
00796
00797 double istring::convert(double default_value) const
00798 {
00799 if (!length()) return default_value;
00800 double to_return;
00801 int fields = sscanf(observe(), "%lf", &to_return);
00802 if (fields < 1) return default_value;
00803 return to_return;
00804 }
00805
00806 istring &istring::operator += (const char *s1)
00807 {
00808 if (!s1) return *this;
00809 int len = length();
00810 _implementation->insert(len, int(strlen(s1)));
00811 memory_assign((char *)&_implementation->operator [](len), s1,
00812 int(strlen(s1)));
00813 return *this;
00814 }
00815
00816 istring &istring::operator += (char s1)
00817 {
00818 int len = length();
00819 _implementation->insert(len, 1);
00820 _implementation->put(len, s1);
00821 return *this;
00822 }
00823
00824 bool istring::compare(const istring &to_compare, int start_first,
00825 int start_second, int count) const
00826 {
00827 bounds_return(start_first, 0, end(), false);
00828 bounds_return(start_second, 0, to_compare.end(), false);
00829 bounds_return(start_first + count, start_first, length(), false);
00830 bounds_return(start_second + count, start_second, to_compare.length(), false);
00831 return !memcmp((void *)&observe()[start_first],
00832 (void *)&to_compare.observe()[start_second], count);
00833 }
00834
00835 int istring::icompare(const char *to_compare, int length_in) const
00836 {
00837 if (!length_in) return 0;
00838 int real_len = length_in;
00839
00840 if (negative(length_in))
00841 real_len = length();
00842
00843 int to_compare_len = int(strlen(to_compare));
00844 if (!real_len) return to_compare_len? -1 : 0;
00845
00846 if (!to_compare_len) return 1;
00847 int to_return = strncasecmp(observe(), to_compare, real_len);
00848 if (negative(length_in) && !to_return && (to_compare_len > length()) ) {
00849
00850
00851
00852 return -1;
00853 } else
00854 return to_return;
00855 }
00856
00857 bool istring::oy_icompare(const istring &to_compare, int start_first,
00858 int start_second, int count) const
00859 {
00860 bounds_return(start_first, 0, end(), false);
00861 bounds_return(start_second, 0, to_compare.end(), false);
00862 bounds_return(start_first + count, start_first, length(), false);
00863 bounds_return(start_second + count, start_second, to_compare.length(), false);
00864 const char *actual_first = this->observe() + start_first;
00865 const char *actual_second = to_compare.observe() + start_second;
00866 return !strncasecmp(actual_first, actual_second, count);
00867 }
00868
00869 void istring::substring(istring &target, int start, int bender) const
00870 {
00871 FUNCDEF("substring");
00872 target.reset();
00873 if (bender < start) return;
00874 const int last = end();
00875 bounds_halt(start, 0, last, );
00876 bounds_halt(bender, 0, last, );
00877 target.reset(UNTERMINATED, observe() + start, bender - start + 1);
00878 }
00879
00880 istring istring::substring(int start, int end) const
00881 {
00882 istring to_return;
00883 substring(to_return, start, end);
00884 return to_return;
00885 }
00886
00887 void istring::insert(int position, const istring &to_insert)
00888 {
00889 bounds_return(position, 0, length(), );
00890 if (this == &to_insert) {
00891 istring copy_of_me(to_insert);
00892 insert(position, copy_of_me);
00893 } else {
00894 _implementation->insert(position, to_insert.length());
00895 _implementation->overwrite(position, *to_insert._implementation,
00896 to_insert.length());
00897 }
00898 }
00899
00900 bool istring::replace(const istring &tag, const istring &replacement)
00901 {
00902 int where = find(tag);
00903 if (negative(where)) return false;
00904 zap(where, where + tag.end());
00905 insert(where, replacement);
00906 return true;
00907 }
00908
00909 bool istring::replace_all(const istring &to_replace, const istring &new_string)
00910 {
00911 bool did_any = false;
00912 for (int i = 0; i < length(); i++) {
00913 int indy = find(to_replace, i);
00914 if (negative(indy)) break;
00915 i = indy;
00916 zap(i, i + to_replace.length() - 1);
00917 insert(i, new_string);
00918 i += new_string.length() - 1;
00919 did_any = true;
00920 }
00921 return did_any;
00922 }
00923
00924 bool istring::replace_all(char to_replace, char new_char)
00925 {
00926 bool did_any = false;
00927 for (int i = 0; i < length(); i++) {
00928 if (get(i) == to_replace) {
00929 put(i, new_char);
00930 did_any = true;
00931 }
00932 }
00933 return did_any;
00934 }
00935
00936 bool istring::matches(const istring &match_list, char to_match)
00937 {
00938 for (int i = 0; i < match_list.length(); i++)
00939 if (to_match == match_list.get(i)) return true;
00940 return false;
00941 }
00942
00943 void istring::strip(const istring &strip_list, how_to_strip way)
00944 {
00945 if (way & FROM_FRONT)
00946 while (length() && matches(strip_list, get(0)))
00947 zap(0, 0);
00948
00949 if (way & FROM_END)
00950 while (length() && matches(strip_list, get(end())))
00951 zap(end(), end());
00952 }
00953
<