From 8d663fe92075c32044ae1e42332ddcc60affbddf Mon Sep 17 00:00:00 2001 From: bandl <1658002533@qq.com> Date: Sun, 26 Sep 2021 16:47:54 +0800 Subject: [PATCH] feat(structure): add stringx type --- pkg/structure/stringx/string.go | 92 ++++++++++++++++++++++++++++----- pkg/structure/value.go | 43 ++++++++++++++- 2 files changed, 121 insertions(+), 14 deletions(-) diff --git a/pkg/structure/stringx/string.go b/pkg/structure/stringx/string.go index 4e7ac6f..08f6850 100644 --- a/pkg/structure/stringx/string.go +++ b/pkg/structure/stringx/string.go @@ -1,8 +1,10 @@ package stringx import ( + "gitee.com/timedb/wheatCache/pkg/errorx" "gitee.com/timedb/wheatCache/pkg/proto" "gitee.com/timedb/wheatCache/pkg/structure" + "strconv" ) type StringSingle struct { @@ -19,7 +21,7 @@ func (s *StringSingle) SizeByte() int64 { return int64(s.val.GetLength()) } -// TODO RollBack 事务相关, V2 实现 +// RollBack TODO 事务相关, V2 实现 func (s *StringSingle) RollBack() error { panic("not implemented") // TODO: Implement } @@ -38,26 +40,90 @@ func (s *StringSingle) Encode() ([]byte, error) { panic("not implemented") // TODO: Implement } -func (s *StringSingle) Set(req *proto.SetRequest) (*structure.ResultConn, error) { - return nil, nil +func (s *StringSingle) Set(req *proto.SetRequest) (*proto.SetResponse, error) { + length := s.val.ChangeValueLength(func() { + s.val.InferValue(req.Val) + }) + + return &proto.SetResponse{ + Result: req.Val, + UpdateSize: length, + }, nil } -func (s *StringSingle) Get(req *proto.GetRequest) (*structure.ResultConn, error) { - panic("not implemented") // TODO: Implement +func (s *StringSingle) Get(req *proto.GetRequest) (*proto.GetResponse, error) { + return &proto.GetResponse{ + Result: s.val.ToString(), + UpdateSize: 0, + }, nil } -func (s *StringSingle) Add(req *proto.AddRequest) (*structure.ResultConn, error) { - panic("not implemented") // TODO: Implement +func updateValueNotString(s *StringSingle, val int32) (string, int64, error) { + switch s.val.GetDynamicType() { + case structure.DynamicNull: + length := s.val.ChangeValueLength(func() { + s.val.SetInt(int64(val)) + }) + return strconv.Itoa(int(val)), length, nil + case structure.DynamicFloat: + f, err := s.val.ToFloat64() + if err != nil { + return "", 0, err + } + s.val.SetFloat64(f + float64(val)) + return strconv.FormatFloat(f+1, 'f', 2, 64), 0, nil + case structure.DynamicInt: + i, err := s.val.ToInt() + if err != nil { + return "", 0, err + } + s.val.SetInt(int64(val) + i) + return strconv.Itoa(int(i + int64(val))), 0, nil + default: + return "", 0, errorx.New("string cannot perform add operations") + } } -func (s *StringSingle) Reduce(req *proto.ReduceRequest) (*structure.ResultConn, error) { - panic("not implemented") // TODO: Implement +func (s *StringSingle) Add(req *proto.AddRequest) (*proto.AddResponse, error) { + result, length, err := updateValueNotString(s, req.Renewal) + if err != nil { + return nil, err + } + + return &proto.AddResponse{ + UpdateSize: length, + Result: result, + }, nil } -func (s *StringSingle) Setbit(req *proto.SetbitRequest) (*structure.ResultConn, error) { - panic("not implemented") // TODO: Implement +func (s *StringSingle) Reduce(req *proto.ReduceRequest) (*proto.ReduceResponse, error) { + result, length, err := updateValueNotString(s, req.Renewal*-1) + if err != nil { + return nil, err + } + + return &proto.ReduceResponse{ + UpdateSize: length, + Result: result, + }, nil } -func (s *StringSingle) Getbit(req *proto.GetbitRequest) (*structure.ResultConn, error) { - panic("not implemented") // TODO: Implement +func (s *StringSingle) Setbit(req *proto.SetbitRequest) (*proto.SetbitResponse, error) { + length := s.val.ChangeValueLength(func() { + s.val.SetByte(int(req.Offer), req.Val) + }) + return &proto.SetbitResponse{ + UpdateSize: length, + }, nil +} + +func (s *StringSingle) Getbit(req *proto.GetbitRequest) (*proto.GetbitResponse, error) { + b, err := s.val.GetByte(int(req.Offer)) + if err != nil { + return nil, err + } + + return &proto.GetbitResponse{ + Val: b, + }, nil } diff --git a/pkg/structure/value.go b/pkg/structure/value.go index d4fa323..c56d998 100644 --- a/pkg/structure/value.go +++ b/pkg/structure/value.go @@ -37,6 +37,7 @@ func (v *Value) SetString(str string) { if len(v.val) >= len(str) { copy(v.val, str) v.length = len(str) + v.val = v.val[:v.length] return } @@ -54,6 +55,18 @@ func (v *Value) SetString(str string) { } func (v *Value) ToString() string { + switch v.onType { + case DynamicNull: + return "" + case DynamicString: + return string(v.val[:v.length]) + case DynamicInt: + i, _ := v.ToInt() + return strconv.FormatInt(i, 10) + case DynamicFloat: + f, _ := v.ToFloat64() + return strconv.FormatFloat(f, 'f', 2, 64) + } return string(v.val[:v.length]) } @@ -84,6 +97,7 @@ func (v *Value) SetFloat64(f float64) { bits := math.Float64bits(f) v.length = 8 binary.LittleEndian.PutUint64(v.val[:v.length], bits) + v.val = v.val[:v.length] v.onType = DynamicFloat } @@ -113,9 +127,36 @@ func (v *Value) InferValue(str string) { v.SetString(str) } -// ChangeValueLength 根据类型推断 change 的大小 +// ChangeValueLength 根据类型推断 change 的大小, 只用于 Set 操作不发生错误 func (v *Value) ChangeValueLength(f func()) int64 { startLen := v.GetLength() f() return int64(v.GetLength() - startLen) } + +func (v *Value) SetByte(offset int, val bool) { + v.onType = DynamicNull // 位图使用无类型 + b := byte(0) + if val { + b = byte(1) + } + + if v.length >= offset { + v.val[offset] = b + return + } + + newByte := make([]byte, offset+1) + newByte[offset] = b + copy(newByte, v.val[:v.length]) + v.val = newByte + v.length = len(newByte) +} + +func (v *Value) GetByte(offset int) (bool, error) { + if v.length >= offset { + return v.val[offset] == byte(1), nil + } + + return false, errorx.New("the maximum length is exceeded") +}