Skip to content

Commit

Permalink
Merge b321412 into 212a636
Browse files Browse the repository at this point in the history
  • Loading branch information
YIDWang committed Mar 22, 2019
2 parents 212a636 + b321412 commit 5bd05c7
Show file tree
Hide file tree
Showing 8 changed files with 639 additions and 28 deletions.
6 changes: 6 additions & 0 deletions command/error.go
Expand Up @@ -49,9 +49,15 @@ var (
// ErrBitInteger bit is not an integer or out of range
ErrBitInteger = errors.New("ERR bit is not an integer or out of range")

// ErrBitInvaild the bit argument must be 1 or 0
ErrBitInvaild = errors.New("ERR The bit argument must be 1 or 0")

// ErrBitOffset bit offset is not an integer or out of range
ErrBitOffset = errors.New("ERR bit offset is not an integer or out of range")

//ErrBitOp not must be called with a single source key.
ErrBitOp = errors.New("BITOP NOT must be called with a single source key.")

// ErrOffset offset is out of range
ErrOffset = errors.New("ERR offset is out of range")

Expand Down
20 changes: 14 additions & 6 deletions command/init.go
Expand Up @@ -28,12 +28,16 @@ func init() {
"getset": GetSet,
"getrange": GetRange,
// "msetnx": MSetNx,
"setnx": SetNx,
"setex": SetEx,
"psetex": PSetEx,
"setrange": SetRange,
"setbit": SetBit,
"setnx": SetNx,
"setex": SetEx,
"psetex": PSetEx,
"setrange": SetRange,
"setbit": SetBit,
// "bitop": BitOp,
// "bitfield": BitField,
"getbit": GetBit,
"bitpos": BitPos,
"bitcount": BitCount,
"incr": Incr,
"incrby": IncrBy,
"decr": Decr,
Expand Down Expand Up @@ -131,7 +135,11 @@ 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}},
// "bitop": Desc{Proc: AutoCommit(BitOp), Cons: Constraint{-4, flags("wm"), 2, -1, 1}},
// "bitfield": Desc{Proc: AutoCommit(BitField), Cons: Constraint{-2, flags("wm"), 1, 1, 1}},
"getbit": Desc{Proc: AutoCommit(GetBit), Cons: Constraint{3, flags("r"), 1, 1, 1}},
"bitcount": Desc{Proc: AutoCommit(BitCount), Cons: Constraint{-2, flags("r"), 1, 1, 1}},
"bitpos": Desc{Proc: AutoCommit(BitPos), Cons: Constraint{-3, flags("r"), 1, 1, 1}},

// keys
"type": Desc{Proc: AutoCommit(Type), Cons: Constraint{2, flags("rF"), 1, 1, 1}},
Expand Down
155 changes: 140 additions & 15 deletions command/strings.go
Expand Up @@ -3,6 +3,7 @@ package command
import (
"errors"
"strconv"
"strings"
"time"

"github.com/meitu/titan/db"
Expand Down Expand Up @@ -247,11 +248,11 @@ func GetRange(ctx *Context, txn *db.Transaction) (OnCommit, error) {
return nil, errors.New("ERR " + err.Error())
}

start, err := strconv.Atoi(string(ctx.Args[1]))
start, err := strconv.Atoi(ctx.Args[1])
if err != nil {
return nil, ErrInteger
}
end, err := strconv.Atoi(string(ctx.Args[2]))
end, err := strconv.Atoi(ctx.Args[2])
if err != nil {
return nil, ErrInteger
}
Expand Down Expand Up @@ -303,7 +304,7 @@ func SetEx(ctx *Context, txn *db.Transaction) (OnCommit, error) {
}

s := db.NewString(txn, key)
ui, err := strconv.ParseInt(string(ctx.Args[1]), 10, 64)
ui, err := strconv.ParseInt(ctx.Args[1], 10, 64)
if err != nil {
return nil, ErrInteger
}
Expand All @@ -315,7 +316,7 @@ func SetEx(ctx *Context, txn *db.Transaction) (OnCommit, error) {
return SimpleString(ctx.Out, OK), nil
}

// PSetEx set the value and expiration in milliseconds of a key
// PSetEx sets the value and expiration in milliseconds of a key
func PSetEx(ctx *Context, txn *db.Transaction) (OnCommit, error) {
//get the key
key := []byte(ctx.Args[0])
Expand All @@ -329,7 +330,7 @@ func PSetEx(ctx *Context, txn *db.Transaction) (OnCommit, error) {
}

s := db.NewString(txn, key)
ui, err := strconv.ParseUint(string(ctx.Args[1]), 10, 64)
ui, err := strconv.ParseUint(ctx.Args[1], 10, 64)
if err != nil {
return nil, ErrInteger
}
Expand All @@ -341,9 +342,9 @@ func PSetEx(ctx *Context, txn *db.Transaction) (OnCommit, error) {
return SimpleString(ctx.Out, OK), nil
}

//SetRange Overwrites part of the string stored at key, starting at the specified offset, for the entire length of value.
//SetRange overwrites part of the string stored at key, starting at the specified offset, for the entire length of value.
func SetRange(ctx *Context, txn *db.Transaction) (OnCommit, error) {
offset, err := strconv.Atoi(string(ctx.Args[1]))
offset, err := strconv.Atoi(ctx.Args[1])
if err != nil {
return nil, ErrInteger
}
Expand Down Expand Up @@ -397,7 +398,7 @@ func IncrBy(ctx *Context, txn *db.Transaction) (OnCommit, error) {
}
return nil, errors.New("ERR " + err.Error())
}
delta, err := strconv.ParseInt(string(ctx.Args[1]), 10, 0)
delta, err := strconv.ParseInt(ctx.Args[1], 10, 0)
if err != nil {
return nil, ErrInteger
}
Expand All @@ -419,7 +420,7 @@ func IncrByFloat(ctx *Context, txn *db.Transaction) (OnCommit, error) {
}
return nil, errors.New("ERR " + err.Error())
}
delta, err := strconv.ParseFloat(string(ctx.Args[1]), 64)
delta, err := strconv.ParseFloat(ctx.Args[1], 64)
if err != nil {
return nil, ErrInteger
}
Expand Down Expand Up @@ -458,7 +459,7 @@ func DecrBy(ctx *Context, txn *db.Transaction) (OnCommit, error) {
}
return nil, errors.New("ERR " + err.Error())
}
delta, err := strconv.ParseInt(string(ctx.Args[1]), 10, 64)
delta, err := strconv.ParseInt(ctx.Args[1], 10, 64)
if err != nil {
return nil, ErrInteger
}
Expand All @@ -470,18 +471,18 @@ func DecrBy(ctx *Context, txn *db.Transaction) (OnCommit, error) {
return Integer(ctx.Out, int64(delta)), nil
}

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

