这个基于数组的操作方法,在某些应用中可以用于简单地替换队列或链表等数据结构。
//Lua.h
//往索引值为idx的位置进行插入操作,记住在这个动作之前应将要插入的元素放置于数组当前有效值的最后位置(即相当于栈顶的push操作)
#define lua_insert(L,idx) lua_rotate(L, (idx), 1)
//删除索引值为idx的位置处的元素,其后的元素都会向前移位
#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
//将栈顶的元素和位置索引值为idx的元素进行替换
#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
//Lapi.h
/*
** Reverse the stack segment from 'from' to 'to'
** (auxiliary to 'lua_rotate')
*/
//反转操作
static void reverse (lua_State *L, StkId from, StkId to) {
for (; from < to; from++, to--) {
TValue temp;
setobj(L, &temp, from);
setobjs2s(L, from, to);
setobj2s(L, to, &temp);
}
}
/*
** Let x = AB, where A is a prefix of length 'n'. Then,
** rotate xn == BA. But BA == (A^r . B^r)^r.
*/
//|n|为要反转的个数
LUA_API void lua_rotate (lua_State *L, int idx, int n) {
StkId p, t, m;
lua_lock(L);
t = L->top - 1; /* end of stack segment being rotated *///将被反转的段的末端
p = index2addr(L, idx); /* start of segment */ //将被反转的段的起始端
api_checkstackindex(L, idx, p);
api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); //
m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ //将要反转的段的前部的末尾索引值:例如0-10的数值序列中,反转3个数,那么m=2,
reverse(L, p, m); /* reverse the prefix with length 'n' */ //这个反转技巧很妙避免了移位操作
reverse(L, m + 1, t); /* reverse the suffix */
reverse(L, p, t); /* reverse the entire segment */
lua_unlock(L);
}
LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
TValue *fr, *to;
lua_lock(L); //
fr = index2addr(L, fromidx);
to = index2addr(L, toidx);
api_checkvalidindex(L, to);
setobj(L, to, fr);
if (isupvalue(toidx)) /* function upvalue? */
luaC_barrier(L, clCvalue(L->ci->func), fr);
/* LUA_REGISTRYINDEX does not need gc barrier
(collector revisits it before finishing collection) */
lua_unlock(L);
}