gtsocial-umbx

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

writer.go (2390B)


      1 // Copyright 2019 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package ccitt
      6 
      7 import (
      8 	"encoding/binary"
      9 	"io"
     10 )
     11 
     12 type bitWriter struct {
     13 	w io.Writer
     14 
     15 	// order is whether to process w's bytes LSB first or MSB first.
     16 	order Order
     17 
     18 	// The high nBits bits of the bits field hold encoded bits to be written to w.
     19 	bits  uint64
     20 	nBits uint32
     21 
     22 	// bytes[:bw] holds encoded bytes not yet written to w.
     23 	// Overflow protection is ensured by using a multiple of 8 as bytes length.
     24 	bw    uint32
     25 	bytes [1024]uint8
     26 }
     27 
     28 // flushBits copies 64 bits from b.bits to b.bytes. If b.bytes is then full, it
     29 // is written to b.w.
     30 func (b *bitWriter) flushBits() error {
     31 	binary.BigEndian.PutUint64(b.bytes[b.bw:], b.bits)
     32 	b.bits = 0
     33 	b.nBits = 0
     34 	b.bw += 8
     35 	if b.bw < uint32(len(b.bytes)) {
     36 		return nil
     37 	}
     38 	b.bw = 0
     39 	if b.order != MSB {
     40 		reverseBitsWithinBytes(b.bytes[:])
     41 	}
     42 	_, err := b.w.Write(b.bytes[:])
     43 	return err
     44 }
     45 
     46 // close finalizes a bitcode stream by writing any
     47 // pending bits to bitWriter's underlying io.Writer.
     48 func (b *bitWriter) close() error {
     49 	// Write any encoded bits to bytes.
     50 	if b.nBits > 0 {
     51 		binary.BigEndian.PutUint64(b.bytes[b.bw:], b.bits)
     52 		b.bw += (b.nBits + 7) >> 3
     53 	}
     54 
     55 	if b.order != MSB {
     56 		reverseBitsWithinBytes(b.bytes[:b.bw])
     57 	}
     58 
     59 	// Write b.bw bytes to b.w.
     60 	_, err := b.w.Write(b.bytes[:b.bw])
     61 	return err
     62 }
     63 
     64 // alignToByteBoundary rounds b.nBits up to a multiple of 8.
     65 // If all 64 bits are used, flush them to bitWriter's bytes.
     66 func (b *bitWriter) alignToByteBoundary() error {
     67 	if b.nBits = (b.nBits + 7) &^ 7; b.nBits == 64 {
     68 		return b.flushBits()
     69 	}
     70 	return nil
     71 }
     72 
     73 // writeCode writes a variable length bitcode to b's underlying io.Writer.
     74 func (b *bitWriter) writeCode(bs bitString) error {
     75 	bits := bs.bits
     76 	nBits := bs.nBits
     77 	if 64-b.nBits >= nBits {
     78 		// b.bits has sufficient room for storing nBits bits.
     79 		b.bits |= uint64(bits) << (64 - nBits - b.nBits)
     80 		b.nBits += nBits
     81 		if b.nBits == 64 {
     82 			return b.flushBits()
     83 		}
     84 		return nil
     85 	}
     86 
     87 	// Number of leading bits that fill b.bits.
     88 	i := 64 - b.nBits
     89 
     90 	// Fill b.bits then flush and write remaining bits.
     91 	b.bits |= uint64(bits) >> (nBits - i)
     92 	b.nBits = 64
     93 
     94 	if err := b.flushBits(); err != nil {
     95 		return err
     96 	}
     97 
     98 	nBits -= i
     99 	b.bits = uint64(bits) << (64 - nBits)
    100 	b.nBits = nBits
    101 	return nil
    102 }