@@ -12,11 +12,11 @@ import (
1212// and writing with an offset. It is not safe for concurrent use by multiple
1313// goroutines. The zero value for Buffer represents a zero length buffer that
1414// can be resized and used.
15- type Buffer BitArray
16-
17- // Buffer fields:
18- // .b []byte // nil only for zero length
19- // .nBits int
15+ type Buffer struct {
16+ b [] byte // nil only for zero length
17+ nBits int
18+ off int
19+ }
2020
2121// NewBuffer creates a Buffer with the specified bit length.
2222func NewBuffer (nBits int ) * Buffer {
@@ -47,6 +47,33 @@ func NewBufferFromBitArray(ba BitArrayer) *Buffer {
4747 return buf
4848}
4949
50+ // NewBufferFromByteSlice creates a new Buffer that references an existing byte
51+ // slice b. The created Buffer references b without copying it, therefore,
52+ // changes to the buffer affect b and vice versa. The length of the buffer
53+ // created will be len(b) * 8. NewBufferFromByteSlice is useful when reading or
54+ // writing a subpart of a byte slice as a bit array without copying or
55+ // bit-shifting.
56+ func NewBufferFromByteSlice (b []byte ) * Buffer {
57+ return NewBufferFromByteSlicePartial (b , 0 , len (b )<< 3 )
58+ }
59+
60+ // NewBufferFromByteSlicePartial is identical to NewBufferFromByteSlice except
61+ // that it creates a buffer with the first bit specified by off, and the length
62+ // specified by nBits.
63+ func NewBufferFromByteSlicePartial (b []byte , off , nBits int ) * Buffer {
64+ switch {
65+ case off < 0 :
66+ panicf ("NewBufferFromByteSlice: negative off %d." , nBits )
67+ case nBits < 0 :
68+ panicf ("NewBufferFromByteSlice: negative nBits %d." , nBits )
69+ case len (b )<< 3 < off + nBits :
70+ panicf ("NewBufferFromByteSlice: out of range: off=%d, nBits=%d > len=%d." , off , nBits , len (b ))
71+ case nBits == 0 :
72+ return & Buffer {}
73+ }
74+ return & Buffer {b : b [off >> 3 :], nBits : nBits , off : off & 7 }
75+ }
76+
5077// IsZero returns whether the Buffer is zero length.
5178func (buf * Buffer ) IsZero () bool {
5279 return buf .Len () == 0
@@ -65,22 +92,22 @@ func (buf *Buffer) Clone() *Buffer {
6592 if buf .Len () == 0 {
6693 return & Buffer {}
6794 }
68- b := allocByteSlice (len (buf .b ) )
69- copy (b , buf .b )
95+ b := allocByteSlice ((buf .nBits + 7 ) >> 3 )
96+ copyBits (b , buf .b , 0 , buf . off , buf . nBits )
7097
7198 return & Buffer {b : b , nBits : buf .nBits }
7299}
73100
74101// BitArray creates an imuurable BitArray from the current content.
75102func (buf * Buffer ) BitArray () * BitArray {
76- return NewFromBytes (buf .b , 0 , buf .nBits )
103+ return NewFromBytes (buf .b , buf . off , buf .nBits )
77104}
78105
79106// String returns the string representation of the current content.
80107func (buf Buffer ) String () string {
81108 sb := make ([]byte , buf .nBits )
82109 for i := 0 ; i < buf .nBits ; i ++ {
83- sb [i ] = '0' + buf .b [i >> 3 ]>> (7 - i & 7 )& 1
110+ sb [i ] = '0' + buf .b [( buf . off + i ) >> 3 ]>> (7 - ( buf . off + i ) & 7 )& 1
84111 }
85112 return string (sb )
86113}
@@ -89,71 +116,51 @@ func (buf Buffer) String() string {
89116// bits in the new range to be extended are initialized with 0. When shrinking,
90117// the extra bits are truncated. In either case, the align specifies whether to
91118// fix the MSBs or the LSBs.
119+ //
120+ // Resize always reallocates internal memory. That is, the buffers created by
121+ // Slice method or NewBufferFromByteSlice break their relationship with the
122+ // parent buffer or slice by calling this Resize, even if nBits is equivalent to
123+ // or less than its current size.
92124func (buf * Buffer ) Resize (nBits int , align Alignment ) {
93125 switch {
94126 case nBits < 0 :
95127 panicf ("Resize: negative nBits %d." , nBits )
96- case nBits == buf .nBits :
97- return
98128 case nBits == 0 :
99129 buf .b = nil
100130 buf .nBits = 0
131+ buf .off = 0
101132 return
102133 }
103- nBytes := (nBits + 7 ) >> 3
104134
105- // AlignLeft
106- if align == AlignLeft {
107- // shrink
108- if nBits < buf .nBits {
109- buf .b = buf .b [:nBytes ]
110- if nBits & 7 != 0 {
111- buf .b [nBits >> 3 ] &= 0xff << (8 - nBits & 7 )
112- }
113- buf .nBits = nBits
114- return
115- }
116-
117- // extend
118- if nBytes <= cap (buf .b ) { // enough cap
119- n := len (buf .b )
120- buf .b = buf .b [:nBytes ]
121- for ; n < nBytes ; n ++ {
122- buf .b [n ] = 0
123- }
124- buf .nBits = nBits
125- return
126- }
127-
128- newb := allocByteSlice (nBytes )
129- copy (newb , buf .b )
130- buf .b = newb
135+ b := allocByteSlice ((nBits + 7 ) >> 3 )
136+ if buf .nBits == 0 {
137+ buf .b = b
131138 buf .nBits = nBits
139+ buf .off = 0
132140 return
133141 }
134-
135- // AlignRight
136- // shrink
137- if nBits < buf .nBits {
138- if nBits & 7 == buf .nBits & 7 { // no shift
139- buf .b = buf .b [len (buf .b )- nBytes :]
140- buf .nBits = nBits
141- return
142+ if align == AlignLeft {
143+ if nBits < buf .nBits { // shrink
144+ copyBits (b , buf .b , 0 , buf .off , nBits )
145+ } else { // extend
146+ copyBits (b , buf .b , 0 , buf .off , buf .nBits )
147+ }
148+ } else {
149+ if nBits < buf .nBits { // shrink
150+ copyBits (b , buf .b , 0 , buf .off + buf .nBits - nBits , nBits )
151+ } else { // extend
152+ copyBits (b , buf .b , nBits - buf .nBits , buf .off , buf .nBits )
142153 }
143- newb := allocByteSlice (nBytes )
144- _ = copyBits (newb , buf .b , 0 , buf .nBits - nBits , nBits )
145- buf .b = newb
146- buf .nBits = nBits
147- return
148154 }
149155
150- // extend
151- newb := allocByteSlice (nBytes )
152- if buf .b != nil {
153- _ = copyBits (newb , buf .b , nBits - buf .nBits , 0 , buf .nBits )
154- }
155- buf .b = newb
156+ buf .b = b
156157 buf .nBits = nBits
158+ buf .off = 0
159+ }
160+
161+ // FillBits sets all the bits in the buffer to the value bit, 0 or 1.
162+ func (buf * Buffer ) FillBits (bit byte ) {
163+ buf .FillBitsAt (0 , buf .nBits , bit )
157164}
158165
159166// FillBitsAt sets the nBits bits starting at off to the value bit.
@@ -166,12 +173,12 @@ func (buf *Buffer) FillBitsAt(off, nBits int, bit byte) {
166173 case buf .nBits < off + nBits :
167174 panicf ("FillBitsAt: out of range: off=%d + nBits=%d > len=%d." , off , nBits , buf .nBits )
168175 case bit & 1 == 0 :
169- clearBits (buf .b , off , nBits )
176+ clearBits (buf .b , buf . off + off , nBits )
170177 default :
171- setBits (buf .b , off , nBits )
178+ setBits (buf .b , buf . off + off , nBits )
172179 }
173180}
174181
175182// Format implements the fmt.Formatter interface to format Buffer value using
176183// the standard fmt.Printf family functions.
177- func (buf Buffer ) Format (s fmt.State , verb rune ) { BitArray (buf ).Format (s , verb ) }
184+ func (buf Buffer ) Format (s fmt.State , verb rune ) { buf . BitArray ().Format (s , verb ) }
0 commit comments