added Array::upsert(), Array::ensert().
enhanced ScopedPtr
This commit is contained in:
		| @ -35,12 +35,12 @@ | |||||||
| QSE_BEGIN_NAMESPACE(QSE) | QSE_BEGIN_NAMESPACE(QSE) | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
|  |  | ||||||
| class Exception | class QSE_EXPORT Exception | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	Exception ( | 	Exception ( | ||||||
| 		const qse_char_t* name, const qse_char_t* msg,  | 		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) | 		name(name), msg(msg) | ||||||
| #if !defined(QSE_NO_LOCATION_IN_EXCEPTION) | #if !defined(QSE_NO_LOCATION_IN_EXCEPTION) | ||||||
| 		, file(file), line(line)  | 		, file(file), line(line)  | ||||||
| @ -52,21 +52,21 @@ public: | |||||||
| 	const qse_char_t* msg; | 	const qse_char_t* msg; | ||||||
| #if !defined(QSE_NO_LOCATION_IN_EXCEPTION) | #if !defined(QSE_NO_LOCATION_IN_EXCEPTION) | ||||||
| 	const qse_char_t* file; | 	const qse_char_t* file; | ||||||
| 	int   line; | 	qse_size_t        line; | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define QSE_THROW(ex_name) \ | #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) \ | #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) \ | #define QSE_EXCEPTION(ex_name) \ | ||||||
| 	class ex_name: public QSE::Exception \ | 	class ex_name: public QSE::Exception \ | ||||||
| 	{ \ | 	{ \ | ||||||
| 	public: \ | 	public: \ | ||||||
| 		ex_name (const qse_char_t* name, const qse_char_t* msg, \ | 		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) {} \ | 			QSE::Exception (name, msg, file, line) {} \ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
| @ -33,31 +33,83 @@ | |||||||
| QSE_BEGIN_NAMESPACE(QSE) | QSE_BEGIN_NAMESPACE(QSE) | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
|  |  | ||||||
| class ScopedPtrType  | template <typename T> | ||||||
|  | struct ScopedPtrDeleter | ||||||
| { | { | ||||||
| public: | 	void operator() (T* ptr, void* arg) | ||||||
| 	enum Value  |  | ||||||
| 	{ | 	{ | ||||||
| 		SINGLETON = 0, | 		delete ptr; | ||||||
| 		ARRAY     = 1 | 	} | ||||||
| 	}; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| 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 | class QSE_EXPORT ScopedPtr: public Uncopyable | ||||||
| { | { | ||||||
| public: | 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 ()  | 	~ScopedPtr ()  | ||||||
| 	{ | 	{ | ||||||
| 		if (this->_ptr)  | 		if (this->_ptr)  | ||||||
| 		{ | 		{ | ||||||
| 			if (type == ScopedPtrType::SINGLETON) delete this->_ptr; | 			this->deleter (this->_ptr, this->_darg); | ||||||
| 			else delete[] this->_ptr; |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -110,22 +162,25 @@ public: | |||||||
| 	{ | 	{ | ||||||
| 		T* t = this->_ptr; | 		T* t = this->_ptr; | ||||||
| 		this->_ptr = (T*)QSE_NULL; | 		this->_ptr = (T*)QSE_NULL; | ||||||
|  | 		this->_darg = QSE_NULL; | ||||||
| 		return t; | 		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 (this->_ptr)  | ||||||
| 		{ | 		{ | ||||||
| 			if (type == ScopedPtrType::SINGLETON) delete this->_ptr; | 			this->deleter (this->_ptr, this->_darg); | ||||||
| 			else delete[] this->_ptr; |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		this->_ptr = p; | 		this->_ptr = ptr; | ||||||
|  | 		this->_darg = darg; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
| 	T* _ptr; | 	T* _ptr; | ||||||
|  | 	void* _darg; | ||||||
|  | 	DELETER deleter; | ||||||
| };  | };  | ||||||
|  |  | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
|  | |||||||
| @ -284,6 +284,12 @@ public: | |||||||
|  |  | ||||||
| 	qse_size_t insert (qse_size_t index, const T& value) | 	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)  | 		if (index >= this->capacity)  | ||||||
| 		{ | 		{ | ||||||
| 			// the position to add the element is beyond the | 			// the position to add the element is beyond the | ||||||
| @ -339,6 +345,22 @@ public: | |||||||
| 		return index; | 		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) | 	void remove (qse_size_t index) | ||||||
| 	{ | 	{ | ||||||
| 		this->remove (index, index); | 		this->remove (index, index); | ||||||
| @ -409,7 +431,9 @@ public: | |||||||
|  |  | ||||||
| 		if (purge_buffer && this->buffer) | 		if (purge_buffer && this->buffer) | ||||||
| 		{ | 		{ | ||||||
|  | 			QSE_ASSERT (this->count <= 0); | ||||||
| 			QSE_ASSERT (this->capacity > 0); | 			QSE_ASSERT (this->capacity > 0); | ||||||
|  |  | ||||||
| 			::operator delete (this->buffer, this->getMmgr()); | 			::operator delete (this->buffer, this->getMmgr()); | ||||||
| 			this->capacity = 0; | 			this->capacity = 0; | ||||||
| 			this->buffer = QSE_NULL; | 			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); | void operator delete[] (void* ptr, QSE::Mmgr* mmgr); | ||||||
| #endif | #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 | #endif | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user