Skip to content

Commit

Permalink
feat: add EachChar to Reader and tests related to it
Browse files Browse the repository at this point in the history
  • Loading branch information
ShindouMihou committed Mar 28, 2024
1 parent 506ff5a commit 13a49f3
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 0 deletions.
44 changes: 44 additions & 0 deletions siopao/siopao_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,50 @@ func TestFile_Text(t *testing.T) {
}
}

func TestFile_Reader(t *testing.T) {
file := Open(".tests/reader-01.txt")
writer, err := file.Writer(true)
if err != nil {
t.Fatal("failed to clean up test file.")
}
for i := 0; i < 50; i++ {
if err := writer.Write("hello world\n"); err != nil {
t.Fatal("failed to write to test text file: ", err)
}
}
if err := writer.End(); err != nil {
t.Fatal("failed to close writer")
}
reader, err := file.Reader()
if err != nil {
t.Fatal("failed to open reader")
}
if err := reader.EachLine(func(line []byte) {
if len(line) != len([]byte("hello world")) {
t.Fatal("invalid size: ", len(line), line)
}
}); err != nil {
t.Fatal("failed to read test file: ", err)
}

// each char test
reader, err = file.Reader()
if err != nil {
t.Fatal("failed to open reader")
}
if err := reader.EachChar(func(char rune) {
if char != 'h' && char != 'e' && char != 'l' && char != 'o' && char != 'w' && char != 'r' && char != 'd' && char != '\n' && char != 32 {
t.Fatal("invalid char read: ", string(char))
}
}); err != nil {
t.Fatal("failed to read test file: ", err)
}

if err := os.Remove(".tests/reader-01.txt"); err != nil {
t.Fatal("failed to clean up test file.")
}
}

func TestFile_Checksum(t *testing.T) {
file := Open(".tests/write-01.txt")

Expand Down
26 changes: 26 additions & 0 deletions streaming/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package streaming

import (
"bufio"
"io"
"os"
)

Expand All @@ -16,6 +17,7 @@ func NewReader(file *os.File) *Reader {
}

type LineReader func(line []byte)
type CharReader func(char rune)

// EachLine reads each line of the file as bytes. Unlike EachImmutableLine, the byte array is reused which means
// it will be overridden each next line, therefore, it is not recommended to store the byte array elsewhere without
Expand All @@ -24,6 +26,12 @@ func (reader *Reader) EachLine(fn LineReader) error {
return reader.eachline(false, fn)
}

// EachChar reads each char of the file. Unlike EachLine, this will do a char-by-char process, which means everything
// including next line characters will be included.
func (reader *Reader) EachChar(fn CharReader) error {
return reader.eachchar(fn)
}

// EachImmutableLine reads each line of the file as bytes. Unlike EachLine, there is copying involved which makes this
// slower than the other, but the byte array here won't be overridden each line, allowing you to store the byte array
// elsewhere without extra copying.
Expand Down Expand Up @@ -100,3 +108,21 @@ func (reader *Reader) eachline(immutable bool, fn LineReader) error {
}
return nil
}

func (reader *Reader) eachchar(fn CharReader) error {
defer reader.Close()

rd := bufio.NewReader(reader.file)
for {
if c, _, err := rd.ReadRune(); err != nil {
if err == io.EOF {
break
} else {
return err
}
} else {
fn(c)
}
}
return nil
}
5 changes: 5 additions & 0 deletions streaming/text_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,8 @@ func (reader *TextReader) EachLine(fn TextLineReader) error {
fn(string(line))
})
}

// EachChar reads each char of the file.
func (reader *TextReader) EachChar(fn CharReader) error {
return reader.reader.eachchar(fn)
}

0 comments on commit 13a49f3

Please sign in to comment.