func ApplyFunc(target, double interface{}) *Patches {return create().ApplyFunc(target, double)}
func ApplyMethod(target reflect.Type, methodName string, double interface{}) *Patches {return create().ApplyMethod(target, methodName, double)}
func ApplyGlobalVar(target, double interface{}) *Patches {return create().ApplyGlobalVar(target, double)}
func ApplyFuncVar(target, double interface{}) *Patches {return create().ApplyFuncVar(target, double)}
func create() *Patches {return &Patches{originals: make(map[reflect.Value][]byte), values: make(map[reflect.Value]reflect.Value), valueHolders: make(map[reflect.Value]reflect.Value)}}
func NewPatches() *Patches {return create()}
type Patches struct {originals map[reflect.Value][]bytevalues map[reflect.Value]reflect.ValuevalueHolders map[reflect.Value]reflect.Value}
func (this *Patches) ApplyMethod(target reflect.Type, methodName string, double interface{}) *Patches {m, ok := target.MethodByName(methodName)if !ok {panic("retrieve method by name failed")}d := reflect.ValueOf(double)return this.ApplyCore(m.Func, d)}
func (this *Patches) ApplyFunc(target, double interface{}) *Patches {t := reflect.ValueOf(target)d := reflect.ValueOf(double)return this.ApplyCore(t, d)}
func (this *Patches) ApplyGlobalVar(target, double interface{}) *Patches {t := reflect.ValueOf(target)if t.Type().Kind() != reflect.Ptr {panic("target is not a pointer")}this.values[t] = reflect.ValueOf(t.Elem().Interface())d := reflect.ValueOf(double)t.Elem().Set(d)return this}
func (this *Patches) ApplyCore(target, double reflect.Value) *Patches {this.check(target, double)if _, ok := this.originals[target]; ok {panic("patch has been existed")}this.valueHolders[double] = doubleoriginal := replace(*(*uintptr)(getPointer(target)), uintptr(getPointer(double)))this.originals[target] = originalreturn this}
func getPointer(v reflect.Value) unsafe.Pointer {return (*funcValue)(unsafe.Pointer(&v)).p}
func replace(target, double uintptr) []byte {code := buildJmpDirective(double)bytes := entryAddress(target, len(code))original := make([]byte, len(bytes))copy(original, bytes)modifyBinary(target, code)return original}
func modifyBinary(target uintptr, bytes []byte) {function := entryAddress(target, len(bytes))page := entryAddress(pageStart(target), syscall.Getpagesize())err := syscall.Mprotect(page, syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC)if err != nil {panic(err)}copy(function, bytes)err = syscall.Mprotect(page, syscall.PROT_READ|syscall.PROT_EXEC)if err != nil {panic(err)}}
func (this *Patches) ApplyFuncSeq(target interface{}, outputs []OutputCell) *Patches {funcType := reflect.TypeOf(target)t := reflect.ValueOf(target)d := getDoubleFunc(funcType, outputs)return this.ApplyCore(t, d)}
func getDoubleFunc(funcType reflect.Type, outputs []OutputCell) reflect.Value {if funcType.NumOut() != len(outputs[0].Values) {panic(fmt.Sprintf("func type has %v return values, but only %v values provided as double",funcType.NumOut(), len(outputs[0].Values)))}slice := make([]Params, 0)for _, output := range outputs {t := 0if output.Times <= 1 {t = 1} else {t = output.Times}for j := 0; j < t; j++ {slice = append(slice, output.Values)}}i := 0len := len(slice)return reflect.MakeFunc(funcType, func(_ []reflect.Value) []reflect.Value {if i < len {i++return GetResultValues(funcType, slice[i-1]...)}panic("double seq is less than call seq")})}


文章转载自golang算法架构leetcode技术php,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




