Skip to content

Instantly share code, notes, and snippets.

@ericlagergren
Created May 12, 2015 04:15
Show Gist options
  • Save ericlagergren/2ce4e0ef82871d513aa2 to your computer and use it in GitHub Desktop.
Save ericlagergren/2ce4e0ef82871d513aa2 to your computer and use it in GitHub Desktop.
Simple fgetc implementation in Go
package main
import (
"fmt"
"os"
"syscall"
)
type File struct {
file *os.File
buf []byte
off int
end int
flags int
}
func main() {
file, err := Open("idk.c")
if err != nil {
panic(err)
}
defer file.Close()
var c byte
for {
c, err = file.FGetC()
if err != nil {
break
}
fmt.Printf("%c", c)
}
}
func Open(name string) (*File, error) {
file, err := os.Open(name)
if err != nil {
return nil, err
}
buf, err := syscall.Mmap(-1, 0, syscall.Getpagesize(),
syscall.PROT_READ|syscall.PROT_WRITE,
syscall.MAP_PRIVATE|syscall.MAP_ANONYMOUS)
if err != nil {
file.Close()
return nil, err
}
return &File{file, buf, 0, 0, 0}, nil
}
func (f *File) Close() error {
err := syscall.Munmap(f.buf)
if err != nil {
return err
}
return f.file.Close()
}
func (f *File) Read() (int, error) {
f.off = -1
n, err := f.file.Read(f.buf[0:])
f.end = n
return n, err
}
// Returns one byte from the file.
func (f *File) FGetC() (byte, error) {
// (re)fill our buffer if needed.
if f.off >= f.end {
_, err := f.Read()
if err != nil {
return 0, err
}
}
f.off++
return f.buf[f.off], nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment