1
0
forked from x/ContextOS
2022-01-24 10:37:00 +08:00

302 lines
5.9 KiB
Go

package kit
import (
"bytes"
"crypto/md5"
"encoding/csv"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"strings"
"unicode"
)
type TERM interface {
Show(...interface{}) bool
}
var STDIO TERM
var DisableLog = false
func Log(action string, str string, args ...interface{}) {
if DisableLog {
return
}
if len(args) > 0 {
str = fmt.Sprintf(str, args...)
}
fmt.Fprintf(os.Stderr, "%s: %s\n", action, str)
}
func Env(key string) {
os.Getenv(key)
}
func Pwd() string {
wd, _ := os.Getwd()
return wd
}
func Create(p string) (*os.File, string, error) {
if dir, _ := path.Split(p); dir != "" {
if e := os.MkdirAll(dir, 0777); e != nil {
return nil, p, e
}
}
f, e := os.Create(p)
return f, p, e
}
func Split(str string, c rune, n int) []string {
res := []string{}
list := []rune(str)
for i, j := 0, 0; i < len(list); i++ {
if list[i] == c || c == ' ' && unicode.IsSpace(list[i]) {
continue
}
for j = i; j < len(list); j++ {
if list[j] == c || c == ' ' && unicode.IsSpace(list[j]) {
break
}
}
if n == len(res)+1 {
j = len(list)
}
res, i = append(res, string(list[i:j])), j
}
return res
}
func FmtSize(size int64) string {
if size > 1<<30 {
return fmt.Sprintf("%d.%dG", size>>30, (size>>20)%1024*100>>10)
}
if size > 1<<20 {
return fmt.Sprintf("%d.%dM", size>>20, (size>>10)%1024*100>>10)
}
if size > 1<<10 {
return fmt.Sprintf("%d.%dK", size>>10, size%1024*100>>10)
}
return fmt.Sprintf("%dB", size)
}
func FmtTime(t int64) string {
sign, time := "", t
if time < 0 {
sign, time = "-", -t
}
if time > 1000000000 {
return fmt.Sprintf("%s%d.%ds", sign, time/1000000000, (time/1000000)%1000*100/1000)
}
if time > 1000000 {
return fmt.Sprintf("%s%d.%dms", sign, time/1000000, (time/1000)%1000*100/1000)
}
if time > 1000 {
return fmt.Sprintf("%s%d.%dus", sign, time/1000, (time/1000)%1000*100/1000)
}
return fmt.Sprintf("%s%dns", sign, time)
}
func Marshal(data interface{}, arg ...interface{}) string {
if len(arg) > 0 {
switch arg := arg[0].(type) {
case string:
if f, p, e := Create(arg); e == nil {
defer f.Close()
switch {
case strings.HasSuffix(arg, ".json"):
b, _ := json.MarshalIndent(data, "", " ")
if n, e := f.Write(b); e == nil && n == len(b) {
return p
}
case strings.HasSuffix(arg, ".csv"):
switch data := data.(type) {
case []interface{}:
w := csv.NewWriter(f)
head := []string{}
for _, v := range data {
switch v := v.(type) {
case map[string]interface{}:
if len(head) == 0 {
for k, _ := range v {
head = append(head, k)
}
w.Write(head)
}
fields := []string{}
for _, k := range head {
fields = append(fields, Format(v[k]))
}
w.Write(fields)
}
}
w.Flush()
}
}
}
}
}
b, _ := json.MarshalIndent(data, "", " ")
return string(b)
}
func UnMarshal(data string) interface{} {
var res interface{}
if strings.HasSuffix(data, ".json") {
if b, e := ioutil.ReadFile(data); e == nil {
json.Unmarshal(b, &res)
}
} else {
json.Unmarshal([]byte(data), &res)
}
return res
}
func UnMarshalm(data string) map[string]interface{} {
res, _ := UnMarshal(data).(map[string]interface{})
return res
}
func IsLocalIP(ip string) bool {
if strings.HasPrefix(ip, "127") {
return true
}
if ip == "::1" {
return true
}
return false
}
func Hashx(f io.Reader) string {
md := md5.New()
io.Copy(md, f)
h := md.Sum(nil)
return hex.EncodeToString(h[:])
}
func Lines(p string, args ...interface{}) []string {
b, e := ioutil.ReadFile(p)
if e != nil {
return nil
}
bs := bytes.Split(b, []byte("\n"))
res := make([]string, 0, len(bs))
for _, v := range bs {
if len(args) > 0 {
switch arg := args[0].(type) {
case func(string) string:
res = append(res, arg(string(v)))
continue
case func(string):
arg(string(v))
}
}
res = append(res, string(v))
}
return res
}
func Linex(p string) map[string]string {
meta := map[string]string{}
Lines(p, func(value string) {
if strings.Contains(value, ":") {
bs := strings.SplitN(value, ":", 2)
meta[strings.TrimSpace(bs[0])] = strings.TrimSpace(bs[1])
}
})
return meta
}
func List(arg interface{}, cb interface{}) {
list := Trans(arg)
for i, v := range list {
switch cb := cb.(type) {
case func(string):
cb(v)
case func(string, int):
cb(v, i)
}
}
}
func Merge(list interface{}, value string) interface{} {
switch val := list.(type) {
case nil:
return value
case string:
return []interface{}{val, value}
case []interface{}:
return append(val, value)
}
return list
}
func Contains(list interface{}, value string) bool {
switch val := list.(type) {
case nil:
case string:
case []string:
for _, v := range val {
if v == value {
return true
}
}
case []interface{}:
}
return false
}
func IndexOf(list interface{}, value string) int {
switch val := list.(type) {
case nil:
case string:
case []string:
for i, v := range val {
if strings.TrimSpace(v) == strings.TrimSpace(value) {
return i
}
}
case []interface{}:
}
return -1
}
func Shortm(data map[string]interface{}, keys ...string) map[string]interface{} {
for _, k := range keys {
switch k {
case "times":
ls := strings.Split(Format(data["time"]), " ")
if len(ls) > 1 {
data["times"] = ls[1]
} else {
data["times"] = data["time"]
}
case "files":
data["files"] = path.Base(Format(data["file"]))
case "sids":
data["sids"] = Short(data["sid"], 6)
}
}
return data
}
func Short(arg interface{}, l int) string {
switch val := arg.(type) {
case string:
if len(val) > l {
return val[:l]
}
return val
}
return ""
}
func ShortKey(list map[string]interface{}, min int, arg ...interface{}) string {
h := Hashs(arg...)
for i := min; i < len(h); i++ {
if _, ok := list[h[:i]]; !ok {
return h[:i]
}
}
return h
}