Skip to content

Commit

Permalink
Merge 623fed7 into 7d307d3
Browse files Browse the repository at this point in the history
  • Loading branch information
YIDWang committed Jan 23, 2019
2 parents 7d307d3 + 623fed7 commit 5e54979
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 11 deletions.
2 changes: 2 additions & 0 deletions command/init.go
Expand Up @@ -33,6 +33,7 @@ func init() {
"psetex": PSetEx,
"setrange": SetRange,
"setbit": SetBit,
"getbit": GetBit,
"incr": Incr,
"incrby": IncrBy,
"decr": Decr,
Expand Down Expand Up @@ -130,6 +131,7 @@ func init() {
"decrby": Desc{Proc: AutoCommit(DecrBy), Cons: Constraint{3, flags("wmF"), 1, 1, 1}},
"incrbyfloat": Desc{Proc: AutoCommit(IncrByFloat), Cons: Constraint{3, flags("wmF"), 1, 1, 1}},
"setbit": Desc{Proc: AutoCommit(SetBit), Cons: Constraint{4, flags("wm"), 1, 1, 1}},
"getbit": Desc{Proc: AutoCommit(GetBit), Cons: Constraint{3, flags("r"), 1, 1, 1}},

// keys
"type": Desc{Proc: AutoCommit(Type), Cons: Constraint{2, flags("rF"), 1, 1, 1}},
Expand Down
2 changes: 1 addition & 1 deletion command/server_test.go
Expand Up @@ -26,7 +26,7 @@ func TestInfo(t *testing.T) {
}),
}
Info(ctx)
t.Log(out.String())
// t.Log(out.String())
if strings.Index(out.String(), "ERR") == 0 {
t.Fail()
}
Expand Down
29 changes: 28 additions & 1 deletion command/strings.go
Expand Up @@ -498,7 +498,7 @@ func SetBit(ctx *Context, txn *db.Transaction) (OnCommit, error) {
}
return nil, errors.New("ERR " + err.Error())
}
val, err := str.SetBit(on, offset)
val, err := str.SetBit(offset, on)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
Expand All @@ -507,3 +507,30 @@ func SetBit(ctx *Context, txn *db.Transaction) (OnCommit, error) {
}
return Integer(ctx.Out, 0), nil
}

// GetBit get the bit at offset in the string value stored at key.
func GetBit(ctx *Context, txn *db.Transaction) (OnCommit, error) {
key := []byte(ctx.Args[0])
offset, err := strconv.Atoi(string(ctx.Args[1]))
if err != nil || offset < 0 {
return nil, ErrBitOffset
}

str, err := txn.String(key)
if err != nil {
if err == db.ErrTypeMismatch {
return nil, ErrTypeMismatch
}
return nil, errors.New("ERR " + err.Error())
}

val, err := str.GetBit(offset)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}

if val != 0 {
return Integer(ctx.Out, 1), nil
}
return Integer(ctx.Out, 0), nil
}
42 changes: 42 additions & 0 deletions command/strings_test.go
Expand Up @@ -549,3 +549,45 @@ func TestStringSetBit(t *testing.T) {
})
}
}

func TestStringGetBit(t *testing.T) {
CallTest("setbit", "getbit", "5", "1")
tests := []struct {
name string
args []string
want string
}{
{
name: "1",
args: []string{"getbit", "1", "0", "0"},
want: "-ERR wrong number of arguments for 'getbit' command",
},
{
name: "2",
args: []string{"getbit", "x"},
want: ErrBitOffset.Error(),
},
{
name: "3",
args: []string{"getbit", "1"},
want: ":0",
},
{
name: "5",
args: []string{"getbit", "5"},
want: ":1",
},
{
name: "6",
args: []string{"getbit", "10"},
want: ":0",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out := CallTest("getbit", tt.args...)
assert.Contains(t, out.String(), tt.want)
})
}
}
21 changes: 19 additions & 2 deletions db/string.go
Expand Up @@ -189,7 +189,7 @@ func (s *String) Incrf(delta float64) (float64, error) {

// SetBit key offset bitvalue
// return the off postion of value
func (s *String) SetBit(on, offset int) (int, error) {
func (s *String) SetBit(offset, on int) (int, error) {
val := s.Meta.Value
bitoff := offset >> 3
llen := int(bitoff) - len(val) + 1
Expand All @@ -206,13 +206,30 @@ func (s *String) SetBit(on, offset int) (int, error) {
byteval &= (^(1 << bit))
byteval = byteval | ((on & 0x1) << bit)
val[bitoff] = byte(byteval)

if err := s.Set(val); err != nil {
return 0, err
}
return bitval, nil
}

// GetBit key offset bitvalye
// offset / 8 > the index of value
// offset mod 8 +1
func (s *String) GetBit(offset int) (int, error) {
val := s.Meta.Value
bitoff := offset >> 3
if int(bitoff) > len(val)-1 {
return 0, nil
}

/* Get current values */
byteval := int(val[bitoff])
bit := uint(7 - (offset & 0x7))
bitval := byteval & (1 << bit)

return bitval, nil
}

// encode because of the value is small size , value and meta decode together
func (s *String) encode() []byte {
b := EncodeObject(&s.Meta.Object)
Expand Down
77 changes: 70 additions & 7 deletions db/string_test.go
Expand Up @@ -580,8 +580,8 @@ func TestStringSetBit(t *testing.T) {
{
name: "one",
args: args{
on: 1,
off: 1,
on: 1,
},
want: want{
retval: 0,
Expand All @@ -591,8 +591,8 @@ func TestStringSetBit(t *testing.T) {
{
name: "two",
args: args{
on: 5,
off: 1,
off: 5,
on: 1,
},
want: want{
retval: 0,
Expand All @@ -602,8 +602,8 @@ func TestStringSetBit(t *testing.T) {
{
name: "three",
args: args{
on: 5,
off: 0,
off: 5,
on: 0,
},
want: want{
retval: 0x4,
Expand All @@ -613,8 +613,8 @@ func TestStringSetBit(t *testing.T) {
{
name: "four",
args: args{
on: 12,
off: 1,
off: 12,
on: 1,
},
want: want{
retval: 0,
Expand All @@ -638,3 +638,66 @@ func TestStringSetBit(t *testing.T) {
})
}
}

func TestStringGetBit(t *testing.T) {
key := []byte("get-bits")
callFunc := func(txn *Transaction) {
s, err := GetString(txn, key)
assert.NoError(t, err)
s.SetBit(4, 1)
}
MockTest(t, callFunc)

type args struct {
off int
}
type want struct {
retval int
}
tests := []struct {
name string
args args
want want
}{
{
name: "one",
args: args{
off: 1,
},
want: want{
retval: 0,
},
},
{
name: "two",
args: args{
off: 100,
},
want: want{
retval: 0,
},
},
{
name: "three",
args: args{
off: 4,
},
want: want{
retval: 8,
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
callFunc := func(txn *Transaction) {
s, err := GetString(txn, key)
assert.NoError(t, err)
want, err := s.GetBit(tt.args.off)
assert.NoError(t, err)
assert.Equal(t, tt.want.retval, want)
}
MockTest(t, callFunc)
})
}
}

0 comments on commit 5e54979

Please sign in to comment.