@ -0,0 +1,13 @@ | |||||
package luaInGo | |||||
import lua "github.com/yuin/gopher-lua" | |||||
const ( | |||||
InitPoolSize = 128 | |||||
NaxPoolSize = 512 | |||||
) | |||||
//初始化lua LState连接池 | |||||
var LuaStatePool = &lStatePool{ | |||||
saved: make([]*lua.LState, 0, InitPoolSize), | |||||
} |
@ -0,0 +1,75 @@ | |||||
package luaInGo | |||||
import ( | |||||
"fmt" | |||||
"io/ioutil" | |||||
"os" | |||||
"path" | |||||
) | |||||
// LuaFile lua文件 | |||||
type LuaFile struct { | |||||
FileName string | |||||
} | |||||
// LuaFileExist 判断某lua脚本是否存在 | |||||
func LuaFileExist(fileName string) bool { | |||||
fileList := GetAllLuaFile() | |||||
for _, file := range fileList { | |||||
if file.FileName == fileName { | |||||
return true | |||||
} | |||||
} | |||||
return false | |||||
} | |||||
// GetAllLuaFile 获取所有文件 | |||||
func GetAllLuaFile() []LuaFile { | |||||
// 声明一个文件列表切片 | |||||
var fileList []LuaFile | |||||
rd, err := ioutil.ReadDir("luafile") | |||||
if err != nil { | |||||
fmt.Println("GetAllLuaFile error", err) | |||||
return fileList | |||||
} | |||||
for _, fi := range rd { | |||||
fileList = append(fileList, LuaFile{fi.Name()}) | |||||
} | |||||
return fileList | |||||
} | |||||
// DeleteLuaFile 删除文件 | |||||
func DeleteLuaFile(fileName string) bool { | |||||
err := os.Remove("luafile/" + fileName) | |||||
if err != nil { | |||||
fmt.Println("DeleteLuaFile error", err) | |||||
return false | |||||
} | |||||
return true | |||||
} | |||||
func ListLuaFile(folder string, luas []string) { | |||||
files, _ := ioutil.ReadDir(folder) | |||||
for _, file := range files { | |||||
if file.IsDir() { | |||||
ListLuaFile(folder+"/"+file.Name(), luas) | |||||
} else { | |||||
var filenameWithSuffix string = path.Base(file.Name()) //获取文件名带后缀 | |||||
var fileSuffix string = path.Ext(filenameWithSuffix) //获取文件后缀 | |||||
if fileSuffix == ".lua" { | |||||
filePath := fmt.Sprintf("%s%s%s", folder, "/", file.Name()) | |||||
luas = append(luas, filePath) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
func GetFileModtime(file string) (int64, error) { | |||||
stat, err := os.Stat(file) | |||||
if err != nil { | |||||
fmt.Printf("stat fail, file=%v err=%v", file, err) | |||||
return 0, err | |||||
} | |||||
return stat.ModTime().Unix(), nil | |||||
} |
@ -0,0 +1,8 @@ | |||||
module luaInGo | |||||
go 1.14 | |||||
require ( | |||||
github.com/vadv/gopher-lua-libs v0.1.0 | |||||
github.com/yuin/gopher-lua v0.0.0-20200603152657-dc2b0ca8b37e | |||||
) |
@ -0,0 +1,18 @@ | |||||
## Usage | |||||
origin code: https://github.com/vadv/gopher-lua-libs/tree/master/crypto | |||||
```lua | |||||
local crypto = require("crypto") | |||||
-- md5 | |||||
if not(crypto.md5("1\n") == "b026324c6904b2a9cb4b88d6d61c81d1") then | |||||
error("md5") | |||||
end | |||||
-- sha256 | |||||
if not(crypto.sha256("1\n") == "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865") then | |||||
error("sha256") | |||||
end | |||||
``` | |||||
@ -0,0 +1,23 @@ | |||||
package crypto | |||||
import ( | |||||
"crypto/md5" | |||||
"crypto/sha256" | |||||
"fmt" | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func MD5(L *lua.LState) int { | |||||
str := L.CheckString(1) | |||||
hash := md5.Sum([]byte(str)) | |||||
L.Push(lua.LString(fmt.Sprintf("%x", hash))) | |||||
return 1 | |||||
} | |||||
func SHA256(L *lua.LState) int { | |||||
str := L.CheckString(1) | |||||
hash := sha256.Sum256([]byte(str)) | |||||
L.Push(lua.LString(fmt.Sprintf("%x", hash))) | |||||
return 1 | |||||
} |
@ -0,0 +1,20 @@ | |||||
package crypto | |||||
import ( | |||||
"io/ioutil" | |||||
"testing" | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func TestApi(t *testing.T) { | |||||
data, err := ioutil.ReadFile("../testScript/test_crypto_api.lua") | |||||
if err != nil { | |||||
t.Fatalf("%s\n", err.Error()) | |||||
} | |||||
state := lua.NewState() | |||||
PreLoadGo(state) | |||||
if err := state.DoString(string(data)); err != nil { | |||||
t.Fatalf("execute test: %s\n", err.Error()) | |||||
} | |||||
} |
@ -0,0 +1,21 @@ | |||||
package crypto | |||||
import ( | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func PreLoadGo(L *lua.LState) { | |||||
L.PreloadModule("crypto", Loader) | |||||
} | |||||
func Loader(L *lua.LState) int { | |||||
t := L.NewTable() | |||||
L.SetFuncs(t, api) | |||||
L.Push(t) | |||||
return 1 | |||||
} | |||||
var api = map[string]lua.LGFunction{ | |||||
"md5": MD5, | |||||
"sha256": SHA256, | |||||
} |
@ -0,0 +1,70 @@ | |||||
package goApis | |||||
import ( | |||||
lua "github.com/yuin/gopher-lua" | |||||
cloudwatch "github.com/vadv/gopher-lua-libs/aws/cloudwatch" | |||||
cert_util "github.com/vadv/gopher-lua-libs/cert_util" | |||||
chef "github.com/vadv/gopher-lua-libs/chef" | |||||
cmd "github.com/vadv/gopher-lua-libs/cmd" | |||||
crypto "github.com/vadv/gopher-lua-libs/crypto" | |||||
db "github.com/vadv/gopher-lua-libs/db" | |||||
filepath "github.com/vadv/gopher-lua-libs/filepath" | |||||
goos "github.com/vadv/gopher-lua-libs/goos" | |||||
http "github.com/vadv/gopher-lua-libs/http" | |||||
humanize "github.com/vadv/gopher-lua-libs/humanize" | |||||
inspect "github.com/vadv/gopher-lua-libs/inspect" | |||||
ioutil "github.com/vadv/gopher-lua-libs/ioutil" | |||||
json "github.com/vadv/gopher-lua-libs/json" | |||||
log "github.com/vadv/gopher-lua-libs/log" | |||||
plugin "github.com/vadv/gopher-lua-libs/plugin" | |||||
pprof "github.com/vadv/gopher-lua-libs/pprof" | |||||
prometheus "github.com/vadv/gopher-lua-libs/prometheus/client" | |||||
regexp "github.com/vadv/gopher-lua-libs/regexp" | |||||
runtime "github.com/vadv/gopher-lua-libs/runtime" | |||||
"github.com/vadv/gopher-lua-libs/stats" | |||||
storage "github.com/vadv/gopher-lua-libs/storage" | |||||
strings "github.com/vadv/gopher-lua-libs/strings" | |||||
tac "github.com/vadv/gopher-lua-libs/tac" | |||||
tcp "github.com/vadv/gopher-lua-libs/tcp" | |||||
telegram "github.com/vadv/gopher-lua-libs/telegram" | |||||
template "github.com/vadv/gopher-lua-libs/template" | |||||
time "github.com/vadv/gopher-lua-libs/time" | |||||
xmlpath "github.com/vadv/gopher-lua-libs/xmlpath" | |||||
yaml "github.com/vadv/gopher-lua-libs/yaml" | |||||
zabbix "github.com/vadv/gopher-lua-libs/zabbix" | |||||
) | |||||
// 这里封装一个函数 统一load go中提供给lua调用的函数 | |||||
func PreLoadLibs(L *lua.LState) { | |||||
time.Preload(L) | |||||
strings.Preload(L) | |||||
filepath.Preload(L) | |||||
ioutil.Preload(L) | |||||
http.Preload(L) | |||||
regexp.Preload(L) | |||||
tac.Preload(L) | |||||
inspect.Preload(L) | |||||
yaml.Preload(L) | |||||
plugin.Preload(L) | |||||
cmd.Preload(L) | |||||
json.Preload(L) | |||||
tcp.Preload(L) | |||||
xmlpath.Preload(L) | |||||
db.Preload(L) | |||||
cert_util.Preload(L) | |||||
runtime.Preload(L) | |||||
telegram.Preload(L) | |||||
zabbix.Preload(L) | |||||
pprof.Preload(L) | |||||
prometheus.Preload(L) | |||||
crypto.Preload(L) | |||||
goos.Preload(L) | |||||
storage.Preload(L) | |||||
humanize.Preload(L) | |||||
chef.Preload(L) | |||||
template.Preload(L) | |||||
cloudwatch.Preload(L) | |||||
log.Preload(L) | |||||
stats.Preload(L) | |||||
} |
@ -0,0 +1,23 @@ | |||||
# json | |||||
origin code: https://github.com/vadv/gopher-lua-libs/tree/master/json | |||||
## Usage | |||||
```lua | |||||
local json = require("json") | |||||
-- json.encode() | |||||
local jsonString = [[ | |||||
{ | |||||
"a": {"b":1} | |||||
} | |||||
]] | |||||
local result, err = json.decode(jsonString) | |||||
if err then error(err) end | |||||
-- json.decode() | |||||
local table = {a={b=1}} | |||||
local result, err = json.encode(table) | |||||
if err then error(err) end | |||||
``` |
@ -0,0 +1,31 @@ | |||||
package json | |||||
import ( | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func Decode(L *lua.LState) int { | |||||
str := L.CheckString(1) | |||||
value, err := ValueDecode(L, []byte(str)) | |||||
if err != nil { | |||||
L.Push(lua.LNil) | |||||
L.Push(lua.LString(err.Error())) | |||||
return 2 | |||||
} | |||||
L.Push(value) | |||||
return 1 | |||||
} | |||||
func Encode(L *lua.LState) int { | |||||
value := L.CheckAny(1) | |||||
data, err := ValueEncode(value) | |||||
if err != nil { | |||||
L.Push(lua.LNil) | |||||
L.Push(lua.LString(err.Error())) | |||||
return 2 | |||||
} | |||||
L.Push(lua.LString(string(data))) | |||||
return 1 | |||||
} |
@ -0,0 +1,15 @@ | |||||
package json | |||||
import ( | |||||
"testing" | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func TestApi(t *testing.T) { | |||||
state := lua.NewState() | |||||
PreloadGo(state) | |||||
if err := state.DoFile("../testScript/test_json_api.lua"); err != nil { | |||||
t.Fatalf("execute test: %s\n", err.Error()) | |||||
} | |||||
} |
@ -0,0 +1,21 @@ | |||||
package json | |||||
import ( | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func PreloadGo(L *lua.LState) { | |||||
L.PreloadModule("json", Loader) | |||||
} | |||||
func Loader(L *lua.LState) int { | |||||
t := L.NewTable() | |||||
L.SetFuncs(t, api) | |||||
L.Push(t) | |||||
return 1 | |||||
} | |||||
var api = map[string]lua.LGFunction{ | |||||
"decode": Decode, | |||||
"encode": Encode, | |||||
} |
@ -0,0 +1,127 @@ | |||||
package json | |||||
import ( | |||||
"encoding/json" | |||||
"errors" | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
var ( | |||||
errNested = errors.New("cannot encode recursively nested tables to JSON") | |||||
errSparseArray = errors.New("cannot encode sparse array") | |||||
errInvalidKeys = errors.New("cannot encode mixed or invalid key types") | |||||
) | |||||
type invalidTypeError lua.LValueType | |||||
func (i invalidTypeError) Error() string { | |||||
return `cannot encode ` + lua.LValueType(i).String() + ` to JSON` | |||||
} | |||||
type jsonValue struct { | |||||
lua.LValue | |||||
visited map[*lua.LTable]bool | |||||
} | |||||
func (j jsonValue) MarshalJSON() (data []byte, err error) { | |||||
switch converted := j.LValue.(type) { | |||||
case lua.LBool: | |||||
data, err = json.Marshal(bool(converted)) | |||||
case lua.LNumber: | |||||
data, err = json.Marshal(float64(converted)) | |||||
case *lua.LNilType: | |||||
data = []byte(`null`) | |||||
case lua.LString: | |||||
data, err = json.Marshal(string(converted)) | |||||
case *lua.LTable: | |||||
if j.visited[converted] { | |||||
return nil, errNested | |||||
} | |||||
j.visited[converted] = true | |||||
key, value := converted.Next(lua.LNil) | |||||
switch key.Type() { | |||||
case lua.LTNil: // empty table | |||||
data = []byte(`[]`) | |||||
case lua.LTNumber: | |||||
arr := make([]jsonValue, 0, converted.Len()) | |||||
expectedKey := lua.LNumber(1) | |||||
for key != lua.LNil { | |||||
if key.Type() != lua.LTNumber { | |||||
err = errInvalidKeys | |||||
return | |||||
} | |||||
if expectedKey != key { | |||||
err = errSparseArray | |||||
return | |||||
} | |||||
arr = append(arr, jsonValue{value, j.visited}) | |||||
expectedKey++ | |||||
key, value = converted.Next(key) | |||||
} | |||||
data, err = json.Marshal(arr) | |||||
case lua.LTString: | |||||
obj := make(map[string]jsonValue) | |||||
for key != lua.LNil { | |||||
if key.Type() != lua.LTString { | |||||
err = errInvalidKeys | |||||
return | |||||
} | |||||
obj[key.String()] = jsonValue{value, j.visited} | |||||
key, value = converted.Next(key) | |||||
} | |||||
data, err = json.Marshal(obj) | |||||
default: | |||||
err = errInvalidKeys | |||||
} | |||||
default: | |||||
err = invalidTypeError(j.LValue.Type()) | |||||
} | |||||
return | |||||
} | |||||
// ValueDecode converts the JSON encoded data to Lua values. | |||||
func ValueDecode(L *lua.LState, data []byte) (lua.LValue, error) { | |||||
var value interface{} | |||||
err := json.Unmarshal(data, &value) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
return decode(L, value), nil | |||||
} | |||||
func decode(L *lua.LState, value interface{}) lua.LValue { | |||||
switch converted := value.(type) { | |||||
case bool: | |||||
return lua.LBool(converted) | |||||
case float64: | |||||
return lua.LNumber(converted) | |||||
case string: | |||||
return lua.LString(converted) | |||||
case []interface{}: | |||||
arr := L.CreateTable(len(converted), 0) | |||||
for _, item := range converted { | |||||
arr.Append(decode(L, item)) | |||||
} | |||||
return arr | |||||
case map[string]interface{}: | |||||
tbl := L.CreateTable(0, len(converted)) | |||||
for key, item := range converted { | |||||
tbl.RawSetH(lua.LString(key), decode(L, item)) | |||||
} | |||||
return tbl | |||||
case nil: | |||||
return lua.LNil | |||||
} | |||||
panic("unreachable") | |||||
} | |||||
// ValueEncode returns the JSON encoding of value. | |||||
func ValueEncode(value lua.LValue) ([]byte, error) { | |||||
return json.Marshal(jsonValue{ | |||||
LValue: value, | |||||
visited: make(map[*lua.LTable]bool), | |||||
}) | |||||
} |
@ -0,0 +1,30 @@ | |||||
# strings | |||||
origin code: https://github.com/vadv/gopher-lua-libs/tree/master/strings | |||||
## Usage | |||||
```lua | |||||
local strings = require("strings") | |||||
-- strings.split(string, sep) | |||||
local result = strings.split("a b c d", " ") | |||||
-- Output: { "a", "b", "c", "d" } | |||||
-- strings.has_prefix(string, prefix) | |||||
local result = strings.has_prefix("abcd", "a") | |||||
-- Output: true | |||||
-- strings.has_suffix(string, suffix) | |||||
local result = strings.has_suffix("abcd", "d") | |||||
-- Output: true | |||||
-- strings.trim(string, cutset) | |||||
local result = strings.trim("abcd", "d") | |||||
-- Output: abc | |||||
-- strings.contains(string, substring) | |||||
local result = strings.contains("abcd", "d") | |||||
-- Output: true | |||||
``` | |||||
@ -0,0 +1,74 @@ | |||||
package strings | |||||
import ( | |||||
"strings" | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
// Split(): lua strings.split(string, sep): port of go string.Split() returns table | |||||
func Split(L *lua.LState) int { | |||||
str := L.CheckString(1) | |||||
delim := L.CheckString(2) | |||||
strSlice := strings.Split(str, delim) | |||||
result := L.CreateTable(len(strSlice), 0) | |||||
for _, str := range strSlice { | |||||
result.Append(lua.LString(str)) | |||||
} | |||||
L.Push(result) | |||||
return 1 | |||||
} | |||||
// HasPrefix(): lua strings.has_prefix(string, suffix): port of go string.HasPrefix() return bool | |||||
func HasPrefix(L *lua.LState) int { | |||||
str1 := L.CheckString(1) | |||||
str2 := L.CheckString(2) | |||||
result := strings.HasPrefix(str1, str2) | |||||
L.Push(lua.LBool(result)) | |||||
return 1 | |||||
} | |||||
// HasSuffix(): lua strings.has_suffix(string, prefix): port of go string.HasSuffix() returns bool | |||||
func HasSuffix(L *lua.LState) int { | |||||
str1 := L.CheckString(1) | |||||
str2 := L.CheckString(2) | |||||
result := strings.HasSuffix(str1, str2) | |||||
L.Push(lua.LBool(result)) | |||||
return 1 | |||||
} | |||||
// Trim(): lua strings.trim(string, cutset) Port of go string.Trim() returns string | |||||
func Trim(L *lua.LState) int { | |||||
str1 := L.CheckString(1) | |||||
str2 := L.CheckString(2) | |||||
result := strings.Trim(str1, str2) | |||||
L.Push(lua.LString(result)) | |||||
return 1 | |||||
} | |||||
// TrimPrefix(): lua strings.trim_prefix(string, cutset) Port of go string.TrimPrefix() returns string | |||||
func TrimPrefix(L *lua.LState) int { | |||||
str1 := L.CheckString(1) | |||||
str2 := L.CheckString(2) | |||||
result := strings.TrimPrefix(str1, str2) | |||||
L.Push(lua.LString(result)) | |||||
return 1 | |||||
} | |||||
// TrimSuffix(): lua strings.trim_suffix(string, cutset) Port of go string.TrimSuffix() returns string | |||||
func TrimSuffix(L *lua.LState) int { | |||||
str1 := L.CheckString(1) | |||||
str2 := L.CheckString(2) | |||||
result := strings.TrimSuffix(str1, str2) | |||||
L.Push(lua.LString(result)) | |||||
return 1 | |||||
} | |||||
// Contains(): lua strings.contains(string, cutset) Port of go string.Contains() returns bool | |||||
func Contains(L *lua.LState) int { | |||||
str1 := L.CheckString(1) | |||||
str2 := L.CheckString(2) | |||||
result := strings.Contains(str1, str2) | |||||
L.Push(lua.LBool(result)) | |||||
return 1 | |||||
} |
@ -0,0 +1,15 @@ | |||||
package strings | |||||
import ( | |||||
"testing" | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func TestApi(t *testing.T) { | |||||
state := lua.NewState() | |||||
PreLoadGo(state) | |||||
if err := state.DoFile("../testScript/test_strings_api.lua"); err != nil { | |||||
t.Fatalf("execute test: %s\n", err.Error()) | |||||
} | |||||
} |
@ -0,0 +1,26 @@ | |||||
package strings | |||||
import ( | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func PreLoadGo(L *lua.LState) { | |||||
L.PreloadModule("strings", Loader) | |||||
} | |||||
func Loader(L *lua.LState) int { | |||||
t := L.NewTable() | |||||
L.SetFuncs(t, api) | |||||
L.Push(t) | |||||
return 1 | |||||
} | |||||
var api = map[string]lua.LGFunction{ | |||||
"split": Split, | |||||
"trim": Trim, | |||||
"trim_prefix": TrimPrefix, | |||||
"trim_suffix": TrimSuffix, | |||||
"has_prefix": HasPrefix, | |||||
"has_suffix": HasSuffix, | |||||
"contains": Contains, | |||||
} |
@ -0,0 +1,4 @@ | |||||
local crypto = require("crypto") | |||||
if not(crypto.md5("1\n") == "b026324c6904b2a9cb4b88d6d61c81d1") then error("md5") end | |||||
if not(crypto.sha256("1\n") == "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865") then error("sha256") end |
@ -0,0 +1,14 @@ | |||||
local json = require("json") | |||||
local jsonStringWithNull = [[{"a":{"b":1, "c":null}}]] | |||||
local jsonString = [[{"a":{"b":1}}]] | |||||
local result, err = json.decode(jsonStringWithNull) | |||||
if err then error(err) end | |||||
if not(result["a"]["b"] == 1) then error("must be decode") end | |||||
print("done: json.decode()") | |||||
local result, err = json.encode(result) | |||||
if err then error(err) end | |||||
if not(result==jsonString) then error("must be encode "..result) end | |||||
print("done: json.encode()") |
@ -0,0 +1,26 @@ | |||||
local strings = require("strings") | |||||
local str = "hello world" | |||||
local t = strings.split(str, " ") | |||||
local count_t = 0 | |||||
for k, v in pairs(t) do | |||||
count_t = count_t + 1 | |||||
if k == 1 then if not(v == "hello") then error("strings.split()") end end | |||||
if k == 2 then if not(v == "world") then error("strings.split()") end end | |||||
end | |||||
if not(count_t == 2) then error("string.split()") end | |||||
print("done: strings.split()") | |||||
if not(strings.has_prefix(str, "hello")) then error("strings.has_prefix()") end | |||||
if not(strings.has_suffix(str, "world")) then error("strings.has_suffix()") end | |||||
print("done: strings.has_suffix, strings.has_prefix") | |||||
if not(strings.trim(str, "world") == "hello ") then error("strings.trim()") end | |||||
if not(strings.trim(str, "hello ") == "world") then error("strings.trim()") end | |||||
if not(strings.trim_prefix(str, "hello ") == "world") then error("strings.trim()") end | |||||
if not(strings.trim_suffix(str, "hello ") == "hello world") then error("strings.trim()") end | |||||
print("done: strings.trim()") | |||||
if not(strings.contains(str, "hello ") == true) then error("strings.contains()") end | |||||
print("done: strings.contains()") |
@ -0,0 +1,24 @@ | |||||
local time = require("time") | |||||
local lua_before = os.clock() | |||||
local before = time.unix() | |||||
time.sleep(2) | |||||
local after = time.unix() | |||||
local lua_after = os.clock() | |||||
if after - before < 1 then error("time.unix()") end | |||||
if lua_after - lua_before < 2 then error("time.sleep()") end | |||||
print("done: time.sleep(), time.unix()") | |||||
local parse, err = time.parse("Dec 2 03:33:05 2018", "Jan 2 15:04:05 2006") | |||||
if err then error(err) end | |||||
if not(parse == 1543721585) then error("time.parse(): 1") end | |||||
print("done: time.parse(): 1") | |||||
local _, err = time.parse("Dec 32 03:33:05 2018", "Jan 2 15:04:05 2006") | |||||
if (err == nil) then error("time.parse(): must be error") end | |||||
print("done: time.parse(): 2") | |||||
local result, err = time.format(1543721585, "Jan 2 15:04:05 2006", "Europe/Moscow") | |||||
if err then error(err) end | |||||
if not(result == "Dec 2 06:33:05 2018") then error("time.format()") end | |||||
print("done: time.format(): 1") |
@ -0,0 +1,28 @@ | |||||
# time | |||||
origin code: https://github.com/vadv/gopher-lua-libs/tree/master/time | |||||
## Usage | |||||
```lua | |||||
local time = require("time") | |||||
-- time.unix(), time.sleep() | |||||
local begin = time.unix() | |||||
time.sleep(1.2) | |||||
local stop = time.unix() | |||||
local result = stop - begin | |||||
result = math.floor(result * 10^2 + 0.5) / 10^2 | |||||
if not(result == 1) then error("time.sleep()") end | |||||
-- time.parse(value, layout) | |||||
local result, err = time.parse("Dec 2 03:33:05 2018", "Jan 2 15:04:05 2006") | |||||
if err then error(err) end | |||||
if not(result == 1543721585) then error("time.parse()") end | |||||
-- time.format(value, layout, location) | |||||
local result, err = time.format(1543721585, "Jan 2 15:04:05 2006", "Europe/Moscow") | |||||
if err then error(err) end | |||||
if not(result == "Dec 2 06:33:05 2018") then error("time.format()") end | |||||
``` | |||||
@ -0,0 +1,62 @@ | |||||
package time | |||||
import ( | |||||
"time" | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func Unix(L *lua.LState) int { | |||||
now := float64(time.Now().UnixNano()) / float64(time.Second) | |||||
L.Push(lua.LNumber(now)) | |||||
return 1 | |||||
} | |||||
func UnixNano(L *lua.LState) int { | |||||
L.Push(lua.LNumber(time.Now().UnixNano())) | |||||
return 1 | |||||
} | |||||
func Sleep(L *lua.LState) int { | |||||
val := L.CheckNumber(1) | |||||
time.Sleep(time.Duration(val) * time.Second) | |||||
return 0 | |||||
} | |||||
func Parse(L *lua.LState) int { | |||||
layout, value := L.CheckString(2), L.CheckString(1) | |||||
result, err := time.Parse(layout, value) | |||||
if err != nil { | |||||
L.Push(lua.LNil) | |||||
L.Push(lua.LString(err.Error())) | |||||
return 2 | |||||
} | |||||
resultFloat := float64(result.UTC().UnixNano()) / float64(time.Second) | |||||
L.Push(lua.LNumber(resultFloat)) | |||||
return 1 | |||||
} | |||||
func Format(L *lua.LState) int { | |||||
tt := float64(L.CheckNumber(1)) | |||||
sec := int64(tt) | |||||
nsec := int64((tt - float64(sec)) * 1000000000) | |||||
result := time.Unix(sec, nsec) | |||||
layout := "Mon Jan 2 15:04:05 -0700 MST 2006" | |||||
if L.GetTop() > 1 { | |||||
layout = L.CheckString(2) | |||||
} | |||||
if L.GetTop() < 3 { | |||||
L.Push(lua.LString(result.Format(layout))) | |||||
return 1 | |||||
} | |||||
location := L.CheckString(3) | |||||
loc, err := time.LoadLocation(location) | |||||
if err != nil { | |||||
L.Push(lua.LNil) | |||||
L.Push(lua.LString(err.Error())) | |||||
return 2 | |||||
} | |||||
result = result.In(loc) | |||||
L.Push(lua.LString(result.Format(layout))) | |||||
return 1 | |||||
} |
@ -0,0 +1,15 @@ | |||||
package time | |||||
import ( | |||||
"testing" | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func TestApi(t *testing.T) { | |||||
state := lua.NewState() | |||||
PreLoadGo(state) | |||||
if err := state.DoFile("../testScript/test_time_api.lua"); err != nil { | |||||
t.Fatalf("execute test: %s\n", err.Error()) | |||||
} | |||||
} |
@ -0,0 +1,24 @@ | |||||
package time | |||||
import ( | |||||
lua "github.com/yuin/gopher-lua" | |||||
) | |||||
func PreLoadGo(L *lua.LState) { | |||||
L.PreloadModule("time", Loader) | |||||
} | |||||
func Loader(L *lua.LState) int { | |||||
t := L.NewTable() | |||||
L.SetFuncs(t, api) | |||||
L.Push(t) | |||||
return 1 | |||||
} | |||||
var api = map[string]lua.LGFunction{ | |||||
"unix": Unix, | |||||
"unix_nano": UnixNano, | |||||
"sleep": Sleep, | |||||
"parse": Parse, | |||||
"format": Format, | |||||
} |
@ -0,0 +1,199 @@ | |||||
package luaInGo | |||||
// import ( | |||||
// "context" | |||||
// "sync" | |||||
// "sync/atomic" | |||||
// "time" | |||||
// | |||||
// log "github.com/iglev/ilog" | |||||
// ) | |||||
// | |||||
// type hotfixMgr interface { | |||||
// reg(file string) | |||||
// check(L *LState) *hotfixList | |||||
// } | |||||
// | |||||
// func newHotfixMgr(ctx context.Context, needCoro bool, hotfixTime int64) hotfixMgr { | |||||
// var ht hotfixMgr | |||||
// if needCoro { | |||||
// htco := &hotfixMgrCoro{ | |||||
// ctx: ctx, | |||||
// ch: make(chan *hotfixList, 16), | |||||
// hotfixTime: hotfixTime, | |||||
// } | |||||
// go htco.loop() | |||||
// ht = htco | |||||
// } else { | |||||
// ht = &hotfixMgrLocal{ | |||||
// mp: make(map[string]int64), | |||||
// lasttime: time.Now().Unix(), | |||||
// hotfixTime: hotfixTime, | |||||
// } | |||||
// } | |||||
// return ht | |||||
// } | |||||
// | |||||
// type hotfixList struct { | |||||
// files []string | |||||
// } | |||||
// | |||||
// func hotfixDoFile(L *LState, ht hotfixMgr, up *hotfixList) { | |||||
// size := len(up.files) | |||||
// for i := 0; i < size; i++ { | |||||
// err := L.L().DoFile(up.files[i]) | |||||
// if err != nil { | |||||
// log.Error("DoFile fail, file=%v err=%v", up.files[i], err) | |||||
// } else { | |||||
// log.Info("reload file=%v success", up.files[i]) | |||||
// } | |||||
// } | |||||
// } | |||||
// | |||||
// ////////////////////////////////////////////////////////////////// | |||||
// // hotfixMgrLocal | |||||
// | |||||
// type hotfixMgrLocal struct { | |||||
// mp map[string]int64 | |||||
// lasttime int64 | |||||
// hotfixTime int64 | |||||
// } | |||||
// | |||||
// func (ht *hotfixMgrLocal) reg(file string) { | |||||
// mt, err := getFileModtime(file) | |||||
// if err != nil { | |||||
// return | |||||
// } | |||||
// ht.mp[file] = mt | |||||
// } | |||||
// | |||||
// func (ht *hotfixMgrLocal) check(L *LState) *hotfixList { | |||||
// curr := time.Now().Unix() | |||||
// lasttime := atomic.LoadInt64(&ht.lasttime) | |||||
// if curr < (lasttime + ht.hotfixTime) { | |||||
// return nil | |||||
// } | |||||
// atomic.StoreInt64(&ht.lasttime, curr) | |||||
// up := ht.getHotfixList() | |||||
// if up != nil { | |||||
// hotfixDoFile(L, ht, up) | |||||
// } | |||||
// return up | |||||
// } | |||||
// | |||||
// func (ht *hotfixMgrLocal) getHotfixList() *hotfixList { | |||||
// size := len(ht.mp) | |||||
// if size <= 0 { | |||||
// return nil | |||||
// } | |||||
// up := &hotfixList{ | |||||
// files: make([]string, 0, size), | |||||
// } | |||||
// tmp := make(map[string]int64) | |||||
// for k, v := range ht.mp { | |||||
// mt, err := getFileModtime(k) | |||||
// if err != nil { | |||||
// log.Error("getFileModtime fail, file=%v err=%v", k, err) | |||||
// continue | |||||
// } | |||||
// if v != mt { | |||||
// up.files = append(up.files, k) | |||||
// tmp[k] = mt | |||||
// } | |||||
// } | |||||
// for k, v := range tmp { | |||||
// ht.mp[k] = v | |||||
// } | |||||
// return up | |||||
// } | |||||
// | |||||
// ////////////////////////////////////////////////////////////////// | |||||
// // hotfixMgrCoro | |||||
// | |||||
// type hotfixMgrCoro struct { | |||||
// ctx context.Context | |||||
// mp sync.Map | |||||
// ch chan *hotfixList | |||||
// hotfixTime int64 | |||||
// } | |||||
// | |||||
// func (ht *hotfixMgrCoro) reg(file string) { | |||||
// mt, err := getFileModtime(file) | |||||
// if err != nil { | |||||
// return | |||||
// } | |||||
// ht.mp.Store(file, mt) | |||||
// } | |||||
// | |||||
// func (ht *hotfixMgrCoro) check(L *LState) *hotfixList { | |||||
// up := ht.getHotfixList() | |||||
// if up != nil { | |||||
// hotfixDoFile(L, ht, up) | |||||
// } | |||||
// return up | |||||
// } | |||||
// | |||||
// func (ht *hotfixMgrCoro) getHotfixList() *hotfixList { | |||||
// select { | |||||
// case up := <-ht.ch: | |||||
// return up | |||||
// default: | |||||
// return nil | |||||
// } | |||||
// } | |||||
// | |||||
// func (ht *hotfixMgrCoro) loop() { | |||||
// timer := time.NewTimer(time.Duration(ht.hotfixTime) * time.Second) | |||||
// defer timer.Stop() | |||||
// Loop: | |||||
// for { | |||||
// select { | |||||
// case <-timer.C: | |||||
// ht.loopCheck() | |||||
// timer.Reset(time.Duration(ht.hotfixTime) * time.Second) | |||||
// case <-ht.ctx.Done(): | |||||
// break Loop | |||||
// } | |||||
// } | |||||
// } | |||||
// | |||||
// func (ht *hotfixMgrCoro) loopCheck() { | |||||
// var up *hotfixList | |||||
// mp := make(map[string]int64) | |||||
// ht.mp.Range(func(k, v interface{}) bool { | |||||
// file, ok := k.(string) | |||||
// if !ok { | |||||
// return false | |||||
// } | |||||
// oldmt, mtOK := v.(int64) | |||||
// if !mtOK { | |||||
// return false | |||||
// } | |||||
// newmt, err := getFileModtime(file) | |||||
// if err != nil { | |||||
// log.Error("getFileModtime fail, file=%v err=%v", file, err) | |||||
// return false | |||||
// } | |||||
// if newmt != oldmt { | |||||
// mp[file] = newmt | |||||
// } | |||||
// return true | |||||
// }) | |||||
// size := len(mp) | |||||
// if size > 0 { | |||||
// up = &hotfixList{ | |||||
// files: make([]string, 0, size), | |||||
// } | |||||
// for k, v := range mp { | |||||
// ht.mp.Store(k, v) | |||||
// up.files = append(up.files, k) | |||||
// } | |||||
// select { | |||||
// case ht.ch <- up: | |||||
// return | |||||
// default: | |||||
// log.Error("hotfix send to channel fail, up=%v", up) | |||||
// } | |||||
// } | |||||
// } | |||||
// |
@ -0,0 +1,136 @@ | |||||
require ("math") | |||||
module('bit', package.seeall) -- 实现按位运算 | |||||
--默认按32位 | |||||
local __bitNum = 32 | |||||
--设置位数 | |||||
function setBitNum(bitNum) | |||||
__bitNum = bitNum | |||||
end | |||||
--按位同或 | |||||
function bxnor(int1, int2) | |||||
return __operaByBit(__bitxnor, int1, int2) | |||||
end | |||||
--按位异或 | |||||
function bxor(int1, int2) | |||||
return __operaByBit(__bitxor, int1, int2) | |||||
end | |||||
--按位与 | |||||
function band(int1, int2) | |||||
return __operaByBit(__bitand, int1, int2) | |||||
end | |||||
--按位或 | |||||
function bor(int1, int2) | |||||
return __operaByBit(__bitor, int1, int2) | |||||
end | |||||
--按位非 | |||||
function bnot(integer) | |||||
return __operaByBit(__bitnot, integer) | |||||
end | |||||
--按位操作 | |||||
function __operaByBit(bitFunc, ...) | |||||
local bDataLst = {} | |||||
for i = 1, select("#", ...) do | |||||
local bData = itob(select(i, ...)) | |||||
table.insert(bDataLst, bData) | |||||
end | |||||
for _, bData in ipairs(bDataLst) do | |||||
for i = #bData + 1, __bitNum do | |||||
table.insert(bData, 1, 0) | |||||
end | |||||
end | |||||
local resData = {} | |||||
for i = 1, __bitNum do | |||||
local args = {} | |||||
for _, bData in ipairs(bDataLst) do | |||||
table.insert(args, bData[i]) | |||||
end | |||||
table.insert(resData, bitFunc(unpack(args))) | |||||
end | |||||
return btoi(resData) | |||||
end | |||||
--按位同或 | |||||
function __bitxnor(bit1, bit2) | |||||
return (bit1 == bit2) and 1 or 0 | |||||
end | |||||
--按位异或 | |||||
function __bitxor(bit1, bit2) | |||||
return (bit1 == bit2) and 0 or 1 | |||||
end | |||||
--按位与 | |||||
function __bitand(bit1, bit2) | |||||
return (bit1 == 1 and bit2 == 1) and 1 or 0 | |||||
end | |||||
--按位或 | |||||
function __bitor(bit1, bit2) | |||||
return (bit1 == 1 or bit2 == 1) and 1 or 0 | |||||
end | |||||
--按位非 | |||||
function __bitnot(bit) | |||||
return 1 - bit | |||||
end | |||||
--2进制转换成10进制 | |||||
function btoi(bData) | |||||
return __ntoi(bData, 2) | |||||
end | |||||
--10进制转换成2进制 | |||||
function itob(integer) | |||||
return __iton(integer, 2) | |||||
end | |||||
--10进制转换成N进制 | |||||
function __iton(integer, num) | |||||
assert(type(integer) == "number") | |||||
if integer == 0 then | |||||
return {0} | |||||
end | |||||
local bNeg = integer < 0 | |||||
local ci = math.abs(integer) | |||||
local nData = {} | |||||
while ci > 0 do | |||||
table.insert(nData, 1, ci % num) | |||||
ci = math.floor(ci / num) | |||||
end | |||||
if bNeg then | |||||
for i = #nData + 1, __bitNum do | |||||
table.insert(nData, 1, num - 1) | |||||
end | |||||
end | |||||
return nData | |||||
end | |||||
--N进制转换成10进制 | |||||
function __ntoi(nData, num) | |||||
assert(type(nData) == "table") | |||||
local integer = 0 | |||||
for i, data in ipairs(nData) do | |||||
integer = integer + data * math.pow(num, #nData - i) | |||||
end | |||||
return integer | |||||
end | |||||
@ -0,0 +1,80 @@ | |||||
function GetClassName(name) | |||||
for k,v in pairs(_G) do | |||||
if name==v then | |||||
return k | |||||
end | |||||
end | |||||
end | |||||
function CreateClass(name,basename) | |||||
if _G[name] ~= nil then | |||||
unilight.error("CreateClass被意外全局初始化,这里强制重置成类:"..name) | |||||
return nil | |||||
end | |||||
_G[name] = {} | |||||
local class = _G[name] | |||||
if basename then | |||||
local baseclass = _G[basename] | |||||
if baseclass then | |||||
for k,v in pairs(baseclass) do | |||||
class[k] = v | |||||
end | |||||
else | |||||
unilight.error("CreateClass error:" .. tostring(name) .. ":" .. tostring(basename)) | |||||
end | |||||
end | |||||
class.__classname = name | |||||
function class:New(initclass) | |||||
local new = initclass or {} | |||||
setmetatable(new, { __index = self}) | |||||
return new | |||||
end | |||||
function class:SetClassName(cname) | |||||
self.__classname = cname or self.__classname | |||||
end | |||||
function class:GetLogPrefix() | |||||
local id = nil | |||||
local name = "" | |||||
if self.GetId then | |||||
id = self:GetId() | |||||
elseif self.id then | |||||
id = self.id | |||||
elseif self.Id then | |||||
id = self.Id | |||||
elseif self.tempid then | |||||
id = self.tempid | |||||
elseif self.Tempid then | |||||
id = self.Tempid | |||||
end | |||||
if self.GetName then | |||||
name = self:GetName() | |||||
elseif self.name then | |||||
name = self.name | |||||
elseif self.Name then | |||||
name = self.Name | |||||
end | |||||
local id = id or "" | |||||
local name = name or "" | |||||
return self.__classname .. "[" .. id .."," ..name.. "] " | |||||
end | |||||
function class:Debug(...) | |||||
unilight.debug(self:GetLogPrefix() .. unpack(arg)) | |||||
end | |||||
function class:Info(...) | |||||
unilight.info(self:GetLogPrefix() .. unpack(arg)) | |||||
end | |||||
function class:Warn(...) | |||||
unilight.warn(self:GetLogPrefix() .. unpack(arg)) | |||||
end | |||||
function class:Error(...) | |||||
unilight.error(self:GetLogPrefix() .. unpack(arg)) | |||||
end | |||||
function class:Stack(...) | |||||
unilight.stack(self:GetLogPrefix() .. unpack(arg)) | |||||
end | |||||
return class | |||||
end | |||||
--Class = CreateClass("Class") | |||||
--new = Class:New() | |||||
--new:Debug("whj") |
@ -0,0 +1,295 @@ | |||||
-- 通用lua扩充函数,与任何游戏逻辑无关 | |||||
-- from http://snippets.luacode.org/?p=snippets/String_to_Hex_String_68 | |||||
string.tohex = function(str, spacer) | |||||
return string.gsub(str,"(.)", function (c) return string.format("%02X%s", string.byte(c), spacer or "") end) | |||||
end | |||||
string.trim = function(str) | |||||
return string.gsub(str, "^%s*(.-)%s*$", "%1") | |||||
end | |||||
string.trimbegin = function(str) | |||||
return string.gsub(str, "^%s*(.-)$", "%1") | |||||
end | |||||
string.trimend = function(str) | |||||
return string.gsub(str, "^(.-)%s*$", "%1") | |||||
end | |||||
string.padleft = function(str, totalWidth, paddingChar) | |||||
local len = #str | |||||
if len >= totalWidth then | |||||
return str | |||||
else | |||||
paddingChar = paddingChar or ' ' | |||||
assert(#paddingChar == 1) | |||||
return string.rep(paddingChar, totalWidth - len) .. str | |||||
end | |||||
end | |||||
string.padright = function(str, totalWidth, paddingChar) | |||||
local len = #str | |||||
if len >= totalWidth then | |||||
return str | |||||
else | |||||
paddingChar = paddingChar or ' ' | |||||
assert(#paddingChar == 1) | |||||
return str .. string.rep(paddingChar, totalWidth - len) | |||||
end | |||||
end | |||||
string.split = function(szFullString, szSeparator) | |||||
local FindStartIndex = 1 | |||||
local SplitArray = {} | |||||
while true do | |||||
local FindLastIndex = string.find(szFullString, szSeparator, FindStartIndex, true) | |||||
if not FindLastIndex then | |||||
table.insert(SplitArray, string.sub(szFullString, FindStartIndex, string.len(szFullString))) | |||||
break | |||||
end | |||||
table.insert(SplitArray, string.sub(szFullString, FindStartIndex, FindLastIndex-1)) | |||||
FindStartIndex = FindLastIndex + string.len(szSeparator) | |||||
end | |||||
return SplitArray | |||||
end | |||||
string.isNilOrEmpty = function(str) | |||||
if str == nil then | |||||
return true, nil | |||||
end | |||||
if type(str) ~= "string" then | |||||
return true, nil | |||||
end | |||||
local fstr = string.match(str,"%s*(.-)%s*$") | |||||
local ret = fstr == "" | |||||
if ret == true then | |||||
str = nil | |||||
end | |||||
return ret, fstr | |||||
end | |||||
table.find = function(this, value) | |||||
for k,v in pairs(this) do | |||||
if v == value then return k end | |||||
end | |||||
end | |||||
table.omit = function(tbl) | |||||
for k,v in pairs(tbl) do | |||||
local typ = type(v) | |||||
if typ == "table" then | |||||
v = table.omit(v) | |||||
if v == nil or next(v) == nil then | |||||
tbl[k] = nil | |||||
end | |||||
elseif (typ == "string" and v == "") or (typ == "number" and v == 0) then | |||||
tbl[k] = nil | |||||
end | |||||
end | |||||
return tbl | |||||
end | |||||
table.tostring = function(data, _indent) | |||||
local visited = {} | |||||
local function dump(data, prefix) | |||||
local str = tostring(data) | |||||
if table.find(visited, data) ~= nil then return str end | |||||
table.insert(visited, data) | |||||
local prefix_next = prefix .. " " | |||||
str = str .. "\n" .. prefix .. "{" | |||||
for k,v in pairs(data) do | |||||
if type(k) == "number" then | |||||
str = str .. "\n" .. prefix_next .. "[" .. tostring(k) .. "] = " | |||||
else | |||||
str = str .. "\n" .. prefix_next .. tostring(k) .. " = " | |||||
end | |||||
if type(v) == "table" then | |||||
str = str .. dump(v, prefix_next) | |||||
elseif type(v) == "string" then | |||||
str = str .. '"' .. v .. '"' | |||||
else | |||||
str = str .. tostring(v) | |||||
end | |||||
end | |||||
str = str .. "\n" .. prefix .. "}" | |||||
return str | |||||
end | |||||
return dump(data, _indent or "") | |||||
end | |||||
table.merge = function(base, delta) | |||||
if type(delta) ~= "table" then return end | |||||
for k,v in pairs(delta) do | |||||
base[k] = v | |||||
end | |||||
end | |||||
table.extend = function(base, delta) | |||||
if type(delta) ~= "table" then return end | |||||
for i,v in ipairs(delta) do | |||||
table.insert(base, v) | |||||
end | |||||
end | |||||
table.len = function(tbl) | |||||
if type(tbl) ~= "table" then return 0 end | |||||
local n = 0 | |||||
for k,v in pairs(tbl) do n = n + 1 end | |||||
return n | |||||
end | |||||
table.empty = function(tbl) | |||||
if tbl == nil then return true end | |||||
assert(type(tbl) == "table") | |||||
return next(tbl) == nil | |||||
--if #tbl > 0 then return false end | |||||
--for k,v in pairs(tbl) do return false end | |||||
--return true | |||||
end | |||||
-- http://snippets.luacode.org/?p=snippets/Deep_copy_of_a_Lua_Table_2 | |||||
table.clone = function(t,deepnum) | |||||
if type(t) ~= 'table' then return t end | |||||
local mt = getmetatable(t) | |||||
local res = {} | |||||
if deepnum and deepnum > 0 then | |||||
deepnum = deepnum - 1 | |||||
end | |||||
for k,v in pairs(t) do | |||||
if type(v) == 'table' then | |||||
if not deepnum or deepnum > 0 then | |||||
v = table.clone(v, deepnum) | |||||
end | |||||
end | |||||
res[k] = v | |||||
end | |||||
setmetatable(res,mt) | |||||
return res | |||||
end | |||||
-- http://snippets.luacode.org/?p=snippets/Table_Slice_116 | |||||
table.slice = function(values,i1,i2) | |||||
local res = {} | |||||
local n = #values | |||||
i1 = i1 or 1 | |||||
i2 = i2 or n | |||||
if i2 < 0 then | |||||
i2 = n + i2 + 1 | |||||
elseif i2 > n then | |||||
i2 = n | |||||
end | |||||
if i1 < 1 or i1 > n then | |||||
return {} | |||||
end | |||||
local k = 1 | |||||
for i = i1,i2 do | |||||
res[k] = values[i] | |||||
k = k + 1 | |||||
end | |||||
return res | |||||
end | |||||
table.reverse = function(tab) | |||||
local size = #tab | |||||
local newTable = {} | |||||
for i,v in ipairs(tab) do | |||||
newTable[size+1-i] = v | |||||
end | |||||
return newTable | |||||
end | |||||
table.reset = function(t) | |||||
for k,v in pairs(t) do | |||||
t[k] = nil | |||||
end | |||||
return t | |||||
end | |||||
-- math.random({0.7, 0.1, 0.2}, {'A', 'B', 'C'}) | |||||
math.random = function(m, n) | |||||
if type(m) == "table" and #m == #n then | |||||
-- 标准化概率表 | |||||
local sum = 0 | |||||
for _,v in ipairs(m) do sum = sum + v end | |||||
local sm = {} | |||||
for k,v in ipairs(m) do sm[k] = v / sum end | |||||
-- 得到下标 | |||||
local r = go.rand.Random() | |||||
for k,v in ipairs(sm) do | |||||
if r <= v then return n[k] | |||||
else r = r - v end | |||||
end | |||||
assert(false) | |||||
end | |||||
if m == nil then return go.rand.Random() end | |||||
local _random = function(m, n) | |||||
m, n = math.min(m, n), math.max(m, n) | |||||
local mi, mf = math.modf(m) | |||||
local ni, nf = math.modf(n) | |||||
if mf == 0 and nf == 0 then | |||||
return go.rand.RandBetween(m, n) | |||||
else | |||||
return m + go.rand.Random() * (n - m) | |||||
end | |||||
end | |||||
if n == nil then return _random(1, m) end | |||||
return _random(m, n) | |||||
end | |||||
-- http://www.cplusplus.com/reference/algorithm/random_shuffle/ | |||||
-- http://stackoverflow.com/questions/17119804/lua-array-shuffle-not-working | |||||
math.shuffle = function(array) | |||||
local counter = #array | |||||
while counter > 1 do | |||||
local index = math.random(counter) | |||||
array[index], array[counter] = array[counter], array[index] | |||||
counter = counter - 1 | |||||
end | |||||
return array | |||||
end | |||||
--按table的key排序遍历table e.g. for k, v in pairsByKeys(tab, function(v1,v2) return v1 > v2 end) do print(k, v) end | |||||
function pairsByKeys(t, sortfunc) | |||||
local kt = {} | |||||
local len = 0 | |||||
for k in pairs(t) do | |||||
len = len + 1 | |||||
kt[len] = k | |||||
end | |||||
table.sort(kt, sortfunc) | |||||
local i = 0 | |||||
return function() | |||||
i = i + 1 | |||||
return kt[i], t[kt[i]] | |||||
end | |||||
end | |||||
--计算utf8字符串的长度 from quickcocos | |||||
function string.utf8len(input) | |||||
local len = string.len(input) | |||||
local left = len | |||||
local cnt = 0 | |||||
local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc} | |||||
while left ~= 0 do | |||||
local tmp = string.byte(input, -left) | |||||
local i = #arr | |||||
while arr[i] do | |||||
if tmp >= arr[i] then | |||||
left = left - i | |||||
break | |||||
end | |||||
i = i - 1 | |||||
end | |||||
cnt = cnt + 1 | |||||
end | |||||
return cnt | |||||
end | |||||
--检查一个文件是否存在 | |||||
function file_exists(path) | |||||
local file = io.open(path, "rb") | |||||
if file then file:close() end | |||||
return file ~= nil | |||||
end |
@ -0,0 +1,37 @@ | |||||
module('random', package.seeall) | |||||
--添加的随机概率函数--------- | |||||
----小数点概率--- | |||||
function selectByPoint(value) | |||||
if value == nil or value <= 0 then | |||||
return false | |||||
end | |||||
local value = math.ceil(1 / value) | |||||
return selectByRegion(1, value) | |||||
end | |||||
----百分比概率--- | |||||
function selectByPercent(value) | |||||
if value < 1 then | |||||
return false | |||||
end | |||||
return selectByRegion(value, 100) | |||||
end | |||||
----万分比概率--- | |||||
function selectByTenTh(value) | |||||
if value < 1 then | |||||
return false | |||||
end | |||||
return selectByRegion(value, 10000) | |||||
end | |||||
function selectByRegion(down, up) | |||||
if down >= up then | |||||
return true | |||||
end | |||||
local random = math.random(1, up) | |||||
return random <= down | |||||
end |
@ -0,0 +1,42 @@ | |||||
unilight = unilight or {} | |||||
os.time = go.time.luatime() | |||||
os.msectime = go.time.Msec | |||||
os.nsectime = go.time.Nsec | |||||
-- log -- | |||||
unilight.debug = function(...) | |||||
local arg = {...} | |||||
go.logging.debug(arg[1], arg[2] or {}) | |||||
end | |||||
unilight.info = function(...) | |||||
local arg = {...} | |||||
go.logging.info(arg[1], arg[2] or {}) | |||||
end | |||||
unilight.warn = function(...) | |||||
print("unilight-warn:" .. tostring(...)) | |||||
local arg = {...} | |||||
go.logging.warning(arg[1], arg[2] or {}) | |||||
end | |||||
unilight.error = function(...) | |||||
local arg = {...} | |||||
if next(arg) == nil then | |||||
unilight.error(debug.traceback()) | |||||
end | |||||
go.logging.error(arg[1], arg[2] or {}) | |||||
end | |||||
unilight.stack = function(...) | |||||
local arg = {...} | |||||
print("unilight-stack:" .. tostring(...)) | |||||
end | |||||
unilight.tablefiles = function() | |||||
return luar.slice2table(go.getLuaFiles(go.tablePath)) | |||||
end | |||||
unilight.scriptfiles = function() | |||||
return luar.slice2table(go.getLuaFiles(go.scriptPath)) | |||||
end |
@ -0,0 +1,21 @@ | |||||
uniregexp= uniregexp or {} | |||||
--[[ | |||||
exp: | |||||
uniregexp.match("foo.*","seafood") => true nil | |||||
uniregexp.match("bar.*","seafood") => false nil | |||||
uniregexp.match("a(b","seafood") => false error parsing regexp: missing closing ): `a(b` | |||||
--]] | |||||
uniregexp.match = function(pattern, s) | |||||
return go.uniregexp.Match(pattern, s) | |||||
end | |||||
--[[ | |||||
exp: | |||||
quotemeta(`[foo]`) => `\[foo\]` | |||||
--]] | |||||
uniregexp.quotemeta = function(s) | |||||
return go.uniregexp.QuoteMeta(s) | |||||
end | |||||
-- 其余api可以调用go.uniregexp.***** 参考go语言 regexp.Regexp类方法 |
@ -0,0 +1,137 @@ | |||||
CreateClass("UniTimerClass") | |||||
CreateClass("UniEventClass") | |||||
function NewUniTimerClass(callback, msec, ...) | |||||
local timer = { | |||||
nextmsec=unitimer.now, | |||||
callback = callback, | |||||
tick = msec, | |||||
params = arg, | |||||
} | |||||
UniTimerClass:New(timer) | |||||
return timer | |||||
end | |||||
function NewUniTimerRandomClass(callback, msec, ...) | |||||
local timer = { | |||||
nextmsec=unitimer.now+math.random(msec/2,msec), | |||||
callback = callback, | |||||
tick = msec, | |||||
params = arg, | |||||
} | |||||
UniTimerClass:New(timer) | |||||
return timer | |||||
end | |||||
function NewUniEventClass(callback, msec,maxtimes, ...) | |||||
local event = { | |||||
nextmsec=unitimer.now+msec, | |||||
callback = callback, | |||||
tick = msec, | |||||
maxtimes = maxtimes, | |||||
params = arg, | |||||
} | |||||
UniEventClass:New(event) | |||||
return event | |||||
end | |||||
function UniTimerClass:GetId() | |||||
return self.tick | |||||
end | |||||
function UniTimerClass:GetName() | |||||
return self.tick | |||||
end | |||||
function UniTimerClass:Stop() | |||||
self.stop = true | |||||
unitimer.removetimer(self) | |||||
end | |||||
function UniTimerClass:Check(now,force) | |||||
if self.nextmsec <= now or force then | |||||
--unilight.error("UniEventClass:"..unpack(self.params)) | |||||
self.nextmsec = now + self.tick --如果callback脚本报错,会悲剧,WHJ,似乎没人用,先提前试试 | |||||
self.callback(unpack(self.params)) | |||||
return true | |||||
end | |||||
--duaration=0 | |||||
--first=true | |||||
--pause=false | |||||
--stop=false | |||||
return false | |||||
end | |||||
function UniEventClass:GetId() | |||||
return self.tick | |||||
end | |||||
function UniEventClass:GetName() | |||||
return self.maxtimes | |||||
end | |||||
function UniEventClass:Check(now,force) | |||||
--if (self.nextmsec <= now or force) and self.tick > 0 then | |||||
if (self.maxtimes > 0 and self.nextmsec <= now) or force then | |||||
self.nextmsec = now + self.tick --如果callback脚本报错,会悲剧,WHJ,似乎没人用,先提前试试 | |||||
self.maxtimes = self.maxtimes - 1 --计数可以提前,时间不能提前,有可能逻辑里要用时间,提前的目的是防止Check报错后就悲剧 | |||||
self.callback(unpack(self.params)) | |||||
return true | |||||
end | |||||
return false | |||||
end | |||||
function UniEventClass:Stop() | |||||
unitimer.removeevent(self) | |||||
end | |||||
unitimer={ | |||||
timermap={}, | |||||
eventmap={}, | |||||
} | |||||
function unitimer.init(msec) --最小精度的定时器 | |||||
unitimer.now = go.time.Msec() | |||||
if unitimer.ticktimer ~= nil then | |||||
unilight.error("unitimer.init已经初始化过了:"..unitimer.tickmsec) | |||||
return false | |||||
end | |||||
unitimer.tickmsec = msec --保存最小精度 | |||||
unitimer.ticktimer = unilight.addtimermsec("unitimer.loop", msec) | |||||
return true | |||||
end | |||||
function unitimer.loop() | |||||
local timer = unitimer | |||||
timer.now = go.time.Msec() | |||||
for k,v in pairs(timer.timermap) do | |||||
if v:Check(timer.now) == true then | |||||
if v.stop == true then | |||||
timer.removetimer(v) | |||||
end | |||||
end | |||||
end | |||||
for k,v in pairs(timer.eventmap) do | |||||
if v:Check(timer.now) == true then | |||||
if v.maxtimes <= 0 then | |||||
--v:Debug("事件结束") | |||||
v:Stop() | |||||
end | |||||
end | |||||
end | |||||
end | |||||
function unitimer.addtimermsec(callback, msec, ...) | |||||
local timer = NewUniTimerClass(callback, msec, ...) | |||||
--timer:Debug("unitimer.addtimermsec:") | |||||
unitimer.timermap[timer]=timer | |||||
return timer | |||||
end | |||||
function unitimer.addtimer(callback, msec, ...) | |||||
return unitimer.addtimermsec(callback, msec*1000, ...) | |||||
end | |||||
function unitimer.removetimer(timer) | |||||
--timer:Debug("unitimer.removetimer:") | |||||
unitimer.timermap[timer] = nil | |||||
end | |||||
function unitimer.addevent(callback, msec,maxtimes, ...) | |||||
return unitimer.addeventmsec(callback, msec*1000,maxtimes, ...) | |||||
end | |||||
function unitimer.addeventmsec(callback, msec,maxtimes, ...) | |||||
maxtime = maxtimes or 1 | |||||
local event = NewUniEventClass(callback, msec,maxtimes, ...) | |||||
--event:Debug("设置事件:"..msec) | |||||
unitimer.eventmap[event]=event | |||||
return event | |||||
end | |||||
function unitimer.removeevent(event) | |||||
unitimer.eventmap[event] = nil | |||||
end |
@ -0,0 +1,118 @@ | |||||
local pattern = '[%z\1-\127\194-\244][\128-\191]*' | |||||
-- helper function | |||||
local posrelat = | |||||
function (pos, len) | |||||
if pos < 0 then | |||||
pos = len + pos + 1 | |||||
end | |||||
return pos | |||||
end | |||||
utf8 = {} | |||||
-- maps f over s's utf8 characters f can accept args: (visual_index, utf8_character, byte_index) | |||||
utf8.map = | |||||
function (s, f, no_subs) | |||||
local i = 0 | |||||
if no_subs then | |||||
for b, e in s:gmatch('()' .. pattern .. '()') do | |||||
i = i + 1 | |||||
local c = e - b | |||||
f(i, c, b) | |||||
end | |||||
else | |||||
for b, c in s:gmatch('()(' .. pattern .. ')') do | |||||
i = i + 1 | |||||
f(i, c, b) | |||||
end | |||||
end | |||||
end | |||||
-- generator for the above -- to iterate over all utf8 chars | |||||
utf8.chars = | |||||
function (s, no_subs) | |||||
return coroutine.wrap(function () return utf8.map(s, coroutine.yield, no_subs) end) | |||||
end | |||||
-- returns the number of characters in a UTF-8 string | |||||
utf8.len = | |||||
function (s) | |||||
-- count the number of non-continuing bytes | |||||
return select(2, s:gsub('[^\128-\193]', '')) | |||||
end | |||||
utf8.GetMaxLenString = | |||||
function (s, maxlen, symbol) | |||||
-- s:待裁剪字符串,maxlen:最大长度,symbol:裁剪后补全符号 | |||||
symbol = symbol or "" | |||||
local len = utf8.len(s) | |||||
local dstString = s | |||||
-- 超长,裁剪,加symbol | |||||
if len > maxlen then | |||||
dstString = utf8.sub(s, 1, maxlen) | |||||
dstString = dstString..symbol | |||||
end | |||||
return dstString | |||||
end | |||||
-- replace all utf8 chars with mapping | |||||
utf8.replace = | |||||
function (s, map) | |||||
return s:gsub(pattern, map) | |||||
end | |||||
-- reverse a utf8 string | |||||
utf8.reverse = | |||||
function (s) | |||||
-- reverse the individual greater-than-single-byte characters | |||||
s = s:gsub(pattern, function (c) return #c > 1 and c:reverse() end) | |||||
return s:reverse() | |||||
end | |||||
-- strip non-ascii characters from a utf8 string | |||||
utf8.strip = | |||||
function (s) | |||||
return s:gsub(pattern, function (c) return #c > 1 and '' end) | |||||
end | |||||
-- like string.sub() but i, j are utf8 strings | |||||
-- a utf8-safe string.sub() | |||||
utf8.sub = | |||||
function (s, i, j) | |||||
local l = utf8.len(s) | |||||
i = posrelat(i, l) | |||||
j = j and posrelat(j, l) or l | |||||
if i < 1 then i = 1 end | |||||
if j > l then j = l end | |||||
if i > j then return '' end | |||||
local diff = j - i | |||||
local iter = utf8.chars(s, true) | |||||
-- advance up to i | |||||
for _ = 1, i - 1 do iter() end | |||||
local c, b = select(2, iter()) | |||||
-- i and j are the same, single-charaacter sub | |||||
if diff == 0 then | |||||
return string.sub(s, b, b + c - 1) | |||||
end | |||||
i = b | |||||
-- advance up to j | |||||
for _ = 1, diff - 1 do iter() end | |||||
c, b = select(2, iter()) | |||||
return string.sub(s, i, b + c - 1) | |||||
end | |||||
@ -0,0 +1,76 @@ | |||||
package luaInGo | |||||
import ( | |||||
lua "github.com/yuin/gopher-lua" | |||||
"strings" | |||||
"sync" | |||||
) | |||||
type lStatePool struct { | |||||
m sync.Mutex | |||||
saved []*lua.LState | |||||
} | |||||
// Get 从池中取出一个LState,若池中没有,则新增一个 | |||||
func (pl *lStatePool) Get() *lua.LState { | |||||
pl.m.Lock() | |||||
defer pl.m.Unlock() | |||||
n := len(pl.saved) | |||||
if n == 0 { | |||||
return pl.New() | |||||
} | |||||
x := pl.saved[n-1] | |||||
pl.saved = pl.saved[0 : n-1] | |||||
return x | |||||
} | |||||
// Put 用完LState后放回池中 | |||||
func (pl *lStatePool) Put(L *lua.LState) { | |||||
pl.m.Lock() | |||||
defer pl.m.Unlock() | |||||
if len(pl.saved) > NaxPoolSize { | |||||
L.Close() | |||||
} else { | |||||
// 放回的时候 清理一下 堆栈 确认数据正常 | |||||
L.SetTop(0) | |||||
pl.saved = append(pl.saved, L) | |||||
} | |||||
} | |||||
func (pl *lStatePool) ShutDown() { | |||||
for _, L := range pl.saved { | |||||
L.Close() | |||||
} | |||||
} | |||||
func (pl *lStatePool) New() *lua.LState { | |||||
L := lua.NewState() | |||||
//提供全局函数给lua | |||||
PreLoadGo(L) | |||||
//加载go提供元表给lua | |||||
// golua.RegisterPersonType(L) | |||||
// 添加lua脚本自动搜索路径 | |||||
// Tamper package.path according to configuration... | |||||
t := L.GetGlobal("package").(*lua.LTable) | |||||
// Get "path" from package table | |||||
lPath := lua.LString("path") | |||||
s := L.RawGet(t, lPath).(lua.LString).String() | |||||
// Create list of elements to join for new package path | |||||
elems := []string{s} | |||||
elems = append(elems, "./luaScript/?.lua") | |||||
// Set new package.path | |||||
L.RawSet(t, lPath, lua.LString(strings.Join(elems, ";"))) | |||||
//加载lua脚本 仅仅加载入口函数模块的lua | |||||
if err := L.DoFile("./luaScript/main.lua"); err != nil { | |||||
println("load the main lua files error") | |||||
panic(err) | |||||
} | |||||
return L | |||||
} |
@ -0,0 +1,21 @@ | |||||
package luaInGo | |||||
import ( | |||||
lua "github.com/yuin/gopher-lua" | |||||
"luaInGo/goApis" | |||||
"luaInGo/goApis/crypto" | |||||
"luaInGo/goApis/json" | |||||
"luaInGo/goApis/strings" | |||||
"luaInGo/goApis/time" | |||||
) | |||||
// 这里封装一个函数 统一load go中提供给lua调用的函数 | |||||
func PreLoadGo(L *lua.LState) { | |||||
// 这里再调用一些子模块的LoadGo()函数 | |||||
time.PreLoadGo(L) | |||||
strings.PreLoadGo(L) | |||||
crypto.PreLoadGo(L) | |||||
json.PreloadGo(L) | |||||
goApis.PreLoadLibs(L) | |||||
} |