github.com/jmigpin/editor@v1.6.0/util/parseutil/scannerr.go (about) 1 package parseutil 2 3 import ( 4 "github.com/jmigpin/editor/util/iout/iorw" 5 "github.com/jmigpin/editor/util/mathutil" 6 ) 7 8 // scanner wrapper to be use with iorw.ReaderAt. Needed because the scanner deals with a []byte src, and the position starts at zero. While the reader first position is at r.Min(), where reading a position less then r.Min() gives error. 9 type ScannerR struct { 10 *Scanner 11 R iorw.ReaderAt 12 } 13 14 func NewScannerR(r iorw.ReaderAt, index int) *ScannerR { 15 sc := &ScannerR{R: r} 16 sc.Scanner = NewScanner() 17 18 src, err := iorw.ReadFastFull(sc.R) 19 if err != nil { 20 return sc // empty scanner, no error (nothing todo, best effort) 21 } 22 sc.Scanner.SetSrc(src) 23 24 sc.SetPos(index) 25 26 return sc 27 } 28 func (sc *ScannerR) SetPos(v int) { 29 u := v - sc.R.Min() 30 sc.Scanner.Pos = mathutil.Limit(u, 0, len(sc.Scanner.Src)) 31 } 32 func (sc *ScannerR) Pos() int { 33 return sc.R.Min() + sc.Scanner.Pos 34 } 35 func (sc *ScannerR) KeepPos() ScannerRPos { 36 return ScannerRPos{sc: sc, Pos: sc.Pos()} 37 } 38 39 func (sc *ScannerR) Src(donotuse int) { panic("!") } 40 func (sc *ScannerR) SetSrc(donotuse int) { panic("!") } 41 42 //---------- 43 //---------- 44 //---------- 45 46 type ScannerRPos struct { 47 sc *ScannerR 48 Pos int 49 } 50 51 func (sp *ScannerRPos) Restore() { 52 sp.sc.SetPos(sp.Pos) 53 } 54 func (sp *ScannerRPos) IsEmpty() bool { 55 return sp.Pos == sp.sc.Pos() 56 } 57 func (sp *ScannerRPos) StartEnd() (int, int) { 58 start, end := sp.Pos, sp.sc.Pos() 59 if start > end { // support reverse mode 60 start, end = end, start 61 } 62 return start, end 63 } 64 func (sp *ScannerRPos) Bytes() []byte { 65 start, end := sp.StartEnd() 66 start -= sp.sc.R.Min() 67 end -= sp.sc.R.Min() 68 return sp.sc.Scanner.Src[start:end] 69 }