on, err := strconv.Atoi(string(ctx.Args[2]))
on, err := strconv.Atoi(ctx.Args[2])
if err != nil {
return nil, ErrBitInteger
}
Expand All @@ -508,10 +509,10 @@ 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.
// GetBit gets 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]))
offset, err := strconv.Atoi(ctx.Args[1])
if err != nil || offset < 0 {
return nil, ErrBitOffset
}
Expand All @@ -524,6 +525,10 @@ func GetBit(ctx *Context, txn *db.Transaction) (OnCommit, error) {
return nil, errors.New("ERR " + err.Error())
}

if !str.Exist() {
return Integer(ctx.Out, 0), nil
}

val, err := str.GetBit(offset)
if err != nil {
return nil, errors.New("ERR " + err.Error())
Expand All @@ -534,3 +539,123 @@ func GetBit(ctx *Context, txn *db.Transaction) (OnCommit, error) {
}
return Integer(ctx.Out, 0), nil
}

// BitCount counts the number of set bits (population counting) in a string.
func BitCount(ctx *Context, txn *db.Transaction) (OnCommit, error) {
key := []byte(ctx.Args[0])
str, err := txn.String(key)
if err != nil {
if err == db.ErrTypeMismatch {
return nil, ErrTypeMismatch
}
return nil, errors.New("ERR " + err.Error())
}

if !str.Exist() {
return Integer(ctx.Out, 0), nil
}

var begin, end int
switch len(ctx.Args) {
case 3:
begin, err = strconv.Atoi(ctx.Args[1])
if err != nil {
return nil, ErrInteger
}
end, err = strconv.Atoi(ctx.Args[2])
if err != nil {
return nil, ErrInteger
}
case 1:
begin = 0
end = len(str.Meta.Value) - 1
default:
return nil, ErrSyntax
}

val, err := str.BitCount(begin, end)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
return Integer(ctx.Out, int64(val)), nil
}

// BitPos finds first bit set or clear in a string
func BitPos(ctx *Context, txn *db.Transaction) (OnCommit, error) {
bit, err := strconv.Atoi(string(ctx.Args[1]))
if err != nil {
return nil, ErrInteger
}

if (bit != 0) && (bit != 1) {
return nil, ErrBitInvaild
}

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

if !str.Exist() {
if bit == 1 {
return Integer(ctx.Out, -1), nil
}
return Integer(ctx.Out, 0), nil
}

var begin, end int
switch len(ctx.Args) {
case 4:
begin, err = strconv.Atoi(ctx.Args[2])
if err != nil {
return nil, ErrInteger
}
end, err = strconv.Atoi(ctx.Args[3])
if err != nil {
return nil, ErrInteger
}
case 3:
begin, err = strconv.Atoi(ctx.Args[2])
if err != nil {
return nil, ErrInteger
}
end = len(str.Meta.Value) - 1
case 2:
begin = 0
end = len(str.Meta.Value) - 1
default:
return nil, ErrSyntax
}

val, err := str.BitPos(bit, begin, end)
if err != nil {
return nil, errors.New("ERR " + err.Error())
}
return Integer(ctx.Out, int64(val)), nil
}

// BitOp performs bitwise operations between strings
func BitOp(ctx *Context, txn *db.Transaction) (OnCommit, error) {
//TODO
if strings.EqualFold(ctx.Args[0], "and") {
} else if strings.EqualFold(ctx.Args[0], "or") {
} else if strings.EqualFold(ctx.Args[0], "xor") {
} else if strings.EqualFold(ctx.Args[0], "not") {
if len(ctx.Args) != 3 {
return nil, ErrBitOp
}
} else {
return nil, ErrSyntax
}
return Integer(ctx.Out, int64(0)), nil
}

// BitField performs arbitrary bitfield integer operations on strings
func BitField(ctx *Context, txn *db.Transaction) (OnCommit, error) {
//TODO
return Integer(ctx.Out, int64(0)), nil
}

0 comments on commit 5bd05c7

Please sign in to comment.