lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



On 11.09.2022 13:15, Lars Müller wrote:

What if the count of values removed exceeds the stack (and thus the vararg) size?

would the return values be truncated? Would an error be thrown (probably preferable)?

I think here we should be consistent with the table.unpack() behaviour, i.e. throw an error.

When handling huge tables in a program, special considerations are unavoidable.

Just like with table.unpack() one could unpack values from a huge table in chunks to avoid stack overflow, same can be applied to the proposed  table.remove().

Here's an updated version that checks for the stack space.

//--------

static int tremove (lua_State *L) {
  lua_Integer i;
  lua_Integer size = aux_getn(L, 1, TAB_RW);
  lua_Integer pos = luaL_optinteger(L, 2, size);
  lua_Integer count = luaL_optinteger(L, 3, 1);
  if(count < 0) {  /* if 'count' is negative, convert the call to 'table.remove(t, pos + count + 1, -count)' */
    lua_pop(L, 2);
    lua_pushinteger(L, pos + count + 1);
    lua_pushinteger(L, -count);
    return tremove(L);
  } /* 'count' from now on is strictly non-negative */
  /* check whether 'pos' is in [1, size + 1] */
  luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 2,
                    "position out of bounds");
  if (l_unlikely(count >= (unsigned int)INT_MAX  ||
                 !lua_checkstack(L, (int)(count + 1))))
    return luaL_error(L, "too many results to remove");
  for(i = 0; i < count; i++)  /* push 'count' elements onto the stack starting from 'pos' */
    lua_geti(L, 1, pos + i);
  for (i = pos ; i <= size; i++) {  /* shift the rest */
    lua_geti(L, 1, i + count);
    lua_seti(L, 1, i);  /* t[pos] = t[pos + count] */
  }
  if(pos + count - 1 <= size) {  /* remove the tail (if present) */
    for(i = size - count + 1; i <= size; i++) {
      lua_pushnil(L);
      lua_seti(L, 1, i);
    }
  }
  return count;
}

//--------

--
With regards, Alex Ch