gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

read.go (1751B)


      1 package bitio
      2 
      3 import "io"
      4 
      5 type Reader interface {
      6 	io.Reader
      7 
      8 	// alignment:
      9 	//  |-1-byte-block-|--------------|--------------|--------------|
     10 	//  |<-offset->|<-------------------width---------------------->|
     11 	ReadBits(width uint) (data []byte, err error)
     12 
     13 	ReadBit() (bit bool, err error)
     14 }
     15 
     16 type ReadSeeker interface {
     17 	Reader
     18 	io.Seeker
     19 }
     20 
     21 type reader struct {
     22 	reader io.Reader
     23 	octet  byte
     24 	width  uint
     25 }
     26 
     27 func NewReader(r io.Reader) Reader {
     28 	return &reader{reader: r}
     29 }
     30 
     31 func (r *reader) Read(p []byte) (n int, err error) {
     32 	if r.width != 0 {
     33 		return 0, ErrInvalidAlignment
     34 	}
     35 	return r.reader.Read(p)
     36 }
     37 
     38 func (r *reader) ReadBits(size uint) ([]byte, error) {
     39 	bytes := (size + 7) / 8
     40 	data := make([]byte, bytes)
     41 	offset := (bytes * 8) - (size)
     42 
     43 	for i := uint(0); i < size; i++ {
     44 		bit, err := r.ReadBit()
     45 		if err != nil {
     46 			return nil, err
     47 		}
     48 
     49 		byteIdx := (offset + i) / 8
     50 		bitIdx := 7 - (offset+i)%8
     51 		if bit {
     52 			data[byteIdx] |= 0x1 << bitIdx
     53 		}
     54 	}
     55 
     56 	return data, nil
     57 }
     58 
     59 func (r *reader) ReadBit() (bool, error) {
     60 	if r.width == 0 {
     61 		buf := make([]byte, 1)
     62 		if n, err := r.reader.Read(buf); err != nil {
     63 			return false, err
     64 		} else if n != 1 {
     65 			return false, ErrDiscouragedReader
     66 		}
     67 		r.octet = buf[0]
     68 		r.width = 8
     69 	}
     70 
     71 	r.width--
     72 	return (r.octet>>r.width)&0x01 != 0, nil
     73 }
     74 
     75 type readSeeker struct {
     76 	reader
     77 	seeker io.Seeker
     78 }
     79 
     80 func NewReadSeeker(r io.ReadSeeker) ReadSeeker {
     81 	return &readSeeker{
     82 		reader: reader{reader: r},
     83 		seeker: r,
     84 	}
     85 }
     86 
     87 func (r *readSeeker) Seek(offset int64, whence int) (int64, error) {
     88 	if whence == io.SeekCurrent && r.reader.width != 0 {
     89 		return 0, ErrInvalidAlignment
     90 	}
     91 	n, err := r.seeker.Seek(offset, whence)
     92 	if err != nil {
     93 		return n, err
     94 	}
     95 	r.reader.width = 0
     96 	return n, nil
     97 }