<commit_before>package ffi

// #include <ffi.h>
// #include <stdint.h>
//
// typedef void (*function)(void);
//
// static int ffi_test_abs__(int n) {
//   return n < 0 ? -n : n;
// }
//
import "C"
import (
	"fmt"
	"io"
	"reflect"
	"runtime"
	"unsafe"
)

type Status int

const (
	OK         Status = Status(C.FFI_OK)
	BadTypedef Status = Status(C.FFI_BAD_TYPEDEF)
	BadABI     Status = Status(C.FFI_BAD_ABI)
)

func (s Status) String() string {
	switch s {
	case OK:
		return "OK"
	case BadTypedef:
		return "bad-typedef"
	case BadABI:
		return "bad-ABI"
	default:
		return "unknown"
	}
}

func (s Status) Error() string {
	return "status: " + s.String()
}

type Type struct {
	ffi_type *C.ffi_type
	name     string
}

var (
	Void Type = Type{&C.ffi_type_void, "void"}

	UChar  Type = Type{&C.ffi_type_uchar, "unsigned char"}
	UShort Type = Type{&C.ffi_type_ushort, "unsigned short"}
	UInt   Type = Type{&C.ffi_type_uint, "unsigned int"}
	ULong  Type = Type{&C.ffi_type_ulong, "unsigned long"}

	UInt8  Type = Type{&C.ffi_type_uint8, "uint8_t"}
	UInt16 Type = Type{&C.ffi_type_uint16, "uint16_t"}
	UInt32 Type = Type{&C.ffi_type_uint32, "uint32_t"}
	UInt64 Type = Type{&C.ffi_type_uint64, "uint64_t"}

	Char  Type = Type{&C.ffi_type_schar, "char"}
	Short Type = Type{&C.ffi_type_sshort, "short"}
	Int   Type = Type{&C.ffi_type_sint, "int"}
	Long  Type = Type{&C.ffi_type_slong, "long"}

	Int8  Type = Type{&C.ffi_type_sint8, "int8_t"}
	Int16 Type = Type{&C.ffi_type_sint16, "int16_t"}
	Int32 Type = Type{&C.ffi_type_sint32, "int32_t"}
	Int64 Type = Type{&C.ffi_type_sint64, "int64_t"}

	Float  Type = Type{&C.ffi_type_float, "float"}
	Double Type = Type{&C.ffi_type_double, "double"}

	Pointer Type = Type{&C.ffi_type_pointer, "void *"}
)

func (t Type) String() string {
	if len(t.name) == 0 {
		return "struct"
	} else {
		return t.name
	}
}

type Interface struct {
	ffi_cif  C.ffi_cif
	ffi_ret  *C.ffi_type
	ffi_args **C.ffi_type

	ret  Type
	args []Type
}

func Prepare(ret Type, args ...Type) (cif Interface) {
	cif.ffi_ret = ret.ffi_type
	cif.ret = ret
	cif.args = args
	argc := len(args)

	if argc != 0 {
		va := make([]*C.ffi_type, argc)

		for i, a := range args {
			va[i] = a.ffi_type
		}

		cif.ffi_args = &va[0]
	}

	if status := Status(C.ffi_prep_cif(&cif.ffi_cif, C.FFI_DEFAULT_ABI, C.uint(argc), cif.ffi_ret, cif.ffi_args)); status != OK {
		panic(status)
	}

	return
}

func (cif Interface) Call(fptr unsafe.Pointer, ret unsafe.Pointer, args ...unsafe.Pointer) (err error) {
	var va *unsafe.Pointer

	if len(args) != 0 {
		va = &args[0]
	}

	_, err = C.ffi_call(&cif.ffi_cif, C.function(fptr), ret, va)
	return
}

func (self Interface) String() string {
	return fmt.Sprint(self)
}

func (self Interface) Format(f fmt.State, r rune) {
	fmt.Fprint(f, self.ret)
	io.WriteString(f, "(*)(")

	for i, arg := range self.args {
		if i != 0 {
			io.WriteString(f, ", ")
		}
		fmt.Fprint(f, arg)
	}

	io.WriteString(f, ")")
}

func Call(fptr unsafe.Pointer, ret interface{}, args ...interface{}) (err error) {
	vret := valueOfRet(ret)
	varg := valueOfArgs(args)

	rett := makeRetType(vret)
	retv := makeRetValue(vret)

	argt := makeArgTypes(varg)
	argv := makeArgValues(varg)

	Prepare(rett, argt...).Call(fptr, retv, argv...)

	setRetValue(vret, retv)
	return
}

