static void pop_lstring(lua_State *L, struct socket_buffer *sb, int sz, int skip) { struct buffer_node * current = sb->head; if (sz < current->sz - sb->offset) { lua_pushlstring(L, current->msg + sb->offset, sz-skip); sb->offset+=sz; return; } if (sz == current->sz - sb->offset) { lua_pushlstring(L, current->msg + sb->offset, sz-skip); return_free_node(L,2,sb); return; } luaL_Buffer b; luaL_buffinit(L, &b); for (;;) { int bytes = current->sz - sb->offset; if (bytes >= sz) { if (sz > skip) { luaL_addlstring(&b, current->msg + sb->offset, sz - skip); } sb->offset += sz; if (bytes == sz) { return_free_node(L,2,sb); } break; } int real_sz = sz - skip; if (real_sz > 0) { luaL_addlstring(&b, current->msg + sb->offset, (real_sz < bytes) ? real_sz : bytes); } return_free_node(L,2,sb); sz-=bytes; if (sz==0) break; current = sb->head; assert(current); } luaL_pushresult(&b); }
/* userdata send_buffer table pool */ static int lclearbuffer(lua_State *L) { struct socket_buffer * sb = lua_touserdata(L, 1); if (sb == NULL) { return luaL_error(L, "Need buffer object at param 1"); } luaL_checktype(L,2,LUA_TTABLE); while(sb->head) { return_free_node(L,2,sb); } return 0; }
static int lreadall(lua_State *L) { struct socket_buffer * sb = lua_touserdata(L, 1); if (sb == NULL) { return luaL_error(L, "Need buffer object at param 1"); } luaL_checktype(L,2,LUA_TTABLE); luaL_Buffer b; luaL_buffinit(L, &b); while(sb->head) { struct buffer_node *current = sb->head; luaL_addlstring(&b, current->msg + sb->offset, current->sz - sb->offset); return_free_node(L,2,sb); } luaL_pushresult(&b); return 1; }
// local ret = driver.readall(s.buffer, buffer_pool) // socket.read(id, sz) socket.lua static int lreadall(lua_State *L) { struct socket_buffer * sb = lua_touserdata(L, 1); if (sb == NULL) { return luaL_error(L, "Need buffer object at param 1"); } luaL_checktype(L,2,LUA_TTABLE); luaL_Buffer b; luaL_buffinit(L, &b); // 遍历缓冲区链表 while(sb->head) { struct buffer_node *current = sb->head; // 把缓冲区节点的所有数据都放入字符串缓存 luaL_addlstring(&b, current->msg + sb->offset, current->sz - sb->offset); return_free_node(L,2,sb); } // 结束对字符串缓存的使用,将最终的字符串留在栈顶,作为lua返回值 luaL_pushresult(&b); sb->size = 0; return 1; }
// sz 需要读的数据长度 // skip 需要跳过的数据长度 比如\n的长度 static void pop_lstring(lua_State *L, struct socket_buffer *sb, int sz, int skip) { struct buffer_node * current = sb->head; if (sz < current->sz - sb->offset) { // 如果需要读的长度小于剩余可读的长度 // 把缓冲区数据压入栈中作为lua返回值 lua_pushlstring(L, current->msg + sb->offset, sz-skip); // 偏移量增加 sb->offset+=sz; return; } if (sz == current->sz - sb->offset) { // 如果需要读的长度等于剩余可读的长度 // 把缓冲区数据压入栈中作为lua返回值 lua_pushlstring(L, current->msg + sb->offset, sz-skip); // 当前缓冲区节点已读完,归还缓冲区节点到缓冲池 return_free_node(L,2,sb); return; } // 字符串缓存可以让c代码分段构造一个Lua字符串 // 定义一个字符串缓存 luaL_Buffer b; // 初始化字符串缓存 luaL_buffinit(L, &b); // 循环读取缓冲区链表的数据 for (;;) { // 当前缓冲区节点可读数据长度 int bytes = current->sz - sb->offset; if (bytes >= sz) { // 如果需要读的长度小于剩余可读的长度 // 刚开始进入循环,不会走这段逻辑,首节点此种情况已处理,此后遍历的节点仍可能出现此种情况 if (sz > skip) { // 把缓冲区数据放入字符串缓存 luaL_addlstring(&b, current->msg + sb->offset, sz - skip); } // 偏移量增加 sb->offset += sz; if (bytes == sz) { // 如果正好全部读完,归还缓冲区节点到缓冲池 return_free_node(L,2,sb); } // 需要读的已读完,跳出循环不必再读 break; } // 实际要读的数据长度,除sep分隔符之外 int real_sz = sz - skip; if (real_sz > 0) { // 把缓冲区数据放入字符串缓存 luaL_addlstring(&b, current->msg + sb->offset, (real_sz < bytes) ? real_sz : bytes); } // 当前缓冲区节点已读完,归还缓冲区节点到缓冲池 return_free_node(L,2,sb); sz-=bytes; if (sz==0) // 如果全部读完,跳出循环不必再读 break; // 换下一个缓冲区节点 current = sb->head; assert(current); } // 结束对字符串缓存的使用,将最终的字符串留在栈顶 luaL_pushresult(&b); }