github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgGoSource/kmgGoReader/reader.go (about) 1 package kmgGoReader 2 3 import ( 4 "bytes" 5 "unicode" 6 "unicode/utf8" 7 ) 8 9 type Reader struct { 10 buf []byte //需要读入的数据 11 pos int //当前位置 12 filePos *FilePos 13 } 14 15 func NewReader(buf []byte, filePos *FilePos) *Reader { 16 return &Reader{ 17 buf: buf, 18 filePos: filePos, 19 } 20 } 21 22 func NewReaderWithPosFile(filename string, content []byte) *Reader { 23 pos := NewPosFile(filename, content) 24 return NewReader(content, pos) 25 } 26 27 func (r *Reader) Pos() int { 28 return r.pos 29 } 30 func (r *Reader) BufToCurrent(start int) []byte { 31 return r.buf[start:r.pos] 32 } 33 34 func (r *Reader) IsEof() bool { 35 return r.pos >= len(r.buf) 36 } 37 func (r *Reader) ReadByte() byte { 38 //if r.IsEof() { 39 // panic(r.GetFileLineInfo() + " unexcept EOF") 40 //} 41 out := r.buf[r.pos] 42 r.pos++ 43 return out 44 } 45 46 func (r *Reader) NextByte() byte { 47 return r.buf[r.pos] 48 } 49 50 func (r *Reader) IsMatchAfter(s []byte) bool { 51 return len(r.buf)-r.pos >= len(s) && r.buf[r.pos] == s[0] && bytes.Equal(r.buf[r.pos:r.pos+len(s)], s) 52 } 53 54 // 读取到某个字符,或者读取到结束(该字符会已经被读过) 55 func (r *Reader) ReadUntilByte(b byte) []byte { 56 startPos := r.pos 57 for { 58 if r.IsEof() { 59 return r.buf[startPos:] 60 } 61 if r.ReadByte() == b { 62 return r.buf[startPos:r.pos] 63 } 64 } 65 } 66 67 // 回调返回真的时候,停止读取,(这个回调提到的字符串也包含在内) 68 func (r *Reader) ReadUntilRuneCb(cb func(run rune) bool) []byte { 69 startPos := r.pos 70 for { 71 if r.IsEof() { 72 return r.buf[startPos:] 73 } 74 run, size := utf8.DecodeRune(r.buf[r.pos:]) 75 r.pos += size 76 if cb(run) { 77 return r.buf[startPos:r.pos] 78 } 79 } 80 } 81 82 // 读取到某个字符串,或者读取到结束(该字符串会已经被读过) 83 func (r *Reader) ReadUntilString(s []byte) []byte { 84 startPos := r.pos 85 for { 86 if r.IsEof() { 87 return r.buf[startPos:] 88 } 89 if r.IsMatchAfter(s) { 90 r.pos += len(s) 91 return r.buf[startPos:r.pos] 92 } 93 r.pos++ 94 } 95 } 96 97 func (r *Reader) ReadAllSpace() { 98 for { 99 if r.IsEof() { 100 return 101 } 102 run, size := utf8.DecodeRune(r.buf[r.pos:]) 103 if !unicode.IsSpace(run) { 104 return 105 } 106 r.pos += size 107 } 108 } 109 110 func (r *Reader) ReadAllSpaceWithoutLineBreak() { 111 for { 112 if r.IsEof() { 113 return 114 } 115 run, size := utf8.DecodeRune(r.buf[r.pos:]) 116 if unicode.IsSpace(run) && run != '\n' { 117 r.pos += size 118 } else { 119 return 120 } 121 } 122 } 123 124 func (r *Reader) ReadRune() rune { 125 run, size := utf8.DecodeRune(r.buf[r.pos:]) 126 r.pos += size 127 return run 128 } 129 130 func (r *Reader) UnreadRune() rune { 131 run, size := utf8.DecodeLastRune(r.buf[:r.pos]) 132 if size == 0 { 133 panic(r.GetFileLineInfo() + " [UnreadRune] last is not valid utf8 code.") 134 } 135 r.pos -= size 136 return run 137 } 138 139 func (r *Reader) UnreadByte() { 140 r.pos -= 1 141 } 142 143 func (r *Reader) MustReadMatch(s []byte) { 144 if !r.IsMatchAfter(s) { 145 panic(r.GetFileLineInfo() + " [MustReadMatch] not match " + string(s)) 146 } 147 r.pos += len(s) 148 } 149 150 func (r *Reader) MustReadWithSize(size int) []byte { 151 if r.IsEof() { 152 panic(r.GetFileLineInfo() + " unexpect EOF") 153 } 154 output := r.buf[r.pos : r.pos+size] 155 r.pos += size 156 return output 157 } 158 159 func (r *Reader) GetFileLineInfo() string { 160 return r.filePos.PosString(r.pos) 161 }