00001
00002 #ifdef POLARIS_GNU_PRAGMAS
00003 #pragma implementation
00004 #endif
00005
00006 #include <stdlib.h>
00007 #include <stream.h>
00008 #include <strstream.h>
00009 #include <string.h>
00010 #include <ctype.h>
00011
00012 #include "String.h"
00013
00014 #include "rotate.h"
00015 #include "p-assert.h"
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 static char *
00038 alloc_str(int size)
00039 {
00040 char *buf = new char[size];
00041
00042 p_assert( buf, "String: Out of memory" );
00043
00044 return buf;
00045 }
00046
00047 char *
00048 upcase_ch(const char *string)
00049 {
00050 if(string == NULL) return NULL;
00051
00052
00053 int len = strlen(string);
00054 char *buf = alloc_str(len + 1);
00055
00056 for (int i = 0; i < len; i++)
00057 buf[i] = toupper(string[i]);
00058 buf[len] = '\0';
00059
00060 return buf;
00061 }
00062
00063 int
00064 fortran_string_length(const char *string)
00065
00066
00067 {
00068 if(string == NULL) return 0;
00069
00070 int len = strlen(string);
00071 int string_len = 0;
00072
00073 for (int i = 1; i < (len - 1); i++) {
00074 if ((string[i] == '\'') && (string[i + 1] == '\''))
00075 i++;
00076 string_len++;
00077 }
00078
00079 return string_len;
00080 }
00081
00082
00083 String::~String()
00084 {
00085 #ifdef CLASS_INSTANCE_REGISTRY
00086 unregister_instance(STRING_CLASS, this);
00087 #endif
00088
00089 if (_defined) {
00090
00091
00092
00093
00094
00095 const char *delete_msg = "*-*";
00096 const int delete_msg_len = 3;
00097
00098 if (_len >= delete_msg_len)
00099 strcpy(_ptr, delete_msg);
00100 else {
00101
00102
00103 _ptr[0] = '\0';
00104 }
00105
00106
00107 delete [] _ptr;
00108 }
00109
00110 _ptr = 0;
00111 _defined = 0;
00112 }
00113
00114 void
00115 String::fillin_string(const int size, const char *chars)
00116
00117 {
00118 if (chars == 0) {
00119 _defined = 0;
00120 _ptr = "";
00121 return;
00122 }
00123
00124 _len = size >= 0 ? size : 0;
00125 _ptr = alloc_str(_len + 1);
00126
00127 strncpy(_ptr, chars, (unsigned int) _len);
00128
00129 _ptr[size] = '\000';
00130 _defined = 1;
00131 }
00132
00133 Boolean
00134 operator == (const char *str, const String & string)
00135 {
00136 return (string == str);
00137 }
00138
00139 Boolean
00140 operator != (const char *str, const String & string)
00141 {
00142 return !(string == str);
00143 }
00144
00145 Boolean
00146 operator < (const char *str, const String & string)
00147 {
00148 return (string < str);
00149 }
00150
00151 String
00152 operator + (const char *str, const String & string)
00153 {
00154 if(str == NULL) return string;
00155
00156 int str_len = strlen(str);
00157
00158 String new_s;
00159
00160 new_s._len = str_len + string._len;
00161 new_s._ptr = alloc_str(new_s._len + 1);
00162
00163 strcpy(new_s._ptr, str);
00164 strcpy(new_s._ptr + str_len, string._ptr);
00165
00166 new_s._defined = 1;
00167
00168 return new_s;
00169 }
00170
00171 String::String(const char *str)
00172 {
00173 #ifdef CLASS_INSTANCE_REGISTRY
00174 register_instance(STRING_CLASS, sizeof(String), this);
00175 #endif
00176
00177 _defined = 0;
00178 *this = str;
00179 }
00180
00181 String::String(const String & other)
00182 {
00183 #ifdef CLASS_INSTANCE_REGISTRY
00184 register_instance(STRING_CLASS, sizeof(String), this);
00185 #endif
00186
00187 _defined = 0;
00188 *this = other.defined() ? other._ptr : 0;
00189 }
00190
00191 String::String(const char *str, int max_len)
00192 {
00193 #ifdef CLASS_INSTANCE_REGISTRY
00194 register_instance(STRING_CLASS, sizeof(String), this);
00195 #endif
00196
00197 if (str == 0) {
00198 _defined = 0;
00199 _ptr = "";
00200 return;
00201 }
00202
00203 int len_to_use = max_len;
00204
00205
00206 const char *s = str;
00207
00208 for (int i = 0; i < max_len; ++i, ++s) {
00209 if (!*s) {
00210 len_to_use = i;
00211 break;
00212 }
00213 }
00214
00215 fillin_string(len_to_use, str);
00216 }
00217
00218 String::String(const String & other, int first, int last)
00219 {
00220 #ifdef CLASS_INSTANCE_REGISTRY
00221 register_instance(STRING_CLASS, sizeof(String), this);
00222 #endif
00223
00224
00225
00226
00227
00228 if (((last - first) <= 0) || (first >= other._len)) {
00229
00230 fillin_string(0, "");
00231 }
00232
00233 int end = (last < other._len ? last : other._len - 1);
00234 int size = end - first + 1;
00235
00236 fillin_string(size, other._ptr + first);
00237 }
00238
00239 String::String(const String & other, char *delim1, char *delim2)
00240 {
00241 #ifdef CLASS_INSTANCE_REGISTRY
00242 register_instance(STRING_CLASS, sizeof(String), this);
00243 #endif
00244
00245 if ( ! other._defined) {
00246 _defined = 0;
00247 _ptr = "";
00248 return;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 int first = -1;
00259 int last = -1;
00260
00261 if (!delim1)
00262 first = 0;
00263 else {
00264 int delim1_len = strlen(delim1);
00265
00266 for (int i = 0; i < other._len; i++) {
00267 for (int j = 0; j < delim1_len; j++) {
00268 if (other._ptr[i] == delim1[j]) {
00269 first = i;
00270 break;
00271 }
00272 }
00273 if (first != -1) {
00274
00275 break;
00276 }
00277 }
00278
00279 if (first == -1) {
00280
00281
00282
00283 fillin_string(0, "");
00284 return;
00285 }
00286 }
00287
00288 if (!delim2)
00289 last = other._len - 1;
00290 else {
00291 int delim2_len = strlen(delim2);
00292
00293 for (int i = first + 1; i < other._len; i++) {
00294 for (int j = 0; j < delim2_len; j++) {
00295 if (other._ptr[i] == delim2[j]) {
00296 last = i;
00297 break;
00298 }
00299 }
00300
00301 if (last != -1) {
00302
00303 break;
00304 }
00305 }
00306
00307
00308
00309
00310 if (last == -1) {
00311
00312
00313
00314 fillin_string(other._len - first, other._ptr + first);
00315 return;
00316 }
00317 }
00318
00319 fillin_string(last - first + 1, other._ptr + first);
00320 }
00321
00322 String &
00323 String::operator = (const String & other)
00324 {
00325 *this = other._defined ? other._ptr : "";
00326
00327 return *this;
00328 }
00329
00330 String &
00331 String::operator = (const String * other)
00332 {
00333 *this = (other && other->_defined) ? other->_ptr : "";
00334
00335 return *this;
00336 }
00337
00338 String &
00339 String::operator = (const char *str)
00340 {
00341 p_assert((str != NULL), "Assign NULL value through String::operator =");
00342 if (_defined)
00343 delete [] _ptr;
00344
00345 fillin_string(strlen(str), str);
00346
00347 return *this;
00348 }
00349
00350 String
00351 String::operator + (const String & other) const
00352 {
00353 return *this + other._ptr;
00354 }
00355
00356 String
00357 String::operator + (const char *str) const
00358 {
00359 if(str == NULL) return *this;
00360
00361 int str_len = strlen(str);
00362 String new_s;
00363
00364 new_s._len = str_len + _len;
00365 new_s._ptr = alloc_str(new_s._len + 1);
00366
00367 strcpy(new_s._ptr, _ptr);
00368 strcpy(new_s._ptr + _len, str);
00369
00370 new_s._defined = 1;
00371
00372 return new_s;
00373 }
00374
00375 String &
00376 String::operator += (const String & other)
00377 {
00378 *this += other._ptr;
00379
00380 return *this;
00381 }
00382
00383 String &
00384 String::operator += (const char *str)
00385 {
00386 p_assert((str != NULL), "NULL value for operand in String::operator =");
00387
00388 int new_len = strlen(str) + _len;
00389 char *buf = alloc_str(new_len + 1);
00390
00391 strcpy(buf, _defined ? _ptr : "");
00392 strcpy(buf + _len, str);
00393
00394 if (_defined)
00395 delete [] _ptr;
00396
00397 _ptr = buf;
00398 _len = new_len;
00399 _defined = 1;
00400
00401 return *this;
00402 }
00403
00404
00405
00406
00407
00408
00409 void
00410 String::absorb(char *allocated_str)
00411 {
00412 if (_defined)
00413 delete [] _ptr;
00414
00415 if (allocated_str == 0) {
00416 _defined = 0;
00417 _ptr = "";
00418 return;
00419 }
00420
00421 _ptr = allocated_str;
00422 _len = strlen(_ptr);
00423 _defined = 1;
00424 }
00425
00426 unsigned
00427 String::hash_value() const
00428 {
00429 if (!_defined)
00430 return 0x12345654;
00431
00432
00433
00434 unsigned val = 0xA65C5793;
00435
00436 for (char *p = _ptr; *p; ++p)
00437 val = rotate_right(val) ^ *p;
00438
00439 return val;
00440 }
00441
00442 int
00443 String::index(const char *substring) const
00444
00445 {
00446 if ( ! _defined )
00447 return -1;
00448
00449 char *subptr = strstr(_ptr, substring);
00450
00451 return subptr ? (subptr - _ptr) : -1;
00452 }
00453
00454 int
00455 String::index_case(const char *substring) const
00456
00457
00458 {
00459 if ( ! _defined )
00460 return -1;
00461
00462
00463
00464 char *upstring = alloc_str(_len + 1);
00465
00466 upstring = upcase_ch(_ptr);
00467 upstring[_len] = '\0';
00468
00469
00470
00471 int sublen = strlen(substring);
00472 char *upsubstring = alloc_str(sublen + 1);
00473
00474 upsubstring = upcase_ch(substring);
00475 upsubstring[sublen] = '\0';
00476
00477 char *subptr = strstr(upstring, upsubstring);
00478
00479 if (subptr == 0) {
00480 delete [] upstring;
00481 delete [] upsubstring;
00482 return -1;
00483 }
00484 else {
00485 int ret = subptr - upstring;
00486 delete [] upstring;
00487 delete [] upsubstring;
00488 return ret;
00489 }
00490 }
00491
00492 String
00493 String::upcase() const
00494 {
00495 if (!_defined)
00496 return 0;
00497
00498 String str;
00499
00500 str.fillin_string(_len, upcase_ch(_ptr));
00501
00502 return str;
00503 }
00504
00505 int
00506 String::structures_OK() const
00507 {
00508 if (_ptr == 0) {
00509 cerr << "Error: String: structures_OK() found a string pointing "
00510 << "to NULL (which is bad even if the String is undefined)\n";
00511 return 0;
00512 }
00513
00514 if (!_defined)
00515 return 1;
00516
00517
00518 int len = strlen(_ptr);
00519
00520 if (len != _len) {
00521 cerr << "Error: String: structures_OK() found a string of length "
00522 << len << " but expected a length of " << _len << ". " << flush;
00523 if (len < 100)
00524 cerr << "String = \"" << *this << "\"\n";
00525 else {
00526 cerr << "First 100 characters of string = \"";
00527 for (int i = 0; i<100; ++i)
00528 cerr << _ptr[i];
00529 cerr << "\"\n";
00530 }
00531
00532 return 0;
00533 }
00534
00535 return 1;
00536 }
00537