From 15d76c28a15eae50db19926f04036603cac91aa1 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 10 Mar 2015 06:25:15 +0000 Subject: [PATCH] added Array::upsert(), Array::ensert(). enhanced ScopedPtr --- qse/include/qse/Exception.hpp | 12 ++--- qse/include/qse/ScopedPtr.hpp | 85 ++++++++++++++++++++++++++++------- qse/include/qse/cmn/Array.hpp | 24 ++++++++++ qse/include/qse/cmn/Mmgr.hpp | 20 +++++++++ 4 files changed, 120 insertions(+), 21 deletions(-) diff --git a/qse/include/qse/Exception.hpp b/qse/include/qse/Exception.hpp index a8dc9e2c..7a7ed57e 100644 --- a/qse/include/qse/Exception.hpp +++ b/qse/include/qse/Exception.hpp @@ -35,12 +35,12 @@ QSE_BEGIN_NAMESPACE(QSE) ///////////////////////////////// -class Exception +class QSE_EXPORT Exception { public: Exception ( const qse_char_t* name, const qse_char_t* msg, - const qse_char_t* file, int line): + const qse_char_t* file, qse_size_t line): name(name), msg(msg) #if !defined(QSE_NO_LOCATION_IN_EXCEPTION) , file(file), line(line) @@ -52,21 +52,21 @@ public: const qse_char_t* msg; #if !defined(QSE_NO_LOCATION_IN_EXCEPTION) const qse_char_t* file; - int line; + qse_size_t line; #endif }; #define QSE_THROW(ex_name) \ - throw ex_name(QSE_Q(ex_name),QSE_Q(ex_name), QSE_T(__FILE__), __LINE__) + throw ex_name(QSE_Q(ex_name),QSE_Q(ex_name), QSE_T(__FILE__), (qse_size_t)__LINE__) #define QSE_THROW_WITH_MSG(ex_name,msg) \ - throw ex_name(QSE_Q(ex_name),msg, QSE_T(__FILE__), __LINE__) + throw ex_name(QSE_Q(ex_name),msg, QSE_T(__FILE__), (qse_size_t)__LINE__) #define QSE_EXCEPTION(ex_name) \ class ex_name: public QSE::Exception \ { \ public: \ ex_name (const qse_char_t* name, const qse_char_t* msg, \ - const qse_char_t* file, int line): \ + const qse_char_t* file, qse_size_t line): \ QSE::Exception (name, msg, file, line) {} \ } diff --git a/qse/include/qse/ScopedPtr.hpp b/qse/include/qse/ScopedPtr.hpp index 8c574a92..ec2c4fd4 100644 --- a/qse/include/qse/ScopedPtr.hpp +++ b/qse/include/qse/ScopedPtr.hpp @@ -33,31 +33,83 @@ QSE_BEGIN_NAMESPACE(QSE) ///////////////////////////////// -class ScopedPtrType +template +struct ScopedPtrDeleter { -public: - enum Value + void operator() (T* ptr, void* arg) { - SINGLETON = 0, - ARRAY = 1 - }; + delete ptr; + } }; -template +template +struct ScopedPtrArrayDeleter +{ + void operator() (T* ptr, void* arg) + { + delete[] ptr; + } +}; + +/// The ScopedPtr class is a template class that destroys the object the +/// pointer points to when its destructor is called. You can use this class +/// to free a certain resource associated to the pointer when it goes out +/// of the current scope. +/// +/// \code +/// #include +/// #include +/// #include +/// +/// +/// class X +/// { +/// public: +/// X() { printf ("X constructured\n"); } +/// ~X() { printf ("X destructed\n"); } +/// }; +/// +/// struct destroy_x_in_mmgr +/// { +/// void operator() (X* x, void* arg) +/// { +/// x->~X(); +/// ::operator delete (x, (QSE::Mmgr*)arg); +/// } +/// }; +/// +/// int main () +/// { +/// QSE::HeapMmgr heap_mmgr (QSE::Mmgr::getDFL(), 30000); +/// +/// { +/// QSE::ScopedPtr x1 (new X); +/// QSE::ScopedPtr > x3 (new X[10]); +/// QSE::ScopedPtr x2 (new(&heap_mmgr) X, &heap_mmgr); +/// } +/// +/// return 0; +/// } +/// \endcode +/// + +template > class QSE_EXPORT ScopedPtr: public Uncopyable { public: - ScopedPtr (T* p = (T*)QSE_NULL) + typedef ScopedPtrDeleter DefaultDeleter; + + ScopedPtr (T* ptr = (T*)QSE_NULL, void* darg = (void*)QSE_NULL) { - this->_ptr = p; + this->_ptr = ptr; + this->_darg = darg; } ~ScopedPtr () { if (this->_ptr) { - if (type == ScopedPtrType::SINGLETON) delete this->_ptr; - else delete[] this->_ptr; + this->deleter (this->_ptr, this->_darg); } } @@ -110,22 +162,25 @@ public: { T* t = this->_ptr; this->_ptr = (T*)QSE_NULL; + this->_darg = QSE_NULL; return t; } - void reset (T* p = (T*)QSE_NULL) + void reset (T* ptr = (T*)QSE_NULL, void* darg = (T*)QSE_NULL) { if (this->_ptr) { - if (type == ScopedPtrType::SINGLETON) delete this->_ptr; - else delete[] this->_ptr; + this->deleter (this->_ptr, this->_darg); } - this->_ptr = p; + this->_ptr = ptr; + this->_darg = darg; } protected: T* _ptr; + void* _darg; + DELETER deleter; }; ///////////////////////////////// diff --git a/qse/include/qse/cmn/Array.hpp b/qse/include/qse/cmn/Array.hpp index 90f1d825..2db824b0 100644 --- a/qse/include/qse/cmn/Array.hpp +++ b/qse/include/qse/cmn/Array.hpp @@ -284,6 +284,12 @@ public: qse_size_t insert (qse_size_t index, const T& value) { + // Unlike insert() in RedBlackTree and HashList, + // it inserts an item when index exists in the existing array. + // It is because array allows duplicate items. + // RedBlckTree::insert() and HashList::insert() return failure + // if existing item exists. + if (index >= this->capacity) { // the position to add the element is beyond the @@ -339,6 +345,22 @@ public: return index; } + qse_size_t upsert (qse_size_t index, const T& value) + { + if (index < this->count) + return this->update (index, value); + else + return this->insert (index, value); + } + + qse_size_t ensert (qse_size_t index, const T& value) + { + if (index < this->count) + return index; // no update + else + return this->insert (index, value); + } + void remove (qse_size_t index) { this->remove (index, index); @@ -409,7 +431,9 @@ public: if (purge_buffer && this->buffer) { + QSE_ASSERT (this->count <= 0); QSE_ASSERT (this->capacity > 0); + ::operator delete (this->buffer, this->getMmgr()); this->capacity = 0; this->buffer = QSE_NULL; diff --git a/qse/include/qse/cmn/Mmgr.hpp b/qse/include/qse/cmn/Mmgr.hpp index dab33d23..7950c236 100644 --- a/qse/include/qse/cmn/Mmgr.hpp +++ b/qse/include/qse/cmn/Mmgr.hpp @@ -193,4 +193,24 @@ void* operator new[] (qse_size_t size, QSE::Mmgr* mmgr); void operator delete[] (void* ptr, QSE::Mmgr* mmgr); #endif + +///////////////////////////////// +QSE_BEGIN_NAMESPACE(QSE) +///////////////////////////////// + +// Customized deleter for ScopedPtr +template +struct ScopedPtrMmgrDeleter +{ + void operator() (T* ptr, void* arg) + { + ptr->~T (); + ::operator delete (ptr, (QSE::Mmgr*)arg); + } +}; + +///////////////////////////////// +QSE_END_NAMESPACE(QSE) +///////////////////////////////// + #endif