[Groonga-commit] groonga/grnxx at 4d0445e [master] Update String to use exceptions.

Zurück zum Archiv-Index

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 



More information about the Groonga-commit mailing list
Zurück zum Archiv-Index