github.com/blong14/gache@v0.0.0-20240124023949-89416fd8bbfa/internal/io/file/csv.go (about) 1 package file 2 3 import ( 4 "encoding/csv" 5 "io" 6 "math" 7 "os" 8 "runtime" 9 10 gerrors "github.com/blong14/gache/internal/errors" 11 ) 12 13 type Reader struct { 14 max int 15 token [][]string 16 errs *gerrors.Error 17 data string 18 handle *os.File 19 csvReader *csv.Reader 20 } 21 22 func (s *Reader) Init() { 23 f, err := os.Open(s.data) 24 if err != nil { 25 panic(err) 26 } 27 s.handle = f 28 s.csvReader = csv.NewReader(s.handle) 29 s.csvReader.ReuseRecord = false 30 s.token = make([][]string, s.max) 31 } 32 33 func (s *Reader) Err() *gerrors.Error { 34 return s.errs 35 } 36 37 func (s *Reader) Rows() [][]string { 38 return s.token 39 } 40 41 func (s *Reader) Close() { 42 if err := s.handle.Close(); err != nil { 43 s.errs = gerrors.Append(s.errs, err) 44 } 45 } 46 47 func (s *Reader) Scan() bool { 48 if err := s.errs.ErrorOrNil(); err != nil { 49 return false 50 } 51 out := make([][]string, 0, s.max) 52 for { 53 row, err := s.csvReader.Read() 54 if err == io.EOF { 55 break 56 } 57 if err != nil { 58 s.errs = gerrors.Append(s.errs, err) 59 break 60 } 61 out = append(out, row) 62 if len(out) == s.max { 63 copy(s.token, out) 64 return true 65 } 66 } 67 if len(out) > 0 { 68 s.token = out 69 return true 70 } 71 return false 72 } 73 74 var ( 75 base = float64(2) 76 exponent = float64(14) 77 ) 78 79 func ScanCSV(data string) *Reader { 80 return &Reader{ 81 data: data, 82 max: int(math.Pow(base, exponent)) / (runtime.NumCPU() / int(base)), 83 } 84 }