github.com/tunabay/go-bitarray@v1.3.1/bitarray_slice.go (about) 1 // Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved. 2 // Use of this source code is governed by the MIT license that can be found in 3 // the LICENSE file. 4 5 package bitarray 6 7 // Slice returns a new BitArray extracted as a subpart from the bit array in 8 // the same manner as Go's native slices. The two arguments start and end 9 // specify the indexes of the bits to select. 0 points to the first bit and 10 // ba.Len()-1 points to the last bit. The start and end select a half-open 11 // range which includes the start, but excludes the end. If the index is 12 // outside the range of the bit array, Slice will panic. 13 func (ba *BitArray) Slice(start, end int) *BitArray { 14 switch { 15 case start < 0, ba.Len() < start: 16 panicf("Slice: start %d out of range: 0..%d.", start, ba.Len()) 17 case end < 0, ba.Len() < end: 18 panicf("Slice: end %d out of range: 0..%d.", end, ba.Len()) 19 case end < start: 20 panicf("Slice: invalid range start=%d > end=%d.", start, end) 21 } 22 nBits := end - start 23 switch { 24 case nBits == 0: 25 return zeroBitArray 26 case start == 0 && end == ba.nBits: 27 return ba 28 case ba.b == nil: 29 return &BitArray{nBits: nBits} 30 case start == 0 && ba.hasTrailingZeros(ba.nBits-end): 31 return &BitArray{b: ba.b[:(end+7)>>3], nBits: nBits} 32 } 33 buf := allocByteSlice((nBits + 7) >> 3) 34 if copyBits(buf, ba.b, 0, start, nBits) { 35 return &BitArray{nBits: nBits} 36 } 37 38 return &BitArray{b: buf, nBits: nBits} 39 } 40 41 // SliceToEnd is shorthand for Slice(start, ba.Len()) and returns the subpart 42 // from the position specified start to the last bit. 43 func (ba *BitArray) SliceToEnd(start int) *BitArray { return ba.Slice(start, ba.Len()) } 44 45 // ToWidth returns a new BitArray resized to wid bits with its contents 46 // preserved. If wid is less than ba.Len(), some bits will be lost. If wid is 47 // greater than be.Len(), the expanded space will be filled with 0s. In both 48 // cases, the MSBs or LSBs are fixed according to the specified align. 49 func (ba *BitArray) ToWidth(wid int, align Alignment) *BitArray { 50 switch { 51 case wid < 0: 52 panicf("ToWidth: negative wid %d.", wid) 53 case wid == 0: 54 return zeroBitArray 55 case ba.IsZero(), ba.b == nil: 56 return &BitArray{nBits: wid} 57 case wid == ba.nBits: 58 return ba 59 case wid < ba.nBits: 60 if align == AlignLeft { 61 return ba.Slice(0, wid) 62 } 63 return ba.Slice(ba.nBits-wid, ba.nBits) 64 } 65 add := &BitArray{nBits: wid - ba.nBits} 66 if align == AlignLeft { 67 return ba.append1(add) 68 } 69 return add.append1(ba) 70 } 71 72 // TrimPrefix returns a new BitArray with the leading prefix removed. If the bit 73 // array does not start with prefix, ba itself is returned unchanged. 74 func (ba *BitArray) TrimPrefix(prefix BitArrayer) *BitArray { 75 var baPrefix *BitArray 76 if prefix != nil { 77 baPrefix = prefix.BitArray() 78 } 79 switch { 80 case ba.IsZero(): 81 return zeroBitArray 82 case !ba.HasPrefix(baPrefix), baPrefix.IsZero(): 83 return ba 84 } 85 86 return ba.Slice(baPrefix.nBits, ba.nBits) 87 } 88 89 // TrimSuffix returns a new BitArray with the trailing suffix removed. If the 90 // bit array does not end with prefix, ba itself is returned unchanged. 91 func (ba *BitArray) TrimSuffix(suffix BitArrayer) *BitArray { 92 var baSuffix *BitArray 93 if suffix != nil { 94 baSuffix = suffix.BitArray() 95 } 96 switch { 97 case ba.IsZero(): 98 return zeroBitArray 99 case !ba.HasSuffix(baSuffix), baSuffix.IsZero(): 100 return ba 101 } 102 103 return ba.Slice(0, ba.nBits-baSuffix.nBits) 104 } 105 106 // TrimLeadingZeros returns a new BitArray with the leading zeros removed. 107 func (ba *BitArray) TrimLeadingZeros() *BitArray { 108 if ba.IsZero() || ba.b == nil { 109 return zeroBitArray 110 } 111 112 return ba.Slice(ba.LeadingZeros(), ba.nBits) 113 } 114 115 // TrimTrailingZeros returns a new BitArray with the trailing zeros removed. 116 func (ba *BitArray) TrimTrailingZeros() *BitArray { 117 if ba.IsZero() || ba.b == nil { 118 return zeroBitArray 119 } 120 121 return ba.Slice(0, ba.nBits-ba.TrailingZeros()) 122 }