blob: 2c8086e60fdc7f73bcf72b0783d961a1657ed4a0 [file] [log] [blame]
//Copyright 2017 Huawei Technologies Co., Ltd
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
package util
import (
"bytes"
"encoding/gob"
"golang.org/x/net/context"
"net/url"
"os"
"time"
"unsafe"
)
func PathExist(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsExist(err)
}
func MinInt(x, y int) int {
if x <= y {
return x
} else {
return y
}
}
func ClearStringMemory(src *string) {
p := (*struct {
ptr uintptr
len int
})(unsafe.Pointer(src))
len := MinInt(p.len, 32)
ptr := p.ptr
for idx := 0; idx < len; idx = idx + 1 {
b := (*byte)(unsafe.Pointer(ptr))
*b = 0
ptr += 1
}
}
func ClearByteMemory(src []byte) {
len := MinInt(len(src), 32)
for idx := 0; idx < len; idx = idx + 1 {
src[idx] = 0
}
}
type StringContext struct {
parentCtx context.Context
kv map[string]interface{}
}
func (c *StringContext) Deadline() (deadline time.Time, ok bool) {
return c.parentCtx.Deadline()
}
func (c *StringContext) Done() <-chan struct{} {
return c.parentCtx.Done()
}
func (c *StringContext) Err() error {
return c.parentCtx.Err()
}
func (c *StringContext) Value(key interface{}) interface{} {
k, ok := key.(string)
if !ok {
return c.parentCtx.Value(key)
}
return c.kv[k]
}
func (c *StringContext) SetKV(key string, val interface{}) {
c.kv[key] = val
}
func NewContext(ctx context.Context, key string, val interface{}) context.Context {
strCtx, ok := ctx.(*StringContext)
if !ok {
strCtx = &StringContext{
parentCtx: ctx,
kv: make(map[string]interface{}, 10),
}
}
strCtx.SetKV(key, val)
return strCtx
}
func FromContext(ctx context.Context, key string) interface{} {
return ctx.Value(key)
}
func ParseTenantProject(ctx context.Context) string {
return StringJoin([]string{ParseTenant(ctx), ParseProject(ctx)}, "/")
}
func ParseTenant(ctx context.Context) string {
v, ok := FromContext(ctx, "tenant").(string)
if !ok {
return ""
}
return v
}
func ParseProject(ctx context.Context) string {
v, ok := FromContext(ctx, "project").(string)
if !ok {
return ""
}
return v
}
func GetIPFromContext(ctx context.Context) string {
remoteIp := ""
remoteIp, _ = ctx.Value("x-remote-ip").(string)
return remoteIp
}
func DeepCopy(dst, src interface{}) error {
var buf bytes.Buffer
if err := gob.NewEncoder(&buf).Encode(src); err != nil {
return err
}
return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst)
}
func SafeCloseChan(c chan struct{}) {
select {
case _, ok := <-c:
if ok {
close(c)
}
default:
close(c)
}
}
func BytesToStringWithNoCopy(bytes []byte) string {
return *(*string)(unsafe.Pointer(&bytes))
}
func StringToBytesWithNoCopy(s string) []byte {
x := (*[2]uintptr)(unsafe.Pointer(&s))
h := [3]uintptr{x[0], x[1], x[1]}
return *(*[]byte)(unsafe.Pointer(&h))
}
func ListToMap(list []string) map[string]struct{} {
ret := make(map[string]struct{}, len(list))
for _, v := range list {
ret[v] = struct{}{}
}
return ret
}
func MapToList(dict map[string]struct{}) []string {
ret := make([]string, 0, len(dict))
for k := range dict {
ret = append(ret, k)
}
return ret
}
func StringJoin(args []string, sep string) string {
l := len(args)
switch l {
case 0:
return ""
case 1:
return args[0]
default:
n := len(sep) * (l - 1)
for i := 0; i < l; i++ {
n += len(args[i])
}
b := make([]byte, n)
sl := copy(b, args[0])
for i := 1; i < l; i++ {
sl += copy(b[sl:], sep)
sl += copy(b[sl:], args[i])
}
return BytesToStringWithNoCopy(b)
}
}
func RecoverAndReport() {
if r := recover(); r != nil {
Logger().Errorf(nil, "recover! %v", r)
}
}
func ParseEndpoint(ep string) (string, error) {
u, err := url.Parse(ep)
if err != nil {
return "", err
}
port := u.Port()
if len(port) > 0 {
return u.Hostname() + ":" + port, nil
}
return u.Hostname(), nil
}