initial commit
This commit is contained in:
		
							
								
								
									
										9
									
								
								errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								errors.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | package bufr | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"git.tordarus.net/Tordarus/adverr" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	ErrNothingToUnread = adverr.NewErrTmpl("ErrNothingToUnread", "Unreading failed because there wasn't any Read yet") | ||||||
|  | ) | ||||||
							
								
								
									
										8
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | module git.tordarus.net/Tordarus/bufr | ||||||
|  |  | ||||||
|  | go 1.18 | ||||||
|  |  | ||||||
|  | require ( | ||||||
|  | 	git.tordarus.net/Tordarus/adverr v0.2.0 | ||||||
|  | 	git.tordarus.net/Tordarus/dstruct v0.0.2 | ||||||
|  | ) | ||||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | |||||||
|  | git.tordarus.net/Tordarus/adverr v0.2.0 h1:kLYjR2/Vb2GHiSAMvAv+WPNaHR9BRphKanf8H/pCZdA= | ||||||
|  | git.tordarus.net/Tordarus/adverr v0.2.0/go.mod h1:XRf0+7nhOkIEr0gi9DUG4RvV2KaOFB0fYPDaR1KLenw= | ||||||
|  | git.tordarus.net/Tordarus/dstruct v0.0.2 h1:oFaZO7YXQeHjxL4DmMaZ+Eb4MvP23dX8GAXs0Z6VQKo= | ||||||
|  | git.tordarus.net/Tordarus/dstruct v0.0.2/go.mod h1:RvLL2G4lUCGzwr8KaBGQRi3qlMG0WTgGhcVN6iyZZuw= | ||||||
							
								
								
									
										81
									
								
								reader.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								reader.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | |||||||
|  | package bufr | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bufio" | ||||||
|  | 	"io" | ||||||
|  | 	"strings" | ||||||
|  |  | ||||||
|  | 	"git.tordarus.net/Tordarus/dstruct" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Reader struct { | ||||||
|  | 	buf *dstruct.Stack[rune] | ||||||
|  | 	src *bufio.Reader | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewReader(r io.Reader) *Reader { | ||||||
|  | 	return &Reader{ | ||||||
|  | 		buf: new(dstruct.Stack[rune]), | ||||||
|  | 		src: bufio.NewReader(r), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Rune returns the next rune in r | ||||||
|  | func (r *Reader) Rune() (rune, error) { | ||||||
|  | 	rn, _, err := r.src.ReadRune() | ||||||
|  | 	if err == nil { | ||||||
|  | 		r.buf.Push(rn) | ||||||
|  | 	} | ||||||
|  | 	return rn, err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // UnreadRune unreads the last rune. | ||||||
|  | // The next read will include the unread rune. | ||||||
|  | // It returns ErrNothingToUnread if there wasn't any read yet | ||||||
|  | func (r *Reader) UnreadRune() error { | ||||||
|  | 	if r.buf.Empty() { | ||||||
|  | 		return ErrNothingToUnread.New() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := r.src.UnreadRune(); err == nil { | ||||||
|  | 		r.buf.Pop() | ||||||
|  | 	} else { | ||||||
|  | 		r.src = prependRune(r.buf.Pop(), r.src) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // UnreadString calls UnreadRune for each rune in str | ||||||
|  | // The actual runes are irrelevant. | ||||||
|  | // Only the rune count of str determines the amount of UnreadRune calls. | ||||||
|  | // The first error occured will be returned immediately. | ||||||
|  | func (r *Reader) UnreadString(str string) error { | ||||||
|  | 	for range str { | ||||||
|  | 		err := r.UnreadRune() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // StringWhile reads runes and calls f for each one. | ||||||
|  | // It returns all runes as a string for which f returned true. | ||||||
|  | // It stops when f returns false or an error occured. | ||||||
|  | // The rune for which f returned false will not be unread. | ||||||
|  | func (r *Reader) StringWhile(f func(rn rune) bool) (string, error) { | ||||||
|  | 	s := new(strings.Builder) | ||||||
|  |  | ||||||
|  | 	var err error | ||||||
|  | 	for rn, err := r.Rune(); err == nil && f(rn); rn, err = r.Rune() { | ||||||
|  | 		s.WriteRune(rn) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return s.String(), err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // StringUntil is a shorthand for r.StringWhile(func(rn rune) bool { return !f(rn) }) | ||||||
|  | func (r *Reader) StringUntil(f func(rn rune) bool) (string, error) { | ||||||
|  | 	return r.StringWhile(func(rn rune) bool { return !f(rn) }) | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								utils.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | package bufr | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bufio" | ||||||
|  | 	"io" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func prependString(str string, r io.Reader) *bufio.Reader { | ||||||
|  | 	return bufio.NewReader(io.MultiReader(strings.NewReader(str), r)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func prependRune(rn rune, r io.Reader) *bufio.Reader { | ||||||
|  | 	return prependString(string(rn), r) | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Timon Ringwald
					Timon Ringwald