| // 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) |
| } |