susumu.yata
null+****@clear*****
Tue Dec 16 10:39:46 JST 2014
susumu.yata 2014-10-31 21:43:45 +0900 (Fri, 31 Oct 2014) New Revision: 4d0445e030abc610dc19b8ce97e9bf94822bf64b https://github.com/groonga/grnxx/commit/4d0445e030abc610dc19b8ce97e9bf94822bf64b Message: Update String to use exceptions. Modified files: include/grnxx/string.hpp lib/grnxx/string.cpp test/test_string.cpp Modified: include/grnxx/string.hpp (+294 -268) =================================================================== --- include/grnxx/string.hpp 2014-10-30 18:49:12 +0900 (0ef00a5) +++ include/grnxx/string.hpp 2014-10-31 21:43:45 +0900 (a9299fe) @@ -3,69 +3,294 @@ #include <cstring> -#include "grnxx/error.hpp" -#include "grnxx/memory.hpp" - namespace grnxx { -// Reference to a byte string. -class StringCRef { +class String { public: - StringCRef() = default; - ~StringCRef() = default; + // Create an empty string. + String() : data_(nullptr), size_(0), capacity_(0) {} + // Free allocated memory. + ~String(); - constexpr StringCRef(const StringCRef &) = default; - StringCRef &operator=(const StringCRef &) = default; + // Create a reference to "string". + String(const String &string) + : data_(string.data_), + size_(string.size_), + capacity_(0) {} + // Create a reference to "rhs". + String &operator=(const String &rhs); + + // Move the ownership of a string. + String(String &&string) + : buffer_(string.buffer_), + size_(string.size_), + capacity_(string.capacity_) { + string.capacity_ = 0; + } + // Move the ownership of a string. + String &operator=(String &&rhs) { + buffer_ = rhs.buffer_; + size_ = rhs.size_; + capacity_ = rhs.capacity_; + rhs.capacity_ = 0; + return *this; + } - StringCRef(const char *str) - : data_(str), - size_(str ? std::strlen(str) : 0) {} - constexpr StringCRef(const char *data, size_t size) + // Create a reference to "string". + // + // If "string" == nullptr, the behavior is undefined. + String(const char *string) + : data_(string), + size_(std::strlen(string)), + capacity_(0) {} + // Create a reference to a byte string. + String(const char *data, size_t size) : data_(data), - size_(size) {} + size_(size), + capacity_(0) {} + // Create an instance. + explicit String(size_t size); + // Create an instance filled with "byte". + String(size_t size, char byte); - // Return the "i"-th byte. + // Create a reference to a substring. + String substring(size_t offset = 0) const { + return String(data_ + offset, size_ - offset); + } + // Create a reference to a substring. + String substring(size_t offset, size_t size) const { + return String(data_ + offset, size); + } + + // Return whether "this" is empty or not. + bool is_empty() const { + return size_ == 0; + } + // Return whether "this" is a reference or not. + bool is_reference() const { + return capacity_ == 0; + } + // Return whether "this" is an instance or not. + bool is_instance() const { + return capacity_ != 0; + } + + // Instanciate the string. + // + // On success, returns a reference to "this". + // On failure, throws an exception. + String &instantiate(); + + // Return a reference to the "i"-th byte. + // + // If "i" is too large, the behavior is undefined. + // If "this" is a reference, the contents must not be modified. + char &operator[](size_t i) { + return buffer_[i]; + } + // Return a reference to the "i"-th byte. + // + // If "i" is too large, the behavior is undefined. const char &operator[](size_t i) const { return data_[i]; } - // Return the address. - constexpr const char *data() const { + + // Return a reference to the first byte. + // + // If "this" is empty, the behavior is undefined. + // If "this" is a reference, the contents must not be modified. + char &front() { + return buffer_[0]; + } + // Return a reference to the first byte. + // + // If "this" is empty, the behavior is undefined. + const char &front() const { + return data_[0]; + } + + // Return a reference to the last byte. + // + // If "this" is empty, the behavior is undefined. + // If "this" is a reference, the contents must not be modified. + char &back() { + return buffer_[size_ - 1]; + } + // Return a reference to the last byte. + // + // If "this" is empty, the behavior is undefined. + const char &back() const { + return data_[size_ - 1]; + } + + // Return a pointer to the buffer. + // + // If "this" is a reference, the contents must not be modified. + char *buffer() { + return buffer_; + } + // Return a pointer to the contents. + const char *data() const { return data_; } - // Return the number of bytes. - constexpr size_t size() const { + // Return the length in bytes. + size_t size() const { return size_; } + // Return the size of the internal buffer. + size_t capacity() const { + return capacity_; + } - // Compare strings. - bool operator==(const StringCRef &rhs) const { + // Reserve memory for at least "new_size" bytes. + // + // On failure, throws an exception. + void reserve(size_t new_size) { + if (new_size > capacity_) { + resize_buffer(new_size); + } + } + + // Store a string. + // + // On failure, throws an exception. + String &assign(const String &string) { + assign(string.data(), string.size()); + return *this; + } + // Store a string. + // + // On failure, throws an exception. + String &assign(const char *data, size_t size) { + if (size > capacity_) { + resize_buffer(size); + } + std::memcpy(buffer_, data, size); + size_ = size; + return *this; + } + + // Resize the string. + // + // On failure, throws an exception. + void resize(size_t new_size) { + if (new_size > capacity_) { + resize_buffer(new_size); + } + size_ = new_size; + } + // Resize the string and fill the new space with "byte". + // + // On failure, throws an exception. + void resize(size_t new_size, char byte) { + if (new_size > capacity_) { + resize_buffer(new_size); + } + if (new_size > size_) { + std::memset(buffer_ + size_, byte, new_size - size_); + } + size_ = new_size; + } + + // Clear the contents. + void clear() { + size_ = 0; + } + + // Concatenate strings. + String operator+(const String rhs) const { + String result(size_ + rhs.size_); + std::memcpy(result.buffer_, data_, size_); + std::memcpy(result.buffer_ + size_, rhs.data_, rhs.size_); + return result; + } + + // Append "rhs" to the end. + // + // On failure, throws an exception. + String &operator+=(char byte) { + return append(byte); + } + // Append "rhs" to the end. + // + // On failure, throws an exception. + String &operator+=(const String &rhs) { + return append(rhs.data_, rhs.size_); + } + + // Append "byte" to the end. + // + // On failure, throws an exception. + String &append(char byte) { + if (size_ == capacity_) { + resize_buffer(size_ + 1); + } + buffer_[size_] = byte; + ++size_; + return *this; + } + // Append "string" to the end. + // + // On failure, throws an exception. + String &append(const String &string) { + append(string.data(), string.size()); + return *this; + } + // Append a string to the end. + // + // On failure, throws an exception. + String &append(const char *data, size_t size) { + if ((size_ + size) > capacity_) { + // NOTE: If the given string is a part of "this", it is destoyed in + // resize_buffer(), so append_overlap() is required. + if ((data >= buffer_) && (data < (buffer_ + size_))) { + append_overlap(data, size); + return *this; + } else { + resize_buffer(size_ + size); + } + } + std::memcpy(buffer_ + size_, data, size); + size_ += size; + return *this; + } + + // Return whether "this" == "rhs" or not. + bool operator==(const String &rhs) const { return (size_ == rhs.size_) && (std::memcmp(data_, rhs.data_, size_) == 0); } - bool operator!=(const StringCRef &rhs) const { + // Return whether "this" != "rhs" or not. + bool operator!=(const String &rhs) const { return (size_ != rhs.size_) || (std::memcmp(data_, rhs.data_, size_) != 0); } - bool operator<(const StringCRef &rhs) const { + // Return whether "this" < "rhs" or not. + bool operator<(const String &rhs) const { size_t min_size = (size_ < rhs.size_) ? size_ : rhs.size_; int result = std::memcmp(data_, rhs.data_, min_size); return (result < 0) || ((result == 0) && (size_ < rhs.size_)); } - bool operator>(const StringCRef &rhs) const { + // Return whether "this" > "rhs" or not. + bool operator>(const String &rhs) const { size_t min_size = (size_ < rhs.size_) ? size_ : rhs.size_; int result = std::memcmp(data_, rhs.data_, min_size); return (result > 0) || ((result == 0) && (size_ > rhs.size_)); } - bool operator<=(const StringCRef &rhs) const { + // Return whether "this" <= "rhs" or not. + bool operator<=(const String &rhs) const { size_t min_size = (size_ < rhs.size_) ? size_ : rhs.size_; int result = std::memcmp(data_, rhs.data_, min_size); return (result < 0) || ((result == 0) && (size_ <= rhs.size_)); } - bool operator>=(const StringCRef &rhs) const { + // Return whether "this" >= "rhs" or not. + bool operator>=(const String &rhs) const { size_t min_size = (size_ < rhs.size_) ? size_ : rhs.size_; int result = std::memcmp(data_, rhs.data_, min_size); return (result > 0) || ((result == 0) && (size_ >= rhs.size_)); } - // Compare a string with a zero-terminated string. + // Return whether "this" == "rhs" or not. + // + // If "rhs" == nullptr, the behavior is undefined. bool operator==(const char *rhs) const { for (size_t i = 0; i < size_; ++i) { if ((rhs[i] == '\0') || (data_[i] != rhs[i])) { @@ -74,6 +299,9 @@ class StringCRef { } return rhs[size_] == '\0'; } + // Return whether "this" != "rhs" or not. + // + // If "rhs" == nullptr, the behavior is undefined. bool operator!=(const char *rhs) const { for (size_t i = 0; i < size_; ++i) { if ((rhs[i] == '\0') || (data_[i] != rhs[i])) { @@ -82,6 +310,9 @@ class StringCRef { } return rhs[size_] != '\0'; } + // Return whether "this" < "rhs" or not. + // + // If "rhs" == nullptr, the behavior is undefined. bool operator<(const char *rhs) const { for (size_t i = 0; i < size_; ++i) { if (rhs[i] == '\0') { @@ -94,6 +325,9 @@ class StringCRef { } return rhs[size_] != '\0'; } + // Return whether "this" > "rhs" or not. + // + // If "rhs" == nullptr, the behavior is undefined. bool operator>(const char *rhs) const { for (size_t i = 0; i < size_; ++i) { if (rhs[i] == '\0') { @@ -106,6 +340,9 @@ class StringCRef { } return false; } + // Return whether "this" <= "rhs" or not. + // + // If "rhs" == nullptr, the behavior is undefined. bool operator<=(const char *rhs) const { for (size_t i = 0; i < size_; ++i) { if (rhs[i] == '\0') { @@ -118,6 +355,9 @@ class StringCRef { } return true; } + // Return whether "this" >= "rhs" or not. + // + // If "rhs" == nullptr, the behavior is undefined. bool operator>=(const char *rhs) const { for (size_t i = 0; i < size_; ++i) { if (rhs[i] == '\0') { @@ -131,13 +371,14 @@ class StringCRef { return rhs[size_] == '\0'; } - // Return true if "*this" starts with "rhs". - bool starts_with(const StringCRef &rhs) const { + // Return whether "this" starts with "rhs" or not. + bool starts_with(const String &rhs) const { if (size_ < rhs.size_) { return false; } return std::memcmp(data_, rhs.data_, rhs.size_) == 0; } + // Return whether "this" starts with "rhs" or not. bool starts_with(const char *rhs) const { for (size_t i = 0; i < size_; ++i) { if (rhs[i] == '\0') { @@ -149,13 +390,14 @@ class StringCRef { return rhs[size_] == '\0'; } - // Return true if "*this" ends with "rhs". - bool ends_with(const StringCRef &rhs) const { + // Return whether "this" ends with "rhs" or not. + bool ends_with(const String &rhs) const { if (size_ < rhs.size_) { return false; } return std::memcmp(data_ + size_ - rhs.size_, rhs.data_, rhs.size_) == 0; } + // Return whether "this" ends with "rhs" or not. bool ends_with(const char *rhs) const { for (size_t i = 0; i < size_; ++i) { if (rhs[i] == '\0') { @@ -167,263 +409,47 @@ class StringCRef { } private: - const char *data_; - size_t size_; -}; - -// Compare a null-terminated string with a string. -inline bool operator==(const char *lhs, const StringCRef &rhs) { - return rhs == lhs; -} -inline bool operator!=(const char *lhs, const StringCRef &rhs) { - return rhs != lhs; -} -inline bool operator<(const char *lhs, const StringCRef &rhs) { - return rhs > lhs; -} -inline bool operator>(const char *lhs, const StringCRef &rhs) { - return rhs < lhs; -} -inline bool operator<=(const char *lhs, const StringCRef &rhs) { - return rhs >= lhs; -} -inline bool operator>=(const char *lhs, const StringCRef &rhs) { - return rhs <= lhs; -} - -class String { - public: - constexpr String() : buf_(nullptr), size_(0), capacity_(0) {} - ~String(); - - String(const String &) = delete; - String& operator=(const String &) = delete; - - String(String &&rhs) - : buf_(rhs.buf_), - size_(rhs.size_), - capacity_(rhs.capacity_) { - rhs.buf_ = nullptr; - rhs.size_ = 0; - rhs.capacity_ = 0; - } - String &operator=(String &&rhs) { - buf_ = rhs.buf_; - size_ = rhs.size_; - capacity_ = rhs.capacity_; - rhs.buf_ = nullptr; - rhs.size_ = 0; - rhs.capacity_ = 0; - return *this; - } - - operator StringCRef() const { - return cref(); - } - - StringCRef cref(size_t offset = 0) const { - return StringCRef(buf_ + offset, size_ - offset); - } - StringCRef cref(size_t offset, size_t size) const { - return StringCRef(buf_ + offset, size); - } - - char &operator[](size_t i) { - return buf_[i]; - } - const char &operator[](size_t i) const { - return buf_[i]; - } - - char &front() { - return buf_[0]; - } - const char &front() const { - return buf_[0]; - } - - char &back() { - return buf_[size_ - 1]; - } - const char &back() const { - return buf_[size_ - 1]; - } - - char *data() { - return buf_; - } - const char *data() const { - return buf_; - } - size_t size() const { - return size_; - } - size_t capacity() const { - return capacity_; - } - - bool reserve(Error *error, size_t new_size) { - if (new_size <= capacity_) { - return true; - } - return resize_buf(error, new_size); - } - - bool assign(Error *error, const StringCRef &rhs) { - if (rhs.size() > capacity_) { - if (!resize_buf(error, rhs.size())) { - return false; - } - } - std::memcpy(buf_, rhs.data(), rhs.size()); - size_ = rhs.size(); - return true; - } - bool assign(Error *error, const char *data, size_t size) { - return assign(error, StringCRef(data, size)); - } - - bool resize(Error *error, size_t new_size) { - if (new_size > capacity_) { - if (!resize_buf(error, new_size)) { - return false; - } - } - size_ = new_size; - return true; - } - bool resize(Error *error, size_t new_size, char value) { - if (new_size > capacity_) { - if (!resize_buf(error, new_size)) { - return false; - } - } - if (new_size > size_) { - std::memset(buf_ + size_, value, new_size - size_); - } - size_ = new_size; - return true; - } - - void clear() { - size_ = 0; - } - - bool push_back(Error *error, char value) { - if (size_ == capacity_) { - if (!resize_buf(error, size_ + 1)) { - return false; - } - } - buf_[size_] = value; - ++size_; - return true; - } - void pop_back() { - --size_; - } - - bool append(Error *error, const StringCRef &rhs) { - if ((size_ + rhs.size()) > capacity_) { - // NOTE: If "rhs" is a part of "*this", "rhs" is destoyed in - // resize_buf(), so append_overlap() is required. - if ((rhs.data() >= buf_) && (rhs.data() < (buf_ + size_))) { - return append_overlap(error, rhs); - } else if (!resize_buf(error, (size_ + rhs.size()))) { - return false; - } - } - std::memcpy(buf_ + size_, rhs.data(), rhs.size()); - size_ += rhs.size(); - return true; - } - bool append(Error *error, const char *data, size_t size) { - return append(error, StringCRef(data, size)); - } - - // Compare a strings. - bool operator==(const StringCRef &rhs) const { - return cref() == rhs; - } - bool operator!=(const StringCRef &rhs) const { - return cref() != rhs; - } - bool operator<(const StringCRef &rhs) const { - return cref() < rhs; - } - bool operator>(const StringCRef &rhs) const { - return cref() > rhs; - } - bool operator<=(const StringCRef &rhs) const { - return cref() <= rhs; - } - bool operator>=(const StringCRef &rhs) const { - return cref() >= rhs; - } - - // Compare a string with a zero-terminated string. - bool operator==(const char *rhs) const { - return cref() == rhs; - } - bool operator!=(const char *rhs) const { - return cref() != rhs; - } - bool operator<(const char *rhs) const { - return cref() < rhs; - } - bool operator>(const char *rhs) const { - return cref() > rhs; - } - bool operator<=(const char *rhs) const { - return cref() <= rhs; - } - bool operator>=(const char *rhs) const { - return cref() >= rhs; - } - - // Return true if "*this" starts with "rhs". - bool starts_with(const StringCRef &rhs) const { - return cref().starts_with(rhs); - } - bool starts_with(const char *rhs) const { - return cref().starts_with(rhs); - } - - // Return true if "*this" ends with "rhs". - bool ends_with(const StringCRef &rhs) const { - return cref().ends_with(rhs); - } - bool ends_with(const char *rhs) const { - return cref().ends_with(rhs); - } - - private: - char *buf_; + union { + char *buffer_; + const char *data_; + }; size_t size_; size_t capacity_; - // Assume new_size > capacity_. - bool resize_buf(Error *error, size_t new_size); - // Resize the internal buffer and append a part of "*this". - bool append_overlap(Error *error, const StringCRef &rhs); + // Resize the internal buffer for at least "new_size". + // + // Assumes that "new_size" is greater than "capacity_". + // + // On failure, throws an exception. + void resize_buffer(size_t new_size); + + // Resize the internal buffer and append a part of "this". + // + // On failure, throws an exception. + void append_overlap(const char *data, size_t size); }; -// Compare a null-terminated string with a string. +// Return whether "lhs" == "rhs" or not. inline bool operator==(const char *lhs, const String &rhs) { return rhs == lhs; } +// Return whether "lhs" != "rhs" or not. inline bool operator!=(const char *lhs, const String &rhs) { return rhs != lhs; } +// Return whether "lhs" < "rhs" or not. inline bool operator<(const char *lhs, const String &rhs) { return rhs > lhs; } +// Return whether "lhs" > "rhs" or not. inline bool operator>(const char *lhs, const String &rhs) { return rhs < lhs; } +// Return whether "lhs" <= "rhs" or not. inline bool operator<=(const char *lhs, const String &rhs) { return rhs >= lhs; } +// Return whether "lhs" >= "rhs" or not. inline bool operator>=(const char *lhs, const String &rhs) { return rhs <= lhs; } Modified: lib/grnxx/string.cpp (+75 -21) =================================================================== --- lib/grnxx/string.cpp 2014-10-30 18:49:12 +0900 (e1f70da) +++ lib/grnxx/string.cpp 2014-10-31 21:43:45 +0900 (7e74c34) @@ -5,44 +5,98 @@ namespace grnxx { String::~String() { - std::free(buf_); + if (capacity_ != 0) { + std::free(buffer_); + } +} + +String &String::operator=(const String &rhs) { + if (capacity_ != 0) { + std::free(buffer_); + } + data_ = rhs.data_; + size_ = rhs.size_; + capacity_ = 0; + return *this; +} + +String::String(size_t size) + : buffer_(), + size_(), + capacity_() { + char *new_buffer = static_cast<char *>(std::malloc(size)); + if (!new_buffer) { + throw "Failed"; // TODO + } + buffer_ = new_buffer; + size_ = size; + capacity_ = size; +} + +String::String(size_t size, char byte) + : buffer_(), + size_(), + capacity_() { + char *new_buffer = static_cast<char *>(std::malloc(size)); + if (!new_buffer) { + throw "Failed"; // TODO + } + std::memset(new_buffer, byte, size); + buffer_ = new_buffer; + size_ = size; + capacity_ = size; +} + +String &String::instantiate() { + if (is_empty() || is_instance()) { + // Nothing to do. + return *this; + } + char *new_buffer = static_cast<char *>(std::malloc(size_)); + if (!new_buffer) { + throw "Failed"; // TODO + } + std::memcpy(new_buffer, data_, size_); + buffer_ = new_buffer; + capacity_ = size_; + return *this; } -bool String::resize_buf(Error *error, size_t new_size) { +void String::resize_buffer(size_t new_size) { size_t new_capacity = capacity_ * 2; if (new_size > new_capacity) { new_capacity = new_size; } - char *new_buf = static_cast<char *>(std::malloc(new_capacity)); - if (!new_buf) { - GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); - return false; + char *new_buffer = static_cast<char *>(std::malloc(new_capacity)); + if (!new_buffer) { + throw "Failed"; // TODO } - std::memcpy(new_buf, buf_, size_); - std::free(buf_); - buf_ = new_buf; + std::memcpy(new_buffer, data_, size_); + if (capacity_ != 0) { + std::free(buffer_); + } + buffer_ = new_buffer; capacity_ = new_capacity; - return true; } -bool String::append_overlap(Error *error, const StringCRef &rhs) { +void String::append_overlap(const char *data, size_t size) { size_t new_capacity = capacity_ * 2; - size_t new_size = size_ + rhs.size(); + size_t new_size = size_ + size; if (new_size > new_capacity) { new_capacity = new_size; } - char *new_buf = static_cast<char *>(std::malloc(new_capacity)); - if (!new_buf) { - GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); - return false; + char *new_buffer = static_cast<char *>(std::malloc(new_capacity)); + if (!new_buffer) { + throw "Failed"; // TODO + } + std::memcpy(new_buffer, buffer_, size_); + std::memcpy(new_buffer + size_, data, size); + if (capacity_ != 0) { + std::free(buffer_); } - std::memcpy(new_buf, buf_, size_); - std::memcpy(new_buf + size_, rhs.data(), rhs.size()); - std::free(buf_); - buf_ = new_buf; + buffer_ = new_buffer; size_ = new_size; capacity_ = new_capacity; - return true; } } // namespace grnxx Modified: test/test_string.cpp (+8 -62) =================================================================== --- test/test_string.cpp 2014-10-30 18:49:12 +0900 (7c1e090) +++ test/test_string.cpp 2014-10-31 21:43:45 +0900 (44e446c) @@ -38,72 +38,20 @@ bool string_ends_with(const std::string &lhs, const std::string &rhs) { return lhs.compare(lhs.size() - rhs.size(), rhs.size(), rhs) == 0; } -void test_string_cref() { - constexpr size_t NUM_STRINGS = 1024; - - std::vector<std::string> strings(NUM_STRINGS); - std::vector<grnxx::StringCRef> refs(NUM_STRINGS); - for (size_t i = 0; i < NUM_STRINGS; ++i) { - std::stringstream stream; - stream << i; - strings[i] = stream.str(); - refs[i] = grnxx::StringCRef(strings[i].data(), strings[i].size()); - } - - for (size_t i = 0; i < NUM_STRINGS; ++i) { - assert(refs[i].size() == static_cast<size_t>(strings[i].size())); - for (size_t j = 0; j < refs[i].size(); ++j) { - assert(refs[i][j] == strings[i][j]); - } - - for (size_t j = 0; j < NUM_STRINGS; ++j) { - assert((refs[i] == refs[j]) == (strings[i] == strings[j])); - assert((refs[i] != refs[j]) == (strings[i] != strings[j])); - assert((refs[i] < refs[j]) == (strings[i] < strings[j])); - assert((refs[i] > refs[j]) == (strings[i] > strings[j])); - assert((refs[i] <= refs[j]) == (strings[i] <= strings[j])); - assert((refs[i] >= refs[j]) == (strings[i] >= strings[j])); - - assert((refs[i] == strings[j].c_str()) == (strings[i] == strings[j])); - assert((refs[i] != strings[j].c_str()) == (strings[i] != strings[j])); - assert((refs[i] < strings[j].c_str()) == (strings[i] < strings[j])); - assert((refs[i] > strings[j].c_str()) == (strings[i] > strings[j])); - assert((refs[i] <= strings[j].c_str()) == (strings[i] <= strings[j])); - assert((refs[i] >= strings[j].c_str()) == (strings[i] >= strings[j])); - - assert((strings[i].c_str() == refs[j]) == (strings[i] == strings[j])); - assert((strings[i].c_str() != refs[j]) == (strings[i] != strings[j])); - assert((strings[i].c_str() < refs[j]) == (strings[i] < strings[j])); - assert((strings[i].c_str() > refs[j]) == (strings[i] > strings[j])); - assert((strings[i].c_str() <= refs[j]) == (strings[i] <= strings[j])); - assert((strings[i].c_str() >= refs[j]) == (strings[i] >= strings[j])); - - assert(refs[i].starts_with(refs[j]) == - string_starts_with(strings[i], strings[j])); - assert(refs[i].starts_with(strings[j].c_str()) == - string_starts_with(strings[i], strings[j])); - assert(refs[i].ends_with(refs[j]) == - string_ends_with(strings[i], strings[j])); - assert(refs[i].ends_with(strings[j].c_str()) == - string_ends_with(strings[i], strings[j])); - } - } -} - void test_string() { constexpr size_t NUM_STRINGS = 1024; - grnxx::Error error; - std::vector<std::string> strings(NUM_STRINGS); - std::vector<grnxx::StringCRef> refs(NUM_STRINGS); + std::vector<grnxx::String> refs(NUM_STRINGS); std::vector<grnxx::String> bodies(NUM_STRINGS); for (size_t i = 0; i < NUM_STRINGS; ++i) { std::stringstream stream; stream << i; strings[i] = stream.str(); - refs[i] = grnxx::StringCRef(strings[i].data(), strings[i].size()); - assert(bodies[i].assign(&error, refs[i])); + refs[i] = grnxx::String(strings[i].data(), strings[i].size()); + assert(refs[i].is_reference()); + bodies[i].assign(refs[i]); + assert(bodies[i].is_instance()); } for (size_t i = 0; i < NUM_STRINGS; ++i) { @@ -164,20 +112,18 @@ void test_string() { stream << (i / 2.0); std::string extra_string = stream.str(); strings[i].append(extra_string); - assert(bodies[i].append(&error, extra_string.data(), extra_string.size())); - assert(bodies[i] == - grnxx::StringCRef(strings[i].data(), strings[i].size())); + bodies[i].append(extra_string.data(), extra_string.size()); + assert(bodies[i] == grnxx::String(strings[i].data(), strings[i].size())); } for (size_t i = 0; i < NUM_STRINGS; ++i) { strings[i].append(strings[i]); - assert(bodies[i].append(&error, bodies[i])); + bodies[i].append(bodies[i]); assert(std::string(bodies[i].data(), bodies[i].size()) == strings[i]); } } int main() { - test_string_cref(); test_string(); return 0; } -------------- next part -------------- HTML����������������������������...Download