version 1.37, 2002/05/03 05:26:17
|
version 1.39, 2002/05/06 20:13:08
|
|
|
// | // |
// Author: Mike Brasher (mbrasher@bmc.com) | // Author: Mike Brasher (mbrasher@bmc.com) |
// | // |
// Modified By: |
// Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
|
|
#include <cctype> | #include <cctype> |
#include "String.h" | #include "String.h" |
#include "Exception.h" | #include "Exception.h" |
#include "String.h" |
|
#include <iostream> | #include <iostream> |
| |
PEGASUS_USING_STD; | PEGASUS_USING_STD; |
|
|
#include <Pegasus/Common/ArrayImpl.h> | #include <Pegasus/Common/ArrayImpl.h> |
#undef PEGASUS_ARRAY_T | #undef PEGASUS_ARRAY_T |
| |
|
/////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// String |
|
// |
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
const String String::EMPTY = String(); | const String String::EMPTY = String(); |
| |
#if 0 // Apparently dead code |
Uint32 _strnlen(const char* str, Uint32 n) |
static inline void _SkipWhitespace(const Char16*& p) |
{ |
|
if (!str) |
|
throw NullPointer(); |
|
|
|
for (Uint32 i=0; i<n; i++) |
|
{ |
|
if (!*str) |
{ | { |
while (*p && isspace(*p)) |
return i; |
p++; |
} |
} | } |
#endif |
|
| |
inline Uint32 StrLen(const char* str) |
return n; |
|
} |
|
|
|
Uint32 _strnlen(const Char16* str, Uint32 n) |
|
{ |
|
if (!str) |
|
throw NullPointer(); |
|
|
|
for (Uint32 i=0; i<n; i++) |
|
{ |
|
if (!*str) |
|
{ |
|
return i; |
|
} |
|
} |
|
|
|
return n; |
|
} |
|
|
|
inline Uint32 _StrLen(const char* str) |
{ | { |
if (!str) | if (!str) |
throw NullPointer(); | throw NullPointer(); |
|
|
return strlen(str); | return strlen(str); |
} | } |
| |
inline Uint32 StrLen(const Char16* str) |
inline Uint32 _StrLen(const Char16* str) |
{ | { |
if (!str) | if (!str) |
throw NullPointer(); | throw NullPointer(); |
|
|
_rep.append('\0'); | _rep.append('\0'); |
} | } |
| |
String::String(const String& x) : _rep(x._rep) |
String::String(const String& str) |
|
: _rep(str._rep) |
{ | { |
|
|
} | } |
| |
String::String(const String& x, Uint32 n) |
String::String(const String& str, Uint32 n) |
{ | { |
_rep.append('\0'); |
assign(str.getData(), n); |
append(x.getData(), n); |
|
} | } |
| |
String::String(const Char16* x) : _rep(x, StrLen(x) + 1) |
String::String(const Char16* str) |
|
: _rep(str, _StrLen(str) + 1) |
{ | { |
|
|
} | } |
| |
String::String(const Char16* x, Uint32 n) |
String::String(const Char16* str, Uint32 n) |
{ | { |
assign(x, n); |
assign(str, n); |
} | } |
| |
String::String(const char* str) | String::String(const char* str) |
{ | { |
Uint32 n = ::strlen(str) + 1; |
assign(str); |
reserve(n); |
} |
| |
while (n--) |
String::String(const char* str, Uint32 n) |
_rep.append(*str++); |
{ |
|
assign(str, n); |
} | } |
| |
String::String(const char* str, Uint32 n_) |
String::~String() |
{ | { |
Uint32 n = _pegasusMin(strlen(str), n_); |
} |
reserve(n + 1); |
|
| |
while (n--) |
String& String::operator=(const String& str) |
_rep.append(*str++); |
{ |
|
return assign(str); |
|
} |
| |
_rep.append('\0'); |
String& String::operator=(const Char16* str) |
|
{ |
|
return assign(str); |
} | } |
| |
String& String::assign(const Char16* x) |
String& String::assign(const String& str) |
|
{ |
|
_rep = str._rep; |
|
return *this; |
|
} |
|
|
|
String& String::assign(const Char16* str) |
{ | { |
_rep.clear(); | _rep.clear(); |
_rep.append(x, StrLen(x) + 1); |
_rep.append(str, _StrLen(str) + 1); |
return *this; | return *this; |
} | } |
| |
String& String::assign(const Char16* str, Uint32 n) | String& String::assign(const Char16* str, Uint32 n) |
{ | { |
_rep.clear(); | _rep.clear(); |
Uint32 m = _pegasusMin(StrLen(str), n); |
Uint32 m = _strnlen(str, n); |
_rep.append(str, m); | _rep.append(str, m); |
_rep.append('\0'); | _rep.append('\0'); |
return *this; | return *this; |
} | } |
| |
String& String::assign(const char* x) |
String& String::assign(const char* str) |
{ | { |
_rep.clear(); | _rep.clear(); |
Uint32 n = strlen(x); |
|
_rep.reserve(n + 1); |
|
| |
while (n--) |
Uint32 n = strlen(str) + 1; |
_rep.append(*x++); |
_rep.reserve(n); |
| |
_rep.append('\0'); |
while (n--) |
|
_rep.append(*str++); |
| |
return *this; | return *this; |
} | } |
| |
String& String::assign(const char* x, Uint32 n_) |
String& String::assign(const char* str, Uint32 n) |
{ | { |
_rep.clear(); | _rep.clear(); |
| |
Uint32 n = _pegasusMin(strlen(x), n_); |
Uint32 _n = _strnlen(str, n); |
_rep.reserve(n + 1); |
_rep.reserve(_n + 1); |
| |
while (n--) |
while (_n--) |
_rep.append(*x++); |
_rep.append(*str++); |
| |
_rep.append('\0'); | _rep.append('\0'); |
| |
return *this; | return *this; |
} | } |
| |
|
void String::clear() |
|
{ |
|
_rep.clear(); |
|
_rep.append('\0'); |
|
} |
|
|
|
void String::reserve(Uint32 capacity) |
|
{ |
|
_rep.reserve(capacity + 1); |
|
} |
|
|
|
Uint32 String::size() const |
|
{ |
|
return _rep.size() - 1; |
|
} |
|
|
|
const Char16* String::getData() const |
|
{ |
|
return _rep.getData(); |
|
} |
|
|
char* String::allocateCString(Uint32 extraBytes, Boolean noThrow) const | char* String::allocateCString(Uint32 extraBytes, Boolean noThrow) const |
{ | { |
Uint32 n = size() + 1; | Uint32 n = size() + 1; |
|
|
if (!str) | if (!str) |
throw NullPointer(); | throw NullPointer(); |
| |
Uint32 n = _pegasusMin(size(), length); |
Uint32 n = (size() < length)? size() : length; |
| |
char* p = str + strlen(str); | char* p = str + strlen(str); |
const Char16* q = getData(); | const Char16* q = getData(); |
|
|
return _rep[i]; | return _rep[i]; |
} | } |
| |
|
String& String::append(const Char16& c) |
|
{ |
|
_rep.insert(_rep.size() - 1, c); |
|
return *this; |
|
} |
|
|
String& String::append(const Char16* str, Uint32 n) | String& String::append(const Char16* str, Uint32 n) |
{ | { |
Uint32 m = _pegasusMin(StrLen(str), n); |
Uint32 m = _strnlen(str, n); |
_rep.reserve(_rep.size() + m); | _rep.reserve(_rep.size() + m); |
_rep.remove(_rep.size() - 1); | _rep.remove(_rep.size() - 1); |
_rep.append(str, m); | _rep.append(str, m); |
|
|
return *this; | return *this; |
} | } |
| |
void String::remove(Uint32 pos, Uint32 size) |
String& String::append(const String& str) |
{ |
|
if (size == PEG_NOT_FOUND) |
|
size = this->size() - pos; |
|
|
|
if (pos + size > this->size()) |
|
ThrowOutOfBounds(); |
|
|
|
if (size) |
|
_rep.remove(pos, size); |
|
} |
|
|
|
int String::compare(const Char16* s1, const Char16* s2, Uint32 n) |
|
{ |
|
while (n--) |
|
{ |
|
int r = *s1++ - *s2++; |
|
|
|
if (r) |
|
return r; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
int String::compareNoCase(const char* s1, const char* s2, Uint32 n) |
|
{ |
|
while (n--) |
|
{ |
|
int r = tolower(*s1++) - tolower(*s2++); |
|
|
|
if (r) |
|
return r; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
Boolean String::equal(const String& x, const String& y) |
|
{ | { |
if (x.size() != y.size()) |
return append(str.getData(), str.size()); |
return false; |
|
|
|
return String::compare(x.getData(), y.getData(), x.size()) == 0; |
|
} | } |
| |
Boolean String::equal(const String& x, const Char16* y) |
String& String::operator+=(const String& str) |
{ | { |
if (x.size() != StrLen(y)) |
return append(str); |
return false; |
|
|
|
return String::compare(x.getData(), y, x.size()) == 0; |
|
} | } |
| |
Boolean String::equal(const Char16* x, const String& y) |
String& String::operator+=(Char16 c) |
{ | { |
return equal(y, x); |
return append(c); |
} | } |
| |
Boolean String::equal(const String& x, const char* y) |
String& String::operator+=(char c) |
{ | { |
return equal(x, String(y)); |
return append(Char16(c)); |
} | } |
| |
Boolean String::equal(const char* x, const String& y) |
void String::remove(Uint32 pos, Uint32 size) |
{ |
|
return equal(String(x), y); |
|
} |
|
|
|
Boolean String::equalNoCase(const String& x, const String& y) |
|
{ | { |
if (x.size() != y.size()) |
if (size == PEG_NOT_FOUND) |
return false; |
size = this->size() - pos; |
|
|
const Char16* p = x.getData(); |
|
const Char16* q = y.getData(); |
|
|
|
Uint32 n = x.size(); |
|
| |
while (n--) |
if (pos + size > this->size()) |
{ |
ThrowOutOfBounds(); |
#ifdef PEGASUS_HAS_EBCDIC |
|
if (*p <= 255 && *q <= 255) |
|
#else |
|
if (*p <= 127 && *q <= 127) |
|
#endif |
|
{ |
|
if (tolower(*p++) != tolower(*q++)) |
|
return false; |
|
} |
|
else if (*p++ != *q++) |
|
return false; |
|
} |
|
| |
return true; |
if (size) |
|
_rep.remove(pos, size); |
} | } |
| |
String String::subString(Uint32 pos, Uint32 length) const | String String::subString(Uint32 pos, Uint32 length) const |
|
|
return PEG_NOT_FOUND; | return PEG_NOT_FOUND; |
} | } |
| |
Uint32 String::find(const char* s) const |
Uint32 String::find(const Char16* s) const |
{ | { |
return find(String(s)); | return find(String(s)); |
} | } |
| |
Uint32 String::find(const Char16* s) const |
Uint32 String::find(const char* s) const |
{ | { |
return find(String(s)); | return find(String(s)); |
} | } |
|
|
} | } |
} | } |
| |
|
void String::toLower(char* str) |
|
{ |
|
while (*str) |
|
tolower(*str++); |
|
} |
|
|
void String::translate(Char16 fromChar, Char16 toChar) | void String::translate(Char16 fromChar, Char16 toChar) |
{ | { |
for (Char16* p = &_rep[0]; *p; p++) | for (Char16* p = &_rep[0]; *p; p++) |
|
|
} | } |
} | } |
| |
int String::compare(const Char16* s1, const Char16* s2) |
void String::print() const |
{ | { |
while (*s1 && *s2) |
cout << *this << endl; |
|
} |
|
|
|
int String::compare(const Char16* s1, const Char16* s2, Uint32 n) |
|
{ |
|
while (n--) |
{ | { |
int r = *s1++ - *s2++; | int r = *s1++ - *s2++; |
| |
|
|
return r; | return r; |
} | } |
| |
if (*s2) |
|
return -1; |
|
else if (*s1) |
|
return 1; |
|
|
|
return 0; | return 0; |
} | } |
| |
int String::compareNoCase(const char* s1, const char* s2) |
int String::compare(const Char16* s1, const Char16* s2) |
{ | { |
while (*s1 && *s2) | while (*s1 && *s2) |
{ | { |
int r = tolower(*s1++) - tolower(*s2++); |
int r = *s1++ - *s2++; |
| |
if (r) | if (r) |
return r; | return r; |
|
|
return 0; | return 0; |
} | } |
| |
PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& x) |
int String::compareNoCase(const char* s1, const char* s2, Uint32 n) |
{ |
|
for (Uint32 i = 0, n = x.size(); i < n; i++) |
|
os << x[i]; |
|
|
|
return os; |
|
} |
|
|
|
void String::toLower(char* str) |
|
{ |
|
while (*str) |
|
tolower(*str++); |
|
} |
|
|
|
String ToLower(const String& str) |
|
{ | { |
String tmp(str); |
while (n--) |
|
|
for (Uint32 i = 0, n = tmp.size(); i < n; i++) |
|
{ | { |
Char16 c = tmp[i]; |
int r = tolower(*s1++) - tolower(*s2++); |
| |
#ifdef PEGASUS_HAS_EBCDIC |
if (r) |
if (c <= 255) |
return r; |
#else |
|
if (c <= 127) |
|
#endif |
|
tmp[i] = tolower(c); |
|
} | } |
| |
return tmp; |
return 0; |
} | } |
| |
int CompareNoCase(const char* s1, const char* s2) |
int String::compareNoCase(const char* s1, const char* s2) |
{ | { |
while (*s1 && *s2) | while (*s1 && *s2) |
{ | { |
|
|
return 0; | return 0; |
} | } |
| |
Boolean GetLine(PEGASUS_STD(istream)& is, String& line) |
Boolean String::equal(const String& str1, const String& str2) |
{ | { |
line.clear(); |
if (str1.size() != str2.size()) |
|
return false; |
| |
Boolean gotChar = false; |
return String::compare(str1.getData(), str2.getData(), str1.size()) == 0; |
char c; |
} |
| |
while (is.get(c)) |
Boolean String::equal(const String& str1, const Char16* str2) |
{ | { |
gotChar = true; |
if (str1.size() != _StrLen(str2)) |
|
return false; |
if (c == '\n') |
|
break; |
|
|
|
line.append(c); |
|
} |
|
| |
return gotChar; |
return String::compare(str1.getData(), str2, str1.size()) == 0; |
} | } |
| |
String::~String() |
Boolean String::equal(const Char16* str1, const String& str2) |
{ | { |
|
return equal(str2, str1); |
} | } |
| |
String& String::assign(const String& x) |
Boolean String::equal(const String& str1, const char* str2) |
{ | { |
_rep = x._rep; |
return equal(str1, String(str2)); |
return *this; |
|
} | } |
| |
String& String::append(const Char16& c) |
Boolean String::equal(const char* str1, const String& str2) |
{ | { |
_rep.insert(_rep.size() - 1, c); |
return equal(String(str1), str2); |
return *this; |
|
} | } |
| |
void String::clear() |
Boolean String::equalNoCase(const String& str1, const String& str2) |
{ | { |
_rep.clear(); |
if (str1.size() != str2.size()) |
_rep.append('\0'); |
return false; |
} |
|
| |
void String::print() const |
const Char16* p = str1.getData(); |
{ |
const Char16* q = str2.getData(); |
cout << *this << endl; |
|
} |
|
| |
void String::reserve(Uint32 capacity) |
Uint32 n = str1.size(); |
|
|
|
while (n--) |
{ | { |
_rep.reserve(capacity + 1); |
#ifdef PEGASUS_HAS_EBCDIC |
|
if (*p <= 255 && *q <= 255) |
|
#else |
|
if (*p <= 127 && *q <= 127) |
|
#endif |
|
{ |
|
if (tolower(*p++) != tolower(*q++)) |
|
return false; |
|
} |
|
else if (*p++ != *q++) |
|
return false; |
} | } |
| |
const Array<String>& EmptyStringArray() |
return true; |
{ |
|
static Array<String> tmp; |
|
return tmp; |
|
} | } |
|
|
//#define NEWMATCHFUNCTION | //#define NEWMATCHFUNCTION |
#if defined NEWMATCHFUNCTION | #if defined NEWMATCHFUNCTION |
// Wildcard String matching function that may be useful in the future | // Wildcard String matching function that may be useful in the future |
|
|
} | } |
} | } |
#endif | #endif |
|
|
Boolean String::match(const String& str, const String& pattern) | Boolean String::match(const String& str, const String& pattern) |
{ | { |
return _StringMatch( | return _StringMatch( |
|
|
(Uint16*)str.getData(), (Uint16*)pattern.getData(), 1) != 0; | (Uint16*)str.getData(), (Uint16*)pattern.getData(), 1) != 0; |
} | } |
| |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// String-related functions |
|
// |
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
Boolean operator==(const String& str1, const String& str2) |
|
{ |
|
return String::equal(str1, str2); |
|
} |
|
|
|
Boolean operator==(const String& str1, const char* str2) |
|
{ |
|
return String::equal(str1, str2); |
|
} |
|
|
|
Boolean operator==(const char* str1, const String& str2) |
|
{ |
|
return String::equal(str1, str2); |
|
} |
|
|
|
Boolean operator!=(const String& str1, const String& str2) |
|
{ |
|
return !String::equal(str1, str2); |
|
} |
|
|
|
PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& str1) |
|
{ |
|
for (Uint32 i = 0, n = str1.size(); i < n; i++) |
|
os << str1[i]; |
|
|
|
return os; |
|
} |
|
|
|
String operator+(const String& str1, const String& str2) |
|
{ |
|
return String(str1).append(str2); |
|
} |
|
|
|
Boolean operator<(const String& str1, const String& str2) |
|
{ |
|
return String::compare(str1.getData(), str2.getData()) < 0; |
|
} |
|
|
|
Boolean operator<=(const String& str1, const String& str2) |
|
{ |
|
return String::compare(str1.getData(), str2.getData()) <= 0; |
|
} |
|
|
|
Boolean operator>(const String& str1, const String& str2) |
|
{ |
|
return String::compare(str1.getData(), str2.getData()) > 0; |
|
} |
|
|
|
Boolean operator>=(const String& str1, const String& str2) |
|
{ |
|
return String::compare(str1.getData(), str2.getData()) >= 0; |
|
} |
|
|
|
int CompareNoCase(const char* s1, const char* s2) |
|
{ |
|
while (*s1 && *s2) |
|
{ |
|
int r = tolower(*s1++) - tolower(*s2++); |
|
|
|
if (r) |
|
return r; |
|
} |
|
|
|
if (*s2) |
|
return -1; |
|
else if (*s1) |
|
return 1; |
|
|
|
return 0; |
|
} |
|
|
|
int EqualNoCase(const char* s1, const char* s2) |
|
{ |
|
return CompareNoCase(s1, s2) == 0; |
|
} |
|
|
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |