File

util-src/table.c @ 13552:f0b2c026e542

net.server_epoll: Improve efficiency of sending much buffered data Problem: The string slice operations when a lot of data gets buffered ends up being expensive and memory-consuming. We have util.dbuffer for precisely this kind of thing. I want to keep the behavior of writebuffer being upgraded from nil to a string to full buffer since the last step involves three table allocations, where the previous buffer method only used one. Avoiding those allocations for simple writes like white space keep alive feels like it would keep memory churn down. This work was started in 2020
author Kim Alvefur <zash@zash.se>
date Sat, 09 Nov 2024 00:37:15 +0100
parent 12976:a187600ec7d6
line wrap: on
line source

#include <lua.h>
#include <lauxlib.h>

#ifndef LUA_MAXINTEGER
#include <stdint.h>
#define LUA_MAXINTEGER PTRDIFF_MAX
#endif

static int Lcreate_table(lua_State *L) {
	lua_createtable(L, luaL_checkinteger(L, 1), luaL_checkinteger(L, 2));
	return 1;
}

/* COMPAT: w/ Lua pre-5.2 */
static int Lpack(lua_State *L) {
	unsigned int n_args = lua_gettop(L);
	lua_createtable(L, n_args, 1);
	lua_insert(L, 1);

	for(int arg = n_args; arg >= 1; arg--) {
		lua_rawseti(L, 1, arg);
	}

	lua_pushinteger(L, n_args);
	lua_setfield(L, -2, "n");
	return 1;
}

/* COMPAT: w/ Lua pre-5.4 */
static int Lmove (lua_State *L) {
	lua_Integer f = luaL_checkinteger(L, 2);
	lua_Integer e = luaL_checkinteger(L, 3);
	lua_Integer t = luaL_checkinteger(L, 4);

	int tt = !lua_isnoneornil(L, 5) ? 5 : 1;  /* destination table */
	luaL_checktype(L, 1, LUA_TTABLE);
	luaL_checktype(L, tt, LUA_TTABLE);

	if (e >= f) {  /* otherwise, nothing to move */
		lua_Integer n, i;
		luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3,
		  "too many elements to move");
		n = e - f + 1;  /* number of elements to move */
		luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
		"destination wrap around");
		if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) {
			for (i = 0; i < n; i++) {
				lua_rawgeti(L, 1, f + i);
				lua_rawseti(L, tt, t + i);
			}
		} else {
			for (i = n - 1; i >= 0; i--) {
				lua_rawgeti(L, 1, f + i);
				lua_rawseti(L, tt, t + i);
			}
		}
	}

	lua_pushvalue(L, tt);  /* return destination table */
	return 1;
}

int luaopen_prosody_util_table(lua_State *L) {
	luaL_checkversion(L);
	lua_createtable(L, 0, 2);
	lua_pushcfunction(L, Lcreate_table);
	lua_setfield(L, -2, "create");
	lua_pushcfunction(L, Lpack);
	lua_setfield(L, -2, "pack");
	lua_pushcfunction(L, Lmove);
	lua_setfield(L, -2, "move");
	return 1;
}

int luaopen_util_table(lua_State *L) {
	return luaopen_prosody_util_table(L);
}