added Array::upsert(), Array::ensert().
enhanced ScopedPtr
This commit is contained in:
		| @ -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) {} \ | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @ -33,31 +33,83 @@ | ||||
| QSE_BEGIN_NAMESPACE(QSE) | ||||
| ///////////////////////////////// | ||||
|  | ||||
| class ScopedPtrType  | ||||
| template <typename T> | ||||
| struct ScopedPtrDeleter | ||||
| { | ||||
| public: | ||||
| 	enum Value  | ||||
| 	void operator() (T* ptr, void* arg) | ||||
| 	{ | ||||
| 		SINGLETON = 0, | ||||
| 		ARRAY     = 1 | ||||
| 	}; | ||||
| 		delete ptr; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| template<class T, ScopedPtrType::Value type = ScopedPtrType::SINGLETON> | ||||
| template <typename T> | ||||
| 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 <stdio.h> | ||||
| /// #include <qse/ScopedPtr.hpp> | ||||
| /// #include <qse/cmn/HeapMmgr.hpp> | ||||
| ///  | ||||
| ///  | ||||
| /// 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<X> x1 (new X); | ||||
| ///         QSE::ScopedPtr<X,QSE::ScopedPtrArrayDeleter<X> > x3 (new X[10]);  | ||||
| ///         QSE::ScopedPtr<X,destroy_x_in_mmgr> x2 (new(&heap_mmgr) X, &heap_mmgr); | ||||
| ///     }    | ||||
| ///  | ||||
| ///     return 0; | ||||
| /// } | ||||
| /// \endcode | ||||
| /// | ||||
|  | ||||
| template<typename T, typename DELETER = ScopedPtrDeleter<T> > | ||||
| class QSE_EXPORT ScopedPtr: public Uncopyable | ||||
| { | ||||
| public: | ||||
| 	ScopedPtr (T* p = (T*)QSE_NULL)  | ||||
| 	typedef ScopedPtrDeleter<T> 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; | ||||
| };  | ||||
|  | ||||
| ///////////////////////////////// | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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 <typename T> | ||||
| struct ScopedPtrMmgrDeleter | ||||
| { | ||||
| 	void operator() (T* ptr, void* arg) | ||||
| 	{ | ||||
| 		ptr->~T (); | ||||
| 		::operator delete (ptr, (QSE::Mmgr*)arg); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| ///////////////////////////////// | ||||
| QSE_END_NAMESPACE(QSE) | ||||
| ///////////////////////////////// | ||||
|  | ||||
| #endif | ||||
|  | ||||
		Reference in New Issue
	
	Block a user