mirror of
https://github.com/google/googletest.git
synced 2025-12-01 00:27:46 -05:00
Enables String to contain NUL (by Zhanyong Wan); Adds scons scripts (by Vlad Losev).
This commit is contained in:
@@ -51,6 +51,22 @@
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// Holds data in a String object. We need this class in order to put
|
||||
// String's data members on the heap instead of on the stack.
|
||||
// Otherwise tests using many assertions (and thus Strings) in one
|
||||
// function may need too much stack frame space to compile.
|
||||
class StringData {
|
||||
StringData() : c_str_(NULL), length_(0) {}
|
||||
~StringData() { delete[] c_str_; }
|
||||
|
||||
private:
|
||||
friend class String;
|
||||
|
||||
const char* c_str_;
|
||||
size_t length_; // Length of the string (excluding the terminating
|
||||
// '\0' character).
|
||||
};
|
||||
|
||||
// String - a UTF-8 string class.
|
||||
//
|
||||
// We cannot use std::string as Microsoft's STL implementation in
|
||||
@@ -80,19 +96,6 @@ class String {
|
||||
public:
|
||||
// Static utility methods
|
||||
|
||||
// Returns the input if it's not NULL, otherwise returns "(null)".
|
||||
// This function serves two purposes:
|
||||
//
|
||||
// 1. ShowCString(NULL) has type 'const char *', instead of the
|
||||
// type of NULL (which is int).
|
||||
//
|
||||
// 2. In MSVC, streaming a null char pointer to StrStream generates
|
||||
// an access violation, so we need to convert NULL to "(null)"
|
||||
// before streaming it.
|
||||
static inline const char* ShowCString(const char* c_str) {
|
||||
return c_str ? c_str : "(null)";
|
||||
}
|
||||
|
||||
// Returns the input enclosed in double quotes if it's not NULL;
|
||||
// otherwise returns "(null)". For example, "\"Hello\"" is returned
|
||||
// for input "Hello".
|
||||
@@ -199,27 +202,36 @@ class String {
|
||||
|
||||
// C'tors
|
||||
|
||||
// The default c'tor constructs a NULL string.
|
||||
String() : c_str_(NULL) {}
|
||||
// The default c'tor constructs a NULL string, which is represented
|
||||
// by data_ being NULL.
|
||||
String() : data_(NULL) {}
|
||||
|
||||
// Constructs a String by cloning a 0-terminated C string.
|
||||
String(const char* c_str) : c_str_(NULL) { // NOLINT
|
||||
*this = c_str;
|
||||
String(const char* c_str) { // NOLINT
|
||||
if (c_str == NULL) {
|
||||
data_ = NULL;
|
||||
} else {
|
||||
ConstructNonNull(c_str, strlen(c_str));
|
||||
}
|
||||
}
|
||||
|
||||
// Constructs a String by copying a given number of chars from a
|
||||
// buffer. E.g. String("hello", 3) will create the string "hel".
|
||||
String(const char* buffer, size_t len);
|
||||
// buffer. E.g. String("hello", 3) creates the string "hel",
|
||||
// String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "",
|
||||
// and String(NULL, 1) results in access violation.
|
||||
String(const char* buffer, size_t length) {
|
||||
ConstructNonNull(buffer, length);
|
||||
}
|
||||
|
||||
// The copy c'tor creates a new copy of the string. The two
|
||||
// String objects do not share content.
|
||||
String(const String& str) : c_str_(NULL) {
|
||||
*this = str;
|
||||
}
|
||||
String(const String& str) : data_(NULL) { *this = str; }
|
||||
|
||||
// D'tor. String is intended to be a final class, so the d'tor
|
||||
// doesn't need to be virtual.
|
||||
~String() { delete[] c_str_; }
|
||||
~String() {
|
||||
delete data_;
|
||||
}
|
||||
|
||||
// Allows a String to be implicitly converted to an ::std::string or
|
||||
// ::string, and vice versa. Converting a String containing a NULL
|
||||
@@ -228,21 +240,23 @@ class String {
|
||||
// character to a String will result in the prefix up to the first
|
||||
// NUL character.
|
||||
#if GTEST_HAS_STD_STRING
|
||||
String(const ::std::string& str) : c_str_(NULL) { *this = str.c_str(); }
|
||||
String(const ::std::string& str) {
|
||||
ConstructNonNull(str.c_str(), str.length());
|
||||
}
|
||||
|
||||
operator ::std::string() const { return ::std::string(c_str_); }
|
||||
operator ::std::string() const { return ::std::string(c_str(), length()); }
|
||||
#endif // GTEST_HAS_STD_STRING
|
||||
|
||||
#if GTEST_HAS_GLOBAL_STRING
|
||||
String(const ::string& str) : c_str_(NULL) { *this = str.c_str(); }
|
||||
String(const ::string& str) {
|
||||
ConstructNonNull(str.c_str(), str.length());
|
||||
}
|
||||
|
||||
operator ::string() const { return ::string(c_str_); }
|
||||
operator ::string() const { return ::string(c_str(), length()); }
|
||||
#endif // GTEST_HAS_GLOBAL_STRING
|
||||
|
||||
// Returns true iff this is an empty string (i.e. "").
|
||||
bool empty() const {
|
||||
return (c_str_ != NULL) && (*c_str_ == '\0');
|
||||
}
|
||||
bool empty() const { return (c_str() != NULL) && (length() == 0); }
|
||||
|
||||
// Compares this with another String.
|
||||
// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
|
||||
@@ -251,19 +265,15 @@ class String {
|
||||
|
||||
// Returns true iff this String equals the given C string. A NULL
|
||||
// string and a non-NULL string are considered not equal.
|
||||
bool operator==(const char* c_str) const {
|
||||
return CStringEquals(c_str_, c_str);
|
||||
}
|
||||
bool operator==(const char* c_str) const { return Compare(c_str) == 0; }
|
||||
|
||||
// Returns true iff this String is less than the given C string. A NULL
|
||||
// string is considered less than "".
|
||||
// Returns true iff this String is less than the given String. A
|
||||
// NULL string is considered less than "".
|
||||
bool operator<(const String& rhs) const { return Compare(rhs) < 0; }
|
||||
|
||||
// Returns true iff this String doesn't equal the given C string. A NULL
|
||||
// string and a non-NULL string are considered not equal.
|
||||
bool operator!=(const char* c_str) const {
|
||||
return !CStringEquals(c_str_, c_str);
|
||||
}
|
||||
bool operator!=(const char* c_str) const { return !(*this == c_str); }
|
||||
|
||||
// Returns true iff this String ends with the given suffix. *Any*
|
||||
// String is considered to end with a NULL or empty suffix.
|
||||
@@ -273,45 +283,66 @@ class String {
|
||||
// case. Any String is considered to end with a NULL or empty suffix.
|
||||
bool EndsWithCaseInsensitive(const char* suffix) const;
|
||||
|
||||
// Returns the length of the encapsulated string, or -1 if the
|
||||
// Returns the length of the encapsulated string, or 0 if the
|
||||
// string is NULL.
|
||||
int GetLength() const {
|
||||
return c_str_ ? static_cast<int>(strlen(c_str_)) : -1;
|
||||
}
|
||||
size_t length() const { return (data_ == NULL) ? 0 : data_->length_; }
|
||||
|
||||
// Gets the 0-terminated C string this String object represents.
|
||||
// The String object still owns the string. Therefore the caller
|
||||
// should NOT delete the return value.
|
||||
const char* c_str() const { return c_str_; }
|
||||
|
||||
// Sets the 0-terminated C string this String object represents.
|
||||
// The old string in this object is deleted, and this object will
|
||||
// own a clone of the input string. This function copies only up to
|
||||
// length bytes (plus a terminating null byte), or until the first
|
||||
// null byte, whichever comes first.
|
||||
//
|
||||
// This function works even when the c_str parameter has the same
|
||||
// value as that of the c_str_ field.
|
||||
void Set(const char* c_str, size_t length);
|
||||
const char* c_str() const { return (data_ == NULL) ? NULL : data_->c_str_; }
|
||||
|
||||
// Assigns a C string to this object. Self-assignment works.
|
||||
const String& operator=(const char* c_str);
|
||||
const String& operator=(const char* c_str) { return *this = String(c_str); }
|
||||
|
||||
// Assigns a String object to this object. Self-assignment works.
|
||||
const String& operator=(const String &rhs) {
|
||||
*this = rhs.c_str_;
|
||||
const String& operator=(const String& rhs) {
|
||||
if (this != &rhs) {
|
||||
delete data_;
|
||||
data_ = NULL;
|
||||
if (rhs.data_ != NULL) {
|
||||
ConstructNonNull(rhs.data_->c_str_, rhs.data_->length_);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* c_str_;
|
||||
};
|
||||
// Constructs a non-NULL String from the given content. This
|
||||
// function can only be called when data_ has not been allocated.
|
||||
// ConstructNonNull(NULL, 0) results in an empty string ("").
|
||||
// ConstructNonNull(NULL, non_zero) is undefined behavior.
|
||||
void ConstructNonNull(const char* buffer, size_t length) {
|
||||
data_ = new StringData;
|
||||
char* const str = new char[length + 1];
|
||||
memcpy(str, buffer, length);
|
||||
str[length] = '\0';
|
||||
data_->c_str_ = str;
|
||||
data_->length_ = length;
|
||||
}
|
||||
|
||||
// Streams a String to an ostream.
|
||||
inline ::std::ostream& operator <<(::std::ostream& os, const String& str) {
|
||||
// We call String::ShowCString() to convert NULL to "(null)".
|
||||
// Otherwise we'll get an access violation on Windows.
|
||||
return os << String::ShowCString(str.c_str());
|
||||
// Points to the representation of the String. A NULL String is
|
||||
// represented by data_ == NULL.
|
||||
StringData* data_;
|
||||
}; // class String
|
||||
|
||||
// Streams a String to an ostream. Each '\0' character in the String
|
||||
// is replaced with "\\0".
|
||||
inline ::std::ostream& operator<<(::std::ostream& os, const String& str) {
|
||||
if (str.c_str() == NULL) {
|
||||
os << "(null)";
|
||||
} else {
|
||||
const char* const c_str = str.c_str();
|
||||
for (size_t i = 0; i != str.length(); i++) {
|
||||
if (c_str[i] == '\0') {
|
||||
os << "\\0";
|
||||
} else {
|
||||
os << c_str[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
// Gets the content of the StrStream's buffer as a String. Each '\0'
|
||||
|
||||
Reference in New Issue
Block a user