package ncurses import ( "os" "sync/atomic" ) func bitmatch(b byte, pattern byte, length int) bool { mask := ^(byte(1 << (8 - length)) - 1) return (b ^ pattern) & mask == 0 } func UTF8Listen(file *os.File, channel chan []byte, active *atomic.Bool) { b := [4]byte{} for active.Load() { out := make([]byte, 4) file.Read(b[0:1]) if bitmatch(b[0], 0b00000000, 1) { copy(out, b[0:1]) channel <- out[0:1] } else if bitmatch(b[0], 0b11000000, 3) { file.Read(b[1:2]) copy(out, b[0:2]) channel <- out[0:2] } else if bitmatch(b[0], 0b11100000, 4) { file.Read(b[1:3]) copy(out, b[0:3]) channel <- out[0:3] } else if bitmatch(b[0], 0b11110000, 5) { file.Read(b[1:4]) copy(out, b[0:4]) channel <- out[0:4] } } } // To cleanup, set active to false then close the channel func UTF8Listener(buffer int, file *os.File) (chan []byte, *atomic.Bool) { channel := make(chan []byte, buffer) active := new(atomic.Bool) active.Store(true) go UTF8Listen(file, channel, active) return channel, active }