4 Commits

Author SHA1 Message Date
94145fb4c7 Add NullLogger to MultiLogger. 2022-03-13 13:34:24 -04:00
81a2d308f0 Add NullLogger.
For when you need a Logger but don't want one. ;)
2022-03-13 13:29:31 -04:00
c4b3c6441a adding Bytes() to MaskBit 2022-02-01 18:27:45 -05:00
1c5abd4083 modifying bitmask to allow specifying an explicit value, and changing to uint instead of uint8 2022-02-01 15:36:56 -05:00
6 changed files with 237 additions and 54 deletions

118
bitmask/bitmask.go Normal file
View File

@@ -0,0 +1,118 @@
package bitmask
import (
"bytes"
"errors"
"encoding/binary"
"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.
func (m *MaskBit) HasFlag(flag MaskBit) (r bool) {
var b MaskBit = *m
if b&flag != 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
}
// Value returns the current raw uint value of a MaskBit.
func (m *MaskBit) Value() (v uint) {
v = uint(*m)
return
}

View File

@@ -1,46 +0,0 @@
package bitmask
// MaskBit is a flag container.
type MaskBit uint8
/*
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
}
// HasFlag is true if m has MaskBit flag set/enabled.
func (m *MaskBit) HasFlag(flag MaskBit) (r bool) {
var b MaskBit = *m
if b&flag != 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
}

View File

@@ -11,18 +11,18 @@ To use this, set constants like thus:
"r00t2.io/goutils/bitmask"
)
const OPTNONE types.MaskBit = 0
const OPTNONE bitmask.MaskBit = 0
const (
OPT1 types.MaskBit = 1 << iota
OPT1 bitmask.MaskBit = 1 << iota
OPT2
OPT3
// ...
)
var MyMask *MaskBit
var MyMask *bitmask.MaskBit
func main() {
MyMask = types.NewMaskBit
MyMask = bitmask.NewMaskBit()
MyMask.AddFlag(OPT1)
MyMask.AddFlag(OPT3)
@@ -41,5 +41,13 @@ As would this:
But this would return false:
MyMask.HasFlag(OPT2)
If you need something with more flexibility (as always, at the cost of complexity),
you may be interested in one of the following libraries:
. github.com/alvaroloes/enumer
. github.com/abice/go-enum
. github.com/jeffreyrichter/enum/enum
*/
package bitmask

View File

@@ -1,10 +1,10 @@
package logging
import (
`path`
"path"
`github.com/google/uuid`
`r00t2.io/sysutils/paths`
"github.com/google/uuid"
"r00t2.io/sysutils/paths"
)
/*
@@ -145,6 +145,40 @@ func (m *MultiLogger) AddFileLogger(identifier string, logFlags int, logfilePath
return
}
/*
AddNullLogger adds a NullLogger to a MultiLogger.
identifier is a string to use to identify the added NullLogger in MultiLogger.Loggers.
If empty, one will be automatically generated.
*/
func (m *MultiLogger) AddNullLogger(identifier string) (err error) {
var exists bool
var prefix string
if identifier == "" {
identifier = uuid.New().String()
}
if _, exists = m.Loggers[identifier]; exists {
err = ErrExistingLogger
return
}
m.Loggers[identifier] = &NullLogger{}
if err = m.Loggers[identifier].Setup(); err != nil {
return
}
if prefix, err = m.Loggers[identifier].GetPrefix(); err != nil {
return
}
m.Loggers[identifier].Debug("logger initialized of type %T with prefix %v", m.Loggers[identifier], prefix)
return
}
// RemoveLogger will let you remove a Logger from MultiLogger.Loggers.
func (m *MultiLogger) RemoveLogger(identifier string) (err error) {

View File

@@ -0,0 +1,66 @@
package logging
// Setup does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) Setup() (err error) {
return
}
// DoDebug does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) DoDebug(d bool) (err error) {
return
}
// SetPrefix does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) SetPrefix(p string) (err error) {
return
}
// GetPrefix does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) GetPrefix() (p string, err error) {
return
}
// Shutdown does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) Shutdown() (err error) {
return
}
// Alert does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) Alert(s string, v ...interface{}) (err error) {
return
}
// Crit does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) Crit(s string, v ...interface{}) (err error) {
return
}
// Debug does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) Debug(s string, v ...interface{}) (err error) {
return
}
// Emerg does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) Emerg(s string, v ...interface{}) (err error) {
return
}
// Err does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) Err(s string, v ...interface{}) (err error) {
return
}
// Info does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) Info(s string, v ...interface{}) (err error) {
return
}
// Notice does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) Notice(s string, v ...interface{}) (err error) {
return
}
// Warning does nothing at all; it's here for interface compat. 🙃
func (l *NullLogger) Warning(s string, v ...interface{}) (err error) {
return
}

View File

@@ -2,7 +2,7 @@ package logging
import (
"log"
`os`
"os"
)
/*
@@ -86,6 +86,9 @@ type FileLogger struct {
writer *os.File
}
// NullLogger is used mainly for test implementations, mockup code, etc. It does absolutely nothing with all messages sent to it.
type NullLogger struct{}
// MultiLogger is used to contain one or more Loggers and present them all as a single Logger.
type MultiLogger struct {
/*