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  }