aboutsummaryrefslogtreecommitdiff
path: root/src/buffer.c
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2003-05-25 01:54:13 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2003-05-25 01:54:13 +0000
commit0f6c8d50a99997ac7829864b1c93362b50f1bbf3 (patch)
treed0cefe3a05484e65b7b7e79d8cae4a1d2e6d19fb /src/buffer.c
parentc1ef3e7103cc652d2004ef1ddc9409b946207f33 (diff)
downloadluasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.tar.gz
luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.tar.bz2
luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.zip
Porting to LUA 5.0 final
Diffstat (limited to 'src/buffer.c')
-rw-r--r--src/buffer.c275
1 files changed, 91 insertions, 184 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 73df8b3..c5ef66c 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1,28 +1,24 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* Buffered input/output routines 2* Buffered input/output routines
3* Lua methods:
4* send: unbuffered send using C base_send
5* receive: buffered read using C base_receive
6* 3*
7* RCS ID: $Id$ 4* RCS ID: $Id$
8\*=========================================================================*/ 5\*=========================================================================*/
9#include <lua.h> 6#include <lua.h>
10#include <lauxlib.h> 7#include <lauxlib.h>
11 8
12#include "lsbuf.h" 9#include "error.h"
10#include "aux.h"
11#include "buf.h"
13 12
14/*=========================================================================*\ 13/*=========================================================================*\
15* Internal function prototypes. 14* Internal function prototypes
16\*=========================================================================*/ 15\*=========================================================================*/
17static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len,
18 size_t *done);
19static int recvraw(lua_State *L, p_buf buf, size_t wanted); 16static int recvraw(lua_State *L, p_buf buf, size_t wanted);
20static int recvdosline(lua_State *L, p_buf buf); 17static int recvline(lua_State *L, p_buf buf);
21static int recvunixline(lua_State *L, p_buf buf);
22static int recvall(lua_State *L, p_buf buf); 18static int recvall(lua_State *L, p_buf buf);
23 19static int buf_get(p_buf buf, const char **data, size_t *count);
24static int buf_contents(lua_State *L, p_buf buf, cchar **data, size_t *len); 20static void buf_skip(p_buf buf, size_t count);
25static void buf_skip(lua_State *L, p_buf buf, size_t len); 21static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent);
26 22
27/*=========================================================================*\ 23/*=========================================================================*\
28* Exported functions 24* Exported functions
@@ -37,98 +33,69 @@ void buf_open(lua_State *L)
37 33
38/*-------------------------------------------------------------------------*\ 34/*-------------------------------------------------------------------------*\
39* Initializes C structure 35* Initializes C structure
40* Input
41* buf: buffer structure to initialize
42* base: socket object to associate with buffer structure
43\*-------------------------------------------------------------------------*/ 36\*-------------------------------------------------------------------------*/
44void buf_init(lua_State *L, p_buf buf, p_base base) 37void buf_init(p_buf buf, p_io io, p_tm tm)
45{ 38{
46 (void) L; 39 buf->first = buf->last = 0;
47 buf->buf_first = buf->buf_last = 0; 40 buf->io = io;
48 buf->buf_base = base; 41 buf->tm = tm;
49} 42}
50 43
51/*-------------------------------------------------------------------------*\ 44/*-------------------------------------------------------------------------*\
52* Send data through buffered object 45* Send data through buffered object
53* Input
54* buf: buffer structure to be used
55* Lua Input: self, a_1 [, a_2, a_3 ... a_n]
56* self: socket object
57* a_i: strings to be sent.
58* Lua Returns
59* On success: nil, followed by the total number of bytes sent
60* On error: error message
61\*-------------------------------------------------------------------------*/ 46\*-------------------------------------------------------------------------*/
62int buf_send(lua_State *L, p_buf buf) 47int buf_meth_send(lua_State *L, p_buf buf)
63{ 48{
64 int top = lua_gettop(L); 49 int top = lua_gettop(L);
65 size_t total = 0; 50 size_t total = 0;
66 int err = PRIV_DONE; 51 int arg, err = IO_DONE;
67 int arg; 52 p_tm tm = buf->tm;
68 p_base base = buf->buf_base; 53 tm_markstart(tm);
69 tm_markstart(&base->base_tm);
70 for (arg = 2; arg <= top; arg++) { /* first arg is socket object */ 54 for (arg = 2; arg <= top; arg++) { /* first arg is socket object */
71 size_t done, len; 55 size_t sent, count;
72 cchar *data = luaL_optlstring(L, arg, NULL, &len); 56 const char *data = luaL_optlstring(L, arg, NULL, &count);
73 if (!data || err != PRIV_DONE) break; 57 if (!data || err != IO_DONE) break;
74 err = sendraw(L, buf, data, len, &done); 58 err = sendraw(buf, data, count, &sent);
75 total += done; 59 total += sent;
76 } 60 }
77 priv_pusherror(L, err);
78 lua_pushnumber(L, total); 61 lua_pushnumber(L, total);
62 error_push(L, err);
79#ifdef LUASOCKET_DEBUG 63#ifdef LUASOCKET_DEBUG
80 /* push time elapsed during operation as the last return value */ 64 /* push time elapsed during operation as the last return value */
81 lua_pushnumber(L, tm_getelapsed(&base->base_tm)/1000.0); 65 lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0);
82#endif 66#endif
83 return lua_gettop(L) - top; 67 return lua_gettop(L) - top;
84} 68}
85 69
86/*-------------------------------------------------------------------------*\ 70/*-------------------------------------------------------------------------*\
87* Receive data from a buffered object 71* Receive data from a buffered object
88* Input
89* buf: buffer structure to be used
90* Lua Input: self [pat_1, pat_2 ... pat_n]
91* self: socket object
92* pat_i: may be one of the following
93* "*l": reads a text line, defined as a string of caracters terminates
94* by a LF character, preceded or not by a CR character. This is
95* the default pattern
96* "*lu": reads a text line, terminanted by a CR character only. (Unix mode)
97* "*a": reads until connection closed
98* number: reads 'number' characters from the socket object
99* Lua Returns
100* On success: one string for each pattern
101* On error: all strings for which there was no error, followed by one
102* nil value for the remaining strings, followed by an error code
103\*-------------------------------------------------------------------------*/ 72\*-------------------------------------------------------------------------*/
104int buf_receive(lua_State *L, p_buf buf) 73int buf_meth_receive(lua_State *L, p_buf buf)
105{ 74{
106 int top = lua_gettop(L); 75 int top = lua_gettop(L);
107 int arg, err = PRIV_DONE; 76 int arg, err = IO_DONE;
108 p_base base = buf->buf_base; 77 p_tm tm = buf->tm;
109 tm_markstart(&base->base_tm); 78 tm_markstart(tm);
110 /* push default pattern if need be */ 79 /* push default pattern if need be */
111 if (top < 2) { 80 if (top < 2) {
112 lua_pushstring(L, "*l"); 81 lua_pushstring(L, "*l");
113 top++; 82 top++;
114 } 83 }
115 /* make sure we have enough stack space */ 84 /* make sure we have enough stack space for all returns */
116 luaL_checkstack(L, top+LUA_MINSTACK, "too many arguments"); 85 luaL_checkstack(L, top+LUA_MINSTACK, "too many arguments");
117 /* receive all patterns */ 86 /* receive all patterns */
118 for (arg = 2; arg <= top && err == PRIV_DONE; arg++) { 87 for (arg = 2; arg <= top && err == IO_DONE; arg++) {
119 if (!lua_isnumber(L, arg)) { 88 if (!lua_isnumber(L, arg)) {
120 static cchar *patternnames[] = {"*l", "*lu", "*a", "*w", NULL}; 89 static const char *patternnames[] = {"*l", "*a", NULL};
121 cchar *pattern = luaL_optstring(L, arg, NULL); 90 const char *pattern = lua_isnil(L, arg) ?
91 "*l" : luaL_checkstring(L, arg);
122 /* get next pattern */ 92 /* get next pattern */
123 switch (luaL_findstring(pattern, patternnames)) { 93 switch (luaL_findstring(pattern, patternnames)) {
124 case 0: /* DOS line pattern */ 94 case 0: /* line pattern */
125 err = recvdosline(L, buf); break; 95 err = recvline(L, buf); break;
126 case 1: /* Unix line pattern */ 96 case 1: /* until closed pattern */
127 err = recvunixline(L, buf); break; 97 err = recvall(L, buf);
128 case 2: /* Until closed pattern */ 98 if (err == IO_CLOSED) err = IO_DONE;
129 err = recvall(L, buf); break;
130 case 3: /* Word pattern */
131 luaL_argcheck(L, 0, arg, "word patterns are deprecated");
132 break; 99 break;
133 default: /* else it is an error */ 100 default: /* else it is an error */
134 luaL_argcheck(L, 0, arg, "invalid receive pattern"); 101 luaL_argcheck(L, 0, arg, "invalid receive pattern");
@@ -140,25 +107,20 @@ int buf_receive(lua_State *L, p_buf buf)
140 /* push nil for each pattern after an error */ 107 /* push nil for each pattern after an error */
141 for ( ; arg <= top; arg++) lua_pushnil(L); 108 for ( ; arg <= top; arg++) lua_pushnil(L);
142 /* last return is an error code */ 109 /* last return is an error code */
143 priv_pusherror(L, err); 110 error_push(L, err);
144#ifdef LUASOCKET_DEBUG 111#ifdef LUASOCKET_DEBUG
145 /* push time elapsed during operation as the last return value */ 112 /* push time elapsed during operation as the last return value */
146 lua_pushnumber(L, tm_getelapsed(&base->base_tm)/1000.0); 113 lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0);
147#endif 114#endif
148 return lua_gettop(L) - top; 115 return lua_gettop(L) - top;
149} 116}
150 117
151/*-------------------------------------------------------------------------*\ 118/*-------------------------------------------------------------------------*\
152* Determines if there is any data in the read buffer 119* Determines if there is any data in the read buffer
153* Input
154* buf: buffer structure to be used
155* Returns
156* 1 if empty, 0 if there is data
157\*-------------------------------------------------------------------------*/ 120\*-------------------------------------------------------------------------*/
158int buf_isempty(lua_State *L, p_buf buf) 121int buf_isempty(p_buf buf)
159{ 122{
160 (void) L; 123 return buf->first >= buf->last;
161 return buf->buf_first >= buf->buf_last;
162} 124}
163 125
164/*=========================================================================*\ 126/*=========================================================================*\
@@ -166,24 +128,16 @@ int buf_isempty(lua_State *L, p_buf buf)
166\*=========================================================================*/ 128\*=========================================================================*/
167/*-------------------------------------------------------------------------*\ 129/*-------------------------------------------------------------------------*\
168* Sends a raw block of data through a buffered object. 130* Sends a raw block of data through a buffered object.
169* Input
170* buf: buffer structure to be used
171* data: data to be sent
172* len: number of bytes to send
173* Output
174* sent: number of bytes sent
175* Returns
176* operation error code.
177\*-------------------------------------------------------------------------*/ 131\*-------------------------------------------------------------------------*/
178static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len, 132static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
179 size_t *sent)
180{ 133{
181 p_base base = buf->buf_base; 134 p_io io = buf->io;
135 p_tm tm = buf->tm;
182 size_t total = 0; 136 size_t total = 0;
183 int err = PRIV_DONE; 137 int err = IO_DONE;
184 while (total < len && err == PRIV_DONE) { 138 while (total < count && err == IO_DONE) {
185 size_t done; 139 size_t done;
186 err = base->base_send(L, base, data + total, len - total, &done); 140 err = io->send(io->ctx, data+total, count-total, &done, tm_get(tm));
187 total += done; 141 total += done;
188 } 142 }
189 *sent = total; 143 *sent = total;
@@ -192,25 +146,21 @@ static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len,
192 146
193/*-------------------------------------------------------------------------*\ 147/*-------------------------------------------------------------------------*\
194* Reads a raw block of data from a buffered object. 148* Reads a raw block of data from a buffered object.
195* Input
196* buf: buffer structure
197* wanted: number of bytes to be read
198* Returns
199* operation error code.
200\*-------------------------------------------------------------------------*/ 149\*-------------------------------------------------------------------------*/
201static int recvraw(lua_State *L, p_buf buf, size_t wanted) 150static
151int recvraw(lua_State *L, p_buf buf, size_t wanted)
202{ 152{
203 int err = PRIV_DONE; 153 int err = IO_DONE;
204 size_t total = 0; 154 size_t total = 0;
205 luaL_Buffer b; 155 luaL_Buffer b;
206 luaL_buffinit(L, &b); 156 luaL_buffinit(L, &b);
207 while (total < wanted && err == PRIV_DONE) { 157 while (total < wanted && err == IO_DONE) {
208 size_t len; cchar *data; 158 size_t count; const char *data;
209 err = buf_contents(L, buf, &data, &len); 159 err = buf_get(buf, &data, &count);
210 len = MIN(len, wanted - total); 160 count = MIN(count, wanted - total);
211 luaL_addlstring(&b, data, len); 161 luaL_addlstring(&b, data, count);
212 buf_skip(L, buf, len); 162 buf_skip(buf, count);
213 total += len; 163 total += count;
214 } 164 }
215 luaL_pushresult(&b); 165 luaL_pushresult(&b);
216 return err; 166 return err;
@@ -218,21 +168,18 @@ static int recvraw(lua_State *L, p_buf buf, size_t wanted)
218 168
219/*-------------------------------------------------------------------------*\ 169/*-------------------------------------------------------------------------*\
220* Reads everything until the connection is closed 170* Reads everything until the connection is closed
221* Input
222* buf: buffer structure
223* Result
224* operation error code.
225\*-------------------------------------------------------------------------*/ 171\*-------------------------------------------------------------------------*/
226static int recvall(lua_State *L, p_buf buf) 172static
173int recvall(lua_State *L, p_buf buf)
227{ 174{
228 int err = PRIV_DONE; 175 int err = IO_DONE;
229 luaL_Buffer b; 176 luaL_Buffer b;
230 luaL_buffinit(L, &b); 177 luaL_buffinit(L, &b);
231 while (err == PRIV_DONE) { 178 while (err == IO_DONE) {
232 cchar *data; size_t len; 179 const char *data; size_t count;
233 err = buf_contents(L, buf, &data, &len); 180 err = buf_get(buf, &data, &count);
234 luaL_addlstring(&b, data, len); 181 luaL_addlstring(&b, data, count);
235 buf_skip(L, buf, len); 182 buf_skip(buf, count);
236 } 183 }
237 luaL_pushresult(&b); 184 luaL_pushresult(&b);
238 return err; 185 return err;
@@ -241,61 +188,27 @@ static int recvall(lua_State *L, p_buf buf)
241/*-------------------------------------------------------------------------*\ 188/*-------------------------------------------------------------------------*\
242* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF 189* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
243* are not returned by the function and are discarded from the buffer. 190* are not returned by the function and are discarded from the buffer.
244* Input
245* buf: buffer structure
246* Result
247* operation error code. PRIV_DONE, PRIV_TIMEOUT or PRIV_CLOSED
248\*-------------------------------------------------------------------------*/ 191\*-------------------------------------------------------------------------*/
249static int recvdosline(lua_State *L, p_buf buf) 192static
193int recvline(lua_State *L, p_buf buf)
250{ 194{
251 int err = 0; 195 int err = 0;
252 luaL_Buffer b; 196 luaL_Buffer b;
253 luaL_buffinit(L, &b); 197 luaL_buffinit(L, &b);
254 while (err == PRIV_DONE) { 198 while (err == IO_DONE) {
255 size_t len, pos; cchar *data; 199 size_t count, pos; const char *data;
256 err = buf_contents(L, buf, &data, &len); 200 err = buf_get(buf, &data, &count);
257 pos = 0; 201 pos = 0;
258 while (pos < len && data[pos] != '\n') { 202 while (pos < count && data[pos] != '\n') {
259 /* we ignore all \r's */ 203 /* we ignore all \r's */
260 if (data[pos] != '\r') luaL_putchar(&b, data[pos]); 204 if (data[pos] != '\r') luaL_putchar(&b, data[pos]);
261 pos++; 205 pos++;
262 } 206 }
263 if (pos < len) { /* found '\n' */ 207 if (pos < count) { /* found '\n' */
264 buf_skip(L, buf, pos+1); /* skip '\n' too */ 208 buf_skip(buf, pos+1); /* skip '\n' too */
265 break; /* we are done */
266 } else /* reached the end of the buffer */
267 buf_skip(L, buf, pos);
268 }
269 luaL_pushresult(&b);
270 return err;
271}
272
273/*-------------------------------------------------------------------------*\
274* Reads a line terminated by a LF character, which is not returned by
275* the function, and is skipped in the buffer.
276* Input
277* buf: buffer structure
278* Returns
279* operation error code. PRIV_DONE, PRIV_TIMEOUT or PRIV_CLOSED
280\*-------------------------------------------------------------------------*/
281static int recvunixline(lua_State *L, p_buf buf)
282{
283 int err = PRIV_DONE;
284 luaL_Buffer b;
285 luaL_buffinit(L, &b);
286 while (err == 0) {
287 size_t pos, len; cchar *data;
288 err = buf_contents(L, buf, &data, &len);
289 pos = 0;
290 while (pos < len && data[pos] != '\n') {
291 luaL_putchar(&b, data[pos]);
292 pos++;
293 }
294 if (pos < len) { /* found '\n' */
295 buf_skip(L, buf, pos+1); /* skip '\n' too */
296 break; /* we are done */ 209 break; /* we are done */
297 } else /* reached the end of the buffer */ 210 } else /* reached the end of the buffer */
298 buf_skip(L, buf, pos); 211 buf_skip(buf, pos);
299 } 212 }
300 luaL_pushresult(&b); 213 luaL_pushresult(&b);
301 return err; 214 return err;
@@ -303,38 +216,32 @@ static int recvunixline(lua_State *L, p_buf buf)
303 216
304/*-------------------------------------------------------------------------*\ 217/*-------------------------------------------------------------------------*\
305* Skips a given number of bytes in read buffer 218* Skips a given number of bytes in read buffer
306* Input
307* buf: buffer structure
308* len: number of bytes to skip
309\*-------------------------------------------------------------------------*/ 219\*-------------------------------------------------------------------------*/
310static void buf_skip(lua_State *L, p_buf buf, size_t len) 220static
221void buf_skip(p_buf buf, size_t count)
311{ 222{
312 buf->buf_first += len; 223 buf->first += count;
313 if (buf_isempty(L, buf)) buf->buf_first = buf->buf_last = 0; 224 if (buf_isempty(buf))
225 buf->first = buf->last = 0;
314} 226}
315 227
316/*-------------------------------------------------------------------------*\ 228/*-------------------------------------------------------------------------*\
317* Return any data available in buffer, or get more data from transport layer 229* Return any data available in buffer, or get more data from transport layer
318* if buffer is empty. 230* if buffer is empty.
319* Input
320* buf: buffer structure
321* Output
322* data: pointer to buffer start
323* len: buffer buffer length
324* Returns
325* PRIV_DONE, PRIV_CLOSED, PRIV_TIMEOUT ...
326\*-------------------------------------------------------------------------*/ 231\*-------------------------------------------------------------------------*/
327static int buf_contents(lua_State *L, p_buf buf, cchar **data, size_t *len) 232static
233int buf_get(p_buf buf, const char **data, size_t *count)
328{ 234{
329 int err = PRIV_DONE; 235 int err = IO_DONE;
330 p_base base = buf->buf_base; 236 p_io io = buf->io;
331 if (buf_isempty(L, buf)) { 237 p_tm tm = buf->tm;
332 size_t done; 238 if (buf_isempty(buf)) {
333 err = base->base_receive(L, base, buf->buf_data, BUF_SIZE, &done); 239 size_t got;
334 buf->buf_first = 0; 240 err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm_get(tm));
335 buf->buf_last = done; 241 buf->first = 0;
242 buf->last = got;
336 } 243 }
337 *len = buf->buf_last - buf->buf_first; 244 *count = buf->last - buf->first;
338 *data = buf->buf_data + buf->buf_first; 245 *data = buf->data + buf->first;
339 return err; 246 return err;
340} 247}