Files
ClassicAPI/src/table/RemoveMulti.cpp
T
Brues 6ed0edc947 feat(baselib): gmatch, table.removemulti, math hyperbolics, difftime, newproxy, scrub
The base-library names that 1.12.1's Lua 5.0 and its compat.lua do not
have:

- gmatch: the global alias of string.gmatch (5.0's str_gfind,
  0x7FCFA0), set by value like strmatch and strrev.
- table.removemulti(t [, pos [, count]]): removes count elements from
  pos, shifts the rest down with lua_rawgeti/lua_rawseti and returns the
  removed elements. 5.0 keeps the length apart from the keys, so like
  the engine's table.remove (0x7FB770) it records the new length with
  luaL_setn (0x6F4EA0).
- math.cosh, math.sinh, math.tanh: luaL_checknumber (0x6F4C80) and the
  C function.
- difftime(t2 [, t1]): C difftime over the two times, next to the
  engine's date and time globals.
- newproxy([false | true | proxy]): an empty userdata from
  lua_newuserdata. The closure's upvalue is a weak table (its own
  metatable, __mode "kv") that marks the metatables newproxy(true)
  makes, so only those can be shared.
- scrub(...): replaces each argument that is not a boolean, number or
  string with nil, in place with lua_replace (0x6F32B0).

All are registered on both Lua states.

Game::Lua gains RawSetI (lua_rawseti, 0x6F3F60), Replace, CheckLString
(luaL_checklstring, 0x6F4BE0), CheckNumber and OptNumber (luaL_optnumber,
0x6F4CD0); string.byte now uses them instead of local typedefs.

issecure, issecurevariable and forceinsecure are left out. 1.12.1 has
no taint, so they could only return constants, and a constant
"secure" from issecurevariable makes AceHook-3.0 refuse every plain
hook.
2026-11-03 14:23:25 -06:00

69 lines
2.5 KiB
C++

// This file is part of ClassicAPI.
//
// ClassicAPI is free software: you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// ClassicAPI is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// ClassicAPI. If not, see <https://www.gnu.org/licenses/>.
// `table.removemulti(t [, pos [, count]])` — WoW's addition to the table
// library (4.3.4's tremovemulti, ltablib.c): removes `count` elements (1 by
// default) from position `pos` (the last element by default), shifts the
// rest down and returns the removed elements in order.
//
// 5.0 keeps a table's length apart from its keys, so like the engine's own
// table.remove (0x7FB770) this records the new length with luaL_setn.
//
// Registered on BOTH states (language-level helper, both are 5.0).
#include "Game.h"
#include "Offsets.h"
namespace Table::RemoveMulti {
namespace {
using luaL_getn_t = int(__fastcall *)(void *L, int t);
int __fastcall Script_table_removemulti(void *L) {
if (Game::Lua::Type(L, 1) != Game::Lua::TYPE_TABLE)
Game::Lua::ArgError(L, 1, "table expected");
const int e = reinterpret_cast<luaL_getn_t>(Offsets::LUAL_GETN)(L, 1);
int pos = static_cast<int>(Game::Lua::OptNumber(L, 2, e));
const int n = static_cast<int>(Game::Lua::OptNumber(L, 3, 1));
if (e == 0)
return 0;
if (pos <= 0 || n < 0 || pos > e || pos + n - 1 > e)
Game::Lua::Error(L, "parameters out of bounds");
if (!Game::Lua::CheckStack(L, n))
Game::Lua::Error(L, "stack overflow");
for (int i = pos; i < pos + n; i++)
Game::Lua::RawGetI(L, 1, i);
for (; pos < e; pos++) {
Game::Lua::RawGetI(L, 1, pos + n);
Game::Lua::RawSetI(L, 1, pos);
}
for (; pos < e + n; pos++) {
Game::Lua::PushNil(L);
Game::Lua::RawSetI(L, 1, pos);
}
Game::Lua::SetN(L, 1, e - n);
return n;
}
void Register() {
Game::Lua::RegisterTableFunction("table", "removemulti", &Script_table_removemulti);
}
const Game::ModuleAutoRegister _autoreg{&Register};
const Game::GlueModuleAutoRegister _autoregGlue{&Register};
} // namespace
} // namespace Table::RemoveMulti