[Groonga-commit] groonga/grnxx at 4076edb [master] Fix a bug that String::append() fails to append itself. (#75)

Back to archive index

susumu.yata null+****@clear*****
Fri Sep 26 15:45:06 JST 2014


susumu.yata	2014-09-26 15:45:06 +0900 (Fri, 26 Sep 2014)

  New Revision: 4076edb73a7cfe65d8acfe73f1115d085f8f6217
  https://github.com/groonga/grnxx/commit/4076edb73a7cfe65d8acfe73f1115d085f8f6217

  Message:
    Fix a bug that String::append() fails to append itself. (#75)

  Modified files:
    include/grnxx/types/string.hpp
    lib/grnxx/types.cpp

  Modified: include/grnxx/types/string.hpp (+7 -1)
===================================================================
--- include/grnxx/types/string.hpp    2014-09-26 15:30:18 +0900 (39e8eae)
+++ include/grnxx/types/string.hpp    2014-09-26 15:45:06 +0900 (f27353a)
@@ -312,7 +312,11 @@ class String {
 
   bool append(Error *error, const StringCRef &arg) {
     if ((size_ + arg.size()) > capacity_) {
-      if (!resize_buf(error, (size_ + arg.size()))) {
+      if ((arg.data() >= buf_.get()) && (arg.data() < (buf_.get() + size_))) {
+        // Note that "arg" will be deleted in resize_buf() if "arg" is a part
+        // of "*this".
+        return append_overlap(error, arg);
+      } else if (!resize_buf(error, (size_ + arg.size()))) {
         return false;
       }
     }
@@ -393,6 +397,8 @@ class String {
 
   // Assume new_size > capacity_.
   bool resize_buf(Error *error, Int new_size);
+  // Resize the internal buffer and append a part of "*this".
+  bool append_overlap(Error *error, const StringCRef &arg);
 };
 
 // Compare a null-terminated string with a string.

  Modified: lib/grnxx/types.cpp (+20 -2)
===================================================================
--- lib/grnxx/types.cpp    2014-09-26 15:30:18 +0900 (7ceca95)
+++ lib/grnxx/types.cpp    2014-09-26 15:45:06 +0900 (a0e0295)
@@ -45,8 +45,7 @@ bool String::resize_buf(Error *error, Int new_size) {
   if (new_size > new_capacity) {
     new_capacity = new_size;
   }
-  Int new_buf_size = new_capacity;
-  unique_ptr<char[]> new_buf(new (nothrow) char[new_buf_size]);
+  unique_ptr<char[]> new_buf(new (nothrow) char[new_capacity]);
   if (!new_buf) {
     GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
     return false;
@@ -57,6 +56,25 @@ bool String::resize_buf(Error *error, Int new_size) {
   return true;
 }
 
+bool String::append_overlap(Error *error, const StringCRef &arg) {
+  Int new_capacity = capacity_ * 2;
+  Int new_size = size_ + arg.size();
+  if (new_size > new_capacity) {
+    new_capacity = new_size;
+  }
+  unique_ptr<char[]> new_buf(new (nothrow) char[new_capacity]);
+  if (!new_buf) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return false;
+  }
+  std::memcpy(new_buf.get(), buf_.get(), size_);
+  std::memcpy(new_buf.get() + size_, arg.data(), arg.size());
+  buf_ = std::move(new_buf);
+  size_ = new_size;
+  capacity_ = new_capacity;
+  return true;
+}
+
 DBOptions::DBOptions() {}
 
 TableOptions::TableOptions() {}
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index