simplify storage

This commit is contained in:
Arpad Ryszka 2017-07-17 23:59:26 +02:00
parent ea01f81ef0
commit b9f05bed7d
2 changed files with 42 additions and 80 deletions

View File

@ -15,7 +15,7 @@ type parser interface {
nodeName() string nodeName() string
nodeID() int nodeID() int
setIncludedBy(parser, *idSet) setIncludedBy(parser, *idSet)
storeIncluded(*context, int, int) storeIncluded(*context, int, int) // can be just an id set, taking what's excluded from the context
parse(Trace, *context) parse(Trace, *context)
} }

120
store.go
View File

@ -1,120 +1,82 @@
package treerack package treerack
type storeEntry struct {
match *idSet
noMatch *idSet
matches []int
all []int
}
type store struct { type store struct {
entries []*storeEntry noMatch []*idSet
} match [][]int
func (s *store) getEntry(offset int) *storeEntry {
if len(s.entries) <= offset {
return nil
}
return s.entries[offset]
} }
func (s *store) hasNoMatch(offset, id int) bool { func (s *store) hasNoMatch(offset, id int) bool {
e := s.getEntry(offset) if len(s.noMatch) <= offset || s.noMatch[offset] == nil {
if e == nil {
return false return false
} }
return e.noMatch.has(id) return s.noMatch[offset].has(id)
} }
func (s *store) getMatch(offset, id int) (int, bool, bool) { func (s *store) getMatch(offset, id int) (int, bool, bool) {
e := s.getEntry(offset) if s.hasNoMatch(offset, id) {
if e == nil {
return 0, false, false
}
if e.noMatch.has(id) {
return 0, false, true return 0, false, true
} }
if !e.match.has(id) { if len(s.match) <= offset {
return 0, false, false return 0, false, false
} }
for i := 0; i < len(e.matches); i += 2 { var (
if e.matches[i] == id { found bool
return e.matches[i + 1], true, true length int
)
for i := 0; i < len(s.match[offset]); i++ {
if s.match[offset][i] != id {
continue
}
found = true
if s.match[offset][i + 1] > length {
length = s.match[offset][i + 1]
} }
} }
return 0, false, false return length, found, found
} }
func (s *store) ensureOffset(offset int) { func (s *store) ensureOffset(offset int) {
if len(s.entries) > offset { if len(s.match) > offset {
return return
} }
if cap(s.entries) > offset { if cap(s.match) > offset {
s.entries = s.entries[:offset+1] s.match = s.match[:offset+1]
return return
} }
s.entries = s.entries[:cap(s.entries)] s.match = s.match[:cap(s.match)]
for len(s.entries) <= offset { for i := len(s.match); i <= offset; i++ {
s.entries = append(s.entries, nil) s.match = append(s.match, nil)
} }
} }
func (s *store) ensureEntry(offset int) *storeEntry {
s.ensureOffset(offset)
e := s.entries[offset]
if e != nil {
return e
}
e = &storeEntry{
match: &idSet{},
noMatch: &idSet{},
}
s.entries[offset] = e
return e
}
func (s *store) setMatch(offset, id, to int) { func (s *store) setMatch(offset, id, to int) {
e := s.ensureEntry(offset) s.ensureOffset(offset)
s.match[offset] = append(s.match[offset], id, to)
e.match.set(id)
for i := 0; i < len(e.matches); i += 2 {
if e.matches[i] == id {
if to > e.matches[i + 1] {
e.matches[i + 1] = to
}
if to != e.matches[i + 1] {
e.all = append(e.all, id, to)
}
return
}
}
e.matches = append(e.matches, id, to)
} }
func (s *store) setNoMatch(offset, id int) { func (s *store) setNoMatch(offset, id int) {
e := s.ensureEntry(offset) if len(s.noMatch) <= offset {
if cap(s.noMatch) > offset {
if e.match.has(id) { s.noMatch = s.noMatch[:offset + 1]
return } else {
s.noMatch = s.noMatch[:cap(s.noMatch)]
for i := len(s.noMatch); i <= offset; i++ {
s.noMatch = append(s.noMatch, nil)
}
}
} }
e.noMatch.set(id) if s.noMatch[offset] == nil {
} s.noMatch[offset] = &idSet{}
}
func (s *store) add(offset, id, to int) { s.noMatch[offset].set(id)
e := s.ensureEntry(offset)
e.all = append(e.all, id, to)
} }