69 lines
		
	
	
	
		
			1.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
	
		
			1.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package models
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"bytes"
 | |
| 	"regexp"
 | |
| 	"sync"
 | |
| )
 | |
| 
 | |
| var reg = regexp.MustCompile("(?sm)^@begin .+?(^| )@end")
 | |
| 
 | |
| type Log struct {
 | |
| 	Name    string
 | |
| 	Entries []Entry
 | |
| }
 | |
| 
 | |
| func (l *Log) UnmarshalText(in []byte) error {
 | |
| 	ch := l.getLogUnarshalChan(in)
 | |
| 	for entry := range ch {
 | |
| 		l.Entries = append(l.Entries, entry)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func scanLog(data []byte, atEOF bool) (advance int, token []byte, err error) {
 | |
| 	if atEOF && len(data) == 0 {
 | |
| 		// done
 | |
| 		return 0, nil, nil
 | |
| 	}
 | |
| 	m := reg.FindIndex(data)
 | |
| 	if len(m) == 0 && atEOF {
 | |
| 		// all trash
 | |
| 		return len(data), nil, nil
 | |
| 	} else if len(m) == 0 && !atEOF {
 | |
| 		// get more
 | |
| 		return 0, nil, nil
 | |
| 	}
 | |
| 	return m[1], data[m[0]:m[1]], nil
 | |
| }
 | |
| 
 | |
| func (l *Log) getLogUnarshalChan(in []byte) chan Entry {
 | |
| 	size := len(in) / 10 // rough estimation
 | |
| 	ch := make(chan Entry, size)
 | |
| 	var wg sync.WaitGroup
 | |
| 
 | |
| 	read := bytes.NewReader(in)
 | |
| 	scan := bufio.NewScanner(read)
 | |
| 	scan.Split(scanLog)
 | |
| 
 | |
| 	for scan.Scan() {
 | |
| 		wg.Add(1)
 | |
| 		go func(field []byte) {
 | |
| 			defer wg.Done()
 | |
| 			f := new(Entry)
 | |
| 			err := f.UnmarshalText(field)
 | |
| 			if err != nil {
 | |
| 				return
 | |
| 			}
 | |
| 			ch <- *f
 | |
| 		}(scan.Bytes())
 | |
| 	}
 | |
| 
 | |
| 	go func() {
 | |
| 		wg.Wait()
 | |
| 		close(ch)
 | |
| 	}()
 | |
| 	return ch
 | |
| }
 |