added to StrBase a special constructor that doesn't allocation a buffer.

added PtrString classes
added removeNode to HashList and HashTable.
added findNode to HashTable
This commit is contained in:
hyung-hwan 2017-08-30 13:50:02 +00:00
parent 211f5b014e
commit 559f965aa5
4 changed files with 226 additions and 48 deletions

View File

@ -581,31 +581,44 @@ public:
Node* np = this->heterofind_node<MT,MEQUALER> (datum, hc);
if (np)
{
qse_size_t head, tail;
head = hc << 1; tail = head + 1;
if (this->nodes[head] == this->nodes[tail])
{
QSE_ASSERT (np == this->nodes[head]);
this->nodes[head] = this->nodes[tail] = QSE_NULL;
}
else if (np == this->nodes[head])
{
this->nodes[head] = np->getNextNode();
}
else if (np == this->nodes[tail])
{
this->nodes[tail] = np->getPrevNode();
}
this->datum_list->remove (np);
this->remove_node (np, hc);
return 0;
}
return -1;
}
void removeNode (Node* np)
{
T& datum = np->value;
qse_size_t hc = this->_hasher(datum) % this->node_capacity;
this->remove_node (np, hc);
}
private:
void remove_node (Node* np, qse_size_t hc)
{
qse_size_t head, tail;
head = hc << 1; tail = head + 1;
if (this->nodes[head] == this->nodes[tail])
{
QSE_ASSERT (np == this->nodes[head]);
this->nodes[head] = this->nodes[tail] = QSE_NULL;
}
else if (np == this->nodes[head])
{
this->nodes[head] = np->getNextNode();
}
else if (np == this->nodes[tail])
{
this->nodes[tail] = np->getPrevNode();
}
this->datum_list->remove (np);
}
public:
void clear (bool clear_mpool = false)
{
for (qse_size_t i = 0; i < (this->node_capacity << 1); i++)

View File

@ -290,6 +290,16 @@ public:
return this->pair_list.clear (clear_mpool);
}
void removeNode (PairNode* node)
{
this->pair_list.removeNode (node);
}
PairNode* findNode (const K& key)
{
return this->pair_list.findNode (key);
}
Iterator getIterator (qse_size_t index = 0)
{
return this->pair_list.getIterator (index);

View File

@ -27,7 +27,6 @@
#ifndef _QSE_CMN_STRBASE_HPP_
#define _QSE_CMN_STRBASE_HPP_
#include <qse/Hashable.hpp>
#include <qse/Growable.hpp>
#include <qse/RefCounted.hpp>
@ -182,6 +181,42 @@ public:
this->ref_item ();
}
StrBase (int capacity): Mmged(QSE_NULL)
{
if (capacity <= -1)
{
// this is a special constructor to instanatiate a string with no buffer.
// it is intended to be followed by truncate() for actual buffer allocation.
// all other functions except the destructor and the truncation() function
// are not aware of this special condition.
//
// String x(0);
// try { x.truncate(10); } catch (...) { return -1; }
// x.append ("xxx");
//
this->_item = QSE_NULL;
}
else
{
this->_item = new(this->getMmgr()) StringItem (this->getMmgr(), this->round_capacity(capacity), (const CHAR_TYPE*)QSE_NULL, 0);
this->ref_item ();
}
}
StrBase (Mmgr* mmgr, int capacity): Mmged(mmgr)
{
if (capacity <= -1)
{
// this is a special constructor to instanatiate a string with no buffer.
// it is intended to be followed by truncate() for actual buffer allocation.
this->_item = QSE_NULL;
}
else
{
this->_item = new(this->getMmgr()) StringItem (this->getMmgr(), this->round_capacity(capacity), (const CHAR_TYPE*)QSE_NULL, 0);
this->ref_item ();
}
}
StrBase (qse_size_t capacity): Mmged(QSE_NULL)
{
this->_item = new(this->getMmgr()) StringItem (this->getMmgr(), this->round_capacity(capacity), (const CHAR_TYPE*)QSE_NULL, 0);
@ -240,7 +275,7 @@ public:
~StrBase ()
{
this->deref_item ();
if (this->_item) this->deref_item ();
}
SelfType& operator= (const SelfType& str)
@ -360,9 +395,14 @@ public:
return this->_item->buffer;
}
const CHAR_TYPE* getData() const
{
return this->_item->buffer;
}
qse_size_t getHashCode () const
{
// keep this in sync with getHashCode of BasePtrString<CHAR_TYPE>
// keep this in sync with getHashCode() of PtrStrBase<CHAR_TYPE>
return Hashable::getHashCode (
this->_item->buffer, this->_item->size * QSE_SIZEOF(CHAR_TYPE));
}
@ -439,33 +479,45 @@ public:
// you can call truncate twice. for instance,
// str.truncate (1000).
// str.truncate (100).
StringItem* old_item = QSE_NULL;
if (this->_item->isShared())
if (this->_item)
{
StringItem* t;
StringItem* old_item = QSE_NULL;
if (new_size > this->_item->capacity)
t = this->_item->copy (this->getMmgr(), this->adjust_desired_capacity(new_size));
else
t = this->_item->copy (this->getMmgr());
if (this->_item->isShared())
{
StringItem* t;
old_item = this->_item;
this->_item = t;
if (new_size > this->_item->capacity)
t = this->_item->copy (this->getMmgr(), this->adjust_desired_capacity(new_size));
else
t = this->_item->copy (this->getMmgr());
old_item = this->_item;
this->_item = t;
this->ref_item ();
}
else if (new_size > this->_item->capacity)
{
StringItem* t = this->_item->copy (this->getMmgr(), this->adjust_desired_capacity(new_size));
old_item = this->_item;
this->_item = t;
this->ref_item ();;
}
this->_item->buffer[new_size] = NULL_CHAR;
this->_item->size = new_size;
if (old_item) this->deref_item (old_item);
}
else
{
// this is the only function that supports some use-cases
// of a string object created with no buffer at all.
// read comments in the special constructor
this->_item = new(this->getMmgr()) StringItem (this->getMmgr(), this->round_capacity(new_size), (const CHAR_TYPE*)QSE_NULL, 0);
this->ref_item ();
this->_item->buffer[new_size] = NULL_CHAR;
this->_item->size = new_size;
}
else if (new_size > this->_item->capacity)
{
StringItem* t = this->_item->copy (this->getMmgr(), this->adjust_desired_capacity(new_size));
old_item = this->_item;
this->_item = t;
this->ref_item ();;
}
this->_item->buffer[new_size] = NULL_CHAR;
this->_item->size = new_size;
if (old_item) this->deref_item (old_item);
}
//
@ -992,7 +1044,6 @@ protected:
OPSET _opset;
RESIZER _resizer;
private:
qse_size_t adjust_desired_capacity (qse_size_t new_desired_capacity)
{
@ -1003,6 +1054,76 @@ private:
};
template <typename CHAR_TYPE, CHAR_TYPE NULL_CHAR, typename OPSET, typename RESIZER = StrBaseResizer>
class PtrStrBase
{
public:
typedef PtrStrBase<CHAR_TYPE,NULL_CHAR,OPSET,RESIZER> ThisType;
typedef StrBase<CHAR_TYPE,NULL_CHAR,OPSET,RESIZER> StringType;
PtrStrBase (): ptr (QSE_NULL), len (0) {}
PtrStrBase (const CHAR_TYPE* ptr): ptr (ptr)
{
this->len = this->_opset.getLength (ptr);
}
PtrStrBase (const CHAR_TYPE* ptr, qse_size_t len): ptr (ptr), len (len)
{
// do nothing
}
qse_size_t getHashCode () const
{
// keep this in sync with hashCode of StringType(StrBase)
return Hashable::getHashCode (this->ptr, this->len * QSE_SIZEOF(CHAR_TYPE));
}
bool operator== (const ThisType& ps) const
{
if (this->len != ps.len) return false;
return this->_opset.compare (this->ptr, ps.ptr, this->len) == 0;
}
bool operator!= (const ThisType& ps) const
{
return !this->operator== (ps);
}
bool operator== (const StringType& s) const
{
if (this->len != s.getLength()) return false;
return this->_opset.compare (this->ptr, s.getBuffer(), this->len) == 0;
}
bool operator!= (const StringType& s) const
{
return !this->operator== (s);
}
operator const CHAR_TYPE* () const
{
return this->ptr;
}
const CHAR_TYPE* getData() const
{
return this->ptr;
}
qse_size_t getLength() const
{
return this->len;
}
protected:
const CHAR_TYPE* ptr;
qse_size_t len;
OPSET _opset;
};
/////////////////////////////////
QSE_END_NAMESPACE(QSE)
/////////////////////////////////

