diff --git a/README.md b/README.md index 6bc8d51..eb300b0 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,12 @@ func main(){ // register emitter.On("myevent", fn) + + // listen to all events + emitter.On("**", fn) + + // listen to events based on widlcard + emitter.On("my*", fn) // now remove it emitter.RemoveListener("myevent", fn) diff --git a/goemitter.go b/goemitter.go index b95ee8e..764f5a9 100644 --- a/goemitter.go +++ b/goemitter.go @@ -6,9 +6,30 @@ package Emitter import ( "reflect" + "strings" "sync" ) +// wildcard helper +func eventMatchPattern(eventName, pattern []rune) bool { + for len(pattern) > 0 { + switch pattern[0] { + case '*': + return eventMatchPattern(eventName, pattern[1:]) || (len(eventName) > 0 && eventMatchPattern(eventName[1:], pattern)) + + default: + if len(eventName) == 0 || eventName[0] != pattern[0] { + return false + } + } + + eventName = eventName[1:] + pattern = pattern[1:] + } + + return len(eventName) == 0 && len(pattern) == 0 +} + // Emitter - our listeners container type Emitter struct { listeners map[interface{}][]Listener @@ -117,10 +138,27 @@ func (self *Emitter) Listeners(event string) []Listener { self.mutex.Lock() defer self.mutex.Unlock() - if _, ok := self.listeners[event]; !ok { - return nil + listeners := make([]Listener, 0) + + // add the ones that follow pattern + for eventPattern, lis := range self.listeners { + shouldAdd := false + + // add generic "**" bound listeners + shouldAdd = shouldAdd || eventPattern.(string) == "**" + // add listener bound on full name event + shouldAdd = shouldAdd || eventPattern.(string) == event + // add listeners that have matching wildcard pattern + shouldAdd = shouldAdd || + (strings.Contains(eventPattern.(string), "*") && + eventMatchPattern([]rune(event), []rune(eventPattern.(string)))) + + if shouldAdd { + listeners = append(listeners, lis...) + } } - return self.listeners[event] + + return listeners } // ListenersCount() - return the count of listeners in the speicifed event diff --git a/goemitter_test.go b/goemitter_test.go index 03a54ad..af91aef 100644 --- a/goemitter_test.go +++ b/goemitter_test.go @@ -47,6 +47,27 @@ func TestOnce(t *testing.T) { expect(t, 1, counter) } +func TestWildCardSupport(t *testing.T) { + emitter := Construct() + + counter := 0 + fn1 := func(args ...interface{}) { + counter++ + } + + emitter.On("testevent", fn1) + emitter.On("test*", fn1) + emitter.On("t*", fn1) + emitter.On("nomatch", fn1) + + emitter.EmitSync("testevent") + + listenersCount := emitter.ListenersCount("testevent") + + expect(t, 3, listenersCount, "wrong listeners count") + expect(t, 3, counter, "wrong fn execution") +} + func TestRandomConcurrentCalls(t *testing.T) { emitter := Construct() @@ -104,8 +125,8 @@ func TestRandomConcurrentCalls(t *testing.T) { expect(t, nil, err) } -func expect(t *testing.T, a interface{}, b interface{}) { +func expect(t *testing.T, a interface{}, b interface{}, desc ...string) { if a != b { - t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) + t.Errorf("%v+ -> Expected %v (type %v) - Got %v (type %v)", desc, a, reflect.TypeOf(a), b, reflect.TypeOf(b)) } }