set.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package datastruct
  2. import (
  3. "strings"
  4. "github.com/xyproto/algernon/lua/convert"
  5. lua "github.com/xyproto/gopher-lua"
  6. "github.com/xyproto/pinterface"
  7. )
  8. // Identifier for the Set class in Lua
  9. const lSetClass = "SET"
  10. // Get the first argument, "self", and cast it from userdata to a set.
  11. func checkSet(L *lua.LState) pinterface.ISet {
  12. ud := L.CheckUserData(1)
  13. if set, ok := ud.Value.(pinterface.ISet); ok {
  14. return set
  15. }
  16. L.ArgError(1, "set expected")
  17. return nil
  18. }
  19. // Create a new set.
  20. // id is the name of the set.
  21. // dbindex is the Redis database index (typically 0).
  22. func newSet(L *lua.LState, creator pinterface.ICreator, id string) (*lua.LUserData, error) {
  23. // Create a new set
  24. set, err := creator.NewSet(id)
  25. if err != nil {
  26. return nil, err
  27. }
  28. // Create a new userdata struct
  29. ud := L.NewUserData()
  30. ud.Value = set
  31. L.SetMetatable(ud, L.GetTypeMetatable(lSetClass))
  32. return ud, nil
  33. }
  34. // String representation
  35. // Returns the entire set as a comma separated string
  36. // tostring(set) -> string
  37. func setToString(L *lua.LState) int {
  38. set := checkSet(L) // arg 1
  39. all, err := set.All()
  40. if err != nil {
  41. L.Push(lua.LString(""))
  42. return 1 // Number of returned values
  43. }
  44. L.Push(lua.LString(strings.Join(all, ", ")))
  45. return 1 // Number of returned values
  46. }
  47. // Add an element to the set
  48. // set:add(string)
  49. func setAdd(L *lua.LState) int {
  50. set := checkSet(L) // arg 1
  51. value := L.ToString(2)
  52. set.Add(value)
  53. return 0 // Number of returned values
  54. }
  55. // Remove an element from the set
  56. // set:del(string)
  57. func setDel(L *lua.LState) int {
  58. set := checkSet(L) // arg 1
  59. value := L.ToString(2)
  60. set.Del(value)
  61. return 0 // Number of returned values
  62. }
  63. // Check if a set contains a value
  64. // Returns true only if the value exists and there were no errors.
  65. // set:has(string) -> bool
  66. func setHas(L *lua.LState) int {
  67. set := checkSet(L) // arg 1
  68. value := L.ToString(2)
  69. b, err := set.Has(value)
  70. if err != nil {
  71. b = false
  72. }
  73. L.Push(lua.LBool(b))
  74. return 1 // Number of returned values
  75. }
  76. // Get all members of the set
  77. // set:getall() -> table
  78. func setAll(L *lua.LState) int {
  79. set := checkSet(L) // arg 1
  80. all, err := set.All()
  81. if err != nil {
  82. // Return an empty table
  83. L.Push(L.NewTable())
  84. return 1 // Number of returned values
  85. }
  86. L.Push(convert.Strings2table(L, all))
  87. return 1 // Number of returned values
  88. }
  89. // Remove the set itself. Returns true if successful.
  90. // set:remove() -> bool
  91. func setRemove(L *lua.LState) int {
  92. set := checkSet(L) // arg 1
  93. L.Push(lua.LBool(nil == set.Remove()))
  94. return 1 // Number of returned values
  95. }
  96. // Clear the set. Returns true if successful.
  97. // set:clear() -> bool
  98. func setClear(L *lua.LState) int {
  99. set := checkSet(L) // arg 1
  100. L.Push(lua.LBool(nil == set.Clear()))
  101. return 1 // Number of returned values
  102. }
  103. // The set methods that are to be registered
  104. var setMethods = map[string]lua.LGFunction{
  105. "__tostring": setToString,
  106. "add": setAdd,
  107. "del": setDel,
  108. "has": setHas,
  109. "getall": setAll,
  110. "remove": setRemove,
  111. "clear": setClear,
  112. }
  113. // LoadSet makes functions related to HTTP requests and responses available to Lua scripts
  114. func LoadSet(L *lua.LState, creator pinterface.ICreator) {
  115. // Register the set class and the methods that belongs with it.
  116. mt := L.NewTypeMetatable(lSetClass)
  117. mt.RawSetH(lua.LString("__index"), mt)
  118. L.SetFuncs(mt, setMethods)
  119. // The constructor for new sets takes a name and an optional redis db index
  120. L.SetGlobal("Set", L.NewFunction(func(L *lua.LState) int {
  121. name := L.CheckString(1)
  122. // Check if the optional argument is given
  123. if L.GetTop() == 2 {
  124. localDBIndex := L.ToInt(2)
  125. // Set the DB index, if possible
  126. switch rh := creator.(type) {
  127. case pinterface.IRedisCreator:
  128. rh.SelectDatabase(localDBIndex)
  129. }
  130. }
  131. // Create a new set in Lua
  132. userdata, err := newSet(L, creator, name)
  133. if err != nil {
  134. L.Push(lua.LNil)
  135. L.Push(lua.LString(err.Error()))
  136. L.Push(lua.LNumber(1))
  137. return 3 // Number of returned values
  138. }
  139. // Return the set object
  140. L.Push(userdata)
  141. return 1 // Number of returned values
  142. }))
  143. }