Remove special nilItem

This commit is contained in:
Junegunn Choi 2017-08-15 01:10:41 +09:00
parent 2069bbc8b5
commit 0d171ba1d8
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
9 changed files with 49 additions and 51 deletions

View File

@ -4,9 +4,8 @@ import "testing"
func TestChunkCache(t *testing.T) { func TestChunkCache(t *testing.T) {
cache := NewChunkCache() cache := NewChunkCache()
chunk2 := make(Chunk, chunkSize)
chunk1p := &Chunk{} chunk1p := &Chunk{}
chunk2p := &chunk2 chunk2p := &Chunk{count: chunkSize}
items1 := []Result{Result{}} items1 := []Result{Result{}}
items2 := []Result{Result{}, Result{}} items2 := []Result{Result{}, Result{}}
cache.Add(chunk1p, "foo", items1) cache.Add(chunk1p, "foo", items1)

View File

@ -3,11 +3,14 @@ package fzf
import "sync" import "sync"
// Chunk is a list of Items whose size has the upper limit of chunkSize // Chunk is a list of Items whose size has the upper limit of chunkSize
type Chunk []Item type Chunk struct {
items [chunkSize]Item
count int
}
// ItemBuilder is a closure type that builds Item object from a pointer to a // ItemBuilder is a closure type that builds Item object from a pointer to a
// string and an integer // string and an integer
type ItemBuilder func([]byte, int) Item type ItemBuilder func(*Item, []byte, int) bool
// ChunkList is a list of Chunks // ChunkList is a list of Chunks
type ChunkList struct { type ChunkList struct {
@ -27,17 +30,16 @@ func NewChunkList(trans ItemBuilder) *ChunkList {
} }
func (c *Chunk) push(trans ItemBuilder, data []byte, index int) bool { func (c *Chunk) push(trans ItemBuilder, data []byte, index int) bool {
item := trans(data, index) if trans(&c.items[c.count], data, index) {
if item.Nil() { c.count++
return false return true
} }
*c = append(*c, item) return false
return true
} }
// IsFull returns true if the Chunk is full // IsFull returns true if the Chunk is full
func (c *Chunk) IsFull() bool { func (c *Chunk) IsFull() bool {
return len(*c) == chunkSize return c.count == chunkSize
} }
func (cl *ChunkList) lastChunk() *Chunk { func (cl *ChunkList) lastChunk() *Chunk {
@ -49,7 +51,7 @@ func CountItems(cs []*Chunk) int {
if len(cs) == 0 { if len(cs) == 0 {
return 0 return 0
} }
return chunkSize*(len(cs)-1) + len(*(cs[len(cs)-1])) return chunkSize*(len(cs)-1) + cs[len(cs)-1].count
} }
// Push adds the item to the list // Push adds the item to the list
@ -57,8 +59,7 @@ func (cl *ChunkList) Push(data []byte) bool {
cl.mutex.Lock() cl.mutex.Lock()
if len(cl.chunks) == 0 || cl.lastChunk().IsFull() { if len(cl.chunks) == 0 || cl.lastChunk().IsFull() {
newChunk := Chunk(make([]Item, 0, chunkSize)) cl.chunks = append(cl.chunks, &Chunk{})
cl.chunks = append(cl.chunks, &newChunk)
} }
if cl.lastChunk().push(cl.trans, data, cl.count) { if cl.lastChunk().push(cl.trans, data, cl.count) {

View File

@ -11,10 +11,10 @@ func TestChunkList(t *testing.T) {
// FIXME global // FIXME global
sortCriteria = []criterion{byScore, byLength} sortCriteria = []criterion{byScore, byLength}
cl := NewChunkList(func(s []byte, i int) Item { cl := NewChunkList(func(item *Item, s []byte, i int) bool {
chars := util.ToChars(s) item.text = util.ToChars(s)
chars.Index = int32(i * 2) item.text.Index = int32(i * 2)
return Item{text: chars} return true
}) })
// Snapshot // Snapshot
@ -40,11 +40,13 @@ func TestChunkList(t *testing.T) {
// Check the content of the ChunkList // Check the content of the ChunkList
chunk1 := snapshot[0] chunk1 := snapshot[0]
if len(*chunk1) != 2 { if chunk1.count != 2 {
t.Error("Snapshot should contain only two items") t.Error("Snapshot should contain only two items")
} }
if (*chunk1)[0].text.ToString() != "hello" || (*chunk1)[0].Index() != 0 || if chunk1.items[0].text.ToString() != "hello" ||
(*chunk1)[1].text.ToString() != "world" || (*chunk1)[1].Index() != 2 { chunk1.items[0].Index() != 0 ||
chunk1.items[1].text.ToString() != "world" ||
chunk1.items[1].Index() != 2 {
t.Error("Invalid data") t.Error("Invalid data")
} }
if chunk1.IsFull() { if chunk1.IsFull() {
@ -67,14 +69,14 @@ func TestChunkList(t *testing.T) {
!snapshot[1].IsFull() || snapshot[2].IsFull() || count != chunkSize*2+2 { !snapshot[1].IsFull() || snapshot[2].IsFull() || count != chunkSize*2+2 {
t.Error("Expected two full chunks and one more chunk") t.Error("Expected two full chunks and one more chunk")
} }
if len(*snapshot[2]) != 2 { if snapshot[2].count != 2 {
t.Error("Unexpected number of items") t.Error("Unexpected number of items")
} }
cl.Push([]byte("hello")) cl.Push([]byte("hello"))
cl.Push([]byte("world")) cl.Push([]byte("world"))
lastChunkCount := len(*snapshot[len(snapshot)-1]) lastChunkCount := snapshot[len(snapshot)-1].count
if lastChunkCount != 2 { if lastChunkCount != 2 {
t.Error("Unexpected number of items:", lastChunkCount) t.Error("Unexpected number of items:", lastChunkCount)
} }

View File

@ -85,29 +85,30 @@ func Run(opts *Options, revision string) {
var chunkList *ChunkList var chunkList *ChunkList
header := make([]string, 0, opts.HeaderLines) header := make([]string, 0, opts.HeaderLines)
if len(opts.WithNth) == 0 { if len(opts.WithNth) == 0 {
chunkList = NewChunkList(func(data []byte, index int) Item { chunkList = NewChunkList(func(item *Item, data []byte, index int) bool {
if len(header) < opts.HeaderLines { if len(header) < opts.HeaderLines {
header = append(header, string(data)) header = append(header, string(data))
eventBox.Set(EvtHeader, header) eventBox.Set(EvtHeader, header)
return nilItem return false
} }
chars, colors := ansiProcessor(data) item.text, item.colors = ansiProcessor(data)
chars.Index = int32(index) item.text.Index = int32(index)
return Item{text: chars, colors: colors} return true
}) })
} else { } else {
chunkList = NewChunkList(func(data []byte, index int) Item { chunkList = NewChunkList(func(item *Item, data []byte, index int) bool {
tokens := Tokenize(string(data), opts.Delimiter) tokens := Tokenize(string(data), opts.Delimiter)
trans := Transform(tokens, opts.WithNth) trans := Transform(tokens, opts.WithNth)
transformed := joinTokens(trans) transformed := joinTokens(trans)
if len(header) < opts.HeaderLines { if len(header) < opts.HeaderLines {
header = append(header, transformed) header = append(header, transformed)
eventBox.Set(EvtHeader, header) eventBox.Set(EvtHeader, header)
return nilItem return false
} }
trimmed, colors := ansiProcessor([]byte(transformed)) item.text, item.colors = ansiProcessor([]byte(transformed))
trimmed.Index = int32(index) item.text.Index = int32(index)
return Item{text: trimmed, colors: colors, origText: &data} item.origText = &data
return true
}) })
} }
@ -151,8 +152,8 @@ func Run(opts *Options, revision string) {
slab := util.MakeSlab(slab16Size, slab32Size) slab := util.MakeSlab(slab16Size, slab32Size)
reader := Reader{ reader := Reader{
func(runes []byte) bool { func(runes []byte) bool {
item := chunkList.trans(runes, 0) item := Item{}
if !item.Nil() { if chunkList.trans(&item, runes, 0) {
if result, _, _ := pattern.MatchItem(&item, false, slab); result != nil { if result, _, _ := pattern.MatchItem(&item, false, slab); result != nil {
opts.Printer(item.text.ToString()) opts.Printer(item.text.ToString())
found = true found = true

View File

@ -17,11 +17,7 @@ func (item *Item) Index() int32 {
return item.text.Index return item.text.Index
} }
var nilItem = Item{text: util.Chars{Index: -1}} var minItem = Item{text: util.Chars{Index: -1}}
func (item *Item) Nil() bool {
return item.Index() < 0
}
func (item *Item) TrimLength() uint16 { func (item *Item) TrimLength() uint16 {
return item.text.TrimLength() return item.text.TrimLength()

View File

@ -29,7 +29,7 @@ func PassMerger(chunks *[]*Chunk, tac bool) *Merger {
count: 0} count: 0}
for _, chunk := range *mg.chunks { for _, chunk := range *mg.chunks {
mg.count += len(*chunk) mg.count += chunk.count
} }
return &mg return &mg
} }
@ -65,7 +65,7 @@ func (mg *Merger) Get(idx int) Result {
idx = mg.count - idx - 1 idx = mg.count - idx - 1
} }
chunk := (*mg.chunks)[idx/chunkSize] chunk := (*mg.chunks)[idx/chunkSize]
return Result{item: &(*chunk)[idx%chunkSize]} return Result{item: &chunk.items[idx%chunkSize]}
} }
if mg.sorted { if mg.sorted {

View File

@ -278,8 +278,8 @@ func (p *Pattern) matchChunk(chunk *Chunk, space []Result, slab *util.Slab) []Re
matches := []Result{} matches := []Result{}
if space == nil { if space == nil {
for idx := range *chunk { for idx := 0; idx < chunk.count; idx++ {
if match, _, _ := p.MatchItem(&(*chunk)[idx], false, slab); match != nil { if match, _, _ := p.MatchItem(&chunk.items[idx], false, slab); match != nil {
matches = append(matches, *match) matches = append(matches, *match)
} }
} }

View File

@ -130,12 +130,11 @@ func TestOrigTextAndTransformed(t *testing.T) {
origBytes := []byte("junegunn.choi") origBytes := []byte("junegunn.choi")
for _, extended := range []bool{false, true} { for _, extended := range []bool{false, true} {
chunk := Chunk{ chunk := Chunk{count: 1}
Item{ chunk.items[0] = Item{
text: util.ToChars([]byte("junegunn")), text: util.ToChars([]byte("junegunn")),
origText: &origBytes, origText: &origBytes,
transformed: &trans}, transformed: &trans}
}
pattern.extended = extended pattern.extended = extended
matches := pattern.matchChunk(&chunk, nil, slab) // No cache matches := pattern.matchChunk(&chunk, nil, slab) // No cache
if !(matches[0].item.text.ToString() == "junegunn" && if !(matches[0].item.text.ToString() == "junegunn" &&
@ -144,7 +143,7 @@ func TestOrigTextAndTransformed(t *testing.T) {
t.Error("Invalid match result", matches) t.Error("Invalid match result", matches)
} }
match, offsets, pos := pattern.MatchItem(&chunk[0], true, slab) match, offsets, pos := pattern.MatchItem(&chunk.items[0], true, slab)
if !(match.item.text.ToString() == "junegunn" && if !(match.item.text.ToString() == "junegunn" &&
string(*match.item.origText) == "junegunn.choi" && string(*match.item.origText) == "junegunn.choi" &&
offsets[0][0] == 0 && offsets[0][1] == 5 && offsets[0][0] == 0 && offsets[0][1] == 5 &&

View File

@ -85,7 +85,7 @@ func (result *Result) Index() int32 {
} }
func minRank() Result { func minRank() Result {
return Result{item: &nilItem, points: [4]uint16{math.MaxUint16, 0, 0, 0}} return Result{item: &minItem, points: [4]uint16{math.MaxUint16, 0, 0, 0}}
} }
func (result *Result) colorOffsets(matchOffsets []Offset, theme *tui.ColorTheme, color tui.ColorPair, attr tui.Attr, current bool) []colorOffset { func (result *Result) colorOffsets(matchOffsets []Offset, theme *tui.ColorTheme, color tui.ColorPair, attr tui.Attr, current bool) []colorOffset {