func valueOfRet(ret interface{}) reflect.Value {
	v := reflect.ValueOf(ret)

	if ret != nil && v.Kind() != reflect.Ptr {
		panic(fmt.Sprintf("ffi: expected return value to be a pointer but got %T", ret))
	}

	return v<commit_msg>fix memory leak for functions accepting c-string arguments<commit_after>package ffi

// #include <ffi.h>
// #include <stdint.h>
// #include <stdlib.h>
//
// typedef void (*function)(void);
//
// static int ffi_test_abs__(int n) {
//   return n < 0 ? -n : n;
// }
//
import "C"
import (
	"fmt"
	"io"
	"reflect"
	"runtime"
	"unsafe"
)

type Status int

const (
	OK         Status = Status(C.FFI_OK)
	BadTypedef Status = Status(C.FFI_BAD_TYPEDEF)
	BadABI     Status = Status(C.FFI_BAD_ABI)
)

func (s Status) String() string {
	switch s {
	case OK:
		return "OK"
	case BadTypedef:
		return "bad-typedef"
	case BadABI:
		return "bad-ABI"
	default:
		return "unknown"
	}
}

func (s Status) Error() string {
	return "status: " + s.String()
}

type Type struct {
	ffi_type *C.ffi_type
	name     string
}

var (
	Void Type = Type{&C.ffi_type_void, "void"}

	UChar  Type = Type{&C.ffi_type_uchar, "unsigned char"}
	UShort Type = Type{&C.ffi_type_ushort, "unsigned short"}
	UInt   Type = Type{&C.ffi_type_uint, "unsigned int"}
	ULong  Type = Type{&C.ffi_type_ulong, "unsigned long"}

	UInt8  Type = Type{&C.ffi_type_uint8, "uint8_t"}
	UInt16 Type = Type{&C.ffi_type_uint16, "uint16_t"}
	UInt32 Type = Type{&C.ffi_type_uint32, "uint32_t"}
	UInt64 Type = Type{&C.ffi_type_uint64, "uint64_t"}

	Char  Type = Type{&C.ffi_type_schar, "char"}
	Short Type = Type{&C.ffi_type_sshort, "short"}
	Int   Type = Type{&C.ffi_type_sint, "int"}
	Long  Type = Type{&C.ffi_type_slong, "long"}

	Int8  Type = Type{&C.ffi_type_sint8, "int8_t"}
	Int16 Type = Type{&C.ffi_type_sint16, "int16_t"}
	Int32 Type = Type{&C.ffi_type_sint32, "int32_t"}
	Int64 Type = Type{&C.ffi_type_sint64, "int64_t"}

	Float  Type = Type{&C.ffi_type_float, "float"}
	Double Type = Type{&C.ffi_type_double, "double"}

	Pointer Type = Type{&C.ffi_type_pointer, "void *"}
)

func (t Type) String() string {
	if len(t.name) == 0 {
		return "struct"
	} else {
		return t.name
	}
}

type Interface struct {
	ffi_cif  C.ffi_cif
	ffi_ret  *C.ffi_type
	ffi_args **C.ffi_type

	ret  Type
	args []Type
}

func Prepare(ret Type, args ...Type) (cif Interface) {
	cif.ffi_ret = ret.ffi_type
	cif.ret = ret
	cif.args = args
	argc := len(args)

	if argc != 0 {
		va := make([]*C.ffi_type, argc)

		for i, a := range args {
			va[i] = a.ffi_type
		}

		cif.ffi_args = &va[0]
	}

	if status := Status(C.ffi_prep_cif(&cif.ffi_cif, C.FFI_DEFAULT_ABI, C.uint(argc), cif.ffi_ret, cif.ffi_args)); status != OK {
		panic(status)
	}

	return
}

func (cif Interface) Call(fptr unsafe.Pointer, ret unsafe.Pointer, args ...unsafe.Pointer) (err error) {
	var va *unsafe.Pointer

	if len(args) != 0 {
		va = &args[0]
	}

	_, err = C.ffi_call(&cif.ffi_cif, C.function(fptr), ret, va)
	return
}

func (self Interface) String() string {
	return fmt.Sprint(self)
}

func (self Interface) Format(f fmt.State, r rune) {
	fmt.Fprint(f, self.ret)
	io.WriteString(f, "(*)(")

	for i, arg := range self.args {
		if i != 0 {
			io.WriteString(f, ", ")
		}
		fmt.Fprint(f, arg)
	}

	io.WriteString(f, ")")
}

func Call(fptr unsafe.Pointer, ret interface{}, args ...interface{}) (err error) {
	vret := valueOfRet(ret)
	varg := valueOfArgs(args)

	rett := makeRetType(vret)
	retv := makeRetValue(vret)

	argt := makeArgTypes(varg)
	argv := makeArgValues(varg)

	defer freeArgValues(argv, varg)

	Prepare(rett, argt...).Call(fptr, retv, argv...)

	setRetValue(vret, retv)
	return
}

func freeArgValues(varg []unsafe.Pointer, args []reflect.Value) {
	for i, a := range args {
		switch a.Kind() {
		case reflect.String:
			C.free(*(*unsafe.Pointer)(varg[i]))
		}
	}
}

func valueOfRet(ret interface{}) reflect.Value {
	v := reflect.ValueOf(ret)

	if ret != nil && v.Kind() != reflect.Ptr {
		panic(fmt.Sprintf("ffi: expected return value to be a pointer but got %T", ret))
	}

	return v
{'fraction_non_alphanumeric': 0.16181718363985725, 'fraction_numerical': 0.013450452923414768, 'mean_word_length': 3.719559585492228, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2777024', 'n_tokens_mistral': 3284, 'n_tokens_neox': 3106, 'n_words': 696}