Skip to content

Commit 26a82cc

Browse files
committed
Add bitwise operations support
Signed-off-by: Dusan Borovcanin <[email protected]>
1 parent c2a4800 commit 26a82cc

File tree

6 files changed

+193
-0
lines changed

6 files changed

+193
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ go get github.com/vadv/gopher-lua-libs
5050
* [xmlpath](/xmlpath) [gopkg.in/xmlpath.v2](https://gopkg.in/xmlpath.v2) port
5151
* [yaml](/yaml) [gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) port
5252
* [zabbix](/zabbix) zabbix bot
53+
* [bit](/bit) bitwise operations
5354

5455

5556
## Usage

bit/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# stats [![GoDoc](https://godoc.org/github.com/vadv/gopher-lua-libs/bit?bit.svg)](https://godoc.org/github.com/vadv/gopher-lua-libs/stats)
2+
3+
## Usage
4+
5+
```lua
6+
local stats = require("bit")
7+
8+
local result, _ = bit.band(1, 0)
9+
print(result)
10+
-- Output: 0
11+
12+
local result, _ = stats.lshift(10, 5)
13+
print(result)
14+
-- Output: 320
15+
```
16+

bit/api.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Package strings implements golang package montanaflynn/stats functionality for lua.
2+
package stats
3+
4+
import (
5+
"fmt"
6+
"math"
7+
8+
lua "github.com/yuin/gopher-lua"
9+
)
10+
11+
type op uint
12+
13+
const (
14+
and op = iota
15+
or
16+
not
17+
xor
18+
ls
19+
rs
20+
)
21+
22+
// ShiftLeft
23+
func Bitwise(kind op) lua.LGFunction {
24+
return func(l *lua.LState) int {
25+
if kind > rs {
26+
l.Push(lua.LString("invalid type of operation"))
27+
return 1
28+
}
29+
val1, val2, err := prepareParams(l)
30+
if err != nil {
31+
l.Push(lua.LString(err.Error()))
32+
return 1
33+
}
34+
var ret uint32
35+
switch kind {
36+
case and:
37+
ret = val1 & val2
38+
case or:
39+
ret = val1 | val2
40+
case xor:
41+
ret = val1 ^ val2
42+
case ls:
43+
ret = val1 << val2
44+
case rs:
45+
ret = val1 >> val2
46+
}
47+
l.Push(lua.LNumber(ret))
48+
return 1
49+
}
50+
}
51+
52+
func Not(l *lua.LState) int {
53+
val, err := intToU32(l.CheckInt(1))
54+
if err != nil {
55+
l.Push(lua.LString(err.Error()))
56+
return 1
57+
}
58+
l.Push(lua.LNumber(^val))
59+
return 1
60+
}
61+
62+
func prepareParams(l *lua.LState) (val, pos uint32, err error) {
63+
val, err = intToU32(l.CheckInt(1))
64+
if err != nil {
65+
return 0, 0, err
66+
}
67+
pos, err = intToU32(l.CheckInt(2))
68+
if err != nil {
69+
return 0, 0, err
70+
}
71+
return
72+
}
73+
74+
func intToU32(i int) (uint32, error) {
75+
if i < 0 {
76+
return 0, fmt.Errorf("cannot convert negative int %d to uint32", i)
77+
}
78+
if i > math.MaxUint32 {
79+
return 0, fmt.Errorf("int %d overflows uint32", i)
80+
}
81+
return uint32(i), nil
82+
}

bit/api_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package stats
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"github.com/vadv/gopher-lua-libs/tests"
6+
"testing"
7+
)
8+
9+
func TestApi(t *testing.T) {
10+
assert.NotZero(t, tests.RunLuaTestFile(t, Preload, "./test/test_api.lua"))
11+
}

bit/loader.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package stats
2+
3+
import lua "github.com/yuin/gopher-lua"
4+
5+
// Preload adds stats to the given Lua state's package.preload table. After it
6+
// has been preloaded, it can be loaded using require:
7+
//
8+
// local bit = require("bit")
9+
func Preload(l *lua.LState) {
10+
l.PreloadModule("bit", Loader)
11+
}
12+
13+
// Loader is the module loader function.
14+
func Loader(L *lua.LState) int {
15+
t := L.NewTable()
16+
L.SetFuncs(t, api)
17+
L.Push(t)
18+
return 1
19+
}
20+
21+
var api = map[string]lua.LGFunction{
22+
"band": Bitwise(and),
23+
"bor": Bitwise(or),
24+
"bxor": Bitwise(xor),
25+
"lshift": Bitwise(ls),
26+
"rshift": Bitwise(rs),
27+
"bnot": Not,
28+
}

bit/test/test_api.lua

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
local bit = require("bit")
2+
3+
function Test_and(t)
4+
local result, err = bit.band(1, 0)
5+
assert(not err, err)
6+
assert(result == 0, "and get: " .. tostring(result))
7+
result, err = bit.band(5, 6)
8+
assert(not err, err)
9+
assert(result == 4, "and get: " .. tostring(result))
10+
end
11+
12+
function Test_or(t)
13+
local result, err = bit.bor(1, 0)
14+
assert(not err, err)
15+
assert(result == 1, "or get: " .. tostring(result))
16+
result, err = bit.bor(5, 6)
17+
assert(not err, err)
18+
assert(result == 7, "or get: " .. tostring(result))
19+
end
20+
21+
function Test_xor(t)
22+
local result, err = bit.bxor(1, 0)
23+
assert(not err, err)
24+
assert(result == 1, "xor get: " .. tostring(result))
25+
result, err = bit.bxor(5, 6)
26+
assert(not err, err)
27+
assert(result == 3, "xor get: " .. tostring(result))
28+
end
29+
30+
function Test_left_shift(t)
31+
local result, err = bit.lshift(1, 0)
32+
assert(not err, err)
33+
assert(result == 1, "left_shift get: " .. tostring(result))
34+
result, err = bit.lshift(0xFF, 8)
35+
assert(not err, err)
36+
assert(result == 65280, "left_shift get: " .. tostring(result))
37+
end
38+
39+
function Test_right_shift(t)
40+
local result, err = bit.rshift(42, 2)
41+
assert(not err, err)
42+
assert(result == 10, "right_shift get: " .. tostring(result))
43+
result, err = bit.rshift(0xFF, 4)
44+
assert(not err, err)
45+
assert(result == 15, "right_shift get: " .. tostring(result))
46+
end
47+
48+
function Test_not(t)
49+
local result, err = bit.bnot(65536)
50+
assert(not err, err)
51+
assert(result == 4294901759, "not get: " .. tostring(result))
52+
result, err = bit.bnot(4294901759)
53+
assert(not err, err)
54+
assert(result == 65536, "not get: " .. tostring(result))
55+
end

0 commit comments

Comments
 (0)