mirror of
https://github.com/lunarmodules/luasocket.git
synced 2025-07-16 05:49:53 +02:00
Porting to LUA 5.0 final
This commit is contained in:
275
src/buffer.c
275
src/buffer.c
@ -1,28 +1,24 @@
|
||||
/*=========================================================================*\
|
||||
* Buffered input/output routines
|
||||
* Lua methods:
|
||||
* send: unbuffered send using C base_send
|
||||
* receive: buffered read using C base_receive
|
||||
*
|
||||
* RCS ID: $Id$
|
||||
\*=========================================================================*/
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "lsbuf.h"
|
||||
#include "error.h"
|
||||
#include "aux.h"
|
||||
#include "buf.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Internal function prototypes.
|
||||
* Internal function prototypes
|
||||
\*=========================================================================*/
|
||||
static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len,
|
||||
size_t *done);
|
||||
static int recvraw(lua_State *L, p_buf buf, size_t wanted);
|
||||
static int recvdosline(lua_State *L, p_buf buf);
|
||||
static int recvunixline(lua_State *L, p_buf buf);
|
||||
static int recvline(lua_State *L, p_buf buf);
|
||||
static int recvall(lua_State *L, p_buf buf);
|
||||
|
||||
static int buf_contents(lua_State *L, p_buf buf, cchar **data, size_t *len);
|
||||
static void buf_skip(lua_State *L, p_buf buf, size_t len);
|
||||
static int buf_get(p_buf buf, const char **data, size_t *count);
|
||||
static void buf_skip(p_buf buf, size_t count);
|
||||
static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent);
|
||||
|
||||
/*=========================================================================*\
|
||||
* Exported functions
|
||||
@ -37,98 +33,69 @@ void buf_open(lua_State *L)
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes C structure
|
||||
* Input
|
||||
* buf: buffer structure to initialize
|
||||
* base: socket object to associate with buffer structure
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void buf_init(lua_State *L, p_buf buf, p_base base)
|
||||
void buf_init(p_buf buf, p_io io, p_tm tm)
|
||||
{
|
||||
(void) L;
|
||||
buf->buf_first = buf->buf_last = 0;
|
||||
buf->buf_base = base;
|
||||
buf->first = buf->last = 0;
|
||||
buf->io = io;
|
||||
buf->tm = tm;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Send data through buffered object
|
||||
* Input
|
||||
* buf: buffer structure to be used
|
||||
* Lua Input: self, a_1 [, a_2, a_3 ... a_n]
|
||||
* self: socket object
|
||||
* a_i: strings to be sent.
|
||||
* Lua Returns
|
||||
* On success: nil, followed by the total number of bytes sent
|
||||
* On error: error message
|
||||
\*-------------------------------------------------------------------------*/
|
||||
int buf_send(lua_State *L, p_buf buf)
|
||||
int buf_meth_send(lua_State *L, p_buf buf)
|
||||
{
|
||||
int top = lua_gettop(L);
|
||||
size_t total = 0;
|
||||
int err = PRIV_DONE;
|
||||
int arg;
|
||||
p_base base = buf->buf_base;
|
||||
tm_markstart(&base->base_tm);
|
||||
int arg, err = IO_DONE;
|
||||
p_tm tm = buf->tm;
|
||||
tm_markstart(tm);
|
||||
for (arg = 2; arg <= top; arg++) { /* first arg is socket object */
|
||||
size_t done, len;
|
||||
cchar *data = luaL_optlstring(L, arg, NULL, &len);
|
||||
if (!data || err != PRIV_DONE) break;
|
||||
err = sendraw(L, buf, data, len, &done);
|
||||
total += done;
|
||||
size_t sent, count;
|
||||
const char *data = luaL_optlstring(L, arg, NULL, &count);
|
||||
if (!data || err != IO_DONE) break;
|
||||
err = sendraw(buf, data, count, &sent);
|
||||
total += sent;
|
||||
}
|
||||
priv_pusherror(L, err);
|
||||
lua_pushnumber(L, total);
|
||||
error_push(L, err);
|
||||
#ifdef LUASOCKET_DEBUG
|
||||
/* push time elapsed during operation as the last return value */
|
||||
lua_pushnumber(L, tm_getelapsed(&base->base_tm)/1000.0);
|
||||
lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0);
|
||||
#endif
|
||||
return lua_gettop(L) - top;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Receive data from a buffered object
|
||||
* Input
|
||||
* buf: buffer structure to be used
|
||||
* Lua Input: self [pat_1, pat_2 ... pat_n]
|
||||
* self: socket object
|
||||
* pat_i: may be one of the following
|
||||
* "*l": reads a text line, defined as a string of caracters terminates
|
||||
* by a LF character, preceded or not by a CR character. This is
|
||||
* the default pattern
|
||||
* "*lu": reads a text line, terminanted by a CR character only. (Unix mode)
|
||||
* "*a": reads until connection closed
|
||||
* number: reads 'number' characters from the socket object
|
||||
* Lua Returns
|
||||
* On success: one string for each pattern
|
||||
* On error: all strings for which there was no error, followed by one
|
||||
* nil value for the remaining strings, followed by an error code
|
||||
\*-------------------------------------------------------------------------*/
|
||||
int buf_receive(lua_State *L, p_buf buf)
|
||||
int buf_meth_receive(lua_State *L, p_buf buf)
|
||||
{
|
||||
int top = lua_gettop(L);
|
||||
int arg, err = PRIV_DONE;
|
||||
p_base base = buf->buf_base;
|
||||
tm_markstart(&base->base_tm);
|
||||
int arg, err = IO_DONE;
|
||||
p_tm tm = buf->tm;
|
||||
tm_markstart(tm);
|
||||
/* push default pattern if need be */
|
||||
if (top < 2) {
|
||||
lua_pushstring(L, "*l");
|
||||
top++;
|
||||
}
|
||||
/* make sure we have enough stack space */
|
||||
/* make sure we have enough stack space for all returns */
|
||||
luaL_checkstack(L, top+LUA_MINSTACK, "too many arguments");
|
||||
/* receive all patterns */
|
||||
for (arg = 2; arg <= top && err == PRIV_DONE; arg++) {
|
||||
for (arg = 2; arg <= top && err == IO_DONE; arg++) {
|
||||
if (!lua_isnumber(L, arg)) {
|
||||
static cchar *patternnames[] = {"*l", "*lu", "*a", "*w", NULL};
|
||||
cchar *pattern = luaL_optstring(L, arg, NULL);
|
||||
static const char *patternnames[] = {"*l", "*a", NULL};
|
||||
const char *pattern = lua_isnil(L, arg) ?
|
||||
"*l" : luaL_checkstring(L, arg);
|
||||
/* get next pattern */
|
||||
switch (luaL_findstring(pattern, patternnames)) {
|
||||
case 0: /* DOS line pattern */
|
||||
err = recvdosline(L, buf); break;
|
||||
case 1: /* Unix line pattern */
|
||||
err = recvunixline(L, buf); break;
|
||||
case 2: /* Until closed pattern */
|
||||
err = recvall(L, buf); break;
|
||||
case 3: /* Word pattern */
|
||||
luaL_argcheck(L, 0, arg, "word patterns are deprecated");
|
||||
case 0: /* line pattern */
|
||||
err = recvline(L, buf); break;
|
||||
case 1: /* until closed pattern */
|
||||
err = recvall(L, buf);
|
||||
if (err == IO_CLOSED) err = IO_DONE;
|
||||
break;
|
||||
default: /* else it is an error */
|
||||
luaL_argcheck(L, 0, arg, "invalid receive pattern");
|
||||
@ -140,25 +107,20 @@ int buf_receive(lua_State *L, p_buf buf)
|
||||
/* push nil for each pattern after an error */
|
||||
for ( ; arg <= top; arg++) lua_pushnil(L);
|
||||
/* last return is an error code */
|
||||
priv_pusherror(L, err);
|
||||
error_push(L, err);
|
||||
#ifdef LUASOCKET_DEBUG
|
||||
/* push time elapsed during operation as the last return value */
|
||||
lua_pushnumber(L, tm_getelapsed(&base->base_tm)/1000.0);
|
||||
lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0);
|
||||
#endif
|
||||
return lua_gettop(L) - top;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Determines if there is any data in the read buffer
|
||||
* Input
|
||||
* buf: buffer structure to be used
|
||||
* Returns
|
||||
* 1 if empty, 0 if there is data
|
||||
\*-------------------------------------------------------------------------*/
|
||||
int buf_isempty(lua_State *L, p_buf buf)
|
||||
int buf_isempty(p_buf buf)
|
||||
{
|
||||
(void) L;
|
||||
return buf->buf_first >= buf->buf_last;
|
||||
return buf->first >= buf->last;
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
@ -166,24 +128,16 @@ int buf_isempty(lua_State *L, p_buf buf)
|
||||
\*=========================================================================*/
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Sends a raw block of data through a buffered object.
|
||||
* Input
|
||||
* buf: buffer structure to be used
|
||||
* data: data to be sent
|
||||
* len: number of bytes to send
|
||||
* Output
|
||||
* sent: number of bytes sent
|
||||
* Returns
|
||||
* operation error code.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len,
|
||||
size_t *sent)
|
||||
static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
|
||||
{
|
||||
p_base base = buf->buf_base;
|
||||
p_io io = buf->io;
|
||||
p_tm tm = buf->tm;
|
||||
size_t total = 0;
|
||||
int err = PRIV_DONE;
|
||||
while (total < len && err == PRIV_DONE) {
|
||||
int err = IO_DONE;
|
||||
while (total < count && err == IO_DONE) {
|
||||
size_t done;
|
||||
err = base->base_send(L, base, data + total, len - total, &done);
|
||||
err = io->send(io->ctx, data+total, count-total, &done, tm_get(tm));
|
||||
total += done;
|
||||
}
|
||||
*sent = total;
|
||||
@ -192,25 +146,21 @@ static int sendraw(lua_State *L, p_buf buf, cchar *data, size_t len,
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Reads a raw block of data from a buffered object.
|
||||
* Input
|
||||
* buf: buffer structure
|
||||
* wanted: number of bytes to be read
|
||||
* Returns
|
||||
* operation error code.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int recvraw(lua_State *L, p_buf buf, size_t wanted)
|
||||
static
|
||||
int recvraw(lua_State *L, p_buf buf, size_t wanted)
|
||||
{
|
||||
int err = PRIV_DONE;
|
||||
int err = IO_DONE;
|
||||
size_t total = 0;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
while (total < wanted && err == PRIV_DONE) {
|
||||
size_t len; cchar *data;
|
||||
err = buf_contents(L, buf, &data, &len);
|
||||
len = MIN(len, wanted - total);
|
||||
luaL_addlstring(&b, data, len);
|
||||
buf_skip(L, buf, len);
|
||||
total += len;
|
||||
while (total < wanted && err == IO_DONE) {
|
||||
size_t count; const char *data;
|
||||
err = buf_get(buf, &data, &count);
|
||||
count = MIN(count, wanted - total);
|
||||
luaL_addlstring(&b, data, count);
|
||||
buf_skip(buf, count);
|
||||
total += count;
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
return err;
|
||||
@ -218,21 +168,18 @@ static int recvraw(lua_State *L, p_buf buf, size_t wanted)
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Reads everything until the connection is closed
|
||||
* Input
|
||||
* buf: buffer structure
|
||||
* Result
|
||||
* operation error code.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int recvall(lua_State *L, p_buf buf)
|
||||
static
|
||||
int recvall(lua_State *L, p_buf buf)
|
||||
{
|
||||
int err = PRIV_DONE;
|
||||
int err = IO_DONE;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
while (err == PRIV_DONE) {
|
||||
cchar *data; size_t len;
|
||||
err = buf_contents(L, buf, &data, &len);
|
||||
luaL_addlstring(&b, data, len);
|
||||
buf_skip(L, buf, len);
|
||||
while (err == IO_DONE) {
|
||||
const char *data; size_t count;
|
||||
err = buf_get(buf, &data, &count);
|
||||
luaL_addlstring(&b, data, count);
|
||||
buf_skip(buf, count);
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
return err;
|
||||
@ -241,61 +188,27 @@ static int recvall(lua_State *L, p_buf buf)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
|
||||
* are not returned by the function and are discarded from the buffer.
|
||||
* Input
|
||||
* buf: buffer structure
|
||||
* Result
|
||||
* operation error code. PRIV_DONE, PRIV_TIMEOUT or PRIV_CLOSED
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int recvdosline(lua_State *L, p_buf buf)
|
||||
static
|
||||
int recvline(lua_State *L, p_buf buf)
|
||||
{
|
||||
int err = 0;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
while (err == PRIV_DONE) {
|
||||
size_t len, pos; cchar *data;
|
||||
err = buf_contents(L, buf, &data, &len);
|
||||
while (err == IO_DONE) {
|
||||
size_t count, pos; const char *data;
|
||||
err = buf_get(buf, &data, &count);
|
||||
pos = 0;
|
||||
while (pos < len && data[pos] != '\n') {
|
||||
while (pos < count && data[pos] != '\n') {
|
||||
/* we ignore all \r's */
|
||||
if (data[pos] != '\r') luaL_putchar(&b, data[pos]);
|
||||
pos++;
|
||||
}
|
||||
if (pos < len) { /* found '\n' */
|
||||
buf_skip(L, buf, pos+1); /* skip '\n' too */
|
||||
if (pos < count) { /* found '\n' */
|
||||
buf_skip(buf, pos+1); /* skip '\n' too */
|
||||
break; /* we are done */
|
||||
} else /* reached the end of the buffer */
|
||||
buf_skip(L, buf, pos);
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Reads a line terminated by a LF character, which is not returned by
|
||||
* the function, and is skipped in the buffer.
|
||||
* Input
|
||||
* buf: buffer structure
|
||||
* Returns
|
||||
* operation error code. PRIV_DONE, PRIV_TIMEOUT or PRIV_CLOSED
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int recvunixline(lua_State *L, p_buf buf)
|
||||
{
|
||||
int err = PRIV_DONE;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
while (err == 0) {
|
||||
size_t pos, len; cchar *data;
|
||||
err = buf_contents(L, buf, &data, &len);
|
||||
pos = 0;
|
||||
while (pos < len && data[pos] != '\n') {
|
||||
luaL_putchar(&b, data[pos]);
|
||||
pos++;
|
||||
}
|
||||
if (pos < len) { /* found '\n' */
|
||||
buf_skip(L, buf, pos+1); /* skip '\n' too */
|
||||
break; /* we are done */
|
||||
} else /* reached the end of the buffer */
|
||||
buf_skip(L, buf, pos);
|
||||
buf_skip(buf, pos);
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
return err;
|
||||
@ -303,38 +216,32 @@ static int recvunixline(lua_State *L, p_buf buf)
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Skips a given number of bytes in read buffer
|
||||
* Input
|
||||
* buf: buffer structure
|
||||
* len: number of bytes to skip
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static void buf_skip(lua_State *L, p_buf buf, size_t len)
|
||||
static
|
||||
void buf_skip(p_buf buf, size_t count)
|
||||
{
|
||||
buf->buf_first += len;
|
||||
if (buf_isempty(L, buf)) buf->buf_first = buf->buf_last = 0;
|
||||
buf->first += count;
|
||||
if (buf_isempty(buf))
|
||||
buf->first = buf->last = 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Return any data available in buffer, or get more data from transport layer
|
||||
* if buffer is empty.
|
||||
* Input
|
||||
* buf: buffer structure
|
||||
* Output
|
||||
* data: pointer to buffer start
|
||||
* len: buffer buffer length
|
||||
* Returns
|
||||
* PRIV_DONE, PRIV_CLOSED, PRIV_TIMEOUT ...
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int buf_contents(lua_State *L, p_buf buf, cchar **data, size_t *len)
|
||||
static
|
||||
int buf_get(p_buf buf, const char **data, size_t *count)
|
||||
{
|
||||
int err = PRIV_DONE;
|
||||
p_base base = buf->buf_base;
|
||||
if (buf_isempty(L, buf)) {
|
||||
size_t done;
|
||||
err = base->base_receive(L, base, buf->buf_data, BUF_SIZE, &done);
|
||||
buf->buf_first = 0;
|
||||
buf->buf_last = done;
|
||||
int err = IO_DONE;
|
||||
p_io io = buf->io;
|
||||
p_tm tm = buf->tm;
|
||||
if (buf_isempty(buf)) {
|
||||
size_t got;
|
||||
err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm_get(tm));
|
||||
buf->first = 0;
|
||||
buf->last = got;
|
||||
}
|
||||
*len = buf->buf_last - buf->buf_first;
|
||||
*data = buf->buf_data + buf->buf_first;
|
||||
*count = buf->last - buf->first;
|
||||
*data = buf->data + buf->first;
|
||||
return err;
|
||||
}
|
||||
|
Reference in New Issue
Block a user