<commit_before>package buffer

import (
	"io"
	"io/ioutil"
	"os"
)

type FileBuffer struct {
	file *os.File
	N    int64
	L    int64
	ROff int64
	WOff int64
}

func NewFile(N int64) *FileBuffer {
	buf := &FileBuffer{
		N: N,
	}
	return buf
}

func (buf *FileBuffer) init() error {
	if buf.file == nil {
		if file, err := ioutil.TempFile("D:\\Downloads\\temp", "buffer"); err == nil {
			buf.file = file
			buf.ROff = 0
			buf.WOff = 0
		} else {
			return err
		}
	}
	return nil
}

func (buf *FileBuffer) Len() int64 {
	return buf.L
}

func (buf *FileBuffer) Cap() int64 {
	return buf.N
}

func (buf *FileBuffer) ReadAt(p []byte, off int64) (n int, err error) {
	wrap := NewWrapReader(buf.file, off, buf.Cap())
	r := io.NewSectionReader(wrap, 0, buf.Len()-off)
	return r.ReadAt(p, 0)
}

func (buf *FileBuffer) Read(p []byte) (n int, err error) {
	wrap := NewWrapReader(buf.file, buf.ROff, buf.Cap())
	r := io.LimitReader(wrap, buf.Len())

	n, err = r.Read(p)
	buf.L -= int64(n)
	buf.ROff = (buf.ROff + int64(n)) % buf.Cap()

	if Empty(buf) {
		buf.Reset()
	}

	return n, err
}

// BUG(Dustin): Add short write
func (buf *FileBuffer) Write(p []byte) (n int, err error) {
	if err := buf.init(); err != nil {
		return 0, err
	}

	wrap := NewWrapWriter(buf.file, buf.WOff, buf.Cap())
	w := LimitWriter(wrap, Gap(buf))
	n, err = w.Write(p)
	buf.L += int64(n)
	buf.WOff = (buf.WOff + int64(n)) % buf.Cap()

	return n, err
}

func (buf *FileBuffer) Reset() {
	if buf.file != nil {
		buf.file.Close()
		os.Remove(buf.file.Name())
		buf.file = nil
		buf.ROff = 0
		buf.WOff = 0
	}
}

func (buf *FileBuffer) FastForward(n int) int {
	if int64(n) > buf.Len() {
		n = int(buf.Len())
	}

	buf.L -= int64(n)
	buf.ROff = (buf.ROff + int64(n)) % buf.Cap()

	return n
}<commit_msg>FileBuffer can use a custom Filename<commit_after>package buffer

import (
	"io"
	"io/ioutil"
	"os"
)

type FileBuffer struct {
	file     *os.File
	Filename string
	N        int64
	L        int64
	ROff     int64
	WOff     int64
}

func NewFile(N int64) *FileBuffer {
	buf := &FileBuffer{
		N: N,
	}
	return buf
}

func (buf *FileBuffer) init() (err error) {
	var file *os.File

	if buf.file == nil {

		if buf.Filename != "" {
			if file, err = os.OpenFile(buf.Filename, os.O_CREATE|os.O_RDWR, 0644); err != nil {
				return err
			}
		} else if file, err = ioutil.TempFile("D:\\Downloads\\temp", "buffer"); err != nil {
			return err
		}

		buf.file = file
		buf.Filename = file.Name()
		buf.ROff = 0
		buf.WOff = 0
	}

	return nil
}

func (buf *FileBuffer) Len() int64 {
	return buf.L
}

func (buf *FileBuffer) Cap() int64 {
	return buf.N
}

func (buf *FileBuffer) ReadAt(p []byte, off int64) (n int, err error) {
	wrap := NewWrapReader(buf.file, off, buf.Cap())
	r := io.NewSectionReader(wrap, 0, buf.Len()-off)
	return r.ReadAt(p, 0)
}

func (buf *FileBuffer) Read(p []byte) (n int, err error) {
	wrap := NewWrapReader(buf.file, buf.ROff, buf.Cap())
	r := io.LimitReader(wrap, buf.Len())

	n, err = r.Read(p)
	buf.L -= int64(n)
	buf.ROff = (buf.ROff + int64(n)) % buf.Cap()

	if Empty(buf) {
		buf.Reset()
	}

	return n, err
}

func (buf *FileBuffer) Write(p []byte) (n int, err error) {
	if err := buf.init(); err != nil {
		return 0, err
	}

	wrap := NewWrapWriter(buf.file, buf.WOff, buf.Cap())
	w := LimitWriter(wrap, Gap(buf))
	n, err = w.Write(p)
	buf.L += int64(n)
	buf.WOff = (buf.WOff + int64(n)) % buf.Cap()

	return n, err
}

func (buf *FileBuffer) Reset() {
	if buf.file != nil {
		buf.file.Close()
		os.Remove(buf.file.Name())
		buf.file = nil
		buf.Filename = ""
		buf.ROff = 0
		buf.WOff = 0
	}
}

func (buf *FileBuffer) FastForward(n int) int {
	if int64(n) > buf.Len() {
		n = int(buf.Len())
	}

	buf.L -= int64(n)
	buf.ROff = (buf.ROff + int64(n)) % buf.Cap()

	return n
}
{'fraction_non_alphanumeric': 0.1783337769496939, 'fraction_numerical': 0.020761245674740483, 'mean_word_length': 3.0365198711063375, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6654517', 'n_tokens_mistral': 1717, 'n_tokens_neox': 1598, 'n_words': 414}