github.com/mitghi/x@v0.0.0-20191206171256-71e86edf750d/bit/bitset.go (about)

     1  /* MIT License
     2  *
     3  * Copyright (c) 2018 Mike Taghavi <mitghi[at]gmail.com>
     4  *
     5  * Permission is hereby granted, free of charge, to any person obtaining a copy
     6  * of this software and associated documentation files (the "Software"), to deal
     7  * in the Software without restriction, including without limitation the rights
     8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     9  * copies of the Software, and to permit persons to whom the Software is
    10  * furnished to do so, subject to the following conditions:
    11  * The above copyright notice and this permission notice shall be included in all
    12  * copies or substantial portions of the Software.
    13  *
    14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20  * SOFTWARE.
    21   */
    22  
    23  package bit
    24  
    25  import (
    26  	"errors"
    27  	"fmt"
    28  )
    29  
    30  // Constants
    31  const (
    32  	// word size
    33  	cWSIZE int = 8
    34  )
    35  
    36  // Error messages
    37  var (
    38  	IndexError error = errors.New("BitArray: index out of range")
    39  )
    40  
    41  type BitArray struct {
    42  	bits []uint8
    43  	size uint64
    44  }
    45  
    46  func NewBitArray(n uint64) (ba *BitArray) {
    47  	ba = &BitArray{
    48  		size: RoundNextP2(n),
    49  	}
    50  	ba.bits = make([]uint8, ba.size/uint64(cWSIZE))
    51  	return ba
    52  }
    53  
    54  func (ba *BitArray) Set(bit int) error {
    55  	var (
    56  		mask uint8 // bit mask
    57  		slot int   // index in slice
    58  		item uint8 // bit from slice
    59  	)
    60  	if uint64(bit) > ba.size {
    61  		goto ERROR
    62  	}
    63  	bit -= 1
    64  	mask, slot, item = ba.access(bit)
    65  	item |= mask
    66  	ba.bits[slot] = item
    67  	return nil
    68  ERROR:
    69  	return IndexError
    70  }
    71  
    72  func (ba *BitArray) Flip(bit int) error {
    73  	var (
    74  		mask uint8 // bit mask
    75  		slot int   // index in slice
    76  		item uint8 // bit from slice
    77  	)
    78  	if uint64(bit) > ba.size {
    79  		goto ERROR
    80  	}
    81  	bit -= 1
    82  	mask, slot, item = ba.access(bit)
    83  	ba.bits[slot] = ^((^item & 0xFF) ^ mask)
    84  	return nil
    85  ERROR:
    86  	return IndexError
    87  }
    88  
    89  func (ba *BitArray) Get(bit int) (uint8, error) {
    90  	var (
    91  		mask uint8 // bit mask
    92  		item uint8 // bit from slice
    93  	)
    94  	if uint64(bit) > ba.size {
    95  		goto ERROR
    96  	}
    97  	bit -= 1
    98  	mask, _, item = ba.access(bit)
    99  	return (item & mask), nil
   100  ERROR:
   101  	return 0x0, IndexError
   102  }
   103  
   104  func (ba *BitArray) IsSet(bit int) (ok bool, err error) {
   105  	var (
   106  		value uint8 // bit value
   107  	)
   108  	value, err = ba.Get(bit)
   109  	if err != nil {
   110  		return false, err
   111  	}
   112  	return value != 0, nil
   113  }
   114  
   115  func (ba *BitArray) access(bit int) (uint8, int, uint8) {
   116  	var (
   117  		mask uint8 // bit mask
   118  		slot int   // index in slice
   119  		item uint8 // bit from slice
   120  	)
   121  	mask = 0x1 << uint8(bit%cWSIZE)
   122  	slot = ba.findslot(bit)
   123  	fmt.Println("access", bit, mask, slot, item)
   124  	item = ba.bits[slot]
   125  	return mask, slot, item
   126  }
   127  
   128  func (ba *BitArray) findslot(n int) int {
   129  	return ((n + cWSIZE - (n % cWSIZE)) / cWSIZE) - 1
   130  }