Skip to content

Commit

Permalink
Merge pull request #2 from soniah/master
Browse files Browse the repository at this point in the history
failure on nil reader
  • Loading branch information
msoap authored Dec 6, 2018
2 parents 2781525 + ed4d2df commit 0fb9019
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
57 changes: 57 additions & 0 deletions byline.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ var (
// ErrOmitLine - error for Map*Err/AWKMode, for omitting current line
ErrOmitLine = errors.New("ErrOmitLine")

// ErrNilReader - error for provided reader being nil
ErrNilReader = errors.New("nil reader")

// default field separator
defaultFS = regexp.MustCompile(`\s+`)
// default line separator
Expand Down Expand Up @@ -42,6 +45,9 @@ type AWKVars struct {

// NewReader - get new line by line Reader
func NewReader(reader io.Reader) *Reader {
if reader == nil {
return nil
}
lr := &Reader{
scanner: bufio.NewScanner(reader),
existsData: true,
Expand Down Expand Up @@ -76,6 +82,9 @@ func (lr *Reader) scanLinesBySep(data []byte, atEOF bool) (advance int, token []

// Read - implement io.Reader interface
func (lr *Reader) Read(p []byte) (n int, err error) {
if lr == nil {
return 0, ErrNilReader
}
var (
bufErr, filterErr error
lineBytes []byte
Expand Down Expand Up @@ -119,26 +128,38 @@ func (lr *Reader) Read(p []byte) (n int, err error) {

// Map - set filter function for process each line
func (lr *Reader) Map(filterFn func([]byte) []byte) *Reader {
if lr == nil {
return nil
}
return lr.MapErr(func(line []byte) ([]byte, error) {
return filterFn(line), nil
})
}

// MapErr - set filter function for process each line, returns error if needed (io.EOF for example)
func (lr *Reader) MapErr(filterFn func([]byte) ([]byte, error)) *Reader {
if lr == nil {
return nil
}
lr.filterFuncs = append(lr.filterFuncs, filterFn)
return lr
}

// MapString - set filter function for process each line as string
func (lr *Reader) MapString(filterFn func(string) string) *Reader {
if lr == nil {
return nil
}
return lr.MapErr(func(line []byte) ([]byte, error) {
return []byte(filterFn(string(line))), nil
})
}

// MapStringErr - set filter function for process each line as string, returns error if needed (io.EOF for example)
func (lr *Reader) MapStringErr(filterFn func(string) (string, error)) *Reader {
if lr == nil {
return nil
}
return lr.MapErr(func(line []byte) ([]byte, error) {
newString, err := filterFn(string(line))
return []byte(newString), err
Expand All @@ -148,6 +169,9 @@ func (lr *Reader) MapStringErr(filterFn func(string) (string, error)) *Reader {
// Each - processing each line.
// Do not save the value of the byte slice, since it can change in the next filter-steps.
func (lr *Reader) Each(filterFn func([]byte)) *Reader {
if lr == nil {
return nil
}
return lr.MapErr(func(line []byte) ([]byte, error) {
filterFn(line)
return line, nil
Expand All @@ -156,6 +180,9 @@ func (lr *Reader) Each(filterFn func([]byte)) *Reader {

// EachString - processing each line as string
func (lr *Reader) EachString(filterFn func(string)) *Reader {
if lr == nil {
return nil
}
return lr.MapErr(func(line []byte) ([]byte, error) {
filterFn(string(line))
return line, nil
Expand All @@ -164,6 +191,9 @@ func (lr *Reader) EachString(filterFn func(string)) *Reader {

// Grep - grep lines by func
func (lr *Reader) Grep(filterFn func([]byte) bool) *Reader {
if lr == nil {
return nil
}
return lr.MapErr(func(line []byte) ([]byte, error) {
if filterFn(line) {
return line, nil
Expand All @@ -175,32 +205,47 @@ func (lr *Reader) Grep(filterFn func([]byte) bool) *Reader {

// GrepString - grep lines as string by func
func (lr *Reader) GrepString(filterFn func(string) bool) *Reader {
if lr == nil {
return nil
}
return lr.Grep(func(line []byte) bool {
return filterFn(string(line))
})
}

// GrepByRegexp - grep lines by regexp
func (lr *Reader) GrepByRegexp(re *regexp.Regexp) *Reader {
if lr == nil {
return nil
}
return lr.Grep(func(line []byte) bool {
return re.Match(line)
})
}

// SetRS - set lines (records) separator
func (lr *Reader) SetRS(rs byte) *Reader {
if lr == nil {
return nil
}
lr.awkVars.RS = rs
return lr
}

// SetFS - set field separator for AWK mode
func (lr *Reader) SetFS(fs *regexp.Regexp) *Reader {
if lr == nil {
return nil
}
lr.awkVars.FS = fs
return lr
}

// AWKMode - process lines with AWK like mode
func (lr *Reader) AWKMode(filterFn func(line string, fields []string, vars AWKVars) (string, error)) *Reader {
if lr == nil {
return nil
}
return lr.MapErr(func(line []byte) ([]byte, error) {
addRS := false
RS := []byte{lr.awkVars.RS}
Expand All @@ -227,6 +272,9 @@ func (lr *Reader) AWKMode(filterFn func(line string, fields []string, vars AWKVa

// Discard - read all content from Reader for side effect from filter functions
func (lr *Reader) Discard() error {
if lr == nil {
return ErrNilReader
}
_, err := io.Copy(ioutil.Discard, lr)
return err
}
Expand All @@ -244,11 +292,17 @@ func (lr *Reader) ReadAllSlice() ([][]byte, error) {

// ReadAll - read all content from Reader to slice of bytes
func (lr *Reader) ReadAll() ([]byte, error) {
if lr == nil {
return []byte{}, ErrNilReader
}
return ioutil.ReadAll(lr)
}

// ReadAllSliceString - read all content from Reader to string slice by lines
func (lr *Reader) ReadAllSliceString() ([]string, error) {
if lr == nil {
return []string{}, ErrNilReader
}
result := []string{}
err := lr.MapString(func(line string) string {
result = append(result, line)
Expand All @@ -260,6 +314,9 @@ func (lr *Reader) ReadAllSliceString() ([]string, error) {

// ReadAllString - read all content from Reader to one string
func (lr *Reader) ReadAllString() (string, error) {
if lr == nil {
return "", ErrNilReader
}
result, err := ioutil.ReadAll(lr)
return string(result), err
}
10 changes: 10 additions & 0 deletions byline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,16 @@ func TestAWKModeWithError(t *testing.T) {
}

func TestReadAll(t *testing.T) {
t.Run("ReadAllNilReader", func(t *testing.T) {
var reader io.Reader
_, err := byline.NewReader(reader).
SetRS('#').
MapString(func(line string) string { return "<" + line }).
ReadAll()
require.Exactly(t, byline.ErrNilReader, err, "ReadAllNilReader")

})

t.Run("ReadAll", func(t *testing.T) {
reader := strings.NewReader(`1 name_one 12.3#2 error_row#3 three row 15.51#4 row#5 row end`)
result, err := byline.NewReader(reader).
Expand Down

0 comments on commit 0fb9019

Please sign in to comment.