Added unique id to callbacks so they can be referenced. Since Go doens't actually provide unique function pointers, we use the closest we can get by grabbing the pointer for the function and slapping a random int on the end. Does it guarantee there will never be a collision? No, but it makes it's pretty damn unlikely that you'll get one during the lifetime of an app unless you are generating millions and millions of callbacks and never, ever deleting them, in which case you probably have something else to worry about
This commit is contained in:
parent
33d8019793
commit
6edb7ec06e
@ -4,46 +4,51 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) (idx int) {
|
||||
func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) string {
|
||||
eventcode = strings.ToUpper(eventcode)
|
||||
|
||||
if _, ok := irc.events[eventcode]; ok {
|
||||
irc.events[eventcode] = append(irc.events[eventcode], callback)
|
||||
idx = len(irc.events[eventcode]) - 1
|
||||
} else {
|
||||
irc.events[eventcode] = make([]func(*Event), 1)
|
||||
irc.events[eventcode][0] = callback
|
||||
idx = 0
|
||||
if _, ok := irc.events[eventcode]; !ok {
|
||||
irc.events[eventcode] = make(map[string]func(*Event))
|
||||
}
|
||||
return
|
||||
h := sha1.New()
|
||||
rawId := []byte(fmt.Sprintf("%v%d", reflect.ValueOf(callback).Pointer(), rand.Int63()))
|
||||
h.Write(rawId)
|
||||
id := fmt.Sprintf("%x", h.Sum(nil))
|
||||
irc.events[eventcode][id] = callback
|
||||
return id
|
||||
}
|
||||
|
||||
func (irc *Connection) RemoveCallback(eventcode string, i int) {
|
||||
func (irc *Connection) RemoveCallback(eventcode string, i string) bool {
|
||||
eventcode = strings.ToUpper(eventcode)
|
||||
|
||||
if event, ok := irc.events[eventcode]; ok {
|
||||
if i < len(event) {
|
||||
irc.events[eventcode] = append(event[:i], event[i+1:]...)
|
||||
return
|
||||
if event, ok := irc.events[eventcode]; ok{
|
||||
if _, ok := event[i]; ok {
|
||||
delete(irc.events[eventcode], i)
|
||||
return true
|
||||
}
|
||||
irc.Log.Printf("Event found, but no callback found at index %d.\n", i)
|
||||
return
|
||||
irc.Log.Printf("Event found, but no callback found at id %s\n", i)
|
||||
return false
|
||||
}
|
||||
irc.Log.Printf("Event not found\n")
|
||||
|
||||
irc.Log.Println("Event not found")
|
||||
return false
|
||||
}
|
||||
|
||||
func (irc *Connection) ReplaceCallback(eventcode string, i int, callback func(*Event)) {
|
||||
func (irc *Connection) ReplaceCallback(eventcode string, i string, callback func(*Event)) {
|
||||
eventcode = strings.ToUpper(eventcode)
|
||||
|
||||
if event, ok := irc.events[eventcode]; ok {
|
||||
if i < len(event) {
|
||||
if _, ok := event[i]; ok {
|
||||
event[i] = callback
|
||||
return
|
||||
}
|
||||
irc.Log.Printf("Event found, but no callback found at index %d. Use AddCallback\n", i)
|
||||
return
|
||||
irc.Log.Printf("Event found, but no callback found at id %s\n", i)
|
||||
}
|
||||
irc.Log.Printf("Event not found. Use AddCallBack\n")
|
||||
}
|
||||
@ -102,7 +107,7 @@ func (irc *Connection) RunCallbacks(event *Event) {
|
||||
}
|
||||
|
||||
func (irc *Connection) setupCallbacks() {
|
||||
irc.events = make(map[string][]func(*Event))
|
||||
irc.events = make(map[string]map[string]func(*Event))
|
||||
|
||||
//Handle ping events
|
||||
irc.AddCallback("PING", func(e *Event) { irc.SendRaw("PONG :" + e.Message) })
|
||||
|
@ -33,7 +33,7 @@ type Connection struct {
|
||||
user string
|
||||
registered bool
|
||||
server string
|
||||
events map[string][]func(*Event)
|
||||
events map[string]map[string]func(*Event)
|
||||
|
||||
lastMessage time.Time
|
||||
|
||||
|
50
irc_test.go
50
irc_test.go
@ -44,3 +44,53 @@ func TestConnectionSSL(t *testing.T) {
|
||||
|
||||
irccon.Loop()
|
||||
}
|
||||
|
||||
func TestRemoveCallback(t *testing.T) {
|
||||
irccon := IRC("go-eventirc", "go-eventirc")
|
||||
irccon.VerboseCallbackHandler = true
|
||||
|
||||
done := make(chan int, 10)
|
||||
|
||||
irccon.AddCallback("TEST", func(e *Event) { done <- 1 })
|
||||
id := irccon.AddCallback("TEST", func(e *Event) { done <- 2 })
|
||||
irccon.AddCallback("TEST", func(e *Event) { done <- 3 })
|
||||
|
||||
// Should remove callback at index 1
|
||||
irccon.RemoveCallback("TEST", id)
|
||||
|
||||
irccon.RunCallbacks(&Event{
|
||||
Code: "TEST",
|
||||
})
|
||||
|
||||
var results []int
|
||||
|
||||
results = append(results, <-done)
|
||||
results = append(results, <-done)
|
||||
|
||||
if len(results) != 2 || !(results[0] == 1 && results[1] == 3) {
|
||||
t.Error("Callback 2 not removed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWildcardCallback(t *testing.T) {
|
||||
irccon := IRC("go-eventirc", "go-eventirc")
|
||||
irccon.VerboseCallbackHandler = true
|
||||
|
||||
done := make(chan int, 10)
|
||||
|
||||
irccon.AddCallback("TEST", func(e *Event) { done <- 1 })
|
||||
irccon.AddCallback("*", func(e *Event) { done <- 2 })
|
||||
|
||||
irccon.RunCallbacks(&Event{
|
||||
Code: "TEST",
|
||||
})
|
||||
|
||||
var results []int
|
||||
|
||||
results = append(results, <-done)
|
||||
results = append(results, <-done)
|
||||
|
||||
if len(results) != 2 || !(results[0] == 1 && results[1] == 2) {
|
||||
t.Error("Wildcard callback not called")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user