Files
gocommon/misc.go

222 lines
4.2 KiB
Go
Raw Normal View History

package gocommon
2023-05-24 15:10:15 +09:00
import (
"encoding/binary"
"encoding/json"
"fmt"
"io"
"math/rand"
2023-06-16 12:22:16 +09:00
"path"
2023-05-24 15:10:15 +09:00
"reflect"
"strconv"
"strings"
"sync/atomic"
"time"
2023-06-21 14:13:30 +09:00
"repositories.action2quare.com/ayo/gocommon/flagx"
2023-05-24 15:10:15 +09:00
)
2023-06-21 14:13:30 +09:00
var devflag = flagx.Bool("dev", false, "")
2023-05-24 15:10:15 +09:00
var sequenceStart = rand.Uint32()
2024-05-17 09:59:42 +09:00
func MakeHttpHandlerPattern(n ...string) (r string) {
r = "/" + path.Join(n...)
defer func() {
for strings.Contains(r, "//") {
r = strings.ReplaceAll(r, "//", "/")
}
}()
2023-06-16 12:22:16 +09:00
if strings.HasSuffix(n[len(n)-1], "/") {
return r + "/"
2023-06-16 12:14:50 +09:00
}
2023-05-24 15:10:15 +09:00
return r
}
func MakeLocalUniqueId() string {
var b [10]byte
now := time.Now()
binary.BigEndian.PutUint32(b[6:10], uint32(now.Unix()))
binary.BigEndian.PutUint32(b[3:7], uint32(now.Nanosecond()))
binary.BigEndian.PutUint32(b[0:4], atomic.AddUint32(&sequenceStart, 1))
u := binary.LittleEndian.Uint64(b[2:])
a := strconv.FormatUint(u, 36)
return a[1:]
}
func SerializeInterface(w io.Writer, val interface{}) (err error) {
if val == nil {
return nil
}
value := reflect.ValueOf(val)
encoder := json.NewEncoder(w)
switch value.Kind() {
case reflect.String:
_, err = w.Write([]byte(value.String()))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
_, err = w.Write([]byte(fmt.Sprintf("%d", value.Int())))
case reflect.Float32, reflect.Float64:
_, err = w.Write([]byte(fmt.Sprintf("%f", value.Float())))
case reflect.Bool:
if value.Bool() {
_, err = w.Write([]byte("true"))
} else {
_, err = w.Write([]byte("false"))
}
case reflect.Slice:
switch value.Type().Elem().Kind() {
case reflect.Uint8:
_, err = w.Write(value.Bytes())
default:
var conv []interface{}
for i := 0; i < value.Len(); i++ {
conv = append(conv, value.Index(i).Interface())
}
if len(conv) == 0 {
_, err = w.Write([]byte("[]"))
} else {
err = encoder.Encode(conv)
}
}
case reflect.Interface, reflect.Struct, reflect.Map:
if value.Kind() == reflect.Struct {
err = encoder.Encode(value.Interface())
} else if !value.IsNil() {
err = encoder.Encode(value.Interface())
}
case reflect.Ptr:
if !value.IsNil() {
if wro, ok := value.Interface().(io.WriterTo); ok {
_, err = wro.WriteTo(w)
} else {
err = json.NewEncoder(w).Encode(value.Interface())
}
}
}
return
}
2023-12-01 19:34:49 +09:00
2023-12-02 20:30:43 +09:00
func ShrinkSliceAt[T any](in []T, from int) []T {
if len(in) == 0 {
return in
}
cursor := from
for i := from + 1; i < len(in); i++ {
in[cursor] = in[i]
cursor++
}
return in[:len(in)-1]
}
2023-12-01 19:34:49 +09:00
func ShrinkSlice[T any](in []T, compare func(elem T) bool) []T {
2023-12-02 20:09:52 +09:00
if len(in) == 0 {
return in
}
2023-12-01 19:34:49 +09:00
cursor := 0
for i := 0; i < len(in); i++ {
if compare(in[i]) {
continue
}
in[cursor] = in[i]
cursor++
}
return in[:cursor]
}
2023-12-02 01:25:12 +09:00
2023-12-02 19:56:37 +09:00
func FindOneInSlice[T any](in []T, compare func(elem *T) bool) (int, bool) {
2023-12-02 01:25:12 +09:00
for i, e := range in {
if compare(&e) {
2023-12-02 19:56:37 +09:00
return i, true
2023-12-02 01:25:12 +09:00
}
}
2023-12-02 19:56:37 +09:00
return -1, false
2023-12-02 01:25:12 +09:00
}
2024-07-18 17:06:51 +09:00
// RotateRight rotates the bits in the byte array to the right by n positions
func rotateBitsRight(data []byte, n int) {
// Normalize n to avoid unnecessary rotations
n = n % (len(data) * 8)
if n == 0 {
return
}
// To hold the final rotated result
inlen := len(data)
for k := 0; k < n/8; k++ {
last := data[inlen-1]
for i := 0; i < inlen-1; i++ {
data[inlen-1-i] = data[inlen-2-i]
}
data[0] = last
}
n = n % 8
if n == 0 {
return
}
mask := byte(1<<n) - 1
carry := data[0] & mask
for i := 1; i < inlen; i++ {
nextcarry := data[i] & mask
data[i] = (data[i] >> n) | (carry << (8 - n))
carry = nextcarry
}
data[0] = (data[0] >> n) | (carry << (8 - n))
}
func rotateBitsLeft(data []byte, n int) {
// Normalize n to avoid unnecessary rotations
n = n % (len(data) * 8)
if n == 0 {
return
}
// To hold the final rotated result
inlen := len(data)
for k := 0; k < n/8; k++ {
last := data[0]
for i := 0; i < inlen-1; i++ {
data[i] = data[i+1]
}
data[inlen-1] = last
}
n = n % 8
if n == 0 {
return
}
mask := (byte(1<<n) - 1) << (8 - n)
carry := data[0] & mask
for i := inlen - 1; i >= 0; i-- {
nextcarry := data[i] & mask
data[i] = (data[i] << n) | (carry >> (8 - n))
carry = nextcarry
}
}
func RotateBits(data []byte, n int) {
if n > 0 {
rotateBitsRight(data, n)
} else {
rotateBitsLeft(data, -n)
}
}