mirror of
https://github.com/albertodemichelis/squirrel.git
synced 2026-01-11 14:08:41 +01:00
faster string cat
This commit is contained in:
@ -52,6 +52,12 @@ SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)
|
||||
return str;
|
||||
}
|
||||
|
||||
SQString* SQString::Concat(SQSharedState* ss, const SQChar* a, SQInteger alen, const SQChar* b, SQInteger blen)
|
||||
{
|
||||
SQString* str = ss->_stringtable->Concat(a, alen, b, blen);
|
||||
return str;
|
||||
}
|
||||
|
||||
void SQString::Release()
|
||||
{
|
||||
REMOVE_STRING(_sharedstate,this);
|
||||
|
||||
@ -577,6 +577,41 @@ void SQStringTable::AllocNodes(SQInteger size)
|
||||
memset(_strings,0,sizeof(SQString*)*_numofslots);
|
||||
}
|
||||
|
||||
SQString* SQStringTable::Concat(const SQChar* a, SQInteger alen, const SQChar* b, SQInteger blen)
|
||||
{
|
||||
SQHash newhash = ::_hashstr2(a, alen, b, blen);
|
||||
SQHash h = newhash & (_numofslots - 1);
|
||||
SQString* s;
|
||||
SQInteger len = alen + blen;
|
||||
for (s = _strings[h]; s; s = s->_next) {
|
||||
if (s->_len == len) {
|
||||
if ((!memcmp(a, s->_val, sq_rsl(alen)))
|
||||
&& (!memcmp(b, &s->_val[alen], sq_rsl(blen)))) {
|
||||
return s; //found
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
SQString* t = (SQString*)SQ_MALLOC(sq_rsl(len) + sizeof(SQString));
|
||||
new (t) SQString;
|
||||
t->_sharedstate = _sharedstate;
|
||||
memcpy(t->_val, a, sq_rsl(alen));
|
||||
memcpy(&t->_val[alen], b, sq_rsl(blen));
|
||||
t->_val[len] = _SC('\0');
|
||||
t->_len = len;
|
||||
t->_hash = newhash;
|
||||
t->_next = _strings[h];
|
||||
_strings[h] = t;
|
||||
_slotused++;
|
||||
#ifdef _DEBUG
|
||||
SQHash old_newhash = ::_hashstr(t->_val, t->_len);
|
||||
assert(old_newhash == newhash);
|
||||
#endif
|
||||
if (_slotused > _numofslots) /* too crowded? */
|
||||
Resize(_numofslots * 2);
|
||||
return t;
|
||||
}
|
||||
|
||||
SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
|
||||
{
|
||||
if(len<0)
|
||||
|
||||
@ -14,6 +14,7 @@ struct SQStringTable
|
||||
SQStringTable(SQSharedState*ss);
|
||||
~SQStringTable();
|
||||
SQString *Add(const SQChar *,SQInteger len);
|
||||
SQString* Concat(const SQChar* a, SQInteger alen, const SQChar* b, SQInteger blen);
|
||||
void Remove(SQString *);
|
||||
private:
|
||||
void Resize(SQInteger size);
|
||||
|
||||
@ -12,12 +12,33 @@ inline SQHash _hashstr (const SQChar *s, size_t l)
|
||||
return h;
|
||||
}
|
||||
|
||||
inline SQHash _hashstr2(const SQChar* as, size_t al, const SQChar* bs, size_t bl)
|
||||
{
|
||||
size_t l = al + bl;
|
||||
SQHash h = (SQHash)l; /* seed */
|
||||
SQInteger step = (SQInteger)((l >> 5) + 1); /* if string is too long, don't hash all its chars */
|
||||
SQInteger l1 = (SQInteger)l;
|
||||
for (; l1 >= step; l1 -= step) {
|
||||
SQInteger idx = l1 - 1 - al;
|
||||
if (idx < 0) {
|
||||
break;
|
||||
}
|
||||
h = h ^ ((h << 5) + (h >> 2) + ((unsigned short)bs[idx]));
|
||||
}
|
||||
for (; l1 >= step; l1 -= step) {
|
||||
SQInteger idx = l1 - 1;
|
||||
h = h ^ ((h << 5) + (h >> 2) + ((unsigned short)as[idx]));
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
struct SQString : public SQRefCounted
|
||||
{
|
||||
SQString(){}
|
||||
~SQString(){}
|
||||
public:
|
||||
static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 );
|
||||
static SQString* Concat(SQSharedState* ss, const SQChar* a, SQInteger alen, const SQChar* b, SQInteger blen);
|
||||
SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
|
||||
void Release();
|
||||
SQSharedState *_sharedstate;
|
||||
|
||||
@ -322,17 +322,20 @@ bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)
|
||||
{
|
||||
SQObjectPtr a, b;
|
||||
if(!ToString(str, a)) return false;
|
||||
if(!ToString(obj, b)) return false;
|
||||
SQInteger l = _string(a)->_len , ol = _string(b)->_len;
|
||||
SQChar *s = _sp(sq_rsl(l + ol + 1));
|
||||
#ifdef SQ_NO_FAST_STRINGCAT
|
||||
SQChar* s = _sp(sq_rsl(l + ol + 1));
|
||||
memcpy(s, _stringval(a), sq_rsl(l));
|
||||
memcpy(s + l, _stringval(b), sq_rsl(ol));
|
||||
dest = SQString::Create(_ss(this), _spval, l + ol);
|
||||
#else
|
||||
dest = SQString::Concat(_ss(this),_stringval(a),l,_stringval(b),ol);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1779,11 +1782,11 @@ void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
|
||||
for(SQInteger i=0;i<size;i++){
|
||||
SQObjectPtr &obj=_stack[i];
|
||||
if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
|
||||
scprintf(_SC("[" _PRINT_INT_FMT "]:"),n);
|
||||
scprintf(_SC("[") _PRINT_INT_FMT _SC("]:"),n);
|
||||
switch(sq_type(obj)){
|
||||
case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break;
|
||||
case OT_INTEGER: scprintf(_SC("INTEGER " _PRINT_INT_FMT),_integer(obj));break;
|
||||
case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;
|
||||
case OT_INTEGER: scprintf(_SC("INTEGER ") _PRINT_INT_FMT,_integer(obj));break;
|
||||
case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?_SC("true"):_SC("false"));break;
|
||||
case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break;
|
||||
case OT_NULL: scprintf(_SC("NULL")); break;
|
||||
case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;
|
||||
|
||||
Reference in New Issue
Block a user