--!A cross-platform build utility based on Lua -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. -- -- Copyright (C) 2015-present, Xmake Open Source Community. -- -- @author ruki -- @file list.lua -- -- load modules local object = require("base/object") -- define module local list = list or object { _init = {"_length"} } {0} -- clear all elements function list:clear() self._length = 0 self._first = nil self._last = nil end -- insert item after the given item function list:insert(t, after) if not after then return self:insert_last(t) end assert(t ~= after) if after._next then after._next._prev = t t._next = after._next else self._last = t end t._prev = after after._next = t self._length = self._length + 1 end -- insert the first item in head function list:insert_first(t) if self._first then self._first._prev = t t._next = self._first self._first = t else self._first = t self._last = t end self._length = self._length + 1 end -- insert the last item in tail function list:insert_last(t) if self._last then self._last._next = t t._prev = self._last self._last = t else self._first = t self._last = t end self._length = self._length + 1 end -- remove item function list:remove(t) if t._next then if t._prev then t._next._prev = t._prev t._prev._next = t._next else assert(t == self._first) t._next._prev = nil self._first = t._next end elseif t._prev then assert(t == self._last) t._prev._next = nil self._last = t._prev else assert(t == self._first and t == self._last) self._first = nil self._last = nil end t._next = nil t._prev = nil self._length = self._length - 1 return t end -- remove the first item function list:remove_first() if not self._first then return end local t = self._first if t._next then t._next._prev = nil self._first = t._next t._next = nil else self._first = nil self._last = nil end self._length = self._length - 1 return t end -- remove last item function list:remove_last() if not self._last then return end local t = self._last if t._prev then t._prev._next = nil self._last = t._prev t._prev = nil else self._first = nil self._last = nil end self._length = self._length - 1 return t end -- push element to the back -- -- @param t the element -- function list:push(t) self:insert_last(t) end -- pop element from the back -- -- @return the removed element -- function list:pop() self:remove_last() end -- shift element from the front -- -- @return the removed element -- function list:shift() self:remove_first() end -- unshift element to the front -- -- @param t the element -- function list:unshift(t) self:insert_first(t) end -- get the first element -- -- @return the first element, or nil if empty -- function list:first() return self._first end -- get the last element -- -- @return the last element, or nil if empty -- function list:last() return self._last end -- get the next element after the given one -- -- @param last the current element -- @return the next element, or nil -- function list:next(last) if last then return last._next else return self._first end end -- get the previous element before the given one -- -- @param last the current element -- @return the previous element, or nil -- function list:prev(last) if last then return last._prev else return self._last end end -- get the list size -- -- @return the number of elements -- function list:size() return self._length end -- is the list empty? -- -- @return true if empty -- function list:empty() return self:size() == 0 end -- get items -- -- e.g. -- -- for item in list:items() do -- print(item) -- end -- -- iterate elements from front to back -- -- @return the iterator function -- -- Stateful closure so the loop body can safely reassign the first loop -- variable under lua 5.4+ (paired with the RDKCONST->VDKREG compile-time -- patch in core/src/lua/xmake.lua). function list:items() -- stateful closure: keep the cursor in an upvalue so the loop body -- can safely reassign the first loop variable (lua 5.4+ merges the -- for-in control slot with the first user variable). local item = nil return function () item = self:next(item) return item end end -- iterate elements from back to front -- -- @return the reverse iterator function -- -- Stateful closure; see `list:items()` for the rationale. function list:ritems() local item = nil return function () item = self:prev(item) return item end end -- create a new doubly-linked list -- -- @return the list instance -- function list.new() return list() end -- return module: list return list