Skip to content

Instantly share code, notes, and snippets.

@kalexmills
Last active May 25, 2020 14:04
Show Gist options
  • Save kalexmills/402089e6723dcd86530082621f6fde38 to your computer and use it in GitHub Desktop.
Save kalexmills/402089e6723dcd86530082621f6fde38 to your computer and use it in GitHub Desktop.
Filtered readers w/out extra buffer allocations (golang)
package main
import (
"fmt"
"io"
"log"
"strings"
)
func main() {
// FilterReader filters out non-alphanumeric bytes.
reader := newFilterReader(strings.NewReader("a2bc123basgh1241vb113f"))
p := make([]byte, 7) // constant memory pressure achieved via buffer limit
for {
n, err := reader.Read(p)
if err != nil {
if err != io.EOF {
log.Panic(err)
}
break
}
fmt.Println(string(p[:n]))
}
}
type filterReader struct {
reader io.Reader
}
func newFilterReader(reader io.Reader) *filterReader {
return &filterReader{reader}
}
func (r *filterReader) Read(p []byte) (int, error) {
n, err := r.reader.Read(p)
if err != nil {
return n, err
}
// re-use p by packing bytes into buffer
j := 0
for i := 0; i < n; i++ {
if char := alpha(p[i]); char != 0 {
p[j] = char
j++
}
}
if j == 0 {
return 0, io.EOF
}
return j, nil
}
func alpha(r byte) byte {
if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') {
return r
}
return 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment