added Mpool and LinkedList
This commit is contained in:
		| @ -71,7 +71,6 @@ protected: | |||||||
| 	mutable qse_size_t ref_count; | 	mutable qse_size_t ref_count; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
| QSE_END_NAMESPACE(QSE) | QSE_END_NAMESPACE(QSE) | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
|  | |||||||
| @ -30,6 +30,9 @@ | |||||||
| #include <qse/types.h> | #include <qse/types.h> | ||||||
| #include <qse/macros.h> | #include <qse/macros.h> | ||||||
|  |  | ||||||
|  | /// \file | ||||||
|  | /// This file defines a class containg aliases to various QSE types. | ||||||
|  |  | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
| QSE_BEGIN_NAMESPACE(QSE) | QSE_BEGIN_NAMESPACE(QSE) | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
|  | |||||||
| @ -27,12 +27,16 @@ | |||||||
| #ifndef _QSE_UNCOPYABLE_HPP_ | #ifndef _QSE_UNCOPYABLE_HPP_ | ||||||
| #define _QSE_UNCOPYABLE_HPP_ | #define _QSE_UNCOPYABLE_HPP_ | ||||||
|  |  | ||||||
| #include <qse/Types.hpp> | #include <qse/types.h> | ||||||
|  | #include <qse/macros.h> | ||||||
|  |  | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
| QSE_BEGIN_NAMESPACE(QSE) | QSE_BEGIN_NAMESPACE(QSE) | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | /// The Uncopyable class disallows an inheriting class to be assigned or | ||||||
|  | /// copied.  | ||||||
|  |  | ||||||
| class QSE_EXPORT Uncopyable  | class QSE_EXPORT Uncopyable  | ||||||
| { | { | ||||||
| public: | public: | ||||||
| @ -48,5 +52,4 @@ private: | |||||||
| QSE_END_NAMESPACE(QSE) | QSE_END_NAMESPACE(QSE) | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ | |||||||
| #include <qse/cmn/Mmged.hpp> | #include <qse/cmn/Mmged.hpp> | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
|  |  | ||||||
| /// @file | /// \file | ||||||
| /// AWK Interpreter | /// AWK Interpreter | ||||||
|  |  | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
| @ -105,24 +105,24 @@ public: | |||||||
|  |  | ||||||
| protected: | protected: | ||||||
| 	/// | 	/// | ||||||
| 	/// @name Error Handling | 	/// \name Error Handling | ||||||
| 	/// | 	/// | ||||||
| 	/// @{ | 	/// \{ | ||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// The getErrorString() function returns a formatting string | 	/// The getErrorString() function returns a formatting string | ||||||
| 	/// for an error code @a num. You can override this function | 	/// for an error code \a num. You can override this function | ||||||
| 	/// to customize an error message. You must include the same numbers | 	/// to customize an error message. You must include the same numbers | ||||||
| 	/// of ${X}'s as the orginal formatting string. Their order may be | 	/// of ${X}'s as the orginal formatting string. Their order may be | ||||||
| 	/// different. The example below changes the formatting string for | 	/// different. The example below changes the formatting string for | ||||||
| 	/// #QSE_AWK_ENOENT. | 	/// #QSE_AWK_ENOENT. | ||||||
| 	/// @code | 	/// \code | ||||||
| 	/// const MyAwk::char_t* MyAwk::getErrorString (errnum_t num) const  | 	/// const MyAwk::char_t* MyAwk::getErrorString (errnum_t num) const  | ||||||
| 	/// { | 	/// { | ||||||
| 	///    if (num == QSE_AWK_ENOENT) return QSE_T("cannot find '${0}'"); | 	///    if (num == QSE_AWK_ENOENT) return QSE_T("cannot find '${0}'"); | ||||||
| 	///    return Awk::getErrorString (num); | 	///    return Awk::getErrorString (num); | ||||||
| 	/// } | 	/// } | ||||||
| 	/// @endcode | 	/// \endcode | ||||||
| 	/// | 	/// | ||||||
| 	virtual const char_t* getErrorString ( | 	virtual const char_t* getErrorString ( | ||||||
| 		errnum_t num | 		errnum_t num | ||||||
| @ -175,7 +175,7 @@ public: | |||||||
| //protected: can't make it protected for borland  | //protected: can't make it protected for borland  | ||||||
| 	void retrieveError (); | 	void retrieveError (); | ||||||
| 	void retrieveError (Run* run); | 	void retrieveError (Run* run); | ||||||
| 	/// @} | 	/// \} | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
| 	class NoSource; | 	class NoSource; | ||||||
| @ -791,14 +791,14 @@ public: | |||||||
|  |  | ||||||
| 		/// | 		/// | ||||||
| 		/// The isIndexed() function determines if a value is arrayed. | 		/// The isIndexed() function determines if a value is arrayed. | ||||||
| 		/// @return true if indexed, false if not. | 		/// \return true if indexed, false if not. | ||||||
| 		/// | 		/// | ||||||
| 		bool isIndexed () const; | 		bool isIndexed () const; | ||||||
|  |  | ||||||
| 		///  | 		///  | ||||||
| 		/// The getIndexed() function gets a value at the given  | 		/// The getIndexed() function gets a value at the given  | ||||||
| 		/// index @a idx and sets it to @a val. | 		/// index \a idx and sets it to \a val. | ||||||
| 		/// @return 0 on success, -1 on failure | 		/// \return 0 on success, -1 on failure | ||||||
| 		/// | 		/// | ||||||
| 		int getIndexed ( | 		int getIndexed ( | ||||||
| 			const Index&  idx, ///< array index | 			const Index&  idx, ///< array index | ||||||
| @ -807,8 +807,8 @@ public: | |||||||
|  |  | ||||||
| 		/// | 		/// | ||||||
| 		/// The getFirstIndex() function stores the first index of | 		/// The getFirstIndex() function stores the first index of | ||||||
| 		/// an arrayed value into @a idx.  | 		/// an arrayed value into \a idx.  | ||||||
| 		/// @return IndexIterator::END if the arrayed value is empty, | 		/// \return IndexIterator::END if the arrayed value is empty, | ||||||
| 		///         iterator that can be passed to getNextIndex() if not | 		///         iterator that can be passed to getNextIndex() if not | ||||||
| 		/// | 		/// | ||||||
| 		IndexIterator getFirstIndex ( | 		IndexIterator getFirstIndex ( | ||||||
| @ -816,10 +816,10 @@ public: | |||||||
| 		) const; | 		) const; | ||||||
|  |  | ||||||
| 		/// | 		/// | ||||||
| 		/// The getNextIndex() function stores into @a idx the next  | 		/// The getNextIndex() function stores into \a idx the next  | ||||||
| 		/// index of an array value from the position indicated by  | 		/// index of an array value from the position indicated by  | ||||||
| 		/// @a iter. | 		/// \a iter. | ||||||
| 		/// @return IndexIterator::END if the arrayed value is empty, | 		/// \return IndexIterator::END if the arrayed value is empty, | ||||||
| 		///         iterator that can be passed to getNextIndex() if not | 		///         iterator that can be passed to getNextIndex() if not | ||||||
| 		/// | 		/// | ||||||
| 		IndexIterator getNextIndex ( | 		IndexIterator getNextIndex ( | ||||||
| @ -882,40 +882,40 @@ public: | |||||||
|  |  | ||||||
| 		///  | 		///  | ||||||
| 		/// The setGlobal() function sets the value of a global  | 		/// The setGlobal() function sets the value of a global  | ||||||
| 		/// variable identified by @a id | 		/// variable identified by \a id | ||||||
| 		/// to @a v. | 		/// to \a v. | ||||||
| 		/// @return 0 on success, -1 on failure | 		/// \return 0 on success, -1 on failure | ||||||
| 		/// | 		/// | ||||||
| 		int setGlobal (int id, int_t v); | 		int setGlobal (int id, int_t v); | ||||||
|  |  | ||||||
| 		///  | 		///  | ||||||
| 		/// The setGlobal() function sets the value of a global  | 		/// The setGlobal() function sets the value of a global  | ||||||
| 		/// variable identified by @a id | 		/// variable identified by \a id | ||||||
| 		/// to @a v. | 		/// to \a v. | ||||||
| 		/// @return 0 on success, -1 on failure | 		/// \return 0 on success, -1 on failure | ||||||
| 		/// | 		/// | ||||||
| 		int setGlobal (int id, flt_t v);  | 		int setGlobal (int id, flt_t v);  | ||||||
|  |  | ||||||
| 		///  | 		///  | ||||||
| 		/// The setGlobal() function sets the value of a global  | 		/// The setGlobal() function sets the value of a global  | ||||||
| 		/// variable identified by @a id | 		/// variable identified by \a id | ||||||
| 		/// to a string as long as @a len characters pointed to by  | 		/// to a string as long as \a len characters pointed to by  | ||||||
| 		/// @a ptr. | 		/// \a ptr. | ||||||
| 		/// @return 0 on success, -1 on failure | 		/// \return 0 on success, -1 on failure | ||||||
| 		/// | 		/// | ||||||
| 		int setGlobal (int id, const char_t* ptr, size_t len); | 		int setGlobal (int id, const char_t* ptr, size_t len); | ||||||
|  |  | ||||||
| 		///  | 		///  | ||||||
| 		/// The setGlobal() function sets a global variable  | 		/// The setGlobal() function sets a global variable  | ||||||
| 		/// identified by @a id to a value @a v. | 		/// identified by \a id to a value \a v. | ||||||
| 		/// @return 0 on success, -1 on failure | 		/// \return 0 on success, -1 on failure | ||||||
| 		///	 | 		///	 | ||||||
| 		int setGlobal (int id, const Value& v); | 		int setGlobal (int id, const Value& v); | ||||||
|  |  | ||||||
| 		/// | 		/// | ||||||
| 		/// The getGlobal() function gets the value of a global  | 		/// The getGlobal() function gets the value of a global  | ||||||
| 		/// variable identified by @a id and stores it in @a v. | 		/// variable identified by \a id and stores it in \a v. | ||||||
| 		/// @return 0 on success, -1 on failure | 		/// \return 0 on success, -1 on failure | ||||||
| 		///	 | 		///	 | ||||||
| 		int getGlobal (int id, Value& v) const; | 		int getGlobal (int id, Value& v) const; | ||||||
|  |  | ||||||
| @ -930,8 +930,8 @@ public: | |||||||
| 	operator awk_t* () const; | 	operator awk_t* () const; | ||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// @name Basic Functions | 	/// \name Basic Functions | ||||||
| 	/// @{ | 	/// \{ | ||||||
| 	/// | 	/// | ||||||
|  |  | ||||||
| 	/// The Awk() function creates an interpreter without fully  | 	/// The Awk() function creates an interpreter without fully  | ||||||
| @ -946,7 +946,7 @@ public: | |||||||
| 	/// | 	/// | ||||||
| 	/// The open() function initializes an interpreter.  | 	/// The open() function initializes an interpreter.  | ||||||
| 	/// You must call this function before doing anything meaningful. | 	/// You must call this function before doing anything meaningful. | ||||||
| 	/// @return 0 on success, -1 on failure | 	/// \return 0 on success, -1 on failure | ||||||
| 	/// | 	/// | ||||||
| 	int open (); | 	int open (); | ||||||
|  |  | ||||||
| @ -957,11 +957,11 @@ public: | |||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// The parse() function parses the source code read from the input | 	/// The parse() function parses the source code read from the input | ||||||
| 	/// stream @a in and writes the parse tree to the output stream @a out. | 	/// stream \a in and writes the parse tree to the output stream \a out. | ||||||
| 	/// To disable deparsing, you may set @a out to Awk::Source::NONE.  | 	/// To disable deparsing, you may set \a out to Awk::Source::NONE.  | ||||||
| 	/// However, it is not allowed to specify Awk::Source::NONE for @a in. | 	/// However, it is not allowed to specify Awk::Source::NONE for \a in. | ||||||
| 	/// | 	/// | ||||||
| 	/// @return Run object on success, #QSE_NULL on failure | 	/// \return Run object on success, #QSE_NULL on failure | ||||||
| 	/// | 	/// | ||||||
| 	Awk::Run* parse ( | 	Awk::Run* parse ( | ||||||
| 		Source& in,  ///< script to parse  | 		Source& in,  ///< script to parse  | ||||||
| @ -1002,15 +1002,15 @@ public: | |||||||
| 	 | 	 | ||||||
| 	/// | 	/// | ||||||
| 	/// The loop() function executes the BEGIN block, pattern-action blocks, | 	/// The loop() function executes the BEGIN block, pattern-action blocks, | ||||||
| 	/// and the END block. The return value is stored into @a ret. | 	/// and the END block. The return value is stored into \a ret. | ||||||
| 	/// @return 0 on succes, -1 on failure | 	/// \return 0 on succes, -1 on failure | ||||||
| 	/// | 	/// | ||||||
| 	int loop ( | 	int loop ( | ||||||
| 		Value* ret  ///< return value holder | 		Value* ret  ///< return value holder | ||||||
| 	); | 	); | ||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// The call() function invokes a function named @a name. | 	/// The call() function invokes a function named \a name. | ||||||
| 	/// | 	/// | ||||||
| 	int call ( | 	int call ( | ||||||
| 		const char_t* name,  ///< function name | 		const char_t* name,  ///< function name | ||||||
| @ -1023,16 +1023,16 @@ public: | |||||||
| 	/// The stop() function makes request to abort execution | 	/// The stop() function makes request to abort execution | ||||||
| 	/// | 	/// | ||||||
| 	void stop (); | 	void stop (); | ||||||
| 	/// @} | 	/// \} | ||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// @name Configuration | 	/// \name Configuration | ||||||
| 	/// @{ | 	/// \{ | ||||||
| 	/// | 	/// | ||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// The getTrait() function gets the current options. | 	/// The getTrait() function gets the current options. | ||||||
| 	/// @return current traits | 	/// \return current traits | ||||||
| 	/// | 	/// | ||||||
| 	int getTrait () const; | 	int getTrait () const; | ||||||
|  |  | ||||||
| @ -1045,7 +1045,7 @@ public: | |||||||
|  |  | ||||||
| 	///  | 	///  | ||||||
| 	/// The setMaxDepth() function sets the maximum processing depth | 	/// The setMaxDepth() function sets the maximum processing depth | ||||||
| 	/// for operations identified by @a ids. | 	/// for operations identified by \a ids. | ||||||
| 	/// | 	/// | ||||||
| 	void setMaxDepth ( | 	void setMaxDepth ( | ||||||
| 		depth_t id,  ///< depth identifier | 		depth_t id,  ///< depth identifier | ||||||
| @ -1054,18 +1054,18 @@ public: | |||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// The getMaxDepth() function gets the maximum depth for an operation | 	/// The getMaxDepth() function gets the maximum depth for an operation | ||||||
| 	/// type identified by @a id. | 	/// type identified by \a id. | ||||||
| 	/// | 	/// | ||||||
| 	size_t getMaxDepth ( | 	size_t getMaxDepth ( | ||||||
| 		depth_t id   ///< depth identifier | 		depth_t id   ///< depth identifier | ||||||
| 	) const; | 	) const; | ||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// The addArgument() function adds an ARGV string as long as @a len  | 	/// The addArgument() function adds an ARGV string as long as \a len  | ||||||
| 	/// characters pointed to  | 	/// characters pointed to  | ||||||
| 	/// by @a arg. loop() and call() make a string added available  | 	/// by \a arg. loop() and call() make a string added available  | ||||||
| 	/// to a script through ARGV.  | 	/// to a script through ARGV.  | ||||||
| 	/// @return 0 on success, -1 on failure | 	/// \return 0 on success, -1 on failure | ||||||
| 	/// | 	/// | ||||||
| 	int addArgument ( | 	int addArgument ( | ||||||
| 		const char_t* arg,  ///< string pointer | 		const char_t* arg,  ///< string pointer | ||||||
| @ -1073,10 +1073,10 @@ public: | |||||||
| 	); | 	); | ||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// The addArgument() function adds a null-terminated string @a arg.  | 	/// The addArgument() function adds a null-terminated string \a arg.  | ||||||
| 	/// loop() and call() make a string added available to a script  | 	/// loop() and call() make a string added available to a script  | ||||||
| 	/// through ARGV.  | 	/// through ARGV.  | ||||||
| 	/// @return 0 on success, -1 on failure | 	/// \return 0 on success, -1 on failure | ||||||
| 	/// | 	/// | ||||||
| 	int addArgument ( | 	int addArgument ( | ||||||
| 		const char_t* arg ///< string pointer | 		const char_t* arg ///< string pointer | ||||||
| @ -1089,7 +1089,7 @@ public: | |||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// The addGlobal() function registers an intrinsic global variable.  | 	/// The addGlobal() function registers an intrinsic global variable.  | ||||||
| 	/// @return integer >= 0 on success, -1 on failure. | 	/// \return integer >= 0 on success, -1 on failure. | ||||||
| 	/// | 	/// | ||||||
| 	int addGlobal ( | 	int addGlobal ( | ||||||
| 		const char_t* name ///< variable name | 		const char_t* name ///< variable name | ||||||
| @ -1098,7 +1098,7 @@ public: | |||||||
| 	/// | 	/// | ||||||
| 	/// The deleteGlobal() function unregisters an intrinsic global  | 	/// The deleteGlobal() function unregisters an intrinsic global  | ||||||
| 	/// variable by name. | 	/// variable by name. | ||||||
| 	/// @return 0 on success, -1 on failure. | 	/// \return 0 on success, -1 on failure. | ||||||
| 	/// | 	/// | ||||||
| 	int deleteGlobal ( | 	int deleteGlobal ( | ||||||
| 		const char_t* name ///< variable name | 		const char_t* name ///< variable name | ||||||
| @ -1107,7 +1107,7 @@ public: | |||||||
| 	/// | 	/// | ||||||
| 	/// The addGlobal() function returns the numeric ID of an intrinsic  | 	/// The addGlobal() function returns the numeric ID of an intrinsic  | ||||||
| 	//  global variable.  | 	//  global variable.  | ||||||
| 	/// @return integer >= 0 on success, -1 on failure. | 	/// \return integer >= 0 on success, -1 on failure. | ||||||
| 	/// | 	/// | ||||||
| 	int findGlobal ( | 	int findGlobal ( | ||||||
| 		const char_t* name ///> variable name | 		const char_t* name ///> variable name | ||||||
| @ -1115,10 +1115,10 @@ public: | |||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// The setGlobal() function sets the value of a global variable  | 	/// The setGlobal() function sets the value of a global variable  | ||||||
| 	/// identified by @a id. The @a id is either a value returned by  | 	/// identified by \a id. The \a id is either a value returned by  | ||||||
| 	/// addGlobal() or one of the #gbl_id_t enumerators. It is not allowed | 	/// addGlobal() or one of the #gbl_id_t enumerators. It is not allowed | ||||||
| 	/// to call this function prior to parse(). | 	/// to call this function prior to parse(). | ||||||
| 	/// @return 0 on success, -1 on failure | 	/// \return 0 on success, -1 on failure | ||||||
| 	/// | 	/// | ||||||
| 	int setGlobal ( | 	int setGlobal ( | ||||||
| 		int          id,  ///< numeric identifier | 		int          id,  ///< numeric identifier | ||||||
| @ -1127,10 +1127,10 @@ public: | |||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// The getGlobal() function gets the value of a global variable  | 	/// The getGlobal() function gets the value of a global variable  | ||||||
| 	/// identified by @a id. The @a id is either a value returned by  | 	/// identified by \a id. The \a id is either a value returned by  | ||||||
| 	/// addGlobal() or one of the #gbl_id_t enumerators. It is not allowed | 	/// addGlobal() or one of the #gbl_id_t enumerators. It is not allowed | ||||||
| 	/// to call this function before parse(). | 	/// to call this function before parse(). | ||||||
| 	/// @return 0 on success, -1 on failure | 	/// \return 0 on success, -1 on failure | ||||||
| 	/// | 	/// | ||||||
| 	int getGlobal ( | 	int getGlobal ( | ||||||
| 		int    id, ///< numeric identifier  | 		int    id, ///< numeric identifier  | ||||||
| @ -1168,7 +1168,7 @@ public: | |||||||
| 	int deleteFunction ( | 	int deleteFunction ( | ||||||
| 		const char_t* name ///< function name | 		const char_t* name ///< function name | ||||||
| 	); | 	); | ||||||
| 	/// @} | 	/// \} | ||||||
|  |  | ||||||
| 	Pipe::Handler* getPipeHandler () | 	Pipe::Handler* getPipeHandler () | ||||||
| 	{ | 	{ | ||||||
| @ -1238,10 +1238,10 @@ public: | |||||||
|  |  | ||||||
| protected: | protected: | ||||||
| 	///  | 	///  | ||||||
| 	/// @name Pipe I/O handlers | 	/// \name Pipe I/O handlers | ||||||
| 	/// Pipe operations are achieved through the following functions | 	/// Pipe operations are achieved through the following functions | ||||||
| 	/// if no external pipe handler is set with setPipeHandler(). | 	/// if no external pipe handler is set with setPipeHandler(). | ||||||
| 	/// @{ | 	/// \{ | ||||||
|  |  | ||||||
| 	/// The openPipe() function is a pure virtual function that must be | 	/// The openPipe() function is a pure virtual function that must be | ||||||
| 	/// overridden by a child class to open a pipe. It must return 1 | 	/// overridden by a child class to open a pipe. It must return 1 | ||||||
| @ -1256,26 +1256,26 @@ protected: | |||||||
| 	virtual ssize_t readPipe  (Pipe& io, char_t* buf, size_t len); | 	virtual ssize_t readPipe  (Pipe& io, char_t* buf, size_t len); | ||||||
| 	virtual ssize_t writePipe (Pipe& io, const char_t* buf, size_t len); | 	virtual ssize_t writePipe (Pipe& io, const char_t* buf, size_t len); | ||||||
| 	virtual int     flushPipe (Pipe& io); | 	virtual int     flushPipe (Pipe& io); | ||||||
| 	/// @} | 	/// \} | ||||||
|  |  | ||||||
| 	///  | 	///  | ||||||
| 	/// @name File I/O handlers | 	/// \name File I/O handlers | ||||||
| 	/// File operations are achieved through the following functions | 	/// File operations are achieved through the following functions | ||||||
| 	/// if no external file handler is set with setFileHandler(). | 	/// if no external file handler is set with setFileHandler(). | ||||||
| 	/// @{ | 	/// \{ | ||||||
| 	/// | 	/// | ||||||
| 	virtual int     openFile  (File& io); | 	virtual int     openFile  (File& io); | ||||||
| 	virtual int     closeFile (File& io); | 	virtual int     closeFile (File& io); | ||||||
| 	virtual ssize_t readFile  (File& io, char_t* buf, size_t len); | 	virtual ssize_t readFile  (File& io, char_t* buf, size_t len); | ||||||
| 	virtual ssize_t writeFile (File& io, const char_t* buf, size_t len); | 	virtual ssize_t writeFile (File& io, const char_t* buf, size_t len); | ||||||
| 	virtual int     flushFile (File& io); | 	virtual int     flushFile (File& io); | ||||||
| 	/// @} | 	/// \} | ||||||
|  |  | ||||||
| 	///  | 	///  | ||||||
| 	/// @name Console I/O handlers | 	/// \name Console I/O handlers | ||||||
| 	/// Console operations are achieved through the following functions. | 	/// Console operations are achieved through the following functions. | ||||||
| 	/// if no external console handler is set with setConsoleHandler(). | 	/// if no external console handler is set with setConsoleHandler(). | ||||||
| 	/// @{ | 	/// \{ | ||||||
| 	/// | 	/// | ||||||
| 	virtual int     openConsole  (Console& io); | 	virtual int     openConsole  (Console& io); | ||||||
| 	virtual int     closeConsole (Console& io); | 	virtual int     closeConsole (Console& io); | ||||||
| @ -1283,7 +1283,7 @@ protected: | |||||||
| 	virtual ssize_t writeConsole (Console& io, const char_t* buf, size_t len); | 	virtual ssize_t writeConsole (Console& io, const char_t* buf, size_t len); | ||||||
| 	virtual int     flushConsole (Console& io); | 	virtual int     flushConsole (Console& io); | ||||||
| 	virtual int     nextConsole  (Console& io); | 	virtual int     nextConsole  (Console& io); | ||||||
| 	/// @} | 	/// \} | ||||||
|  |  | ||||||
| 	// primitive handlers  | 	// primitive handlers  | ||||||
| 	virtual flt_t pow (flt_t x, flt_t y) = 0; | 	virtual flt_t pow (flt_t x, flt_t y) = 0; | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ | |||||||
| #include <qse/cmn/StdMmgr.hpp> | #include <qse/cmn/StdMmgr.hpp> | ||||||
| #include <qse/cmn/time.h> | #include <qse/cmn/time.h> | ||||||
|  |  | ||||||
| /// @file | /// \file | ||||||
| /// Standard AWK Interpreter | /// Standard AWK Interpreter | ||||||
|  |  | ||||||
| ///////////////////////////////// | ///////////////////////////////// | ||||||
|  | |||||||
							
								
								
									
										583
									
								
								qse/include/qse/cmn/LinkedList.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										583
									
								
								qse/include/qse/cmn/LinkedList.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,583 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |     Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. | ||||||
|  |  | ||||||
|  |     Redistribution and use in source and binary forms, with or without | ||||||
|  |     modification, are permitted provided that the following conditions | ||||||
|  |     are met: | ||||||
|  |     1. Redistributions of source code must retain the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer. | ||||||
|  |     2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer in the | ||||||
|  |        documentation and/or other materials provided with the distribution. | ||||||
|  |  | ||||||
|  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||||
|  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||||
|  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||||
|  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||||
|  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||||
|  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||||
|  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _QSE_CMN_LINKEDLIST_HPP_ | ||||||
|  | #define _QSE_CMN_LINKEDLIST_HPP_ | ||||||
|  |  | ||||||
|  | #include <qse/Types.hpp> | ||||||
|  | #include <xp/bas/MemoryPool.hpp> | ||||||
|  | #include <xp/bas/MemoryPoolable.hpp> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_BEGIN_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | template <typename T> class LinkedList; | ||||||
|  |  | ||||||
|  | template <typename T>  | ||||||
|  | class LinkedListNode: protected MemoryPoolable | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	friend class LinkedList<T>; | ||||||
|  |  | ||||||
|  | 	T value; | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	LinkedListNode<T>* next; | ||||||
|  | 	LinkedListNode<T>* prev; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  | 	LinkedListNode<T>* getNext () { return this->next; } | ||||||
|  | 	const LinkedListNode<T>* getNext () const { return this->next; } | ||||||
|  |  | ||||||
|  | 	LinkedListNode<T>* getPrev () { return this->prev; } | ||||||
|  | 	const LinkedListNode<T>* getPrev () const { return this->prev; } | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	LinkedListNode () {} | ||||||
|  | 	LinkedListNode (const T& v): value(v) {} | ||||||
|  |  | ||||||
|  | 	void setNext (const LinkedListNode<T>* node) | ||||||
|  | 	{ | ||||||
|  | 		this->next = node; | ||||||
|  | 	} | ||||||
|  | 	void setPrev (const LinkedListNode<T>* node) | ||||||
|  | 	{ | ||||||
|  | 		this->prev = node; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /// | ||||||
|  | /// The LinkedList<T> class provides a template for a doubly-linked list. | ||||||
|  | /// | ||||||
|  | template <typename T> class LinkedList | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	typedef LinkedListNode<T> Node; | ||||||
|  |  | ||||||
|  | 	enum  | ||||||
|  | 	{ | ||||||
|  | 		INVALID_INDEX = ~(qse_size_t)0 | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	~LinkedList ()  | ||||||
|  | 	{ | ||||||
|  | 		this->clearout (); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	LinkedList (qse_size_t mpb_size = 0): mp (QSE_SIZEOF(Node), mpb_size) | ||||||
|  | 	{ | ||||||
|  | 		this->node_count = 0; | ||||||
|  | 		this->head_node = QSE_NULL; | ||||||
|  | 		this->tail_node = QSE_NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	LinkedList (const LinkedList<T>& ll): mp (ll.mp.datumSize(), ll.mp.blockSize()) | ||||||
|  | 	{ | ||||||
|  | 		this->node_count = 0; | ||||||
|  | 		this->head_node = QSE_NULL; | ||||||
|  | 		this->tail_node = QSE_NULL; | ||||||
|  | 		for (Node* p = ll.head_node; p != QSE_NULL; p = p->next)  | ||||||
|  | 			this->append (p->value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	LinkedList<T>& operator= (const LinkedList<T>& ll)  | ||||||
|  | 	{ | ||||||
|  | 		this->clear (); | ||||||
|  | 		for (Node* p = ll.head_node; p != QSE_NULL; p = p->next) | ||||||
|  | 			this->append (p->value); | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	T& operator[] (qse_size_t index) | ||||||
|  | 	{ | ||||||
|  | 		// same as getValueAt() | ||||||
|  | 		QSE_ASSERT (index < this->node_count); | ||||||
|  | 		Node* np = this->getNodeAt (index); | ||||||
|  | 		return np->value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const T& operator[] (qse_size_t index) const | ||||||
|  | 	{ | ||||||
|  | 		// same as getValueAt() | ||||||
|  | 		QSE_ASSERT (index < this->node_count); | ||||||
|  | 		Node* np = this->getNodeAt (index); | ||||||
|  | 		return np->value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_size_t getMPBlockSize() const | ||||||
|  | 	{ | ||||||
|  | 		return this->mp.blockSize(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bool isMPEnabled () const | ||||||
|  | 	{ | ||||||
|  | 		return this->mp.isEnabled(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_size_t getSize () const  | ||||||
|  | 	{ | ||||||
|  | 		return this->node_count; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bool isEmpty () const  | ||||||
|  | 	{ | ||||||
|  | 		return this->node_count == 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bool contains (const T& value) const | ||||||
|  | 	{ | ||||||
|  | 		return this->findFirstNode(value) != QSE_NULL;     | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// insert an externally created node. | ||||||
|  | 	// may need to take extra care when using this method. | ||||||
|  | 	Node* insertNode (Node* pos, Node* node); | ||||||
|  |  | ||||||
|  | 	// create a new node to hold the value and insert it. | ||||||
|  | 	Node* insertValue (Node* pos, const T& value) | ||||||
|  | 	{ | ||||||
|  | 		Node* n = this->mp.isEnabled()?  | ||||||
|  | 			(new(&mp) Node(value)): (new Node(value)); | ||||||
|  | 		return this->insertNode (pos, n); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	T& insert (Node* node, const T& value) | ||||||
|  | 	{ | ||||||
|  | 		return this->insertValue(node, value)->value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	T& insert (qse_size_t index, const T& value) | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (index <= node_count); | ||||||
|  |  | ||||||
|  | 		if (index >= node_count)  | ||||||
|  | 		{ | ||||||
|  | 			// insert it at the back | ||||||
|  | 			return this->insert ((Node*)QSE_NULL, value); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return this->insert (this->getNodeAt(index), value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	T& prepend (const T& value) | ||||||
|  | 	{ | ||||||
|  | 		return this->insert (this->head_node, value); | ||||||
|  | 	} | ||||||
|  | 	T& append (const T& value) | ||||||
|  | 	{ | ||||||
|  | 		return this->insert ((Node*)QSE_NULL, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* prependNode (Node* node) | ||||||
|  | 	{ | ||||||
|  | 		return this->insertNode (head_node, node); | ||||||
|  | 	} | ||||||
|  | 	Node* appendNode (Node* node) | ||||||
|  | 	{ | ||||||
|  | 		return this->insertNode ((Node*)QSE_NULL, node); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* prependValue (const T& value) | ||||||
|  | 	{ | ||||||
|  | 		return this->insertValue (this->head_node, value); | ||||||
|  | 	} | ||||||
|  | 	Node* appendValue (const T& value) | ||||||
|  | 	{ | ||||||
|  | 		return this->insertValue ((Node*)QSE_NULL, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void prependAll (const LinkedList<T>& list) | ||||||
|  | 	{ | ||||||
|  | 		Node* n = list.tail_node; | ||||||
|  |  | ||||||
|  | 		if (&list == this)  | ||||||
|  | 		{ | ||||||
|  | 			Node* head = list.head_node; | ||||||
|  | 			while (n)  | ||||||
|  | 			{ | ||||||
|  | 				this->prepend (n->value); | ||||||
|  | 				if (n == head) break; | ||||||
|  | 				n = (Node*)n->prev; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			while (n)  | ||||||
|  | 			{ | ||||||
|  | 				this->prepend (n->value); | ||||||
|  | 				n = (Node*)n->prev; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void appendAll (const LinkedList<T>& list)  | ||||||
|  | 	{ | ||||||
|  | 		Node* n = list.head_node; | ||||||
|  |  | ||||||
|  | 		if (&list == this)   | ||||||
|  | 		{ | ||||||
|  | 			Node* tail = list.tail_node; | ||||||
|  | 			while (n)  | ||||||
|  | 			{ | ||||||
|  | 				this->append (n->value); | ||||||
|  | 				if (n == tail) break; | ||||||
|  | 				n = n->next; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			while (n)  | ||||||
|  | 			{ | ||||||
|  | 				this->append (n->value); | ||||||
|  | 				n = n->next; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// remove a node from the list without freeing it. | ||||||
|  | 	// take extra care when using this method as the node  | ||||||
|  | 	// can be freed through the memory pool when the list is  | ||||||
|  | 	// destructed if the memory pool is enabled. | ||||||
|  | 	Node* yield (Node* node, bool clear_links = true); | ||||||
|  |  | ||||||
|  | 	// remove a node from the list and free it. | ||||||
|  | 	void remove (Node* node) | ||||||
|  | 	{ | ||||||
|  | 		this->yield (node, false); | ||||||
|  | 		if (mp.isDisabled()) delete node; | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			node->~Node (); | ||||||
|  | 		#if defined(_MSC_VER) | ||||||
|  | 			node->operator delete (node, &mp); | ||||||
|  | 		#else | ||||||
|  | 			node->dispose (node, &mp); | ||||||
|  | 		#endif | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void remove (qse_size_t index)  | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (index < node_count); | ||||||
|  |  | ||||||
|  | 		Node* np = this->head_node;  | ||||||
|  | 		while (index > 0)  | ||||||
|  | 		{ | ||||||
|  | 			np = np->next; | ||||||
|  | 			index--; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		this->remove (np); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* yieldByValue (const T& value, bool clear_links = true) | ||||||
|  | 	{ | ||||||
|  | 		Node* p = this->findFirstNode (value); | ||||||
|  | 		Node* p = this->findFirstNode (value); | ||||||
|  | 		if (p == QSE_NULL) return -1; | ||||||
|  | 		return this->yield (p, clear_links); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_size_t removeByValue (const T& value) | ||||||
|  | 	{ | ||||||
|  | 		Node* p = this->findFirstNode (value); | ||||||
|  | 		if (!p) return 0; | ||||||
|  | 		this->remove (p); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/// \return the number of items deleted | ||||||
|  | 	qse_size_t removeAllByValue (const T& value) | ||||||
|  | 	{ | ||||||
|  | 		Node* p = this->findFirstNode (value); | ||||||
|  | 		if (!p) return 0; | ||||||
|  |  | ||||||
|  | 		qse_size_t cnt = 0; | ||||||
|  | 		do  | ||||||
|  | 		{ | ||||||
|  | 			Node* tmp = p->next; | ||||||
|  | 			this->remove (p); | ||||||
|  | 			cnt++; | ||||||
|  | 			p = this->findFirstNode (value, tmp); | ||||||
|  | 		}  | ||||||
|  | 		while (p); | ||||||
|  |  | ||||||
|  | 		return cnt; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void removeHead () | ||||||
|  | 	{ | ||||||
|  | 		this->remove (this->head_node); | ||||||
|  | 	} | ||||||
|  | 	void removeTail () | ||||||
|  | 	{ | ||||||
|  | 		this->remove (this->tail_node); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* getHeadNode () const  | ||||||
|  | 	{ | ||||||
|  | 		return this->head_node; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* getTailNode () const  | ||||||
|  | 	{ | ||||||
|  | 		return this->tail_node; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* getNodeAt (qse_size_t index) const | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (index < this->node_count); | ||||||
|  |  | ||||||
|  | 		register Node* np; | ||||||
|  | 		register qse_size_t cnt; | ||||||
|  |  | ||||||
|  | 		if (index < (this->node_count >> 1))  | ||||||
|  | 		{ | ||||||
|  | 			for (np = this->head_node, cnt = 0; cnt < index; np = np->next, cnt++)  | ||||||
|  | 			{ | ||||||
|  | 				QSE_ASSERT (np != QSE_NULL); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			for (np = this->tail_node, cnt = this->node_count - 1;  cnt > index; np = np->prev, cnt--)  | ||||||
|  | 			{ | ||||||
|  | 				QSE_ASSERT (np != QSE_NULL); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return np; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	T& getValueAt (qse_size_t index)  | ||||||
|  | 	{ | ||||||
|  | 		// same as operator[] | ||||||
|  | 		QSE_ASSERT (index < this->node_count); | ||||||
|  | 		Node* np = this->getNodeAt (index); | ||||||
|  | 		return np->value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const T& getValueAt (qse_size_t index) const | ||||||
|  | 	{ | ||||||
|  | 		// same as operator[] | ||||||
|  | 		QSE_ASSERT (index < this->node_count); | ||||||
|  | 		Node* np = this->getNodeAt (index); | ||||||
|  | 		return np->value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void setValueAt (qse_size_t index, const T& value) | ||||||
|  | 	{ | ||||||
|  | 		QSE_ASSERT (index < this->node_count); | ||||||
|  | 		Node* np = this->getNodeAt (index); | ||||||
|  | 		np->value = value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* findFirstNode (const T& value) const | ||||||
|  | 	{ | ||||||
|  | 		for (Node* p = this->head_node; p; p = p->next)  | ||||||
|  | 		{ | ||||||
|  | 			if (value == p->value) return p; | ||||||
|  | 		} | ||||||
|  | 		return QSE_NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* findLastNode (const T& value) const | ||||||
|  | 	{ | ||||||
|  | 		for (Node* p = tail_node; p; p = p->prev)  | ||||||
|  | 		{ | ||||||
|  | 			if (value == p->value) return p; | ||||||
|  | 		} | ||||||
|  | 		return QSE_NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* findFirstNode (const T& value, Node* head) const | ||||||
|  | 	{ | ||||||
|  | 		for (Node* p = head; p; p = p->next) | ||||||
|  | 		{ | ||||||
|  | 			if (value == p->value) return p; | ||||||
|  | 		} | ||||||
|  | 		return QSE_NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Node* findLastNode (const T& value, Node* tail) const | ||||||
|  | 	{ | ||||||
|  | 		for (Node* p = tail; p; p = p->prev)  | ||||||
|  | 		{ | ||||||
|  | 			if (value == p->value) return p; | ||||||
|  | 		} | ||||||
|  | 		return QSE_NULL; | ||||||
|  | 	}	 | ||||||
|  |  | ||||||
|  | 	qse_size_t findFirstIndex (const T& value) const | ||||||
|  | 	{ | ||||||
|  | 		qse_size_t index = 0; | ||||||
|  | 		for (Node* p = this->head_node; p; p = p->next)  | ||||||
|  | 		{ | ||||||
|  | 			if (value == p->value) return index; | ||||||
|  | 			index++; | ||||||
|  | 		} | ||||||
|  | 		return INVALID_INDEX; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	qse_size_t findLastIndex (const T& value) const | ||||||
|  | 	{ | ||||||
|  | 		qse_size_t index = node_count; | ||||||
|  | 		for (Node* p = tail_node; p; p = p->prev)  | ||||||
|  | 		{ | ||||||
|  | 			index--; | ||||||
|  | 			if (value == p->value) return index; | ||||||
|  | 		} | ||||||
|  | 		return INVALID_INDEX; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void clear ()  | ||||||
|  | 	{ | ||||||
|  | 		Node* p, * saved; | ||||||
|  |  | ||||||
|  | 		p = this->head_node; | ||||||
|  | 		while (p)  | ||||||
|  | 		{ | ||||||
|  | 			saved = p->next; | ||||||
|  | 			 | ||||||
|  | 			if (this->mp.isDisabled()) delete p; | ||||||
|  | 			else  | ||||||
|  | 			{ | ||||||
|  | 				p->~Node (); | ||||||
|  | 			#if defined(_MSC_VER) | ||||||
|  | 				p->operator delete (p, &mp); | ||||||
|  | 			#else | ||||||
|  | 				p->dispose (p, &mp); | ||||||
|  | 			#endif | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			this->node_count--; | ||||||
|  | 			p = saved; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		this->head_node = this->tail_node = QSE_NULL; | ||||||
|  | 		QSE_ASSERT (this->node_count == 0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void clearout () | ||||||
|  | 	{ | ||||||
|  | 		this->clear (); | ||||||
|  | 		this->mp.dispose (); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	typedef int (LinkedList<T>::*TraverseCallback) (Node* start, Node* cur); | ||||||
|  |  | ||||||
|  | 	void traverse (TraverseCallback callback, Node* start) | ||||||
|  | 	{ | ||||||
|  | 		Node* cur, * prev, * next; | ||||||
|  |  | ||||||
|  | 		cur = start; | ||||||
|  | 		while (cur) | ||||||
|  | 		{ | ||||||
|  | 			prev = cur->prev; | ||||||
|  | 			next = cur->next; | ||||||
|  |  | ||||||
|  | 			int n = (this->*callback) (start, cur); | ||||||
|  |  | ||||||
|  | 			if (n > 0) cur = next; | ||||||
|  | 			else if (n < 0) cur = prev; | ||||||
|  | 			else break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	MemoryPool  mp; | ||||||
|  | 	Node*       head_node; | ||||||
|  | 	Node*       tail_node; | ||||||
|  | 	qse_size_t  node_count; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename T>  | ||||||
|  | inline typename LinkedList<T>::Node* LinkedList<T>::insertNode (Node* pos, Node* node) | ||||||
|  | { | ||||||
|  | 	if (pos == QSE_NULL)  | ||||||
|  | 	{ | ||||||
|  | 		if (this->node_count == 0)  | ||||||
|  | 		{ | ||||||
|  | 			QSE_ASSERT (head_node == QSE_NULL); | ||||||
|  | 			QSE_ASSERT (tail_node == QSE_NULL); | ||||||
|  | 			this->head_node = this->tail_node = node; | ||||||
|  | 		} | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			node->prev = this->tail_node; | ||||||
|  | 			this->tail_node->next = node; | ||||||
|  | 			this->tail_node = node; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else  | ||||||
|  | 	{ | ||||||
|  | 		node->next = pos; | ||||||
|  | 		node->prev = pos->prev; | ||||||
|  | 		if (pos->prev) pos->prev->next = node; | ||||||
|  | 		else this->head_node = node; | ||||||
|  | 		pos->prev = node; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	this->node_count++; | ||||||
|  | 	return n; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | inline typename LinkedList<T>::Node* LinkedList<T>::yield (Node* node, bool clear_links)  | ||||||
|  | { | ||||||
|  | 	QSE_ASSERT (node != QSE_NULL); | ||||||
|  | 	QSE_ASSERT (this->node_count > 0); | ||||||
|  |  | ||||||
|  | 	if (node->next) | ||||||
|  | 		node->next->prev = node->next; | ||||||
|  | 	else | ||||||
|  | 		this->tail_node = node->prev; | ||||||
|  |  | ||||||
|  | 	if (node->prev) | ||||||
|  | 		node->prev->next = node->next; | ||||||
|  | 	else | ||||||
|  | 		this->head_node = node->next; | ||||||
|  | 		 | ||||||
|  | 	this->node_count--; | ||||||
|  |  | ||||||
|  | 	if (clear_links) | ||||||
|  | 	{ | ||||||
|  | 		node->next = QSE_NULL; | ||||||
|  | 		node->prev = QSE_NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return node; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_END_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -50,6 +50,8 @@ pkginclude_HEADERS = \ | |||||||
| 	xma.h  | 	xma.h  | ||||||
|  |  | ||||||
| if ENABLE_CXX | if ENABLE_CXX | ||||||
| pkginclude_HEADERS += Mmgr.hpp StdMmgr.hpp Mmged.hpp | pkginclude_HEADERS += \ | ||||||
|  | 	Mmgr.hpp StdMmgr.hpp Mmged.hpp Mpool.hpp Mpoolable.hpp \ | ||||||
|  | 	LinkedList.hpp | ||||||
| endif | endif | ||||||
|  |  | ||||||
|  | |||||||
| @ -50,7 +50,10 @@ PRE_UNINSTALL = : | |||||||
| POST_UNINSTALL = : | POST_UNINSTALL = : | ||||||
| build_triplet = @build@ | build_triplet = @build@ | ||||||
| host_triplet = @host@ | host_triplet = @host@ | ||||||
| @ENABLE_CXX_TRUE@am__append_1 = Mmgr.hpp StdMmgr.hpp Mmged.hpp | @ENABLE_CXX_TRUE@am__append_1 = \ | ||||||
|  | @ENABLE_CXX_TRUE@	Mmgr.hpp StdMmgr.hpp Mmged.hpp Mpool.hpp Mpoolable.hpp \ | ||||||
|  | @ENABLE_CXX_TRUE@	LinkedList.hpp | ||||||
|  |  | ||||||
| subdir = include/qse/cmn | subdir = include/qse/cmn | ||||||
| DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \ | DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \ | ||||||
| 	$(srcdir)/Makefile.in | 	$(srcdir)/Makefile.in | ||||||
| @ -87,7 +90,8 @@ am__pkginclude_HEADERS_DIST = alg.h chr.h cp949.h cp950.h dir.h dll.h \ | |||||||
| 	lda.h main.h map.h mb8.h mbwc.h mem.h mux.h nwad.h nwif.h \ | 	lda.h main.h map.h mb8.h mbwc.h mem.h mux.h nwad.h nwif.h \ | ||||||
| 	nwio.h oht.h opt.h path.h pio.h pma.h rbt.h rex.h sck.h sio.h \ | 	nwio.h oht.h opt.h path.h pio.h pma.h rbt.h rex.h sck.h sio.h \ | ||||||
| 	sll.h slmb.h str.h task.h time.h tio.h tmr.h tre.h uni.h uri.h \ | 	sll.h slmb.h str.h task.h time.h tio.h tmr.h tre.h uni.h uri.h \ | ||||||
| 	utf8.h xma.h Mmgr.hpp StdMmgr.hpp Mmged.hpp | 	utf8.h xma.h Mmgr.hpp StdMmgr.hpp Mmged.hpp Mpool.hpp \ | ||||||
|  | 	Mpoolable.hpp LinkedList.hpp | ||||||
| am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | ||||||
| am__vpath_adj = case $$p in \ | am__vpath_adj = case $$p in \ | ||||||
|     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ | ||||||
|  | |||||||
							
								
								
									
										107
									
								
								qse/include/qse/cmn/Mpool.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								qse/include/qse/cmn/Mpool.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,107 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |     Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. | ||||||
|  |  | ||||||
|  |     Redistribution and use in source and binary forms, with or without | ||||||
|  |     modification, are permitted provided that the following conditions | ||||||
|  |     are met: | ||||||
|  |     1. Redistributions of source code must retain the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer. | ||||||
|  |     2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer in the | ||||||
|  |        documentation and/or other materials provided with the distribution. | ||||||
|  |  | ||||||
|  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||||
|  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||||
|  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||||
|  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||||
|  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||||
|  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||||
|  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _QSE_CMN_MPOOL_HPP_ | ||||||
|  | #define _QSE_CMN_MPOOL_HPP_ | ||||||
|  |  | ||||||
|  | #include <qse/Uncopyable.hpp> | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_BEGIN_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | // | ||||||
|  | // allocator for fixed-size data | ||||||
|  | // | ||||||
|  |  | ||||||
|  | class Mpool: public Uncopyable  | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	enum  | ||||||
|  | 	{ | ||||||
|  | 		DEFAULT_BLOCK_SIZE = 128 | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	Mpool ( | ||||||
|  | 		qse_size_t datum_size,  | ||||||
|  | 		qse_size_t block_size = DEFAULT_BLOCK_SIZE); | ||||||
|  | 	~Mpool (); | ||||||
|  |  | ||||||
|  | 	void* allocate (); | ||||||
|  | 	void  dispose (void* ptr); | ||||||
|  | 	void  dispose (); | ||||||
|  |  | ||||||
|  | 	inline bool isEnabled () const | ||||||
|  | 	{ | ||||||
|  | 		return this->datum_size > 0 && this->block_size > 0; | ||||||
|  | 	} | ||||||
|  | 	inline bool isDisabled () const | ||||||
|  | 	{ | ||||||
|  | 		return this->datum_size <= 0 || this->block_size <= 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	inline qse_size_t datumSize () const | ||||||
|  | 	{ | ||||||
|  | 		return this->datum_size; | ||||||
|  | 	} | ||||||
|  | 	inline qse_size_t blockSize () const | ||||||
|  | 	{ | ||||||
|  | 		return this->block_size; | ||||||
|  | 	} | ||||||
|  | 	inline void setBlockSize (qse_size_t blockSize)  | ||||||
|  | 	{ | ||||||
|  | 		this->block_size = blockSize; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if defined(QSE_DEBUG_MPOOL) | ||||||
|  | 	qse_size_t  nalloc; | ||||||
|  | 	qse_size_t  navail; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	struct Block  | ||||||
|  | 	{ | ||||||
|  | 		Block*  next; | ||||||
|  | 		//qse_uint8_t data[0]; | ||||||
|  | 	}; | ||||||
|  | 	struct Chain  | ||||||
|  | 	{ | ||||||
|  | 		Chain* next; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	Block* mp_blocks; | ||||||
|  | 	Chain* free_list; | ||||||
|  | 	qse_size_t datum_size; | ||||||
|  | 	qse_size_t block_size; | ||||||
|  |  | ||||||
|  | 	void add_block (); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_END_NAMESPACE(QSE) | ||||||
|  | //////////////////////////////// | ||||||
|  | #endif | ||||||
|  |  | ||||||
							
								
								
									
										73
									
								
								qse/include/qse/cmn/Mpoolable.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								qse/include/qse/cmn/Mpoolable.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |     Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. | ||||||
|  |  | ||||||
|  |     Redistribution and use in source and binary forms, with or without | ||||||
|  |     modification, are permitted provided that the following conditions | ||||||
|  |     are met: | ||||||
|  |     1. Redistributions of source code must retain the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer. | ||||||
|  |     2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer in the | ||||||
|  |        documentation and/or other materials provided with the distribution. | ||||||
|  |  | ||||||
|  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||||
|  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||||
|  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||||
|  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||||
|  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||||
|  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||||
|  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _QSE_CMN_MPOOLABLE_HPP_ | ||||||
|  | #define _QSE_CMN_MPOOLABLE_HPP_ | ||||||
|  |  | ||||||
|  | #include <qse/cmn/Mpool.hpp> | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_BEGIN_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | class Mpoolable | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	typedef qse_size_t mp_size_t; | ||||||
|  |  | ||||||
|  | 	inline void* operator new (mp_size_t size) | ||||||
|  | 	{ | ||||||
|  | 		return ::operator new (size); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	inline void operator delete (void* ptr) | ||||||
|  | 	{ | ||||||
|  | 		::operator delete (ptr); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	inline void* operator new (mp_size_t /*size*/, Mpool* mp) | ||||||
|  | 	{ | ||||||
|  | 		return mp->allocate (); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if defined(_MSC_VER) | ||||||
|  | 	void operator delete (void* ptr, Mpool* mp) | ||||||
|  | 	{ | ||||||
|  | 		mp->dispose (ptr); | ||||||
|  | 	} | ||||||
|  | #else | ||||||
|  | 	inline void dispose (void* ptr, Mpool* mp) | ||||||
|  | 	{ | ||||||
|  | 		mp->dispose (ptr); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_END_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @ -27,7 +27,7 @@ | |||||||
| #ifndef _QSE_HTTP_HTTP_H_ | #ifndef _QSE_HTTP_HTTP_H_ | ||||||
| #define _QSE_HTTP_HTTP_H_ | #define _QSE_HTTP_HTTP_H_ | ||||||
|  |  | ||||||
| /** @file | /** \file | ||||||
|  * This file provides basic data types and functions for the http protocol. |  * This file provides basic data types and functions for the http protocol. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| @ -131,7 +131,7 @@ enum qse_http_range_type_t | |||||||
| typedef enum qse_http_range_type_t qse_http_range_type_t; | typedef enum qse_http_range_type_t qse_http_range_type_t; | ||||||
| /** | /** | ||||||
|  * The qse_http_range_t type defines a structure that can represent |  * The qse_http_range_t type defines a structure that can represent | ||||||
|  * a value for the @b Range: http header.  |  * a value for the \b Range: http header.  | ||||||
|  * |  * | ||||||
|  * If type is #QSE_HTTP_RANGE_NONE, this range is not valid. |  * If type is #QSE_HTTP_RANGE_NONE, this range is not valid. | ||||||
|  *  |  *  | ||||||
| @ -141,10 +141,10 @@ typedef enum qse_http_range_type_t qse_http_range_type_t; | |||||||
|  * |  * | ||||||
|  * You should adjust a range when the size that this range belongs to is  |  * You should adjust a range when the size that this range belongs to is  | ||||||
|  * made known. See this code: |  * made known. See this code: | ||||||
|  * @code |  * \code | ||||||
|  *  range.from = total_size - range.to; |  *  range.from = total_size - range.to; | ||||||
|  *  range.to = range.to + range.from - 1; |  *  range.to = range.to + range.from - 1; | ||||||
|  * @endcode |  * \endcode | ||||||
|  * |  * | ||||||
|  * If type is #QSE_HTTP_RANGE_PROPER, 'from' and 'to' represents a proper range |  * If type is #QSE_HTTP_RANGE_PROPER, 'from' and 'to' represents a proper range | ||||||
|  * where the value of 0 indicates the first byte. This doesn't require any  |  * where the value of 0 indicates the first byte. This doesn't require any  | ||||||
|  | |||||||
| @ -141,7 +141,7 @@ if ENABLE_CXX | |||||||
|  |  | ||||||
| lib_LTLIBRARIES += libqsecmnxx.la | lib_LTLIBRARIES += libqsecmnxx.la | ||||||
| libqsecmnxx_la_SOURCES = \ | libqsecmnxx_la_SOURCES = \ | ||||||
| 	Mmgr.cpp StdMmgr.cpp | 	Mmgr.cpp StdMmgr.cpp Mpool.cpp | ||||||
| libqsecmnxx_la_LDFLAGS = -version-info 1:0:0 -no-undefined | libqsecmnxx_la_LDFLAGS = -version-info 1:0:0 -no-undefined | ||||||
| libqsecmnxx_la_LIBADD =  | libqsecmnxx_la_LIBADD =  | ||||||
|  |  | ||||||
|  | |||||||
| @ -149,8 +149,9 @@ libqsecmn_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ | |||||||
| 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ | 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ | ||||||
| 	$(libqsecmn_la_LDFLAGS) $(LDFLAGS) -o $@ | 	$(libqsecmn_la_LDFLAGS) $(LDFLAGS) -o $@ | ||||||
| libqsecmnxx_la_DEPENDENCIES = | libqsecmnxx_la_DEPENDENCIES = | ||||||
| am__libqsecmnxx_la_SOURCES_DIST = Mmgr.cpp StdMmgr.cpp | am__libqsecmnxx_la_SOURCES_DIST = Mmgr.cpp StdMmgr.cpp Mpool.cpp | ||||||
| @ENABLE_CXX_TRUE@am_libqsecmnxx_la_OBJECTS = Mmgr.lo StdMmgr.lo | @ENABLE_CXX_TRUE@am_libqsecmnxx_la_OBJECTS = Mmgr.lo StdMmgr.lo \ | ||||||
|  | @ENABLE_CXX_TRUE@	Mpool.lo | ||||||
| libqsecmnxx_la_OBJECTS = $(am_libqsecmnxx_la_OBJECTS) | libqsecmnxx_la_OBJECTS = $(am_libqsecmnxx_la_OBJECTS) | ||||||
| libqsecmnxx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ | libqsecmnxx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ | ||||||
| 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ | 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ | ||||||
| @ -433,7 +434,7 @@ libqsecmn_la_SOURCES = alg-base64.c alg-rand.c alg-search.c alg-sort.c \ | |||||||
| libqsecmn_la_LDFLAGS = -version-info 1:0:0 -no-undefined | libqsecmn_la_LDFLAGS = -version-info 1:0:0 -no-undefined | ||||||
| libqsecmn_la_LIBADD = $(SOCKET_LIBS) $(QUADMATH_LIBS) | libqsecmn_la_LIBADD = $(SOCKET_LIBS) $(QUADMATH_LIBS) | ||||||
| @ENABLE_CXX_TRUE@libqsecmnxx_la_SOURCES = \ | @ENABLE_CXX_TRUE@libqsecmnxx_la_SOURCES = \ | ||||||
| @ENABLE_CXX_TRUE@	Mmgr.cpp StdMmgr.cpp | @ENABLE_CXX_TRUE@	Mmgr.cpp StdMmgr.cpp Mpool.cpp | ||||||
|  |  | ||||||
| @ENABLE_CXX_TRUE@libqsecmnxx_la_LDFLAGS = -version-info 1:0:0 -no-undefined | @ENABLE_CXX_TRUE@libqsecmnxx_la_LDFLAGS = -version-info 1:0:0 -no-undefined | ||||||
| @ENABLE_CXX_TRUE@libqsecmnxx_la_LIBADD =  | @ENABLE_CXX_TRUE@libqsecmnxx_la_LIBADD =  | ||||||
| @ -515,6 +516,7 @@ distclean-compile: | |||||||
| 	-rm -f *.tab.c | 	-rm -f *.tab.c | ||||||
|  |  | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Mmgr.Plo@am__quote@ | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Mmgr.Plo@am__quote@ | ||||||
|  | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Mpool.Plo@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StdMmgr.Plo@am__quote@ | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StdMmgr.Plo@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-base64.Plo@am__quote@ | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-base64.Plo@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-rand.Plo@am__quote@ | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-rand.Plo@am__quote@ | ||||||
|  | |||||||
							
								
								
									
										127
									
								
								qse/lib/cmn/Mpool.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								qse/lib/cmn/Mpool.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,127 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |     Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. | ||||||
|  |  | ||||||
|  |     Redistribution and use in source and binary forms, with or without | ||||||
|  |     modification, are permitted provided that the following conditions | ||||||
|  |     are met: | ||||||
|  |     1. Redistributions of source code must retain the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer. | ||||||
|  |     2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |        notice, this list of conditions and the following disclaimer in the | ||||||
|  |        documentation and/or other materials provided with the distribution. | ||||||
|  |  | ||||||
|  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||||
|  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||||
|  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||||
|  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||||
|  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||||
|  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||||
|  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <qse/cmn/Mpool.hpp> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // TODO: can i use QSE_MMGR_XXXXX instead of ::new and ::delete??? | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_BEGIN_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
|  |  | ||||||
|  | Mpool::Mpool (qse_size_t datum_size, qse_size_t block_size) | ||||||
|  | { | ||||||
|  | 	if (datum_size > 0 && datum_size < QSE_SIZEOF(void*)) | ||||||
|  | 		datum_size = QSE_SIZEOF(void*); | ||||||
|  |  | ||||||
|  | 	this->mp_blocks  = QSE_NULL; | ||||||
|  | 	this->free_list  = QSE_NULL; | ||||||
|  | 	this->datum_size = datum_size; | ||||||
|  | 	this->block_size = block_size; | ||||||
|  | #if defined(QSE_DEBUG_MPOOL) | ||||||
|  | 	this->navail = 0; | ||||||
|  | 	this->nalloc = 0; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | Mpool::~Mpool () | ||||||
|  | { | ||||||
|  | 	this->dispose (); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void* Mpool::allocate () | ||||||
|  | { | ||||||
|  | 	if (this->datum_size <= 0 || this->block_size <= 0) return QSE_NULL; | ||||||
|  |  | ||||||
|  | 	void* ptr = this->free_list; | ||||||
|  | 	if (!ptr)  | ||||||
|  | 	{ | ||||||
|  | 		this->add_block (); | ||||||
|  | 		ptr = this->free_list; | ||||||
|  | 	} | ||||||
|  | 	this->free_list = this->free_list->next; | ||||||
|  | #if defined(QSE_DEBUG_MPOOL) | ||||||
|  | 	this->navail--; | ||||||
|  | #endif | ||||||
|  | 	return ptr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Mpool::dispose (void* ptr) | ||||||
|  | { | ||||||
|  | 	((Chain*)ptr)->next = this->free_list; | ||||||
|  | 	this->free_list = (Chain*)ptr; | ||||||
|  | #if defined(QSE_DEBUG_MPOOL) | ||||||
|  | 	this->navail++; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Mpool::dispose () | ||||||
|  | { | ||||||
|  | 	Block* block = this->mp_blocks; | ||||||
|  | 	while (block)  | ||||||
|  | 	{ | ||||||
|  | 		Block* next = block->next; | ||||||
|  | 		::delete[] block; | ||||||
|  | 		block = next; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	this->free_list = QSE_NULL; | ||||||
|  | 	this->mp_blocks = QSE_NULL; | ||||||
|  | #if defined(QSE_DEBUG_MPOOL) | ||||||
|  | 	this->navail = 0; | ||||||
|  | 	this->nalloc = 0; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Mpool::add_block () | ||||||
|  | { | ||||||
|  | 	QSE_ASSERT (this->datum_size > 0 && this->block_size > 0); | ||||||
|  |  | ||||||
|  | 	Block* block = (Block*)::new qse_uint8_t[ | ||||||
|  | 		QSE_SIZEOF(Block) + this->block_size * this->datum_size]; | ||||||
|  |  | ||||||
|  | 	//this->free_list = (Chain*)block->data; | ||||||
|  | 	this->free_list = (Chain*)(block + 1); | ||||||
|  | 	Chain* ptr = this->free_list; | ||||||
|  | 	for (qse_size_t i = 0; i < this->block_size - 1; i++)  | ||||||
|  | 	{ | ||||||
|  | 		Chain* next = (Chain*)((qse_uint8_t*)ptr + this->datum_size); | ||||||
|  | 		ptr->next = next; | ||||||
|  | 		ptr = next; | ||||||
|  | 	} | ||||||
|  | 	ptr->next = QSE_NULL; | ||||||
|  |  | ||||||
|  | 	block->next  = this->mp_blocks; | ||||||
|  | 	this->mp_blocks = block; | ||||||
|  | #if defined(QSE_DEBUG_MPOOL) | ||||||
|  | 	this->navail += this->block_size; | ||||||
|  | 	this->nalloc += this->block_size; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | QSE_END_NAMESPACE(QSE) | ||||||
|  | ///////////////////////////////// | ||||||
| @ -36,7 +36,7 @@ QSE_BEGIN_NAMESPACE(QSE) | |||||||
| int Sed::open () | int Sed::open () | ||||||
| { | { | ||||||
| 	sed = qse_sed_open (this->mmgr, QSE_SIZEOF(Sed*)); | 	sed = qse_sed_open (this->mmgr, QSE_SIZEOF(Sed*)); | ||||||
| 	if (sed == QSE_NULL) return -1; | 	if (!sed) return -1; | ||||||
| 	*(Sed**)QSE_XTN(sed) = this; | 	*(Sed**)QSE_XTN(sed) = this; | ||||||
|  |  | ||||||
| 	dflerrstr = qse_sed_geterrstr (sed); | 	dflerrstr = qse_sed_geterrstr (sed); | ||||||
| @ -47,10 +47,10 @@ int Sed::open () | |||||||
|  |  | ||||||
| void Sed::close () | void Sed::close () | ||||||
| { | { | ||||||
| 	if (sed != QSE_NULL) | 	if (sed) | ||||||
| 	{ | 	{ | ||||||
| 		qse_sed_close (sed); | 		qse_sed_close (sed); | ||||||
| 		sed = QSE_NULL;	 | 		sed = QSE_NULL; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user