
FIXED: * More clear docs for bitmask * Resolved potential issue for using PriorityAll in logging.logPrio.HasFlag.
172 lines
3.6 KiB
Go
172 lines
3.6 KiB
Go
package bitmask
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"math/bits"
|
|
)
|
|
|
|
// MaskBit is a flag container.
|
|
type MaskBit uint
|
|
|
|
/*
|
|
NewMaskBit is a convenience function.
|
|
It will return a MaskBit with a (referenced) value of 0, so set your consts up accordingly.
|
|
|
|
It is highly recommended to set this default as a "None" flag (separate from your iotas!)
|
|
as shown in the example.
|
|
*/
|
|
func NewMaskBit() (m *MaskBit) {
|
|
|
|
m = new(MaskBit)
|
|
|
|
return
|
|
}
|
|
|
|
// NewMaskBitExplicit is like NewMaskBit, but allows you to specify a non-zero (0x0) value.
|
|
func NewMaskBitExplicit(value uint) (m *MaskBit) {
|
|
|
|
var v MaskBit = MaskBit(value)
|
|
|
|
m = &v
|
|
|
|
return
|
|
}
|
|
|
|
/*
|
|
HasFlag is true if m has MaskBit flag set/enabled.
|
|
|
|
THIS WILL RETURN FALSE FOR OR'd FLAGS.
|
|
|
|
For example:
|
|
|
|
flagA MaskBit = 0x01
|
|
flagB MaskBit = 0x02
|
|
flagComposite = flagA | flagB
|
|
|
|
m *MaskBit = NewMaskBitExplicit(uint(flagA))
|
|
|
|
m.HasFlag(flagComposite) will return false even though flagComposite is an OR
|
|
that contains flagA.
|
|
Use [MaskBit.IsOneOf] instead if you do not desire this behavior,
|
|
and instead want to test composite flag *membership*.
|
|
(MaskBit.IsOneOf will also return true for non-composite equality.)
|
|
|
|
To be more clear, if MaskBit flag is a composite MaskBit (e.g. flagComposite above),
|
|
HasFlag will only return true of ALL bits in flag are also set in MaskBit m.
|
|
*/
|
|
func (m *MaskBit) HasFlag(flag MaskBit) (r bool) {
|
|
|
|
var b MaskBit = *m
|
|
|
|
if b&flag == flag {
|
|
r = true
|
|
}
|
|
return
|
|
}
|
|
|
|
/*
|
|
IsOneOf is like a "looser" form of [MaskBit.HasFlag]
|
|
in that it allows for testing composite membership.
|
|
|
|
See [MaskBit.HasFlag] for more information.
|
|
|
|
If composite is *not* an OR'd MaskBit (i.e.
|
|
it falls directly on a boundary -- 0, 1, 2, 4, 8, 16, etc.),
|
|
then IsOneOf will behave exactly like HasFlag.
|
|
|
|
If m is a composite MaskBit (it usually is) and composite is ALSO a composite MaskBit,
|
|
IsOneOf will return true if ANY of the flags set in m is set in composite.
|
|
*/
|
|
func (m *MaskBit) IsOneOf(composite MaskBit) (r bool) {
|
|
|
|
var b MaskBit = *m
|
|
|
|
if b&composite != 0 {
|
|
r = true
|
|
}
|
|
return
|
|
}
|
|
|
|
// AddFlag adds MaskBit flag to m.
|
|
func (m *MaskBit) AddFlag(flag MaskBit) {
|
|
|
|
*m |= flag
|
|
|
|
return
|
|
}
|
|
|
|
// ClearFlag removes MaskBit flag from m.
|
|
func (m *MaskBit) ClearFlag(flag MaskBit) {
|
|
|
|
*m &^= flag
|
|
|
|
return
|
|
}
|
|
|
|
// ToggleFlag switches MaskBit flag in m to its inverse; if true, it is now false and vice versa.
|
|
func (m *MaskBit) ToggleFlag(flag MaskBit) {
|
|
|
|
*m ^= flag
|
|
|
|
return
|
|
}
|
|
|
|
/*
|
|
Bytes returns the current value of a MasBit as a byte slice (big-endian).
|
|
|
|
If trim is false, b will (probably) be 4 bytes long if you're on a 32-bit size system,
|
|
and b will (probably) be 8 bytes long if you're on a 64-bit size system. You can determine
|
|
the size of the resulting slice via (math/)bits.UintSize / 8.
|
|
|
|
If trim is true, it will trim leading null bytes (if any). This will lead to an unpredictable
|
|
byte slice length in b, but is most likely preferred for byte operations.
|
|
|
|
*/
|
|
func (m *MaskBit) Bytes(trim bool) (b []byte) {
|
|
|
|
var b2 []byte
|
|
var size int = bits.UintSize / 8
|
|
var err error
|
|
|
|
b2 = make([]byte, size)
|
|
|
|
switch s := bits.UintSize; s {
|
|
case 32:
|
|
binary.BigEndian.PutUint32(b2[:], uint32(*m))
|
|
case 64:
|
|
binary.BigEndian.PutUint64(b2[:], uint64(*m))
|
|
default:
|
|
err = errors.New("unsupported Uint/system bit size")
|
|
panic(err)
|
|
}
|
|
|
|
if trim {
|
|
b = bytes.TrimLeft(b2, "\x00")
|
|
return
|
|
} else {
|
|
b = b2
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// Copy returns a pointer to a (new) copy of a MaskBit.
|
|
func (m *MaskBit) Copy() (newM *MaskBit) {
|
|
|
|
newM = new(MaskBit)
|
|
*newM = *m
|
|
|
|
return
|
|
}
|
|
|
|
// Value returns the current raw uint value of a MaskBit.
|
|
func (m *MaskBit) Value() (v uint) {
|
|
|
|
v = uint(*m)
|
|
|
|
return
|
|
}
|