123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- package datastruct
- import (
- "strings"
- "github.com/xyproto/algernon/lua/convert"
- lua "github.com/xyproto/gopher-lua"
- "github.com/xyproto/pinterface"
- )
- // Identifier for the List class in Lua
- const lListClass = "LIST"
- // Get the first argument, "self", and cast it from userdata to a list.
- func checkList(L *lua.LState) pinterface.IList {
- ud := L.CheckUserData(1)
- if list, ok := ud.Value.(pinterface.IList); ok {
- return list
- }
- L.ArgError(1, "list expected")
- return nil
- }
- // Create a new list.
- // id is the name of the list.
- // dbindex is the Redis database index (typically 0).
- func newList(L *lua.LState, creator pinterface.ICreator, id string) (*lua.LUserData, error) {
- // Create a new list
- list, err := creator.NewList(id)
- if err != nil {
- return nil, err
- }
- // Create a new userdata struct
- ud := L.NewUserData()
- ud.Value = list
- L.SetMetatable(ud, L.GetTypeMetatable(lListClass))
- return ud, nil
- }
- // String representation
- // Returns the entire list as a comma separated string
- // tostring(list) -> string
- func listToString(L *lua.LState) int {
- list := checkList(L) // arg 1
- all, err := list.All()
- if err != nil {
- L.Push(lua.LString(""))
- return 1 // Number of returned values
- }
- L.Push(lua.LString(strings.Join(all, ", ")))
- return 1 // Number of returned values
- }
- // Add an element to the list
- // list:add(string)
- func listAdd(L *lua.LState) int {
- list := checkList(L) // arg 1
- value := L.ToString(2)
- list.Add(value)
- return 0 // Number of returned values
- }
- // Get all members of the list
- // list::getall() -> table
- func listAll(L *lua.LState) int {
- list := checkList(L) // arg 1
- all, err := list.All()
- if err != nil {
- // Return an empty table
- L.Push(L.NewTable())
- return 1 // Number of returned values
- }
- L.Push(convert.Strings2table(L, all))
- return 1 // Number of returned values
- }
- // Return the list as a JSON list (assumes the elements to be in JSON already)
- // list::json() -> string
- func listJSON(L *lua.LState) int {
- list := checkList(L) // arg 1
- all, err := list.All()
- if err != nil {
- // Return an empty JSON list
- L.Push(lua.LString("[]"))
- return 1 // Number of returned values
- }
- L.Push(lua.LString("[" + strings.Join(all, ",") + "]"))
- return 1 // Number of returned values
- }
- // Get the last element of the list
- // The returned value can be empty
- // list::getlast() -> string
- func listLast(L *lua.LState) int {
- list := checkList(L) // arg 1
- value, err := list.Last()
- if err != nil {
- value = ""
- }
- L.Push(lua.LString(value))
- return 1 // Number of returned values
- }
- // Get the N last elements of the list
- // list::getlastn(number) -> table
- func listLastN(L *lua.LState) int {
- list := checkList(L) // arg 1
- n := int(L.ToNumber(2)) // arg 2
- results, err := list.LastN(n)
- if err != nil {
- // Return an empty table
- L.Push(L.NewTable())
- return 1 // Number of returned values
- }
- L.Push(convert.Strings2table(L, results))
- return 1 // Number of returned values
- }
- // Remove the list itself. Returns true if successful.
- // list:remove() -> bool
- func listRemove(L *lua.LState) int {
- list := checkList(L) // arg 1
- L.Push(lua.LBool(nil == list.Remove()))
- return 1 // Number of returned values
- }
- // Clear the list. Returns true if successful.
- // list:clear() -> bool
- func listClear(L *lua.LState) int {
- list := checkList(L) // arg 1
- L.Push(lua.LBool(nil == list.Clear()))
- return 1 // Number of returned values
- }
- // The list methods that are to be registered
- var listMethods = map[string]lua.LGFunction{
- "__tostring": listToString,
- "add": listAdd,
- "getall": listAll,
- "getlast": listLast,
- "getlastn": listLastN,
- "remove": listRemove,
- "clear": listClear,
- "json": listJSON,
- }
- // LoadList makes functions related to HTTP requests and responses available to Lua scripts
- func LoadList(L *lua.LState, creator pinterface.ICreator) {
- // Register the list class and the methods that belongs with it.
- mt := L.NewTypeMetatable(lListClass)
- mt.RawSetH(lua.LString("__index"), mt)
- L.SetFuncs(mt, listMethods)
- // The constructor for new lists takes a name and an optional redis db index
- L.SetGlobal("List", L.NewFunction(func(L *lua.LState) int {
- name := L.CheckString(1)
- // Check if the optional argument is given
- if L.GetTop() == 2 {
- localDBIndex := L.ToInt(2)
- // Set the DB index, if possible
- switch rh := creator.(type) {
- case pinterface.IRedisCreator:
- rh.SelectDatabase(localDBIndex)
- }
- }
- // Create a new list in Lua
- userdata, err := newList(L, creator, name)
- if err != nil {
- L.Push(lua.LNil)
- L.Push(lua.LString(err.Error()))
- L.Push(lua.LNumber(1))
- return 3 // Number of returned values
- }
- // Return the list object
- L.Push(userdata)
- return 1 // Number of returned values
- }))
- }
|