added Mpool and LinkedList
This commit is contained in:
parent
91e4e06318
commit
3b672857aa
@ -71,7 +71,6 @@ protected:
|
||||
mutable qse_size_t ref_count;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_END_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
@ -30,6 +30,9 @@
|
||||
#include <qse/types.h>
|
||||
#include <qse/macros.h>
|
||||
|
||||
/// \file
|
||||
/// This file defines a class containg aliases to various QSE types.
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
@ -27,12 +27,16 @@
|
||||
#ifndef _QSE_UNCOPYABLE_HPP_
|
||||
#define _QSE_UNCOPYABLE_HPP_
|
||||
|
||||
#include <qse/Types.hpp>
|
||||
#include <qse/types.h>
|
||||
#include <qse/macros.h>
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
||||
/// The Uncopyable class disallows an inheriting class to be assigned or
|
||||
/// copied.
|
||||
|
||||
class QSE_EXPORT Uncopyable
|
||||
{
|
||||
public:
|
||||
@ -48,5 +52,4 @@ private:
|
||||
QSE_END_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include <qse/cmn/Mmged.hpp>
|
||||
#include <stdarg.h>
|
||||
|
||||
/// @file
|
||||
/// \file
|
||||
/// AWK Interpreter
|
||||
|
||||
/////////////////////////////////
|
||||
@ -105,24 +105,24 @@ public:
|
||||
|
||||
protected:
|
||||
///
|
||||
/// @name Error Handling
|
||||
/// \name Error Handling
|
||||
///
|
||||
/// @{
|
||||
/// \{
|
||||
|
||||
///
|
||||
/// 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
|
||||
/// of ${X}'s as the orginal formatting string. Their order may be
|
||||
/// different. The example below changes the formatting string for
|
||||
/// #QSE_AWK_ENOENT.
|
||||
/// @code
|
||||
/// \code
|
||||
/// const MyAwk::char_t* MyAwk::getErrorString (errnum_t num) const
|
||||
/// {
|
||||
/// if (num == QSE_AWK_ENOENT) return QSE_T("cannot find '${0}'");
|
||||
/// return Awk::getErrorString (num);
|
||||
/// }
|
||||
/// @endcode
|
||||
/// \endcode
|
||||
///
|
||||
virtual const char_t* getErrorString (
|
||||
errnum_t num
|
||||
@ -175,7 +175,7 @@ public:
|
||||
//protected: can't make it protected for borland
|
||||
void retrieveError ();
|
||||
void retrieveError (Run* run);
|
||||
/// @}
|
||||
/// \}
|
||||
|
||||
protected:
|
||||
class NoSource;
|
||||
@ -791,14 +791,14 @@ public:
|
||||
|
||||
///
|
||||
/// 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;
|
||||
|
||||
///
|
||||
/// The getIndexed() function gets a value at the given
|
||||
/// index @a idx and sets it to @a val.
|
||||
/// @return 0 on success, -1 on failure
|
||||
/// index \a idx and sets it to \a val.
|
||||
/// \return 0 on success, -1 on failure
|
||||
///
|
||||
int getIndexed (
|
||||
const Index& idx, ///< array index
|
||||
@ -807,8 +807,8 @@ public:
|
||||
|
||||
///
|
||||
/// The getFirstIndex() function stores the first index of
|
||||
/// an arrayed value into @a idx.
|
||||
/// @return IndexIterator::END if the arrayed value is empty,
|
||||
/// an arrayed value into \a idx.
|
||||
/// \return IndexIterator::END if the arrayed value is empty,
|
||||
/// iterator that can be passed to getNextIndex() if not
|
||||
///
|
||||
IndexIterator getFirstIndex (
|
||||
@ -816,10 +816,10 @@ public:
|
||||
) 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
|
||||
/// @a iter.
|
||||
/// @return IndexIterator::END if the arrayed value is empty,
|
||||
/// \a iter.
|
||||
/// \return IndexIterator::END if the arrayed value is empty,
|
||||
/// iterator that can be passed to getNextIndex() if not
|
||||
///
|
||||
IndexIterator getNextIndex (
|
||||
@ -882,40 +882,40 @@ public:
|
||||
|
||||
///
|
||||
/// The setGlobal() function sets the value of a global
|
||||
/// variable identified by @a id
|
||||
/// to @a v.
|
||||
/// @return 0 on success, -1 on failure
|
||||
/// variable identified by \a id
|
||||
/// to \a v.
|
||||
/// \return 0 on success, -1 on failure
|
||||
///
|
||||
int setGlobal (int id, int_t v);
|
||||
|
||||
///
|
||||
/// The setGlobal() function sets the value of a global
|
||||
/// variable identified by @a id
|
||||
/// to @a v.
|
||||
/// @return 0 on success, -1 on failure
|
||||
/// variable identified by \a id
|
||||
/// to \a v.
|
||||
/// \return 0 on success, -1 on failure
|
||||
///
|
||||
int setGlobal (int id, flt_t v);
|
||||
|
||||
///
|
||||
/// The setGlobal() function sets the value of a global
|
||||
/// variable identified by @a id
|
||||
/// to a string as long as @a len characters pointed to by
|
||||
/// @a ptr.
|
||||
/// @return 0 on success, -1 on failure
|
||||
/// variable identified by \a id
|
||||
/// to a string as long as \a len characters pointed to by
|
||||
/// \a ptr.
|
||||
/// \return 0 on success, -1 on failure
|
||||
///
|
||||
int setGlobal (int id, const char_t* ptr, size_t len);
|
||||
|
||||
///
|
||||
/// The setGlobal() function sets a global variable
|
||||
/// identified by @a id to a value @a v.
|
||||
/// @return 0 on success, -1 on failure
|
||||
/// identified by \a id to a value \a v.
|
||||
/// \return 0 on success, -1 on failure
|
||||
///
|
||||
int setGlobal (int id, const Value& v);
|
||||
|
||||
///
|
||||
/// The getGlobal() function gets the value of a global
|
||||
/// variable identified by @a id and stores it in @a v.
|
||||
/// @return 0 on success, -1 on failure
|
||||
/// variable identified by \a id and stores it in \a v.
|
||||
/// \return 0 on success, -1 on failure
|
||||
///
|
||||
int getGlobal (int id, Value& v) const;
|
||||
|
||||
@ -930,8 +930,8 @@ public:
|
||||
operator awk_t* () const;
|
||||
|
||||
///
|
||||
/// @name Basic Functions
|
||||
/// @{
|
||||
/// \name Basic Functions
|
||||
/// \{
|
||||
///
|
||||
|
||||
/// The Awk() function creates an interpreter without fully
|
||||
@ -946,7 +946,7 @@ public:
|
||||
///
|
||||
/// The open() function initializes an interpreter.
|
||||
/// 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 ();
|
||||
|
||||
@ -957,11 +957,11 @@ public:
|
||||
|
||||
///
|
||||
/// 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.
|
||||
/// 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.
|
||||
/// 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.
|
||||
/// 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 (
|
||||
Source& in, ///< script to parse
|
||||
@ -1002,15 +1002,15 @@ public:
|
||||
|
||||
///
|
||||
/// The loop() function executes the BEGIN block, pattern-action blocks,
|
||||
/// and the END block. The return value is stored into @a ret.
|
||||
/// @return 0 on succes, -1 on failure
|
||||
/// and the END block. The return value is stored into \a ret.
|
||||
/// \return 0 on succes, -1 on failure
|
||||
///
|
||||
int loop (
|
||||
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 (
|
||||
const char_t* name, ///< function name
|
||||
@ -1023,16 +1023,16 @@ public:
|
||||
/// The stop() function makes request to abort execution
|
||||
///
|
||||
void stop ();
|
||||
/// @}
|
||||
/// \}
|
||||
|
||||
///
|
||||
/// @name Configuration
|
||||
/// @{
|
||||
/// \name Configuration
|
||||
/// \{
|
||||
///
|
||||
|
||||
///
|
||||
/// The getTrait() function gets the current options.
|
||||
/// @return current traits
|
||||
/// \return current traits
|
||||
///
|
||||
int getTrait () const;
|
||||
|
||||
@ -1045,7 +1045,7 @@ public:
|
||||
|
||||
///
|
||||
/// The setMaxDepth() function sets the maximum processing depth
|
||||
/// for operations identified by @a ids.
|
||||
/// for operations identified by \a ids.
|
||||
///
|
||||
void setMaxDepth (
|
||||
depth_t id, ///< depth identifier
|
||||
@ -1054,18 +1054,18 @@ public:
|
||||
|
||||
///
|
||||
/// The getMaxDepth() function gets the maximum depth for an operation
|
||||
/// type identified by @a id.
|
||||
/// type identified by \a id.
|
||||
///
|
||||
size_t getMaxDepth (
|
||||
depth_t id ///< depth identifier
|
||||
) 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
|
||||
/// 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.
|
||||
/// @return 0 on success, -1 on failure
|
||||
/// \return 0 on success, -1 on failure
|
||||
///
|
||||
int addArgument (
|
||||
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
|
||||
/// through ARGV.
|
||||
/// @return 0 on success, -1 on failure
|
||||
/// \return 0 on success, -1 on failure
|
||||
///
|
||||
int addArgument (
|
||||
const char_t* arg ///< string pointer
|
||||
@ -1089,7 +1089,7 @@ public:
|
||||
|
||||
///
|
||||
/// 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 (
|
||||
const char_t* name ///< variable name
|
||||
@ -1098,7 +1098,7 @@ public:
|
||||
///
|
||||
/// The deleteGlobal() function unregisters an intrinsic global
|
||||
/// variable by name.
|
||||
/// @return 0 on success, -1 on failure.
|
||||
/// \return 0 on success, -1 on failure.
|
||||
///
|
||||
int deleteGlobal (
|
||||
const char_t* name ///< variable name
|
||||
@ -1107,7 +1107,7 @@ public:
|
||||
///
|
||||
/// The addGlobal() function returns the numeric ID of an intrinsic
|
||||
// global variable.
|
||||
/// @return integer >= 0 on success, -1 on failure.
|
||||
/// \return integer >= 0 on success, -1 on failure.
|
||||
///
|
||||
int findGlobal (
|
||||
const char_t* name ///> variable name
|
||||
@ -1115,10 +1115,10 @@ public:
|
||||
|
||||
///
|
||||
/// 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
|
||||
/// to call this function prior to parse().
|
||||
/// @return 0 on success, -1 on failure
|
||||
/// \return 0 on success, -1 on failure
|
||||
///
|
||||
int setGlobal (
|
||||
int id, ///< numeric identifier
|
||||
@ -1127,10 +1127,10 @@ public:
|
||||
|
||||
///
|
||||
/// 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
|
||||
/// to call this function before parse().
|
||||
/// @return 0 on success, -1 on failure
|
||||
/// \return 0 on success, -1 on failure
|
||||
///
|
||||
int getGlobal (
|
||||
int id, ///< numeric identifier
|
||||
@ -1168,7 +1168,7 @@ public:
|
||||
int deleteFunction (
|
||||
const char_t* name ///< function name
|
||||
);
|
||||
/// @}
|
||||
/// \}
|
||||
|
||||
Pipe::Handler* getPipeHandler ()
|
||||
{
|
||||
@ -1238,10 +1238,10 @@ public:
|
||||
|
||||
protected:
|
||||
///
|
||||
/// @name Pipe I/O handlers
|
||||
/// \name Pipe I/O handlers
|
||||
/// Pipe operations are achieved through the following functions
|
||||
/// if no external pipe handler is set with setPipeHandler().
|
||||
/// @{
|
||||
/// \{
|
||||
|
||||
/// The openPipe() function is a pure virtual function that must be
|
||||
/// 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 writePipe (Pipe& io, const char_t* buf, size_t len);
|
||||
virtual int flushPipe (Pipe& io);
|
||||
/// @}
|
||||
/// \}
|
||||
|
||||
///
|
||||
/// @name File I/O handlers
|
||||
/// \name File I/O handlers
|
||||
/// File operations are achieved through the following functions
|
||||
/// if no external file handler is set with setFileHandler().
|
||||
/// @{
|
||||
/// \{
|
||||
///
|
||||
virtual int openFile (File& io);
|
||||
virtual int closeFile (File& io);
|
||||
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 int flushFile (File& io);
|
||||
/// @}
|
||||
/// \}
|
||||
|
||||
///
|
||||
/// @name Console I/O handlers
|
||||
/// \name Console I/O handlers
|
||||
/// Console operations are achieved through the following functions.
|
||||
/// if no external console handler is set with setConsoleHandler().
|
||||
/// @{
|
||||
/// \{
|
||||
///
|
||||
virtual int openConsole (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 int flushConsole (Console& io);
|
||||
virtual int nextConsole (Console& io);
|
||||
/// @}
|
||||
/// \}
|
||||
|
||||
// primitive handlers
|
||||
virtual flt_t pow (flt_t x, flt_t y) = 0;
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <qse/cmn/StdMmgr.hpp>
|
||||
#include <qse/cmn/time.h>
|
||||
|
||||
/// @file
|
||||
/// \file
|
||||
/// 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
|
||||
|
||||
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
|
||||
|
||||
|
@ -50,7 +50,10 @@ PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
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
|
||||
DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \
|
||||
$(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 \
|
||||
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 \
|
||||
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 = case $$p in \
|
||||
$(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_
|
||||
#define _QSE_HTTP_HTTP_H_
|
||||
|
||||
/** @file
|
||||
/** \file
|
||||
* 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;
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@ -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
|
||||
* made known. See this code:
|
||||
* @code
|
||||
* \code
|
||||
* range.from = total_size - range.to;
|
||||
* range.to = range.to + range.from - 1;
|
||||
* @endcode
|
||||
* \endcode
|
||||
*
|
||||
* 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
|
||||
|
@ -141,7 +141,7 @@ if ENABLE_CXX
|
||||
|
||||
lib_LTLIBRARIES += libqsecmnxx.la
|
||||
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_LIBADD =
|
||||
|
||||
|
@ -149,8 +149,9 @@ libqsecmn_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(libqsecmn_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
libqsecmnxx_la_DEPENDENCIES =
|
||||
am__libqsecmnxx_la_SOURCES_DIST = Mmgr.cpp StdMmgr.cpp
|
||||
@ENABLE_CXX_TRUE@am_libqsecmnxx_la_OBJECTS = Mmgr.lo StdMmgr.lo
|
||||
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@ Mpool.lo
|
||||
libqsecmnxx_la_OBJECTS = $(am_libqsecmnxx_la_OBJECTS)
|
||||
libqsecmnxx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
|
||||
$(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_LIBADD = $(SOCKET_LIBS) $(QUADMATH_LIBS)
|
||||
@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_LIBADD =
|
||||
@ -515,6 +516,7 @@ distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@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)/alg-base64.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 ()
|
||||
{
|
||||
sed = qse_sed_open (this->mmgr, QSE_SIZEOF(Sed*));
|
||||
if (sed == QSE_NULL) return -1;
|
||||
if (!sed) return -1;
|
||||
*(Sed**)QSE_XTN(sed) = this;
|
||||
|
||||
dflerrstr = qse_sed_geterrstr (sed);
|
||||
@ -47,7 +47,7 @@ int Sed::open ()
|
||||
|
||||
void Sed::close ()
|
||||
{
|
||||
if (sed != QSE_NULL)
|
||||
if (sed)
|
||||
{
|
||||
qse_sed_close (sed);
|
||||
sed = QSE_NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user