blob: 7d437813d4b3425d26c738c2cb7a6135710fe388 [file] [log] [blame]
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you 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 core
import (
"os"
"reflect"
"strconv"
"strings"
"sync"
"unsafe"
)
type TracerTools struct {
}
func NewTracerTools() *TracerTools {
return &TracerTools{}
}
type ReflectFieldFilter struct {
name string
interfaceType interface{}
typeVal reflect.Type
}
func (r *ReflectFieldFilter) SetName(val string) {
r.name = val
}
func (r *ReflectFieldFilter) SetInterfaceType(val interface{}) {
r.interfaceType = val
}
func (r *ReflectFieldFilter) SetType(val interface{}) {
r.typeVal = reflect.TypeOf(val)
}
type ReflectFieldFilterOpts interface {
Apply(interface{})
}
func (t *TracerTools) ReflectGetValue(instance interface{}, filterOpts []interface{}) interface{} {
instanceVal := reflect.ValueOf(instance)
if instanceVal.Kind() == reflect.Ptr && instanceVal.Elem().Kind() == reflect.Struct {
instanceVal = instanceVal.Elem()
} else {
// only support the pointer struct
return nil
}
filter := &ReflectFieldFilter{}
for _, opt := range filterOpts {
if f, ok := opt.(ReflectFieldFilterOpts); ok {
f.Apply(filter)
}
}
for i := 0; i < instanceVal.NumField(); i++ {
field := instanceVal.Field(i)
fieldType := instanceVal.Type().Field(i)
if t.checkFieldSupport(field, &fieldType, filter) {
// for getting the export field value
// 1. get a pointer to the field, then convert it to a 'generic' pointer
// 2. convert the pointer back to an interface{}
fieldPtr := unsafe.Pointer(field.UnsafeAddr())
return reflect.NewAt(field.Type(), fieldPtr).Elem().Interface()
}
}
return nil
}
func (t *TracerTools) GetEnvValue(key string) string {
return os.Getenv(key)
}
func (t *TracerTools) ParseFloat(val string, bitSize int) (float64, error) {
return strconv.ParseFloat(val, bitSize)
}
func (t *TracerTools) ParseBool(val string) bool {
return strings.EqualFold(val, "true")
}
func (t *TracerTools) ParseInt(val string, base, bitSize int) (int64, error) {
return strconv.ParseInt(val, base, bitSize)
}
func (t *TracerTools) Atoi(val string) (int, error) {
return strconv.Atoi(val)
}
func (t *TracerTools) NewSyncMap() interface{} {
return newSyncMap()
}
func (t *TracerTools) checkFieldSupport(field reflect.Value, instanceField *reflect.StructField, filter *ReflectFieldFilter) bool {
if filter.name != "" {
if instanceField.Name != filter.name {
return false
}
}
if filter.interfaceType != nil {
interfaceType := reflect.TypeOf(filter.interfaceType).Elem()
if !field.Type().Implements(interfaceType) {
return false
}
}
if filter.typeVal != nil {
if field.Type() != filter.typeVal {
return false
}
}
return true
}
type syncMapImpl struct {
data *sync.Map
}
func newSyncMap() *syncMapImpl {
return &syncMapImpl{
data: &sync.Map{},
}
}
func (s *syncMapImpl) Put(key string, value interface{}) {
s.data.Store(key, value)
}
func (s *syncMapImpl) Get(key string) (interface{}, bool) {
return s.data.Load(key)
}
func (s *syncMapImpl) Remove(key string) (interface{}, bool) {
return s.data.LoadAndDelete(key)
}