-
Notifications
You must be signed in to change notification settings - Fork 9
/
util.go
112 lines (98 loc) · 2.85 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package hsm
import "container/list"
import "errors"
// Trigger() is a helper function to dispatch event of different types to
// the corresponding method.
func Trigger(hsm HSM, state State, event Event) State {
switch event.Type() {
case EventEmpty:
return state.Super()
case EventInit:
return state.Init(hsm, event)
case EventEntry:
return state.Entry(hsm, event)
case EventExit:
return state.Exit(hsm, event)
default:
return state.Handle(hsm, event)
}
}
func TriggerInit(hsm HSM, state State, event Event) State {
return state.Init(hsm, event)
}
func TriggerEntry(hsm HSM, state State, event Event) State {
return state.Entry(hsm, event)
}
func TriggerExit(hsm HSM, state State, event Event) State {
return state.Exit(hsm, event)
}
func Record(
stdEvent Event, actions *list.List, hsm HSM, state State, event Event) {
var trigger func(hsm HSM, state State, event Event) State
switch stdEvent.Type() {
case EventInit:
trigger = TriggerInit
case EventEntry:
trigger = TriggerEntry
case EventExit:
trigger = TriggerExit
default:
// invalid call
AssertTrue(false)
}
if trigger(hsm, state, event) == nil {
action := &StaticTranAction{
State: state,
Event: stdEvent,
}
actions.PushBack(action)
}
}
func RecordInit(actions *list.List, hsm HSM, state State, event Event) {
Record(StdEvents[EventInit], actions, hsm, state, event)
}
func RecordEntry(actions *list.List, hsm HSM, state State, event Event) {
Record(StdEvents[EventEntry], actions, hsm, state, event)
}
func RecordExit(actions *list.List, hsm HSM, state State, event Event) {
Record(StdEvents[EventExit], actions, hsm, state, event)
}
// ListTruncate() removes elements from `e' to the last element in list `l'.
// The range to be removed is [e, l.Back()]. It returns list `l'.
func ListTruncate(l *list.List, e *list.Element) *list.List {
AssertNotEqual(nil, l)
AssertNotEqual(nil, e)
// remove `e' and all elements after `e'
var next *list.Element
for ; e != nil; e = next {
next = e.Next()
l.Remove(e)
}
return l
}
// ListFind() searchs the first element which has the same value of `value' in
// list `l'. It uses object comparation for equality check.
func ListFind(l *list.List, value interface{}) (*list.Element, error) {
predicate := func(v interface{}) bool {
return ObjectAreEqual(value, v)
}
return ListFindIf(l, predicate)
}
// ListFindIf() searchs for and element of the list `l' that
// satifies the predicate function `predicate'.
func ListFindIf(l *list.List, predicate func(value interface{}) bool) (*list.Element, error) {
for e := l.Front(); e != nil; e = e.Next() {
if predicate(e.Value) {
return e, nil
}
}
return nil, errors.New("find no match")
}
// ListIn() tests whether `value' is in list `l'.
func ListIn(l *list.List, value interface{}) bool {
e, err := ListFind(l, value)
if e == nil && err != nil {
return false
}
return true
}