]> 127.0.0.1 Git - part/.git/commitdiff
add v0.28.0+2023072509487cf
authorqydysky <qydysky@foxmail.com>
Tue, 25 Jul 2023 02:32:32 +0000 (10:32 +0800)
committerqydysky <qydysky@foxmail.com>
Tue, 25 Jul 2023 02:32:32 +0000 (10:32 +0800)
component/Component.go
component/Component_test.go

index 872cb051f33a4ce5b2e01ae911a3c71b123552fe..4b0a43c2d857f7d596ba98af1fb5b2efb409bb30 100644 (file)
@@ -4,7 +4,6 @@ import (
        "context"
        "errors"
        "sort"
-       "strings"
        "sync"
 )
 
@@ -14,21 +13,12 @@ var (
 
 type CItem struct {
        Key  string
-       Lock bool
        Deal func(ctx context.Context, ptr any) error
-       l    sync.Mutex
 }
 
-func (t *CItem) deal(ctx context.Context, ptr any) error {
-       t.l.Lock()
-       defer t.l.Unlock()
-       return t.Deal(ctx, ptr)
-}
-
-func NewCI[T any](key string, lock bool, f func(ctx context.Context, ptr *T) error) *CItem {
+func NewCI[T any](key string, f func(ctx context.Context, ptr *T) error) *CItem {
        return &CItem{
-               Key:  key,
-               Lock: lock,
+               Key: key,
                Deal: func(ctx context.Context, ptr any) error {
                        if item, ok := ptr.(*T); ok {
                                return f(ctx, item)
@@ -44,73 +34,90 @@ var (
        ErrConflict = errors.New("ErrConflict")
 )
 
-type Components struct {
+type components struct {
+       MatchF func(mkey, key string) bool
+
        m  []*CItem
        mm map[string]int
        sync.RWMutex
 }
 
-func (t *Components) Put(item *CItem) error {
+// strings.HasPrefix
+//
+// strings.HasSuffix
+//
+// DotMatch
+func NewComp(matchf func(mkey, key string) bool) *components {
+       return &components{
+               MatchF: matchf,
+               mm:     make(map[string]int),
+       }
+}
+
+func (t *components) Put(item *CItem) error {
        t.Lock()
        defer t.Unlock()
-       for i := 0; i < len(t.m); i++ {
-               if t.m[i].Key == item.Key {
-                       return ErrConflict
-               }
+       if _, ok := t.mm[item.Key]; ok {
+               return errors.Join(ErrConflict, errors.New(item.Key))
        }
        t.m = append(t.m, item)
        sort.Slice(t.m, func(i, j int) bool {
                return t.m[i].Key < t.m[j].Key
        })
-       if t.mm == nil {
-               t.mm = make(map[string]int)
-       }
        for i := 0; i < len(t.m); i++ {
-               if strings.HasPrefix(item.Key, t.m[i].Key) {
-                       t.mm[t.m[i].Key] = i
-               }
+               t.mm[t.m[i].Key] = i
        }
        return nil
 }
 
-func (t *Components) Del(key string) {
+func (t *components) Del(key string) {
        t.Lock()
        for i := 0; i < len(t.m); i++ {
-               if strings.HasPrefix(t.m[i].Key, key) {
+               if t.MatchF(t.m[i].Key, key) {
                        delete(t.mm, t.m[i].Key)
                        t.m = append(t.m[:i], t.m[i+1:]...)
                        i -= 1
                }
        }
+       for i := 0; i < len(t.m); i++ {
+               t.mm[t.m[i].Key] = i
+       }
        t.Unlock()
 }
 
-func (t *Components) Run(key string, ctx context.Context, ptr any) error {
+func (t *components) Run(key string, ctx context.Context, ptr any) error {
        t.RLock()
        defer t.RUnlock()
 
-       if i, ok := t.mm[key]; ok {
-               for ; i < len(t.m) && strings.HasPrefix(t.m[i].Key, key); i++ {
-                       if e := t.m[i].deal(ctx, ptr); e != nil {
-                               return errors.Join(ErrCItemErr, e)
-                       }
+       var (
+               i   = 0
+               got = false
+       )
+
+       if mi, ok := t.mm[key]; ok {
+               i = mi
+       }
+       for ; i < len(t.m) && t.MatchF(t.m[i].Key, key); i++ {
+               got = true
+               if e := t.m[i].Deal(ctx, ptr); e != nil {
+                       return errors.Join(ErrCItemErr, e)
                }
-       } else {
-               return ErrNotExist
+       }
+       if !got {
+               return errors.Join(ErrNotExist, errors.New(key))
        }
 
        return nil
 }
 
-func Put[T any](key string, lock bool, f func(ctx context.Context, ptr *T) error) error {
+func Put[T any](key string, f func(ctx context.Context, ptr *T) error) error {
        return Comp.Put(&CItem{
-               Key:  key,
-               Lock: lock,
+               Key: key,
                Deal: func(ctx context.Context, ptr any) error {
                        if item, ok := ptr.(*T); ok {
                                return f(ctx, item)
                        }
-                       return ErrWrongType
+                       return errors.Join(ErrWrongType, errors.New(key))
                },
        })
 }
@@ -119,4 +126,12 @@ func Run[T any](key string, ctx context.Context, ptr *T) error {
        return Comp.Run(key, ctx, ptr)
 }
 
-var Comp Components
+func Init(f func(mkey, key string) bool) {
+       Comp = NewComp(f)
+}
+
+func DotMatch(mkey, key string) bool {
+       return mkey == key || (len(mkey) > len(key) && mkey[0:len(key)] == key && mkey[len(key)] == '.')
+}
+
+var Comp *components = NewComp(DotMatch)
index 0f34c20f2202bc3ea5ba1c5aef51eaf06b39d41c..bd6192445832c4ff21c6ba5fc47f6da0238b112a 100644 (file)
@@ -3,24 +3,28 @@ package part
 import (
        "context"
        "errors"
+       "strconv"
+       "strings"
        "testing"
 )
 
 func Test1(t *testing.T) {
-       Put(`1`, false, func(ctx context.Context, ptr *int) error {
+       Init(DotMatch)
+
+       Put(`1`, func(ctx context.Context, ptr *int) error {
                if *ptr > 1 {
                        return nil
                }
                return errors.New("1")
        })
 
-       if e := Put(`1`, false, func(ctx context.Context, ptr *int) error {
+       if e := Put(`1`, func(ctx context.Context, ptr *int) error {
                if *ptr > 1 {
                        return nil
                }
                return errors.New("1")
-       }); e != ErrConflict {
-               t.Fatal()
+       }); !errors.Is(e, ErrConflict) {
+               t.Fatal(e)
        }
 
        Comp.Put(&CItem{
@@ -50,8 +54,11 @@ func Test1(t *testing.T) {
 
        Comp.Del(`1.2`)
 
-       if e := Comp.Run(`1.2.1`, context.Background(), &s); e != ErrNotExist {
-               t.Fatal(e)
+       for i := 0; i < len(Comp.m); i++ {
+               t.Log(Comp.m[i])
+       }
+       if e := Comp.Run(`1.2.1`, context.Background(), &s); e == nil {
+               t.Fatal()
        }
 
        if e := Comp.Run(`1`, context.Background(), &s); e != nil {
@@ -59,26 +66,64 @@ func Test1(t *testing.T) {
        }
 }
 
+func TestDot(t *testing.T) {
+       Init(DotMatch)
+       Put[int](`1`, func(ctx context.Context, ptr *int) error {
+               if *ptr == 1 {
+                       return nil
+               } else {
+                       return errors.New("1")
+               }
+       })
+       Put[int](`12`, func(ctx context.Context, ptr *int) error {
+               return errors.New("12")
+       })
+       Put[int](`1.2`, func(ctx context.Context, ptr *int) error {
+               return errors.New("1.2")
+       })
+       i := 1
+       if e := Run(`1`, context.Background(), &i); !strings.Contains(e.Error(), "1.2") {
+               t.Fatal(e)
+       }
+}
+
+func Test3(t *testing.T) {
+       sumup := func(ctx context.Context, ptr *int) error {
+               return nil
+       }
+       if e := Put[int](`bili_danmu.Reply.wsmsg.preparing.sumup`, sumup); e != nil {
+               panic(e)
+       } else {
+               println("bili_danmu.Reply.wsmsg.preparing.sumup")
+       }
+       i := 1
+       if e := Run(`bili_danmu.Reply.wsmsg.preparing`, context.Background(), &i); e != nil {
+               t.Fatal(e)
+       }
+}
+
 func Benchmark2(b *testing.B) {
+       Init(DotMatch)
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
-               Put[int](`1`, false, func(ctx context.Context, ptr *int) error {
+               Put[int](strconv.Itoa(i), func(ctx context.Context, ptr *int) error {
                        return nil
                })
        }
 }
 
 func Benchmark1(b *testing.B) {
-       Put[int](`1`, false, func(ctx context.Context, ptr *int) error {
-               return nil
-       })
-       Put[int](`1.2`, false, func(ctx context.Context, ptr *int) error {
-               return nil
-       })
+       Init(DotMatch)
+       for i := 0; i < 1000; i++ {
+               Put[int](strconv.Itoa(i), func(ctx context.Context, ptr *int) error {
+                       return nil
+               })
+       }
+       ctx := context.Background()
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
-               if e := Run(`1.2`, context.Background(), &i); e != nil {
-                       b.Fatal()
+               if e := Run(`1`, ctx, &i); e != nil {
+                       b.Fatal(e)
                }
        }
 }