github.com/tunabay/go-bitarray@v1.3.1/bitarray_search.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  import (
     8  	"bytes"
     9  )
    10  
    11  // HasPrefix reports whether the bit array starts with prefix.
    12  func (ba *BitArray) HasPrefix(prefix BitArrayer) bool {
    13  	var baPrefix *BitArray
    14  	if prefix != nil {
    15  		baPrefix = prefix.BitArray()
    16  	}
    17  	switch {
    18  	case baPrefix.IsZero():
    19  		return true
    20  	case ba.IsZero(), ba.nBits < baPrefix.nBits:
    21  		return false
    22  	case ba.b == nil:
    23  		return baPrefix.b == nil || allBytesZero(baPrefix.b)
    24  	}
    25  	if baPrefix.nBits < ba.nBits {
    26  		ba = ba.Slice(0, baPrefix.nBits)
    27  	}
    28  	switch {
    29  	case baPrefix.b == nil:
    30  		return ba.b == nil || allBytesZero(ba.b)
    31  	case ba.b == nil:
    32  		return allBytesZero(baPrefix.b)
    33  	}
    34  
    35  	return bytes.Equal(ba.b, baPrefix.b)
    36  }
    37  
    38  // HasSuffix reports whether the bit array ends with suffix.
    39  func (ba *BitArray) HasSuffix(suffix BitArrayer) bool {
    40  	var baSuffix *BitArray
    41  	if suffix != nil {
    42  		baSuffix = suffix.BitArray()
    43  	}
    44  	switch {
    45  	case baSuffix.IsZero():
    46  		return true
    47  	case ba.IsZero(), ba.nBits < baSuffix.nBits:
    48  		return false
    49  	case ba.b == nil:
    50  		return baSuffix.b == nil || allBytesZero(baSuffix.b)
    51  	}
    52  	if baSuffix.nBits < ba.nBits {
    53  		ba = ba.Slice(ba.nBits-baSuffix.nBits, ba.nBits)
    54  	}
    55  	switch {
    56  	case baSuffix.b == nil:
    57  		return ba.b == nil || allBytesZero(ba.b)
    58  	case ba.b == nil:
    59  		return allBytesZero(baSuffix.b)
    60  	}
    61  
    62  	return bytes.Equal(ba.b, baSuffix.b)
    63  }
    64  
    65  // Index returns the index of the first instance of x in the bit array ba, or -1
    66  // if x is not present in ba.
    67  func (ba *BitArray) Index(x BitArrayer) int {
    68  	var bax *BitArray
    69  	if x != nil {
    70  		bax = x.BitArray()
    71  	}
    72  	switch {
    73  	case ba.Len() < bax.Len():
    74  		return -1
    75  	case bax.IsZero():
    76  		return 0
    77  	case ba.b == nil && bax.b == nil:
    78  		return 0
    79  	}
    80  	ba8 := ba.bits8()
    81  	bax8 := bax.bits8()
    82  
    83  	return bytes.Index(ba8, bax8)
    84  }
    85  
    86  // LastIndex returns the index of the last instance of x in the bit array ba, or
    87  // -1 if x is not present in ba.
    88  func (ba *BitArray) LastIndex(x BitArrayer) int {
    89  	var bax *BitArray
    90  	if x != nil {
    91  		bax = x.BitArray()
    92  	}
    93  	switch {
    94  	case ba.Len() < bax.Len():
    95  		return -1
    96  	case bax.IsZero():
    97  		return ba.Len()
    98  	case ba.b == nil && bax.b == nil:
    99  		return ba.nBits - bax.nBits
   100  	}
   101  	ba8 := ba.bits8()
   102  	bax8 := bax.bits8()
   103  
   104  	return bytes.LastIndex(ba8, bax8)
   105  }
   106  
   107  // AllIndex returns the indexes of the all instance of x in the bit array ba, or
   108  // empty slice if x is not present in ba.
   109  func (ba *BitArray) AllIndex(x BitArrayer) []int {
   110  	var bax *BitArray
   111  	if x != nil {
   112  		bax = x.BitArray()
   113  	}
   114  	switch {
   115  	case ba.Len() < bax.Len():
   116  		return []int{}
   117  	case bax.IsZero():
   118  		idxs := make([]int, ba.Len()+1)
   119  		for i := range idxs {
   120  			idxs[i] = i
   121  		}
   122  		return idxs
   123  	case ba.b == nil && bax.b == nil:
   124  		idxs := make([]int, ba.nBits-bax.nBits+1)
   125  		for i := range idxs {
   126  			idxs[i] = i
   127  		}
   128  		return idxs
   129  	}
   130  	ba8 := ba.bits8()
   131  	bax8 := bax.bits8()
   132  	var idxs []int
   133  	i := 0
   134  	for i < ba.nBits-bax.nBits+1 {
   135  		idx := bytes.Index(ba8[i:], bax8)
   136  		if idx < 0 {
   137  			break
   138  		}
   139  		idx += i
   140  		idxs = append(idxs, idx)
   141  		i = idx + 1
   142  	}
   143  	return idxs
   144  }