From c2833ba4d254f92e3138cbdbfe33ac00f51c811f Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Sat, 22 Apr 2023 20:51:53 +0200 Subject: [PATCH] Update (#1) --- .github/dependabot.yml | 6 ++- .github/workflows/build.yml | 21 +++------- README.md | 14 ++----- dsvreader_bench_test.go | 8 ++++ dsvreader_example_test.go => example_test.go | 42 ++++++++++---------- read_date.go | 22 +++++++++- util_pure.go => util_purego.go | 0 util_nopure.go => util_unsafe.go | 0 8 files changed, 64 insertions(+), 49 deletions(-) rename dsvreader_example_test.go => example_test.go (98%) rename util_pure.go => util_purego.go (100%) rename util_nopure.go => util_unsafe.go (100%) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index cb2aff7..20d5f35 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,5 +4,7 @@ updates: directory: "/" schedule: interval: daily - commit-message: - prefix: "Bump:" + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 61b5aed..29e63dc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,11 +1,12 @@ name: build -permissions: read-all - on: push: branches: [main] pull_request: + branches: [main] + schedule: + - cron: '0 0 * * 0' # run "At 00:00 on Sunday" workflow_dispatch: inputs: tag: @@ -16,17 +17,7 @@ on: # See https://github.com/cristalhq/.github/.github/workflows jobs: build: - uses: cristalhq/.github/.github/workflows/build.yml@454df049fccd7d81729b0c567b75662a2b77e97a # v0.1.3 - - codeql: - permissions: - security-events: write - uses: cristalhq/.github/.github/workflows/codeql.yml@454df049fccd7d81729b0c567b75662a2b77e97a # v0.1.3 + uses: cristalhq/.github/.github/workflows/build.yml@v0.5.0 - release: - if: github.event_name == 'workflow_dispatch' - uses: cristalhq/.github/.github/workflows/release.yml@454df049fccd7d81729b0c567b75662a2b77e97a # v0.1.3 - permissions: - contents: write - with: - tag: ${{ github.event.input.tag }} + vuln: + uses: cristalhq/.github/.github/workflows/vuln.yml@v0.5.0 diff --git a/README.md b/README.md index 634b431..308ef74 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,9 @@ [![build-img]][build-url] [![pkg-img]][pkg-url] -[![reportcard-img]][reportcard-url] -[![coverage-img]][coverage-url] [![version-img]][version-url] -Fast reader for delimiter-separated data. +Fast reader for delimiter-separated data in Go. ## Features @@ -16,6 +14,8 @@ Fast reader for delimiter-separated data. * Optimized for speed. * Based on [Aliaksandr Valialkin's TSVReader](https://github.com/valyala/tsvreader) +See [docs][pkg-url]. + ## Install Go version 1.17+ @@ -43,9 +43,7 @@ if err := r.Error(); err != nil { } ``` -## Documentation - -See [these docs][pkg-url]. +See examples: [example_test.go](example_test.go). ## License @@ -55,9 +53,5 @@ See [these docs][pkg-url]. [build-url]: https://github.com/cristalhq/dsvreader/actions [pkg-img]: https://pkg.go.dev/badge/cristalhq/dsvreader [pkg-url]: https://pkg.go.dev/github.com/cristalhq/dsvreader -[reportcard-img]: https://goreportcard.com/badge/cristalhq/dsvreader -[reportcard-url]: https://goreportcard.com/report/cristalhq/dsvreader -[coverage-img]: https://codecov.io/gh/cristalhq/dsvreader/branch/master/graph/badge.svg -[coverage-url]: https://codecov.io/gh/cristalhq/dsvreader [version-img]: https://img.shields.io/github/v/release/cristalhq/dsvreader [version-url]: https://github.com/cristalhq/dsvreader/releases diff --git a/dsvreader_bench_test.go b/dsvreader_bench_test.go index bcd3bbc..4b33693 100644 --- a/dsvreader_bench_test.go +++ b/dsvreader_bench_test.go @@ -19,6 +19,7 @@ func BenchmarkReaderBytes(b *testing.B) { } func benchmarkReaderBytes(b *testing.B, rows, cols int) { + b.Helper() b.StopTimer() bb := createBytesTSV(rows, cols) br := bytes.NewReader(bb) @@ -33,6 +34,7 @@ func benchmarkReaderBytes(b *testing.B, rows, cols int) { } func benchmarkReaderBytesSingleIter(b *testing.B, r *Reader, rows, cols int) { + b.Helper() for i := 0; i < rows; i++ { if !r.Next() { b.Fatalf("Reader.Next must return true on row #%d", i+1) @@ -58,6 +60,7 @@ func BenchmarkReaderInt(b *testing.B) { } func benchmarkReaderInt(b *testing.B, rows, cols int) { + b.Helper() b.StopTimer() bb := createIntTSV(rows, cols) br := bytes.NewReader(bb) @@ -72,6 +75,7 @@ func benchmarkReaderInt(b *testing.B, rows, cols int) { } func benchmarkReaderIntSingleIter(b *testing.B, r *Reader, rows, cols int) { + b.Helper() for i := 0; i < rows; i++ { if !r.Next() { b.Fatalf("Reader.Next must return true on row #%d", i+1) @@ -97,6 +101,8 @@ func BenchmarkReaderUint(b *testing.B) { } func benchmarkReaderUint(b *testing.B, rows, cols int) { + b.Helper() + b.StopTimer() bb := createUintTSV(rows, cols) br := bytes.NewReader(bb) @@ -111,6 +117,8 @@ func benchmarkReaderUint(b *testing.B, rows, cols int) { } func benchmarkReaderUintSingleIter(b *testing.B, r *Reader, rows, cols int) { + b.Helper() + for i := 0; i < rows; i++ { if !r.Next() { b.Fatalf("Reader.Next must return true on row #%d", i+1) diff --git a/dsvreader_example_test.go b/example_test.go similarity index 98% rename from dsvreader_example_test.go rename to example_test.go index 054f6d7..33e6ce3 100644 --- a/dsvreader_example_test.go +++ b/example_test.go @@ -28,27 +28,6 @@ bar 123 // col1=bar, col2=123 } -func ExampleCSVReader() { - bs := bytes.NewBufferString( - `foo,42 -bar,123 -`) - - r := dsvreader.NewCSV(bs) - for r.Next() { - col1 := r.String() - col2 := r.Int() - fmt.Printf("col1=%s, col2=%d\n", col1, col2) - } - if err := r.Error(); err != nil { - fmt.Printf("unexpected error: %s", err) - } - - // Output: - // col1=foo, col2=42 - // col1=bar, col2=123 -} - func ExampleReader_HasCols() { bs := bytes.NewBufferString( "foo\n" + @@ -93,3 +72,24 @@ func ExampleReader_Next() { // 3 // 42 } + +func Example_csvReader() { + bs := bytes.NewBufferString( + `foo,42 +bar,123 +`) + + r := dsvreader.NewCSV(bs) + for r.Next() { + col1 := r.String() + col2 := r.Int() + fmt.Printf("col1=%s, col2=%d\n", col1, col2) + } + if err := r.Error(); err != nil { + fmt.Printf("unexpected error: %s", err) + } + + // Output: + // col1=foo, col2=42 + // col1=bar, col2=123 +} diff --git a/read_date.go b/read_date.go index 9795266..00c8446 100644 --- a/read_date.go +++ b/read_date.go @@ -11,7 +11,7 @@ var zeroTime time.Time // Date returns the next date column value from the current row. // -// date must be in the format YYYY-MM-DD +// date must be in the format YYYY-MM-DD. func (tr *Reader) Date() time.Time { if tr.err != nil { return zeroTime @@ -52,6 +52,26 @@ func (tr *Reader) DateTime() time.Time { return dt } +// DateTimeFormatted returns the next datetime column value from the current row. +func (tr *Reader) DateTimeFormatted(layout string) time.Time { + if tr.err != nil { + return zeroTime + } + + b, err := tr.nextCol() + if err != nil { + tr.setColError("cannot read `datetime`", err) + return zeroTime + } + + dt, err := time.Parse(layout, b2s(b)) + if err != nil { + tr.setColError("cannot parse `datetime`", err) + return zeroTime + } + return dt +} + func parseDateTime(s string) (time.Time, error) { if len(s) != len("YYYY-MM-DD hh:mm:ss") { return zeroTime, errors.New("too short datetime") diff --git a/util_pure.go b/util_purego.go similarity index 100% rename from util_pure.go rename to util_purego.go diff --git a/util_nopure.go b/util_unsafe.go similarity index 100% rename from util_nopure.go rename to util_unsafe.go