diff options
Diffstat (limited to 'src/google/protobuf/repeated_field.cc')
-rw-r--r-- | src/google/protobuf/repeated_field.cc | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc index 77004f59..310000aa 100644 --- a/src/google/protobuf/repeated_field.cc +++ b/src/google/protobuf/repeated_field.cc @@ -58,14 +58,16 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { (std::numeric_limits<size_t>::max() - kRepHeaderSize) / sizeof(old_rep->elements[0])) << "Requested size is too large to fit into size_t."; + size_t bytes = kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size; if (arena == NULL) { - rep_ = reinterpret_cast<Rep*>( - new char[kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size]); + rep_ = reinterpret_cast<Rep*>(::operator new(bytes)); } else { rep_ = reinterpret_cast<Rep*>( - ::google::protobuf::Arena::CreateArray<char>(arena, - kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size)); + ::google::protobuf::Arena::CreateArray<char>(arena, bytes)); } +#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) + const int old_total_size = total_size_; +#endif total_size_ = new_size; if (old_rep && old_rep->allocated_size > 0) { memcpy(rep_->elements, old_rep->elements, @@ -75,7 +77,13 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { rep_->allocated_size = 0; } if (arena == NULL) { - delete [] reinterpret_cast<char*>(old_rep); +#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) + const size_t old_size = + old_total_size * sizeof(rep_->elements[0]) + kRepHeaderSize; + ::operator delete(static_cast<void*>(old_rep), old_size); +#else + ::operator delete(static_cast<void*>(old_rep)); +#endif } return &rep_->elements[current_size_]; } @@ -95,6 +103,22 @@ void RepeatedPtrFieldBase::CloseGap(int start, int num) { rep_->allocated_size -= num; } +google::protobuf::MessageLite* RepeatedPtrFieldBase::AddWeak( + const google::protobuf::MessageLite* prototype) { + if (rep_ != NULL && current_size_ < rep_->allocated_size) { + return reinterpret_cast<google::protobuf::MessageLite*>( + rep_->elements[current_size_++]); + } + if (!rep_ || rep_->allocated_size == total_size_) { + Reserve(total_size_ + 1); + } + ++rep_->allocated_size; + google::protobuf::MessageLite* result = prototype ? prototype->New(arena_) : + Arena::CreateMessage<ImplicitWeakMessage>(arena_); + rep_->elements[current_size_++] = result; + return result; +} + } // namespace internal |