From 21031ad28a73f0633e720997d310440c5bc31ec5 Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Wed, 6 May 2015 17:29:29 -0700 Subject: Support arrays in nonstd::unique_ptr<>. This mimics the std:: behaviour. R=thestig@chromium.org Review URL: https://codereview.chromium.org/1130053003 --- core/include/fxcrt/fx_basic.h | 26 ------- core/src/fpdfdoc/doc_bookmark.cpp | 6 +- third_party/base/nonstd_unique_ptr.h | 128 +++++++++++++++++++++++++---------- 3 files changed, 95 insertions(+), 65 deletions(-) diff --git a/core/include/fxcrt/fx_basic.h b/core/include/fxcrt/fx_basic.h index 275653ef9e..bd53d9e7a4 100644 --- a/core/include/fxcrt/fx_basic.h +++ b/core/include/fxcrt/fx_basic.h @@ -773,32 +773,6 @@ private: DataType m_Data[FixedSize]; DataType* m_pData; }; -template -class CFX_TempBuf -{ -public: - CFX_TempBuf(int size) - { - m_pData = FX_Alloc(DataType, size); - } - ~CFX_TempBuf() - { - if (m_pData) { - FX_Free(m_pData); - } - } - DataType& operator[](int i) - { - FXSYS_assert(m_pData != NULL); - return m_pData[i]; - } - operator DataType*() - { - return m_pData; - } -private: - DataType* m_pData; -}; class CFX_MapPtrToPtr { protected: diff --git a/core/src/fpdfdoc/doc_bookmark.cpp b/core/src/fpdfdoc/doc_bookmark.cpp index 6ba98e655d..10ef07e93e 100644 --- a/core/src/fpdfdoc/doc_bookmark.cpp +++ b/core/src/fpdfdoc/doc_bookmark.cpp @@ -63,14 +63,12 @@ CFX_WideString CPDF_Bookmark::GetTitle() const if (!len) { return CFX_WideString(); } - nonstd::unique_ptr > vec; - vec.reset(new std::vector(len)); - FX_WCHAR* buf = &vec->front(); + nonstd::unique_ptr buf(new FX_WCHAR[len]); for (int i = 0; i < len; i++) { FX_WCHAR w = title[i]; buf[i] = w > 0x20 ? w : 0x20; } - return CFX_WideString(buf, len); + return CFX_WideString(buf.get(), len); } CPDF_Dest CPDF_Bookmark::GetDest(CPDF_Document* pDocument) const { diff --git a/third_party/base/nonstd_unique_ptr.h b/third_party/base/nonstd_unique_ptr.h index 9c0b13c1bf..c24bfff74c 100644 --- a/third_party/base/nonstd_unique_ptr.h +++ b/third_party/base/nonstd_unique_ptr.h @@ -35,6 +35,13 @@ // a pointer within a scope, and automatically destroying the pointer at the // end of a scope. // +// A unique_ptr is like a T*, except that the destructor of unique_ptr +// automatically deletes the pointer it holds (if any). +// That is, unique_ptr owns the T object that it points to. +// Like a T*, a unique_ptr may hold either NULL or a pointer to a T object. +// Also like T*, unique_ptr is thread-compatible, and once you +// dereference it, you get the thread safety guarantees of T. +// // Example usage (unique_ptr): // { // unique_ptr foo(new Foo("wee")); @@ -53,6 +60,8 @@ // foo.reset(); // Foo("wee4") destroyed, foo no longer // // manages a pointer. // } // foo wasn't managing a pointer, so nothing was destroyed. +// +// The size of a unique_ptr is small: sizeof(unique_ptr) == sizeof(C*) #ifndef NONSTD_UNIQUE_PTR_H_ #define NONSTD_UNIQUE_PTR_H_ @@ -66,45 +75,17 @@ namespace nonstd { -// A unique_ptr is like a T*, except that the destructor of unique_ptr -// automatically deletes the pointer it holds (if any). -// That is, unique_ptr owns the T object that it points to. -// Like a T*, a unique_ptr may hold either NULL or a pointer to a T object. -// Also like T*, unique_ptr is thread-compatible, and once you -// dereference it, you get the threadsafety guarantees of T. -// -// The size of a unique_ptr is small: -// sizeof(unique_ptr) == sizeof(C*) +// Common implementation for both pointers to elements and pointers to +// arrays. These are differentiated below based on the need to invoke +// delete vs. delete[] as appropriate. template -class unique_ptr { +class unique_ptr_base { public: // The element type typedef C element_type; - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized unique_ptr. - // The input parameter must be allocated with new. - explicit unique_ptr(C* p = NULL) : ptr_(p) { } - - // Destructor. If there is a C object, delete it. - // We don't need to test ptr_ == NULL because C++ does that for us. - ~unique_ptr() { - enum { type_must_be_complete = sizeof(C) }; - delete ptr_; - } - - // Reset. Deletes the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (p != ptr_) { - enum { type_must_be_complete = sizeof(C) }; - C* old_ptr = ptr_; - ptr_ = p; - delete old_ptr; - } - } + explicit unique_ptr_base(C* p) : ptr_(p) { } // Accessors to get the owned object. // operator* and operator-> will assert() if there is no current object. @@ -125,7 +106,7 @@ class unique_ptr { bool operator!=(C* p) const { return ptr_ != p; } // Swap two scoped pointers. - void swap(unique_ptr& p2) { + void swap(unique_ptr_base& p2) { C* tmp = ptr_; ptr_ = p2.ptr_; p2.ptr_ = tmp; @@ -145,9 +126,86 @@ class unique_ptr { // Allow promotion to bool for conditional statements. operator bool() const { return ptr_ != NULL; } - private: + protected: C* ptr_; +}; + +// Implementation for ordinary pointers using delete. +template +class unique_ptr : public unique_ptr_base { + public: + using unique_ptr_base::ptr_; + + // Constructor. Defaults to initializing with NULL. There is no way + // to create an uninitialized unique_ptr. The input parameter must be + // allocated with new (not new[] - see below). + explicit unique_ptr(C* p = NULL) : unique_ptr_base(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~unique_ptr() { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != ptr_) { + enum { type_must_be_complete = sizeof(C) }; + C* old_ptr = ptr_; + ptr_ = p; + delete old_ptr; + } + } + +private: + // Forbid comparison of unique_ptr types. If C2 != C, it totally doesn't + // make sense, and if C2 == C, it still doesn't make sense because you should + // never have the same object owned by two different unique_ptrs. + template bool operator==(unique_ptr const& p2) const; + template bool operator!=(unique_ptr const& p2) const; + + // Disallow evil constructors + unique_ptr(const unique_ptr&); + void operator=(const unique_ptr&); +}; + +// Specialization for arrays using delete[]. +template +class unique_ptr : public unique_ptr_base { + public: + using unique_ptr_base::ptr_; + + // Constructor. Defaults to initializing with NULL. There is no way + // to create an uninitialized unique_ptr. The input parameter must be + // allocated with new[] (not new - see above). + explicit unique_ptr(C* p = NULL) : unique_ptr_base(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~unique_ptr() { + enum { type_must_be_complete = sizeof(C) }; + delete[] ptr_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != ptr_) { + enum { type_must_be_complete = sizeof(C) }; + C* old_ptr = ptr_; + ptr_ = p; + delete[] old_ptr; + } + } + + // Support indexing since it is holding array. + C& operator[] (size_t i) { return ptr_[i]; } +private: // Forbid comparison of unique_ptr types. If C2 != C, it totally doesn't // make sense, and if C2 == C, it still doesn't make sense because you should // never have the same object owned by two different unique_ptrs. -- cgit v1.2.3