Wrapped a bunch of stuff just because I could

This commit is contained in:
Brandon Dyck 2022-11-27 21:49:36 -07:00
parent 880c237e6d
commit 28e7040a09
4 changed files with 133 additions and 28 deletions

6
cgo.c
View File

@ -18,4 +18,8 @@ int vm_create_function(ph7_vm *pVm, const char *zName, void *pUserData) {
int vm_config_err_report(ph7_vm *pVm) {
return ph7_vm_config(pVm, PH7_VM_CONFIG_ERR_REPORT);
}
}
int vm_output_length(ph7_vm *pVm, unsigned int *pLength) {
return ph7_vm_config(pVm, PH7_VM_OUTPUT_LENGTH, pLength);
}

1
cgo.h
View File

@ -4,6 +4,7 @@
int engine_config_err_log(ph7 *pEngine, const char **pzPtr, int *pLen);
int vm_extract_output(ph7_vm *pVm, const char **pzPtr, int *pLen);
int vm_config_err_report(ph7_vm *pVm);
int vm_output_length(ph7_vm *pVm, unsigned int *pLength);
extern int write_vm_output(void*, unsigned int, void*);
int vm_set_output_callback(ph7_vm *pVm, void *pUserData);

150
ph7.go
View File

@ -192,7 +192,26 @@ func (c *Context) ResultString(s string) error {
return newError(C.ph7_result_string((*C.ph7_context)(c), cs, C.int(len(s))))
}
// TODO (*Context).ResultStringFormat maybe? Or just use fmt.Sprint*.
type resultWriter Context
func (rw *resultWriter) Write(p []byte) (int, error) {
cp := C.CBytes(p)
defer C.free(cp)
err := newError(C.ph7_result_string(
(*C.ph7_context)(rw),
(*C.char)(cp),
C.int(len(p))))
if err != nil {
return 0, err
}
return len(p), nil
}
func (c *Context) ResultWriter() io.Writer {
return (*resultWriter)(c)
}
// ph7_result_string_format is redundant when we have fmt.Sprintf and fmt.Fprintf.
func (c *Context) ResultValue(value *Value) error {
return newError(C.ph7_result_value((*C.ph7_context)(c), (*C.ph7_value)(value)))
@ -200,16 +219,25 @@ func (c *Context) ResultValue(value *Value) error {
// TODO (*Context).ResultResource
func (c *Context) Write(p []byte) (int, error) {
type outputWriter Context
func (ow *outputWriter) Write(p []byte) (int, error) {
cp := C.CBytes(p)
defer C.free(cp)
err := newError(C.ph7_context_output((*C.ph7_context)(c), (*C.char)(cp), C.int(len(p))))
err := newError(C.ph7_context_output(
(*C.ph7_context)(ow),
(*C.char)(cp),
C.int(len(p))))
if err != nil {
return 0, err
}
return len(p), nil
}
func (c *Context) OutputWriter() io.Writer {
return (*outputWriter)(c)
}
type Severity int
const (
@ -225,7 +253,7 @@ func (c *Context) ThrowError(severity Severity, msg string) error {
return newError(C.ph7_context_throw_error((*C.ph7_context)(c), C.int(severity), cmsg))
}
// TODO (*Context).ThrowErrorFormat maybe?
// ph7_context_throw_error_format is redundant when we have fmt.Sprintf.
func (c *Context) RandomNum() uint {
return uint(C.ph7_context_random_num((*C.ph7_context)(c)))
@ -246,7 +274,10 @@ func (c *Context) RandomString(length int) (string, error) {
// TODO (*Context).PushAuxData
// TODO (*Context).PeekAuxData
// TODO (*Context).PopAuxData
// TODO (*Context).ResultBufLength
func (c *Context) ResultBufLength() uint {
return uint(C.ph7_context_result_buf_length((*C.ph7_context)(c)))
}
func (c *Context) FunctionName() string {
return C.GoString(C.ph7_function_name((*C.ph7_context)(c)))
@ -258,6 +289,8 @@ func (c *Context) FunctionName() string {
type Value C.ph7_value
// TODO Make *Value a fmt.Formatter, or at least a Stringer.
func (v *Value) ToInt() int {
return int(C.ph7_value_to_int((*C.ph7_value)(v)))
}
@ -290,16 +323,58 @@ func (v *Value) CompareStrict(v2 *Value) int {
return int(C.ph7_value_compare((*C.ph7_value)(v), (*C.ph7_value)(v2), 1))
}
// TODO (*Value).Int
// TODO (*Value).Int64
// TODO (*Value).Bool
// TODO (*Value).Null
// TODO (*Value).Double
// TODO (*Value).String
// TODO (*Value).StringFormat maybe?
// TODO (*Value).ResetStringCursor
func (v *Value) Int(n int) error {
return newError(C.ph7_value_int((*C.ph7_value)(v), C.int(n)))
}
func (v *Value) Int64(n int64) error {
return newError(C.ph7_value_int64((*C.ph7_value)(v), C.ph7_int64(n)))
}
func (v *Value) Bool(b bool) error {
var cb C.int
if b {
cb = 1
}
return newError(C.ph7_value_bool((*C.ph7_value)(v), cb))
}
func (v *Value) Null() error {
return newError(C.ph7_value_null((*C.ph7_value)(v)))
}
func (v *Value) Double(d float64) error {
return newError(C.ph7_value_double((*C.ph7_value)(v), C.double(d)))
}
func (v *Value) String(s string) error {
cstr := C.CString(s)
defer C.free(unsafe.Pointer(cstr))
return newError(C.ph7_value_string(
(*C.ph7_value)(v),
cstr,
C.int(len(s))))
}
func (v *Value) Write(p []byte) error {
cp := C.CBytes(p)
defer C.free(cp)
return newError(C.ph7_value_string(
(*C.ph7_value)(v),
(*C.char)(cp),
C.int(len(p))))
}
func (v *Value) ResetStringCursor() error {
return newError(C.ph7_value_reset_string_cursor((*C.ph7_value)(v)))
}
// TODO (*Value).Resource
// TODO (*Value).Release
func (v *Value) Release() error {
return newError(C.ph7_value_release((*C.ph7_value)(v)))
}
// TODO (*Value).ArrayFetch
// TODO (*Value).ArrayWalk
// TODO (*Value).ArrayAddElem
@ -360,18 +435,36 @@ func (v *Value) IsEmpty() bool {
// ph7_lib_init is unnecessary when single-threaded, and possibly always.
// TODO Config
// TODO Shutdown
// TODO IsThreadsafe
// TODO Version
// TODO Signature
// TODO Ident
// TODO Copyright
func Shutdown() error {
return newError(C.ph7_lib_shutdown())
}
func IsThreadsafe() bool {
return C.ph7_lib_is_threadsafe() != 0
}
func Version() string {
return C.GoString(C.ph7_lib_version())
}
func Signature() string {
return C.GoString(C.ph7_lib_signature())
}
func Ident() string {
return C.GoString(C.ph7_lib_ident())
}
func Copyright() string {
return C.GoString(C.ph7_lib_copyright()) +
"\ngo-ph7 by Brandon Dyck. Do whatever the hell you want with it."
}
type VM struct {
ptr *C.ph7_vm
pointerKey unsafe.Pointer
outputWriter io.Writer
// TODO clear outputWriteError when resetting VM
ptr *C.ph7_vm
pointerKey unsafe.Pointer
outputWriter io.Writer
outputWriteErr error
userFunctionKeys []unsafe.Pointer
}
@ -401,6 +494,13 @@ func (vm *VM) SetOutputWriter(w io.Writer) error {
// TODO PH7_VM_CONFIG_IMPORT_PATH
// TODO PH7_VM_CONFIG_RECURSION_DEPTH
func (vm *VM) OutputLength() (uint, error) {
var n C.uint
err := newError(C.vm_output_length(vm.ptr, &n))
return uint(n), err
}
// TODO PH7_VM_CONFIG_CREATE_SUPER
// TODO PH7_VM_CONFIG_CREATE_VAR
// TODO PH7_VM_CONFIG_HTTP_REQUEST
@ -414,7 +514,6 @@ func (vm *VM) SetOutputWriter(w io.Writer) error {
// TODO PH7_VM_CONFIG_EXEC_VALUE
// TODO PH7_VM_CONFIG_IO_STREAM
// TODO PH7_VM_CONFIG_ARGV_ENTRY
// TODO PH7_VM_CONFIG_EXTRACT_OUTPUT
// TODO PH7_VM_CONFIG_ERR_LOG_HANDLER
// TODO (*VM).Dump(w io.Writer)
@ -445,6 +544,7 @@ func (vm *VM) Exec() error {
}
func (vm *VM) Reset() error {
vm.outputWriteErr = nil
return newError(C.ph7_vm_reset(vm.ptr))
}

View File

@ -168,7 +168,7 @@ func TestContextWrite(t *testing.T) {
var written int
f := func(ctx *ph7.Context) error {
var err error
written, err = ctx.Write([]byte(s))
written, err = ctx.OutputWriter().Write([]byte(s))
return err
}
@ -204,7 +204,7 @@ func TestFunctionName(t *testing.T) {
defer close()
f := func(ctx *ph7.Context) error {
_, err := fmt.Fprint(ctx, ctx.FunctionName())
_, err := fmt.Fprint(ctx.OutputWriter(), ctx.FunctionName())
return err
}
mustSucceed(t, vm.CreateFunction("doStuff", CtxFunc(f)))