github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/mattn/go-sqlite3/callback.go (about)

     1  // Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
     2  //
     3  // Use of this source code is governed by an MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package sqlite3
     7  
     8  // You can't export a Go function to C and have definitions in the C
     9  // preamble in the same file, so we have to have callbackTrampoline in
    10  // its own file. Because we need a separate file anyway, the support
    11  // code for SQLite custom functions is in here.
    12  
    13  /*
    14  #include <sqlite3-binding.h>
    15  #include <stdlib.h>
    16  
    17  void _sqlite3_result_text(sqlite3_context* ctx, const char* s);
    18  void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l);
    19  */
    20  import "C"
    21  
    22  import (
    23  	"errors"
    24  	"fmt"
    25  	"math"
    26  	"reflect"
    27  	"sync"
    28  	"unsafe"
    29  )
    30  
    31  //export callbackTrampoline
    32  func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
    33  	args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
    34  	fi := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*functionInfo)
    35  	fi.Call(ctx, args)
    36  }
    37  
    38  //export stepTrampoline
    39  func stepTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
    40  	args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
    41  	ai := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*aggInfo)
    42  	ai.Step(ctx, args)
    43  }
    44  
    45  //export doneTrampoline
    46  func doneTrampoline(ctx *C.sqlite3_context) {
    47  	handle := uintptr(C.sqlite3_user_data(ctx))
    48  	ai := lookupHandle(handle).(*aggInfo)
    49  	ai.Done(ctx)
    50  }
    51  
    52  // Use handles to avoid passing Go pointers to C.
    53  
    54  type handleVal struct {
    55  	db  *SQLiteConn
    56  	val interface{}
    57  }
    58  
    59  var handleLock sync.Mutex
    60  var handleVals = make(map[uintptr]handleVal)
    61  var handleIndex uintptr = 100
    62  
    63  func newHandle(db *SQLiteConn, v interface{}) uintptr {
    64  	handleLock.Lock()
    65  	defer handleLock.Unlock()
    66  	i := handleIndex
    67  	handleIndex++
    68  	handleVals[i] = handleVal{db, v}
    69  	return i
    70  }
    71  
    72  func lookupHandle(handle uintptr) interface{} {
    73  	handleLock.Lock()
    74  	defer handleLock.Unlock()
    75  	r, ok := handleVals[handle]
    76  	if !ok {
    77  		if handle >= 100 && handle < handleIndex {
    78  			panic("deleted handle")
    79  		} else {
    80  			panic("invalid handle")
    81  		}
    82  	}
    83  	return r.val
    84  }
    85  
    86  func deleteHandles(db *SQLiteConn) {
    87  	handleLock.Lock()
    88  	defer handleLock.Unlock()
    89  	for handle, val := range handleVals {
    90  		if val.db == db {
    91  			delete(handleVals, handle)
    92  		}
    93  	}
    94  }
    95  
    96  // This is only here so that tests can refer to it.
    97  type callbackArgRaw C.sqlite3_value
    98  
    99  type callbackArgConverter func(*C.sqlite3_value) (reflect.Value, error)
   100  
   101  type callbackArgCast struct {
   102  	f   callbackArgConverter
   103  	typ reflect.Type
   104  }
   105  
   106  func (c callbackArgCast) Run(v *C.sqlite3_value) (reflect.Value, error) {
   107  	val, err := c.f(v)
   108  	if err != nil {
   109  		return reflect.Value{}, err
   110  	}
   111  	if !val.Type().ConvertibleTo(c.typ) {
   112  		return reflect.Value{}, fmt.Errorf("cannot convert %s to %s", val.Type(), c.typ)
   113  	}
   114  	return val.Convert(c.typ), nil
   115  }
   116  
   117  func callbackArgInt64(v *C.sqlite3_value) (reflect.Value, error) {
   118  	if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
   119  		return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
   120  	}
   121  	return reflect.ValueOf(int64(C.sqlite3_value_int64(v))), nil
   122  }
   123  
   124  func callbackArgBool(v *C.sqlite3_value) (reflect.Value, error) {
   125  	if C.sqlite3_value_type(v) != C.SQLITE_INTEGER {
   126  		return reflect.Value{}, fmt.Errorf("argument must be an INTEGER")
   127  	}
   128  	i := int64(C.sqlite3_value_int64(v))
   129  	val := false
   130  	if i != 0 {
   131  		val = true
   132  	}
   133  	return reflect.ValueOf(val), nil
   134  }
   135  
   136  func callbackArgFloat64(v *C.sqlite3_value) (reflect.Value, error) {
   137  	if C.sqlite3_value_type(v) != C.SQLITE_FLOAT {
   138  		return reflect.Value{}, fmt.Errorf("argument must be a FLOAT")
   139  	}
   140  	return reflect.ValueOf(float64(C.sqlite3_value_double(v))), nil
   141  }
   142  
   143  func callbackArgBytes(v *C.sqlite3_value) (reflect.Value, error) {
   144  	switch C.sqlite3_value_type(v) {
   145  	case C.SQLITE_BLOB:
   146  		l := C.sqlite3_value_bytes(v)
   147  		p := C.sqlite3_value_blob(v)
   148  		return reflect.ValueOf(C.GoBytes(p, l)), nil
   149  	case C.SQLITE_TEXT:
   150  		l := C.sqlite3_value_bytes(v)
   151  		c := unsafe.Pointer(C.sqlite3_value_text(v))
   152  		return reflect.ValueOf(C.GoBytes(c, l)), nil
   153  	default:
   154  		return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
   155  	}
   156  }
   157  
   158  func callbackArgString(v *C.sqlite3_value) (reflect.Value, error) {
   159  	switch C.sqlite3_value_type(v) {
   160  	case C.SQLITE_BLOB:
   161  		l := C.sqlite3_value_bytes(v)
   162  		p := (*C.char)(C.sqlite3_value_blob(v))
   163  		return reflect.ValueOf(C.GoStringN(p, l)), nil
   164  	case C.SQLITE_TEXT:
   165  		c := (*C.char)(unsafe.Pointer(C.sqlite3_value_text(v)))
   166  		return reflect.ValueOf(C.GoString(c)), nil
   167  	default:
   168  		return reflect.Value{}, fmt.Errorf("argument must be BLOB or TEXT")
   169  	}
   170  }
   171  
   172  func callbackArgGeneric(v *C.sqlite3_value) (reflect.Value, error) {
   173  	switch C.sqlite3_value_type(v) {
   174  	case C.SQLITE_INTEGER:
   175  		return callbackArgInt64(v)
   176  	case C.SQLITE_FLOAT:
   177  		return callbackArgFloat64(v)
   178  	case C.SQLITE_TEXT:
   179  		return callbackArgString(v)
   180  	case C.SQLITE_BLOB:
   181  		return callbackArgBytes(v)
   182  	case C.SQLITE_NULL:
   183  		// Interpret NULL as a nil byte slice.
   184  		var ret []byte
   185  		return reflect.ValueOf(ret), nil
   186  	default:
   187  		panic("unreachable")
   188  	}
   189  }
   190  
   191  func callbackArg(typ reflect.Type) (callbackArgConverter, error) {
   192  	switch typ.Kind() {
   193  	case reflect.Interface:
   194  		if typ.NumMethod() != 0 {
   195  			return nil, errors.New("the only supported interface type is interface{}")
   196  		}
   197  		return callbackArgGeneric, nil
   198  	case reflect.Slice:
   199  		if typ.Elem().Kind() != reflect.Uint8 {
   200  			return nil, errors.New("the only supported slice type is []byte")
   201  		}
   202  		return callbackArgBytes, nil
   203  	case reflect.String:
   204  		return callbackArgString, nil
   205  	case reflect.Bool:
   206  		return callbackArgBool, nil
   207  	case reflect.Int64:
   208  		return callbackArgInt64, nil
   209  	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
   210  		c := callbackArgCast{callbackArgInt64, typ}
   211  		return c.Run, nil
   212  	case reflect.Float64:
   213  		return callbackArgFloat64, nil
   214  	case reflect.Float32:
   215  		c := callbackArgCast{callbackArgFloat64, typ}
   216  		return c.Run, nil
   217  	default:
   218  		return nil, fmt.Errorf("don't know how to convert to %s", typ)
   219  	}
   220  }
   221  
   222  func callbackConvertArgs(argv []*C.sqlite3_value, converters []callbackArgConverter, variadic callbackArgConverter) ([]reflect.Value, error) {
   223  	var args []reflect.Value
   224  
   225  	if len(argv) < len(converters) {
   226  		return nil, fmt.Errorf("function requires at least %d arguments", len(converters))
   227  	}
   228  
   229  	for i, arg := range argv[:len(converters)] {
   230  		v, err := converters[i](arg)
   231  		if err != nil {
   232  			return nil, err
   233  		}
   234  		args = append(args, v)
   235  	}
   236  
   237  	if variadic != nil {
   238  		for _, arg := range argv[len(converters):] {
   239  			v, err := variadic(arg)
   240  			if err != nil {
   241  				return nil, err
   242  			}
   243  			args = append(args, v)
   244  		}
   245  	}
   246  	return args, nil
   247  }
   248  
   249  type callbackRetConverter func(*C.sqlite3_context, reflect.Value) error
   250  
   251  func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
   252  	switch v.Type().Kind() {
   253  	case reflect.Int64:
   254  	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
   255  		v = v.Convert(reflect.TypeOf(int64(0)))
   256  	case reflect.Bool:
   257  		b := v.Interface().(bool)
   258  		if b {
   259  			v = reflect.ValueOf(int64(1))
   260  		} else {
   261  			v = reflect.ValueOf(int64(0))
   262  		}
   263  	default:
   264  		return fmt.Errorf("cannot convert %s to INTEGER", v.Type())
   265  	}
   266  
   267  	C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Interface().(int64)))
   268  	return nil
   269  }
   270  
   271  func callbackRetFloat(ctx *C.sqlite3_context, v reflect.Value) error {
   272  	switch v.Type().Kind() {
   273  	case reflect.Float64:
   274  	case reflect.Float32:
   275  		v = v.Convert(reflect.TypeOf(float64(0)))
   276  	default:
   277  		return fmt.Errorf("cannot convert %s to FLOAT", v.Type())
   278  	}
   279  
   280  	C.sqlite3_result_double(ctx, C.double(v.Interface().(float64)))
   281  	return nil
   282  }
   283  
   284  func callbackRetBlob(ctx *C.sqlite3_context, v reflect.Value) error {
   285  	if v.Type().Kind() != reflect.Slice || v.Type().Elem().Kind() != reflect.Uint8 {
   286  		return fmt.Errorf("cannot convert %s to BLOB", v.Type())
   287  	}
   288  	i := v.Interface()
   289  	if i == nil || len(i.([]byte)) == 0 {
   290  		C.sqlite3_result_null(ctx)
   291  	} else {
   292  		bs := i.([]byte)
   293  		C._sqlite3_result_blob(ctx, unsafe.Pointer(&bs[0]), C.int(len(bs)))
   294  	}
   295  	return nil
   296  }
   297  
   298  func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error {
   299  	if v.Type().Kind() != reflect.String {
   300  		return fmt.Errorf("cannot convert %s to TEXT", v.Type())
   301  	}
   302  	C._sqlite3_result_text(ctx, C.CString(v.Interface().(string)))
   303  	return nil
   304  }
   305  
   306  func callbackRet(typ reflect.Type) (callbackRetConverter, error) {
   307  	switch typ.Kind() {
   308  	case reflect.Slice:
   309  		if typ.Elem().Kind() != reflect.Uint8 {
   310  			return nil, errors.New("the only supported slice type is []byte")
   311  		}
   312  		return callbackRetBlob, nil
   313  	case reflect.String:
   314  		return callbackRetText, nil
   315  	case reflect.Bool, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
   316  		return callbackRetInteger, nil
   317  	case reflect.Float32, reflect.Float64:
   318  		return callbackRetFloat, nil
   319  	default:
   320  		return nil, fmt.Errorf("don't know how to convert to %s", typ)
   321  	}
   322  }
   323  
   324  func callbackError(ctx *C.sqlite3_context, err error) {
   325  	cstr := C.CString(err.Error())
   326  	defer C.free(unsafe.Pointer(cstr))
   327  	C.sqlite3_result_error(ctx, cstr, -1)
   328  }
   329  
   330  // Test support code. Tests are not allowed to import "C", so we can't
   331  // declare any functions that use C.sqlite3_value.
   332  func callbackSyntheticForTests(v reflect.Value, err error) callbackArgConverter {
   333  	return func(*C.sqlite3_value) (reflect.Value, error) {
   334  		return v, err
   335  	}
   336  }