aboutsummaryrefslogtreecommitdiff
path: root/lstring.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2012-01-25 19:05:40 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2012-01-25 19:05:40 -0200
commita4b96ce9a3305ae3585c0bb143fa7342c140f20b (patch)
treefbb635282c4b72dde25e5c9ffb2bc6d314419d05 /lstring.c
parent291f564485d8968fc7b0d043dda5ff91a7ce604b (diff)
downloadlua-a4b96ce9a3305ae3585c0bb143fa7342c140f20b.tar.gz
lua-a4b96ce9a3305ae3585c0bb143fa7342c140f20b.tar.bz2
lua-a4b96ce9a3305ae3585c0bb143fa7342c140f20b.zip
first implementation of long strings
Diffstat (limited to 'lstring.c')
-rw-r--r--lstring.c96
1 files changed, 77 insertions, 19 deletions
diff --git a/lstring.c b/lstring.c
index 95a8a6f1..75861cf4 100644
--- a/lstring.c
+++ b/lstring.c
@@ -18,7 +18,37 @@
18#include "lstring.h" 18#include "lstring.h"
19 19
20 20
21/*
22** equality for long strings
23*/
24int 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*/
34int 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
40unsigned 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*/
22void luaS_resize (lua_State *L, int newsize) { 52void 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
53static 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 */ 86static 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
76TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { 101/*
102** creates a new short string, inserting it into string table
103*/
104static 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*/
121static 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*/
143TString *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*/
99TString *luaS_new (lua_State *L, const char *str) { 157TString *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}