added Mpool and LinkedList

This commit is contained in:
hyung-hwan 2015-01-02 06:40:41 +00:00
parent 91e4e06318
commit 3b672857aa
15 changed files with 988 additions and 85 deletions

View File

@ -71,7 +71,6 @@ protected:
mutable qse_size_t ref_count;
};
/////////////////////////////////
QSE_END_NAMESPACE(QSE)
/////////////////////////////////

View File

@ -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)
/////////////////////////////////

View File

@ -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

View File

@ -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;

View File

@ -31,7 +31,7 @@
#include <qse/cmn/StdMmgr.hpp>
#include <qse/cmn/time.h>
/// @file
/// \file
/// Standard AWK Interpreter
/////////////////////////////////

View 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

View File

@ -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

View File

@ -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/||"`;; \

View 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

View 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

View File

@ -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

View File

@ -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 =

View File

@ -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
View 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)
/////////////////////////////////

View File

@ -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,10 +47,10 @@ int Sed::open ()
void Sed::close ()
{
if (sed != QSE_NULL)
if (sed)
{
qse_sed_close (sed);
sed = QSE_NULL;
sed = QSE_NULL;
}
}