Towards external strings
Long strings have a pointer to string contents.
This commit is contained in:
4
lgc.c
4
lgc.c
@@ -808,12 +808,12 @@ static void freeobj (lua_State *L, GCObject *o) {
|
|||||||
case LUA_VSHRSTR: {
|
case LUA_VSHRSTR: {
|
||||||
TString *ts = gco2ts(o);
|
TString *ts = gco2ts(o);
|
||||||
luaS_remove(L, ts); /* remove it from hash table */
|
luaS_remove(L, ts); /* remove it from hash table */
|
||||||
luaM_freemem(L, ts, sizelstring(ts->shrlen));
|
luaM_freemem(L, ts, sizestrshr(ts->shrlen));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_VLNGSTR: {
|
case LUA_VLNGSTR: {
|
||||||
TString *ts = gco2ts(o);
|
TString *ts = gco2ts(o);
|
||||||
luaM_freemem(L, ts, sizelstring(ts->u.lnglen));
|
luaM_freemem(L, ts, sizestrlng(ts->u.lnglen));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: lua_assert(0);
|
default: lua_assert(0);
|
||||||
|
|||||||
23
lobject.h
23
lobject.h
@@ -388,35 +388,38 @@ typedef struct GCObject {
|
|||||||
typedef struct TString {
|
typedef struct TString {
|
||||||
CommonHeader;
|
CommonHeader;
|
||||||
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
|
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
|
||||||
lu_byte shrlen; /* length for short strings, 0xFF for long strings */
|
ls_byte shrlen; /* length for short strings, negative for long strings */
|
||||||
unsigned int hash;
|
unsigned int hash;
|
||||||
union {
|
union {
|
||||||
size_t lnglen; /* length for long strings */
|
size_t lnglen; /* length for long strings */
|
||||||
struct TString *hnext; /* linked list for hash table */
|
struct TString *hnext; /* linked list for hash table */
|
||||||
} u;
|
} u;
|
||||||
char contents[1]; /* string body starts here */
|
char *contents; /* pointer to content in long strings */
|
||||||
} TString;
|
} TString;
|
||||||
|
|
||||||
|
|
||||||
|
#define strisshr(ts) ((ts)->shrlen >= 0)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Get the actual string (array of bytes) from a 'TString'. (Generic
|
** Get the actual string (array of bytes) from a 'TString'. (Generic
|
||||||
** version and specialized versions for long and short strings.)
|
** version and specialized versions for long and short strings.)
|
||||||
*/
|
*/
|
||||||
#define getlngstr(ts) check_exp((ts)->shrlen == 0xFF, (ts)->contents)
|
#define rawgetshrstr(ts) (cast_charp(&(ts)->contents))
|
||||||
#define getshrstr(ts) check_exp((ts)->shrlen != 0xFF, (ts)->contents)
|
#define getshrstr(ts) check_exp(strisshr(ts), rawgetshrstr(ts))
|
||||||
#define getstr(ts) ((ts)->contents)
|
#define getlngstr(ts) check_exp(!strisshr(ts), (ts)->contents)
|
||||||
|
#define getstr(ts) (strisshr(ts) ? rawgetshrstr(ts) : (ts)->contents)
|
||||||
|
|
||||||
|
|
||||||
/* get string length from 'TString *s' */
|
/* get string length from 'TString *ts' */
|
||||||
#define tsslen(s) \
|
#define tsslen(ts) \
|
||||||
((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen)
|
(strisshr(ts) ? cast_uint((ts)->shrlen) : (ts)->u.lnglen)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Get string and length */
|
** Get string and length */
|
||||||
#define getlstr(ts, len) \
|
#define getlstr(ts, len) \
|
||||||
((ts)->shrlen != 0xFF \
|
(strisshr(ts) \
|
||||||
? (cast_void(len = (ts)->shrlen), (ts)->contents) \
|
? (cast_void(len = (ts)->shrlen), rawgetshrstr(ts)) \
|
||||||
: (cast_void(len = (ts)->u.lnglen), (ts)->contents))
|
: (cast_void(len = (ts)->u.lnglen), (ts)->contents))
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|||||||
19
lstring.c
19
lstring.c
@@ -140,24 +140,25 @@ void luaS_init (lua_State *L) {
|
|||||||
/*
|
/*
|
||||||
** creates a new string object
|
** creates a new string object
|
||||||
*/
|
*/
|
||||||
static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
|
static TString *createstrobj (lua_State *L, size_t totalsize, int tag,
|
||||||
|
unsigned int h) {
|
||||||
TString *ts;
|
TString *ts;
|
||||||
GCObject *o;
|
GCObject *o;
|
||||||
size_t totalsize; /* total size of TString object */
|
|
||||||
totalsize = sizelstring(l);
|
|
||||||
o = luaC_newobj(L, tag, totalsize);
|
o = luaC_newobj(L, tag, totalsize);
|
||||||
ts = gco2ts(o);
|
ts = gco2ts(o);
|
||||||
ts->hash = h;
|
ts->hash = h;
|
||||||
ts->extra = 0;
|
ts->extra = 0;
|
||||||
getstr(ts)[l] = '\0'; /* ending 0 */
|
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
|
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
|
||||||
TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed);
|
size_t totalsize = sizestrlng(l);
|
||||||
|
TString *ts = createstrobj(L, totalsize, LUA_VLNGSTR, G(L)->seed);
|
||||||
ts->u.lnglen = l;
|
ts->u.lnglen = l;
|
||||||
ts->shrlen = 0xFF; /* signals that it is a long string */
|
ts->shrlen = -1; /* signals that it is a long string */
|
||||||
|
ts->contents = cast_charp(ts) + sizeof(TString);
|
||||||
|
ts->contents[l] = '\0'; /* ending 0 */
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +195,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
|
|||||||
TString **list = &tb->hash[lmod(h, tb->size)];
|
TString **list = &tb->hash[lmod(h, tb->size)];
|
||||||
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
|
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
|
||||||
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
|
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
|
||||||
if (l == ts->shrlen && (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) {
|
if (l == cast_uint(ts->shrlen) &&
|
||||||
|
(memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) {
|
||||||
/* found! */
|
/* found! */
|
||||||
if (isdead(g, ts)) /* dead (but not collected yet)? */
|
if (isdead(g, ts)) /* dead (but not collected yet)? */
|
||||||
changewhite(ts); /* resurrect it */
|
changewhite(ts); /* resurrect it */
|
||||||
@@ -206,8 +208,9 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
|
|||||||
growstrtab(L, tb);
|
growstrtab(L, tb);
|
||||||
list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */
|
list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */
|
||||||
}
|
}
|
||||||
ts = createstrobj(L, l, LUA_VSHRSTR, h);
|
ts = createstrobj(L, sizestrshr(l), LUA_VSHRSTR, h);
|
||||||
ts->shrlen = cast_byte(l);
|
ts->shrlen = cast_byte(l);
|
||||||
|
getshrstr(ts)[l] = '\0'; /* ending 0 */
|
||||||
memcpy(getshrstr(ts), str, l * sizeof(char));
|
memcpy(getshrstr(ts), str, l * sizeof(char));
|
||||||
ts->u.hnext = *list;
|
ts->u.hnext = *list;
|
||||||
*list = ts;
|
*list = ts;
|
||||||
|
|||||||
12
lstring.h
12
lstring.h
@@ -20,10 +20,18 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Size of a TString: Size of the header plus space for the string
|
** Size of a short TString: Size of the header plus space for the string
|
||||||
** itself (including final '\0').
|
** itself (including final '\0').
|
||||||
*/
|
*/
|
||||||
#define sizelstring(l) (offsetof(TString, contents) + ((l) + 1) * sizeof(char))
|
#define sizestrshr(l) \
|
||||||
|
(offsetof(TString, contents) + ((l) + 1) * sizeof(char))
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Size of a long TString: Size of the header plus space for the string
|
||||||
|
** itself (including final '\0').
|
||||||
|
*/
|
||||||
|
#define sizestrlng(l) (sizeof(TString) + ((l) + 1) * sizeof(char))
|
||||||
|
|
||||||
|
|
||||||
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
|
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
|
||||||
(sizeof(s)/sizeof(char))-1))
|
(sizeof(s)/sizeof(char))-1))
|
||||||
|
|||||||
Reference in New Issue
Block a user