View File

@ -181,11 +181,14 @@ struct MbStringOpset
class WcString: public StrBase<qse_wchar_t, QSE_WT('\0'), WcStringOpset>
{
public:
private:
typedef StrBase<qse_wchar_t, QSE_WT('\0'), WcStringOpset> ParentType;
public:
WcString (): ParentType() {}
WcString (Mmgr* mmgr): ParentType(mmgr) {}
WcString (int capacity): ParentType(capacity) {}
WcString (Mmgr* mmgr, int capacity): ParentType(mmgr, capacity) {}
WcString (qse_size_t capacity): ParentType(capacity) {}
WcString (Mmgr* mmgr, qse_size_t capacity): ParentType(mmgr, capacity) {}
WcString (const qse_wchar_t* str): ParentType(str) {}
@ -207,11 +210,14 @@ public:
class MbString: public StrBase<qse_mchar_t, QSE_MT('\0'), MbStringOpset>
{
public:
private:
typedef StrBase<qse_mchar_t, QSE_MT('\0'), MbStringOpset> ParentType;
public:
MbString (): ParentType() {}
MbString (Mmgr* mmgr): ParentType(mmgr) {}
MbString (int capacity): ParentType(capacity) {}
MbString (Mmgr* mmgr, int capacity): ParentType(mmgr, capacity) {}
MbString (qse_size_t capacity): ParentType(capacity) {}
MbString (Mmgr* mmgr, qse_size_t capacity): ParentType(mmgr, capacity) {}
MbString (const qse_mchar_t* str): ParentType(str) {}
@ -231,10 +237,38 @@ public:
int formatv (const qse_mchar_t* fmt, va_list ap);
};
class WcPtrString: public PtrStrBase<qse_wchar_t, QSE_MT('\0'), WcStringOpset>
{
private:
typedef PtrStrBase<qse_wchar_t, QSE_MT('\0'), WcStringOpset> ParentType;
public:
WcPtrString () {}
WcPtrString (const qse_wchar_t* ptr): ParentType(ptr) {}
WcPtrString (const qse_wchar_t* ptr, qse_size_t len): ParentType(ptr, len) {}
};
class MbPtrString: public PtrStrBase<qse_mchar_t, QSE_MT('\0'), MbStringOpset>
{
private:
typedef PtrStrBase<qse_mchar_t, QSE_MT('\0'), MbStringOpset> ParentType;
public:
MbPtrString () {}
MbPtrString (const qse_mchar_t* ptr): ParentType(ptr) {}
MbPtrString (const qse_mchar_t* ptr, qse_size_t len): ParentType(ptr, len) {}
};
#if defined(QSE_CHAR_IS_MCHAR)
typedef MbString String;
typedef MbPtrString PtrString;
#else
typedef WcString String;
typedef WcPtrString PtrString;
#endif
/////////////////////////////////