mirror of
https://github.com/albertodemichelis/squirrel.git
synced 2026-01-18 13:49:55 +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;
|
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()
|
void SQString::Release()
|
||||||
{
|
{
|
||||||
REMOVE_STRING(_sharedstate,this);
|
REMOVE_STRING(_sharedstate,this);
|
||||||
|
|||||||
@ -577,6 +577,41 @@ void SQStringTable::AllocNodes(SQInteger size)
|
|||||||
memset(_strings,0,sizeof(SQString*)*_numofslots);
|
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)
|
SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
|
||||||
{
|
{
|
||||||
if(len<0)
|
if(len<0)
|
||||||
|
|||||||
@ -14,6 +14,7 @@ struct SQStringTable
|
|||||||
SQStringTable(SQSharedState*ss);
|
SQStringTable(SQSharedState*ss);
|
||||||
~SQStringTable();
|
~SQStringTable();
|
||||||
SQString *Add(const SQChar *,SQInteger len);
|
SQString *Add(const SQChar *,SQInteger len);
|
||||||
|
SQString* Concat(const SQChar* a, SQInteger alen, const SQChar* b, SQInteger blen);
|
||||||
void Remove(SQString *);
|
void Remove(SQString *);
|
||||||
private:
|
private:
|
||||||
void Resize(SQInteger size);
|
void Resize(SQInteger size);
|
||||||
|
|||||||
@ -12,12 +12,33 @@ inline SQHash _hashstr (const SQChar *s, size_t l)
|
|||||||
return h;
|
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
|
struct SQString : public SQRefCounted
|
||||||
{
|
{
|
||||||
SQString(){}
|
SQString(){}
|
||||||
~SQString(){}
|
~SQString(){}
|
||||||
public:
|
public:
|
||||||
static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 );
|
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);
|
SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
|
||||||
void Release();
|
void Release();
|
||||||
SQSharedState *_sharedstate;
|
SQSharedState *_sharedstate;
|
||||||
|
|||||||
@ -322,17 +322,20 @@ bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)
|
bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)
|
||||||
{
|
{
|
||||||
SQObjectPtr a, b;
|
SQObjectPtr a, b;
|
||||||
if(!ToString(str, a)) return false;
|
if(!ToString(str, a)) return false;
|
||||||
if(!ToString(obj, b)) return false;
|
if(!ToString(obj, b)) return false;
|
||||||
SQInteger l = _string(a)->_len , ol = _string(b)->_len;
|
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, _stringval(a), sq_rsl(l));
|
||||||
memcpy(s + l, _stringval(b), sq_rsl(ol));
|
memcpy(s + l, _stringval(b), sq_rsl(ol));
|
||||||
dest = SQString::Create(_ss(this), _spval, l + ol);
|
dest = SQString::Create(_ss(this), _spval, l + ol);
|
||||||
|
#else
|
||||||
|
dest = SQString::Concat(_ss(this),_stringval(a),l,_stringval(b),ol);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1779,11 +1782,11 @@ void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
|
|||||||
for(SQInteger i=0;i<size;i++){
|
for(SQInteger i=0;i<size;i++){
|
||||||
SQObjectPtr &obj=_stack[i];
|
SQObjectPtr &obj=_stack[i];
|
||||||
if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
|
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)){
|
switch(sq_type(obj)){
|
||||||
case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break;
|
case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break;
|
||||||
case OT_INTEGER: scprintf(_SC("INTEGER " _PRINT_INT_FMT),_integer(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_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?_SC("true"):_SC("false"));break;
|
||||||
case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break;
|
case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break;
|
||||||
case OT_NULL: scprintf(_SC("NULL")); break;
|
case OT_NULL: scprintf(_SC("NULL")); break;
|
||||||
case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;
|
case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;
|
||||||
|
|||||||
Reference in New Issue
Block a user