From 590f3eb4fa5cda9684c9720b7ef5bf58e14a0686 Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Sun, 30 Jan 2022 20:45:53 +0100 Subject: [PATCH] Cleanups --- dsvreader.go | 27 ++++++++++++--------------- dsvreader_test.go | 6 +++--- read_date.go | 26 +++++++++++--------------- read_nums.go | 23 ++++++++++++++--------- 4 files changed, 40 insertions(+), 42 deletions(-) diff --git a/dsvreader.go b/dsvreader.go index 2c6499b..c84829a 100644 --- a/dsvreader.go +++ b/dsvreader.go @@ -2,40 +2,37 @@ package dsvreader import ( "bytes" + "errors" "fmt" "io" ) // NewCSV returns new Reader that reads CSV data from r. func NewCSV(r io.Reader) *Reader { - var tr Reader - tr.sep = ',' + tr := &Reader{sep: ','} tr.Reset(r) - return &tr + return tr } // NewTSV returns new Reader that reads TSV data from r. func NewTSV(r io.Reader) *Reader { - var tr Reader - tr.sep = '\t' + tr := &Reader{sep: '\t'} tr.Reset(r) - return &tr + return tr } // NewPSV returns new Reader that reads PSV data from r. func NewPSV(r io.Reader) *Reader { - var tr Reader - tr.sep = '|' + tr := &Reader{sep: '|'} tr.Reset(r) - return &tr + return tr } // NewCustom returns new Reader that reads arbitrary delimiter-separated data from r. func NewCustom(sep byte, r io.Reader) *Reader { - var tr Reader - tr.sep = sep + tr := &Reader{sep: sep} tr.Reset(r) - return &tr + return tr } // Reader reads delimiter-separated data. @@ -130,7 +127,7 @@ func (tr *Reader) Next() bool { if tr.rErr != nil { tr.err = tr.rErr if tr.err != io.EOF { - tr.err = fmt.Errorf("cannot read row #%d: %s", tr.row, tr.err) + tr.err = fmt.Errorf("cannot read row #%d: %w", tr.row, tr.err) } else if len(tr.scratch) > 0 { tr.err = fmt.Errorf("cannot find newline at the end of row #%d; row: %q", tr.row, tr.scratch) } @@ -249,12 +246,12 @@ func (tr *Reader) String() string { func (tr *Reader) nextCol() ([]byte, error) { if tr.row == 0 { - return nil, fmt.Errorf("missing Next call") + return nil, errors.New("missing Next call") } tr.col++ if tr.b == nil { - return nil, fmt.Errorf("no more columns") + return nil, errors.New("no more columns") } n := bytes.IndexByte(tr.b, tr.sep) diff --git a/dsvreader_test.go b/dsvreader_test.go index 88289b7..c8bc909 100644 --- a/dsvreader_test.go +++ b/dsvreader_test.go @@ -109,14 +109,14 @@ func TestReaderResetError(t *testing.T) { t.Fatalf("Next must return true") } bb = r.Bytes() - if string(bb) != "" { + if len(bb) != 0 { t.Fatalf("unexpected non-empty bytes: %q", bb) } if r.Error() != nil { t.Fatalf("unexpected error: %s", r.Error()) } bb = r.Bytes() - if string(bb) != "" { + if len(bb) != 0 { t.Fatalf("unexpected non-empty bytes: %q", bb) } err := r.Error() @@ -673,7 +673,7 @@ func TestReaderMultiRowsMultiCols(t *testing.T) { testReaderMultiRowsMultiCols(t, 3, 500) } -func testReaderMultiRowsMultiCols(t *testing.T, rows int, cols int) { +func testReaderMultiRowsMultiCols(t *testing.T, rows, cols int) { t.Helper() var expected [][]string diff --git a/read_date.go b/read_date.go index ec29122..8514ebd 100644 --- a/read_date.go +++ b/read_date.go @@ -1,6 +1,7 @@ package dsvreader import ( + "errors" "fmt" "strconv" "time" @@ -58,7 +59,7 @@ func (tr *Reader) DateTime() time.Time { func parseDateTime(s string) (time.Time, error) { if len(s) != len("YYYY-MM-DD hh:mm:ss") { - return zeroTime, fmt.Errorf("too short datetime") + return zeroTime, errors.New("too short datetime") } y, m, d, err := parseDate(s[:len("YYYY-MM-DD")]) if err != nil { @@ -66,22 +67,22 @@ func parseDateTime(s string) (time.Time, error) { } s = s[len("YYYY-MM-DD"):] if s[0] != ' ' || s[3] != ':' || s[6] != ':' { - return zeroTime, fmt.Errorf("invalid time format. Must be hh:mm:ss") + return zeroTime, errors.New("invalid time format. Must be hh:mm:ss") } hS := s[1:3] minS := s[4:6] secS := s[7:] h, err := strconv.Atoi(hS) if err != nil { - return zeroTime, fmt.Errorf("invalid hour: %s", err) + return zeroTime, fmt.Errorf("invalid hour: %w", err) } min, err := strconv.Atoi(minS) if err != nil { - return zeroTime, fmt.Errorf("invalid minute: %s", err) + return zeroTime, fmt.Errorf("invalid minute: %w", err) } sec, err := strconv.Atoi(secS) if err != nil { - return zeroTime, fmt.Errorf("invalid second: %s", err) + return zeroTime, fmt.Errorf("invalid second: %w", err) } if y == 0 && m == 0 && d == 0 { // Special case for ClickHouse @@ -92,31 +93,26 @@ func parseDateTime(s string) (time.Time, error) { func parseDate(s string) (y, m, d int, err error) { if len(s) != len("YYYY-MM-DD") { - err = fmt.Errorf("too short date") - return + return 0, 0, 0, errors.New("too short date") } s = s[:len("YYYY-MM-DD")] if s[4] != '-' && s[7] != '-' { - err = fmt.Errorf("invalid date format. Must be YYYY-MM-DD") - return + return 0, 0, 0, errors.New("invalid date format. Must be YYYY-MM-DD") } yS := s[:4] mS := s[5:7] dS := s[8:] y, err = strconv.Atoi(yS) if err != nil { - err = fmt.Errorf("invalid year: %s", err) - return + return 0, 0, 0, fmt.Errorf("invalid year: %w", err) } m, err = strconv.Atoi(mS) if err != nil { - err = fmt.Errorf("invalid month: %s", err) - return + return 0, 0, 0, fmt.Errorf("invalid month: %w", err) } d, err = strconv.Atoi(dS) if err != nil { - err = fmt.Errorf("invalid day: %s", err) - return + return 0, 0, 0, fmt.Errorf("invalid day: %w", err) } return y, m, d, nil } diff --git a/read_nums.go b/read_nums.go index 23411d2..d1c2bbe 100644 --- a/read_nums.go +++ b/read_nums.go @@ -1,11 +1,16 @@ package dsvreader import ( - "fmt" + "errors" "math" "strconv" ) +var ( + errOutOfRange = errors.New("out of range") + errInvalidSyntex = errors.New("invalid syntax") +) + // Int returns the next int column value from the current row. func (tr *Reader) Int() int { if tr.err != nil { @@ -122,7 +127,7 @@ func (tr *Reader) Int16() int16 { return 0 } if n < math.MinInt16 || n > math.MaxInt16 { - tr.setColError("cannot parse `int16`", fmt.Errorf("out of range")) + tr.setColError("cannot parse `int16`", errOutOfRange) return 0 } return int16(n) @@ -144,11 +149,11 @@ func (tr *Reader) Uint16() uint16 { return 0 } if n < 0 { - tr.setColError("cannot parse `uint16`", fmt.Errorf("invalid syntax")) + tr.setColError("cannot parse `uint16`", errInvalidSyntex) return 0 } if n > math.MaxUint16 { - tr.setColError("cannot parse `uint16`", fmt.Errorf("out of range")) + tr.setColError("cannot parse `uint16`", errOutOfRange) return 0 } return uint16(n) @@ -170,7 +175,7 @@ func (tr *Reader) Int8() int8 { return 0 } if n < math.MinInt8 || n > math.MaxInt8 { - tr.setColError("cannot parse `int8`", fmt.Errorf("out of range")) + tr.setColError("cannot parse `int8`", errOutOfRange) return 0 } return int8(n) @@ -192,11 +197,11 @@ func (tr *Reader) Uint8() uint8 { return 0 } if n < 0 { - tr.setColError("cannot parse `uint8`", fmt.Errorf("invalid syntax")) + tr.setColError("cannot parse `uint8`", errInvalidSyntex) return 0 } if n > math.MaxUint8 { - tr.setColError("cannot parse `uint8`", fmt.Errorf("out of range")) + tr.setColError("cannot parse `uint8`", errOutOfRange) return 0 } return uint8(n) @@ -216,7 +221,7 @@ func (tr *Reader) Int64() int64 { // Fast path - attempt to use Atoi n, err := strconv.Atoi(s) - if err == nil && int64(n) >= math.MinInt64 && int64(n) <= math.MaxInt64 { + if err == nil { return int64(n) } @@ -243,7 +248,7 @@ func (tr *Reader) Uint64() uint64 { // Fast path - attempt to use Atoi n, err := strconv.Atoi(s) - if err == nil && n >= 0 && uint64(n) <= math.MaxUint64 { + if err == nil && n >= 0 { return uint64(n) }