diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2012-01-25 19:05:40 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2012-01-25 19:05:40 -0200 |
| commit | a4b96ce9a3305ae3585c0bb143fa7342c140f20b (patch) | |
| tree | fbb635282c4b72dde25e5c9ffb2bc6d314419d05 /lstring.c | |
| parent | 291f564485d8968fc7b0d043dda5ff91a7ce604b (diff) | |
| download | lua-a4b96ce9a3305ae3585c0bb143fa7342c140f20b.tar.gz lua-a4b96ce9a3305ae3585c0bb143fa7342c140f20b.tar.bz2 lua-a4b96ce9a3305ae3585c0bb143fa7342c140f20b.zip | |
first implementation of long strings
Diffstat (limited to 'lstring.c')
| -rw-r--r-- | lstring.c | 96 |
1 files changed, 77 insertions, 19 deletions
| @@ -18,7 +18,37 @@ | |||
| 18 | #include "lstring.h" | 18 | #include "lstring.h" |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | /* | ||
| 22 | ** equality for long strings | ||
| 23 | */ | ||
| 24 | int luaS_eqlngstr (TString *a, TString *b) { | ||
| 25 | size_t len = a->tsv.len; | ||
| 26 | lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR); | ||
| 27 | return (len == b->tsv.len) && (memcmp(getstr(a), getstr(b), len) == 0); | ||
| 28 | } | ||
| 29 | |||
| 30 | |||
| 31 | /* | ||
| 32 | ** equality for strings | ||
| 33 | */ | ||
| 34 | int luaS_eqstr (TString *a, TString *b) { | ||
| 35 | return (a->tsv.tt == b->tsv.tt) && | ||
| 36 | (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b)); | ||
| 37 | } | ||
| 38 | |||
| 39 | |||
| 40 | unsigned int luaS_hash (const char *str, size_t l) { | ||
| 41 | unsigned int h = cast(unsigned int, l); /* seed */ | ||
| 42 | size_t l1; | ||
| 43 | for (l1 = 0; l1 < l; l1++) | ||
| 44 | h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1])); | ||
| 45 | return h; | ||
| 46 | } | ||
| 47 | |||
| 21 | 48 | ||
| 49 | /* | ||
| 50 | ** resizes the string table | ||
| 51 | */ | ||
| 22 | void luaS_resize (lua_State *L, int newsize) { | 52 | void luaS_resize (lua_State *L, int newsize) { |
| 23 | int i; | 53 | int i; |
| 24 | stringtable *tb = &G(L)->strt; | 54 | stringtable *tb = &G(L)->strt; |
| @@ -50,36 +80,47 @@ void luaS_resize (lua_State *L, int newsize) { | |||
| 50 | } | 80 | } |
| 51 | 81 | ||
| 52 | 82 | ||
| 53 | static TString *newlstr (lua_State *L, const char *str, size_t l, | 83 | /* |
| 54 | unsigned int h) { | 84 | ** creates a new string object |
| 55 | size_t totalsize; /* total size of TString object */ | 85 | */ |
| 56 | GCObject **list; /* (pointer to) list where it will be inserted */ | 86 | static TString *createstrobj (lua_State *L, const char *str, size_t l, |
| 87 | int tag, unsigned int h, GCObject **list) { | ||
| 57 | TString *ts; | 88 | TString *ts; |
| 58 | stringtable *tb = &G(L)->strt; | 89 | size_t totalsize; /* total size of TString object */ |
| 59 | if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) | ||
| 60 | luaM_toobig(L); | ||
| 61 | if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) | ||
| 62 | luaS_resize(L, tb->size*2); /* too crowded */ | ||
| 63 | totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); | 90 | totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); |
| 64 | list = &tb->hash[lmod(h, tb->size)]; | 91 | ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts; |
| 65 | ts = &luaC_newobj(L, LUA_TSTRING, totalsize, list, 0)->ts; | ||
| 66 | ts->tsv.len = l; | 92 | ts->tsv.len = l; |
| 67 | ts->tsv.hash = h; | 93 | ts->tsv.hash = h; |
| 68 | ts->tsv.extra = 0; | 94 | ts->tsv.extra = 0; |
| 69 | memcpy(ts+1, str, l*sizeof(char)); | 95 | memcpy(ts+1, str, l*sizeof(char)); |
| 70 | ((char *)(ts+1))[l] = '\0'; /* ending 0 */ | 96 | ((char *)(ts+1))[l] = '\0'; /* ending 0 */ |
| 71 | tb->nuse++; | ||
| 72 | return ts; | 97 | return ts; |
| 73 | } | 98 | } |
| 74 | 99 | ||
| 75 | 100 | ||
| 76 | TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | 101 | /* |
| 102 | ** creates a new short string, inserting it into string table | ||
| 103 | */ | ||
| 104 | static TString *newshrstr (lua_State *L, const char *str, size_t l, | ||
| 105 | unsigned int h) { | ||
| 106 | GCObject **list; /* (pointer to) list where it will be inserted */ | ||
| 107 | stringtable *tb = &G(L)->strt; | ||
| 108 | TString *s; | ||
| 109 | if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) | ||
| 110 | luaS_resize(L, tb->size*2); /* too crowded */ | ||
| 111 | list = &tb->hash[lmod(h, tb->size)]; | ||
| 112 | s = createstrobj(L, str, l, LUA_TSHRSTR, h, list); | ||
| 113 | tb->nuse++; | ||
| 114 | return s; | ||
| 115 | } | ||
| 116 | |||
| 117 | |||
| 118 | /* | ||
| 119 | ** checks whether short string exists and reuses it or creates a new one | ||
| 120 | */ | ||
| 121 | static TString *internshrstr (lua_State *L, const char *str, size_t l) { | ||
| 77 | GCObject *o; | 122 | GCObject *o; |
| 78 | unsigned int h = cast(unsigned int, l); /* seed */ | 123 | unsigned int h = luaS_hash(str, l); |
| 79 | size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ | ||
| 80 | size_t l1; | ||
| 81 | for (l1=l; l1>=step; l1-=step) /* compute hash */ | ||
| 82 | h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); | ||
| 83 | for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; | 124 | for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; |
| 84 | o != NULL; | 125 | o != NULL; |
| 85 | o = gch(o)->next) { | 126 | o = gch(o)->next) { |
| @@ -92,10 +133,27 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | |||
| 92 | return ts; | 133 | return ts; |
| 93 | } | 134 | } |
| 94 | } | 135 | } |
| 95 | return newlstr(L, str, l, h); /* not found; create a new string */ | 136 | return newshrstr(L, str, l, h); /* not found; create a new string */ |
| 96 | } | 137 | } |
| 97 | 138 | ||
| 98 | 139 | ||
| 140 | /* | ||
| 141 | ** new string (with explicit length) | ||
| 142 | */ | ||
| 143 | TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | ||
| 144 | if (l <= LUA_MAXSHORTLEN) /* short string? */ | ||
| 145 | return internshrstr(L, str, l); | ||
| 146 | else { | ||
| 147 | if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) | ||
| 148 | luaM_toobig(L); | ||
| 149 | return createstrobj(L, str, l, LUA_TLNGSTR, 0, NULL); | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | |||
| 154 | /* | ||
| 155 | ** new zero-terminated string | ||
| 156 | */ | ||
| 99 | TString *luaS_new (lua_State *L, const char *str) { | 157 | TString *luaS_new (lua_State *L, const char *str) { |
| 100 | return luaS_newlstr(L, str, strlen(str)); | 158 | return luaS_newlstr(L, str, strlen(str)); |
| 101 | } | 159 | } |
