Compare commits

...

3 Commits

Author SHA1 Message Date
brent saner ae49f42c0c
v1.6.0
Added bitmask/MaskBit.Copy()
2024-04-14 01:54:59 -04:00
brent saner b87934e8a9
v1.5.0
Added structutils
2024-04-13 13:04:17 -04:00
brent s 70d6c2cbb3
updating logging TODO 2023-07-12 23:16:31 -04:00
5 changed files with 387 additions and 1 deletions

View File

@ -2,8 +2,8 @@ package bitmask

import (
"bytes"
"errors"
"encoding/binary"
"errors"
"math/bits"
)

@ -109,6 +109,15 @@ func (m *MaskBit) Bytes(trim bool) (b []byte) {
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) {


View File

@ -3,9 +3,14 @@
https://golang.org/pkg/runtime/#Caller
-- log.LlongFile and log.Lshortfile flags don't currently work properly for StdLogger/FileLogger; they refer to the file in logging package rather than the caller.

- StdLogger2; where stdout and stderr are both logged to depending on severity level.
- make configurable via OR bitmask

- Suport remote loggers? (eventlog, syslog, systemd)

- JSON logger? YAML logger? XML logger?

- DOCS.
-- Done, but flesh out.

- Implement io.Writer interfaces

5
structutils/consts.go Normal file
View File

@ -0,0 +1,5 @@
package structutils

const (
TagMapTrim tagMapOpt = iota
)

362
structutils/funcs.go Normal file
View File

@ -0,0 +1,362 @@
/*
GoUtils - a library to assist with various Golang-related functions
Copyright (C) 2020 Brent Saner

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package structutils

import (
`reflect`
`strings`
)

/*
TagToBoolMap takes struct field `field` and tag name `tagName`,
optionally with options `opts`, and returns a map of the tag values.
The tag value string is assumed to be in the form of:
option[,option,option...]
and returns a map[string]bool (map[option]true).

If field does not have tag tagName, m will be nil.

See the TagMap* constants for opts.
*/
func TagToBoolMap(field reflect.StructField, tagName string, opts ...tagMapOpt) (m map[string]bool) {

var s string
var optSplit []string
var tagOpts map[tagMapOpt]bool = getTagMapOpts(opts)

s = field.Tag.Get(tagName)

if strings.TrimSpace(s) == "" {
return
}

optSplit = strings.Split(s, ",")
if optSplit == nil || len(optSplit) == 0 {
return
}
m = make(map[string]bool)
for _, o := range optSplit {
if tagOpts[TagMapTrim] {
o = strings.TrimSpace(o)
}
m[o] = true
}

return
}

/*
TagToBoolMapWithValue is like TagToBoolMap but additionally assumes the first value is an "identifier".
The tag value string is assumed to be in the form of:
value,option[,option,option...]
and returns a map[string]bool (map[option]true) with the value.
*/
func TagToBoolMapWithValue(field reflect.StructField, tagName string, opts ...tagMapOpt) (value string, m map[string]bool) {

var s string
var optSplit []string
var tagOpts map[tagMapOpt]bool = getTagMapOpts(opts)

s = field.Tag.Get(tagName)

if strings.TrimSpace(s) == "" {
return
}

optSplit = strings.Split(s, ",")
if optSplit == nil || len(optSplit) == 0 {
return
}
m = make(map[string]bool)
for idx, o := range optSplit {
if idx == 0 {
if tagOpts[TagMapTrim] {
o = strings.TrimSpace(o)
}
value = o
continue
}
if tagOpts[TagMapTrim] {
o = strings.TrimSpace(o)
}
m[o] = true
}

return
}

/*
TagToMixedMap combines TagToBoolMap and TagToStringMap.
It takes struct field `field` and tag name `tagName`,
and returns all single-value options in mapBool, and all key/value options in mapString.

If field does not have tag tagName, m will be nil.

See the TagMap* constants for opts.
*/
func TagToMixedMap(field reflect.StructField, tagName string, opts ...tagMapOpt) (mapBool map[string]bool, mapString map[string]string) {

var s string
var valStr string
var split []string
var kvSplit []string
var valSplit []string
var k string
var v string
var tagOpts map[tagMapOpt]bool = getTagMapOpts(opts)

s = field.Tag.Get(tagName)

if strings.TrimSpace(s) == "" {
return
}

split = strings.Split(s, ",")
if split == nil || len(split) == 0 {
return
}
mapBool = make(map[string]bool)
mapString = make(map[string]string)
for _, valStr = range split {
if strings.Contains(valStr, "=") {
kvSplit = strings.SplitN(valStr, "=", 2)
if kvSplit == nil || len(kvSplit) == 0 {
continue
}
k = valSplit[0]
switch len(valSplit) {
case 1:
v = ""
case 2:
v = kvSplit[1]
}
if tagOpts[TagMapTrim] {
k = strings.TrimSpace(k)
v = strings.TrimSpace(v)
}
mapString[k] = v
} else {
if tagOpts[TagMapTrim] {
valStr = strings.TrimSpace(valStr)
}
mapBool[valStr] = true
}
}

return
}

/*
TagToMixedMapWithValue combines TagToBoolMapWithValue and TagToStringMapWithValue.
It takes struct field `field` and tag name `tagName`,
and returns all single-value options in mapBool, and all key/value options in mapString
along with the first single-value option as value..

If field does not have tag tagName, m will be nil.

See the TagMap* constants for opts.
*/
func TagToMixedMapWithValue(field reflect.StructField, tagName string, opts ...tagMapOpt) (value string, mapBool map[string]bool, mapString map[string]string) {

var s string
var idx int
var valStr string
var split []string
var kvSplit []string
var valSplit []string
var k string
var v string
var tagOpts map[tagMapOpt]bool = getTagMapOpts(opts)

s = field.Tag.Get(tagName)

if strings.TrimSpace(s) == "" {
return
}

split = strings.Split(s, ",")
if split == nil || len(split) == 0 {
return
}
mapBool = make(map[string]bool)
mapString = make(map[string]string)
for idx, valStr = range split {
if idx == 0 {
if tagOpts[TagMapTrim] {
valStr = strings.TrimSpace(valStr)
}
value = valStr
continue
}
if strings.Contains(valStr, "=") {
kvSplit = strings.SplitN(valStr, "=", 2)
if kvSplit == nil || len(kvSplit) == 0 {
continue
}
k = valSplit[0]
switch len(valSplit) {
case 1:
v = ""
case 2:
v = kvSplit[1]
}
if tagOpts[TagMapTrim] {
k = strings.TrimSpace(k)
v = strings.TrimSpace(v)
}
mapString[k] = v
} else {
if tagOpts[TagMapTrim] {
valStr = strings.TrimSpace(valStr)
}
mapBool[valStr] = true
}
}

return
}

/*
TagToStringMap takes struct field `field` and tag name `tagName`,
optionally with options `opts`, and returns a map of the tag values.
The tag value string is assumed to be in the form of:
key=value[,key=value,key=value...]
and returns a map[string]string (map[key]value).
It is proccessed in order; later duplicate keys overwrite previous ones.

If field does not have tag tagName, m will be nil.

If only a key is provided with no value, the value in the map will be an empty string.
(e.g. "foo,bar=baz" => map[string]string{"foo": "", "bar: "baz"}

See the TagMap* constants for opts.
*/
func TagToStringMap(field reflect.StructField, tagName string, opts ...tagMapOpt) (m map[string]string) {

var s string
var kvSplit []string
var valSplit []string
var k string
var v string
var tagOpts map[tagMapOpt]bool = getTagMapOpts(opts)

s = field.Tag.Get(tagName)

if strings.TrimSpace(s) == "" {
return
}

kvSplit = strings.Split(s, ",")
if kvSplit == nil || len(kvSplit) == 0 {
return
}
for _, kv := range kvSplit {
valSplit = strings.SplitN(kv, "=", 2)
if valSplit == nil || len(valSplit) == 0 {
continue
}
k = valSplit[0]
switch len(valSplit) {
case 1:
v = ""
case 2:
v = valSplit[1]
// It's not possible to have more than 2.
}
if m == nil {
m = make(map[string]string)
}
if tagOpts[TagMapTrim] {
k = strings.TrimSpace(k)
v = strings.TrimSpace(v)
}
m[k] = v
}

return
}

/*
TagToStringMapWithValue is like TagToStringMap but additionally assumes the first value is an "identifier".
The tag value string is assumed to be in the form of:
value,key=value[,key=value,key=value...]
and returns a map[string]string (map[key]value) with the value.
*/
func TagToStringMapWithValue(field reflect.StructField, tagName string, opts ...tagMapOpt) (value string, m map[string]string) {

var s string
var kvSplit []string
var valSplit []string
var k string
var v string
var tagOpts map[tagMapOpt]bool = getTagMapOpts(opts)

s = field.Tag.Get(tagName)

if strings.TrimSpace(s) == "" {
return
}

kvSplit = strings.Split(s, ",")
if kvSplit == nil || len(kvSplit) == 0 {
return
}
for idx, kv := range kvSplit {
if idx == 0 {
if tagOpts[TagMapTrim] {
kv = strings.TrimSpace(kv)
}
value = kv
continue
}
valSplit = strings.SplitN(kv, "=", 2)
if valSplit == nil || len(valSplit) == 0 {
continue
}
k = valSplit[0]
switch len(valSplit) {
case 1:
v = ""
case 2:
v = valSplit[1]
// It's not possible to have more than 2.
}
if m == nil {
m = make(map[string]string)
}
if tagOpts[TagMapTrim] {
k = strings.TrimSpace(k)
v = strings.TrimSpace(v)
}
m[k] = v
}

return
}

func getTagMapOpts(opts []tagMapOpt) (optMap map[tagMapOpt]bool) {

optMap = make(map[tagMapOpt]bool)

if opts == nil {
return
}

return
}

5
structutils/types.go Normal file
View File

@ -0,0 +1,5 @@
package structutils

type (
tagMapOpt uint8
)