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 | } |