123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- package datastruct
- import (
- lua "github.com/xyproto/gopher-lua"
- "github.com/xyproto/pinterface"
- log "github.com/sirupsen/logrus"
- )
- // Identifier for the Set class in Lua
- const lKeyValueClass = "KEYVALUE"
- // Get the first argument, "self", and cast it from userdata to a key/value
- func checkKeyValue(L *lua.LState) pinterface.IKeyValue {
- ud := L.CheckUserData(1)
- if kv, ok := ud.Value.(pinterface.IKeyValue); ok {
- return kv
- }
- L.ArgError(1, "keyvalue expected")
- return nil
- }
- // Create a new KeyValue collection.
- // id is the name of the KeyValue collection.
- // dbindex is the Redis database index (typically 0).
- func newKeyValue(L *lua.LState, creator pinterface.ICreator, id string) (*lua.LUserData, error) {
- // Create a new key/value
- kv, err := creator.NewKeyValue(id)
- if err != nil {
- return nil, err
- }
- // Create a new userdata struct
- ud := L.NewUserData()
- ud.Value = kv
- L.SetMetatable(ud, L.GetTypeMetatable(lKeyValueClass))
- return ud, nil
- }
- // String representation
- // Returns the name of the KeyValue collection
- // tostring(kv) -> string
- func kvToString(L *lua.LState) int {
- L.Push(lua.LString("keyvalue"))
- return 1 // Number of returned values
- }
- // Set a key and value. Returns true if successful.
- // kv:set(string, string) -> bool
- func kvSet(L *lua.LState) int {
- kv := checkKeyValue(L) // arg 1
- key := L.CheckString(2)
- value := L.ToString(3)
- L.Push(lua.LBool(nil == kv.Set(key, value)))
- return 1 // Number of returned values
- }
- // Takes a key, returns a value. May return an empty string.
- // kv:get(string) -> string
- func kvGet(L *lua.LState) int {
- kv := checkKeyValue(L) // arg 1
- key := L.CheckString(2)
- retval, err := kv.Get(key)
- if err != nil {
- retval = ""
- }
- L.Push(lua.LString(retval))
- return 1 // Number of returned values
- }
- // Takes a key, returns the value+1.
- // Creates a key/value and returns "1" if it did not already exist.
- // May return an empty string.
- // kv:inc(string) -> string
- func kvInc(L *lua.LState) int {
- kv := checkKeyValue(L) // arg 1
- key := L.CheckString(2)
- increased, err := kv.Inc(key)
- if err != nil {
- log.Error(err.Error())
- L.Push(lua.LString("0"))
- return 1
- }
- L.Push(lua.LString(increased))
- return 1 // Number of returned values
- }
- // Remove a key. Returns true if successful.
- // kv:del(string) -> bool
- func kvDel(L *lua.LState) int {
- kv := checkKeyValue(L) // arg 1
- value := L.CheckString(2)
- L.Push(lua.LBool(nil == kv.Del(value)))
- return 1 // Number of returned values
- }
- // Remove the keyvalue itself. Returns true if successful.
- // kv:remove() -> bool
- func kvRemove(L *lua.LState) int {
- kv := checkKeyValue(L) // arg 1
- L.Push(lua.LBool(nil == kv.Remove()))
- return 1 // Number of returned values
- }
- // Clear the keyvalue. Returns true if successful.
- // kv:clear() -> bool
- func kvClear(L *lua.LState) int {
- kv := checkKeyValue(L) // arg 1
- L.Push(lua.LBool(nil == kv.Clear()))
- return 1 // Number of returned values
- }
- // The keyvalue methods that are to be registered
- var kvMethods = map[string]lua.LGFunction{
- "__tostring": kvToString,
- "set": kvSet,
- "get": kvGet,
- "inc": kvInc,
- "del": kvDel,
- "remove": kvRemove,
- "clear": kvClear,
- }
- // LoadKeyValue makes functions related to HTTP requests and responses available to Lua scripts
- func LoadKeyValue(L *lua.LState, creator pinterface.ICreator) {
- // Register the KeyValue class and the methods that belongs with it.
- mt := L.NewTypeMetatable(lKeyValueClass)
- mt.RawSetH(lua.LString("__index"), mt)
- L.SetFuncs(mt, kvMethods)
- // The constructor for new KeyValues takes a name and an optional redis db index
- L.SetGlobal("KeyValue", 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 keyvalue in Lua
- userdata, err := newKeyValue(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 keyvalue object
- L.Push(userdata)
- return 1 // Number of returned values
- }))
- }
|