1
0
mirror of https://github.com/deuill/go-php.git synced 2024-09-21 00:40:45 +00:00

Move NewContext function to engine package

Call order is now enforced when using the root `php` package by moving
the `NewContext` function in the `engine` package, as a method of the
`Engine` method receiver. Further clean-ups have been made to the code
as a result of this change.
This commit is contained in:
Alex Palaistras 2015-10-16 14:41:13 +01:00
parent 0523266e32
commit 7ed2c81ec6
8 changed files with 60 additions and 42 deletions

View File

@ -92,6 +92,10 @@ void context_bind(engine_context *context, char *name, void *zvalptr) {
return NULL;
}
int context_write(engine_context *context, const char *str, unsigned int len) {
return contextWrite(context->parent, (void *) str, len);
}
void context_destroy(engine_context *context) {
php_request_shutdown((void *) 0);

View File

@ -81,15 +81,17 @@ func (c *Context) Eval(script string) error {
return nil
}
// Destroy tears down the current execution context along with any values binded
// in.
// Destroy tears down the current execution context along with any active value
// bindings for that context.
func (c *Context) Destroy() {
for _, v := range c.values {
v.Destroy()
}
C.context_destroy(c.context)
c = nil
if c.context != nil {
C.context_destroy(c.context)
c.context = nil
}
}
// New creates a new execution context, passing all script output into w. It
@ -107,8 +109,8 @@ func New(w io.Writer) (*Context, error) {
return ctx, nil
}
//export context_write
func context_write(ctxptr unsafe.Pointer, buffer unsafe.Pointer, length C.uint) C.int {
//export contextWrite
func contextWrite(ctxptr unsafe.Pointer, buffer unsafe.Pointer, length C.uint) C.int {
c := (*Context)(ctxptr)
written, err := c.writer.Write(C.GoBytes(buffer, C.int(length)))

View File

@ -11,13 +11,14 @@ typedef struct _engine_context {
#endif
void *parent; // Pointer to parent Go context, used for passing to callbacks.
int (*write)(void *parent, void *msg, unsigned int len);
int (*write)(struct _engine_context *context, const char *msg, unsigned int len);
} engine_context;
engine_context *context_new(void *parent);
void context_exec(engine_context *context, char *filename);
void context_eval(engine_context *context, char *script);
void context_bind(engine_context *context, char *name, void *zvalptr);
int context_write(engine_context *context, const char *str, unsigned int len);
void context_destroy(engine_context *context);
#endif

View File

@ -23,10 +23,10 @@ const char engine_ini_defaults[] =
"max_input_time = -1\n\0"
;
static int engine_ub_write(const char *str, uint str_length TSRMLS_DC) {
static int engine_ub_write(const char *str, uint str_length TSRMLS_DC) {
engine_context *context = (engine_context *) SG(server_context);
int written = context->write(context->parent, (void *) str, str_length);
int written = context->write(context, str, str_length);
if (written != str_length) {
php_handle_aborted_connection();
}

View File

@ -16,18 +16,41 @@ import "C"
import (
"fmt"
"io"
"github.com/deuill/go-php/context"
)
// Engine represents the core PHP engine bindings.
type Engine struct {
engine *C.struct__php_engine
engine *C.struct__php_engine
contexts []*context.Context
}
// Destroy shuts down and frees any resources related to the PHP engine
// bindings.
// NewContext creates a new execution context on which scripts can be executed
// and variables can be binded. It corresponds to PHP's RINIT (request init)
// phase.
func (e *Engine) NewContext(w io.Writer) (*context.Context, error) {
c, err := context.New(w)
if err != nil {
return nil, err
}
e.contexts = append(e.contexts, c)
return c, nil
}
// Destroy shuts down and frees any resources related to the PHP engine bindings.
func (e *Engine) Destroy() {
C.engine_shutdown(e.engine)
e = nil
for _, c := range e.contexts {
c.Destroy()
}
if e.engine != nil {
C.engine_shutdown(e.engine)
e.engine = nil
}
}
// New initializes a PHP engine instance on which contexts can be executed. It
@ -38,5 +61,5 @@ func New() (*Engine, error) {
return nil, fmt.Errorf("PHP engine failed to initialize")
}
return &Engine{engine: ptr}, nil
return &Engine{engine: ptr, contexts: make([]*context.Context, 0)}, nil
}

10
php.go
View File

@ -8,9 +8,6 @@
package php
import (
"io"
"github.com/deuill/go-php/context"
"github.com/deuill/go-php/engine"
)
@ -19,10 +16,3 @@ import (
func New() (*engine.Engine, error) {
return engine.New()
}
// NewContext creates a new execution context on which scripts can be executed
// and variables can be binded. It corresponds to PHP's RINIT (request init
// phase and *must* be preceeded by a call to `php.New()`.
func NewContext(w io.Writer) (*context.Context, error) {
return context.New(w)
}

View File

@ -49,12 +49,10 @@ func TestNewEngineContext(t *testing.T) {
defer e.Destroy()
ctx, err := NewContext(os.Stdout)
_, err = e.NewContext(os.Stdout)
if err != nil {
t.Errorf("NewContext(): %s", err)
}
defer ctx.Destroy()
}
var execTests = []struct {
@ -68,10 +66,9 @@ func TestContextExec(t *testing.T) {
var w MockWriter
e, _ := New()
ctx, _ := NewContext(&w)
ctx, _ := e.NewContext(&w)
defer e.Destroy()
defer ctx.Destroy()
for _, tt := range execTests {
file := path.Join(testDir, tt.file)
@ -94,16 +91,16 @@ var evalTests = []struct {
}{
{"echo 'Hello World';", "Hello World"},
{"$i = 10; $d = 20; echo $i + $d;", "30"},
{"notascript{}!!*", ""},
}
func TestContextEval(t *testing.T) {
var w MockWriter
e, _ := New()
ctx, _ := NewContext(&w)
ctx, _ := e.NewContext(&w)
defer e.Destroy()
defer ctx.Destroy()
for _, tt := range evalTests {
if err := ctx.Eval(tt.script); err != nil {
@ -135,10 +132,9 @@ func TestContextBind(t *testing.T) {
var w MockWriter
e, _ := New()
ctx, _ := NewContext(&w)
ctx, _ := e.NewContext(&w)
defer e.Destroy()
defer ctx.Destroy()
for i, tt := range bindTests {
if err := ctx.Bind(strconv.FormatInt(int64(i), 10), tt.value); err != nil {

View File

@ -36,20 +36,22 @@ func (v *Value) Ptr() unsafe.Pointer {
// Destroy removes all active references to the internal PHP value and frees
// any resources used.
func (v *Value) Destroy() {
C.value_destroy(v.value)
v = nil
if v.value != nil {
C.value_destroy(v.value)
v.value = nil
}
}
// New creates a PHP value representtion of a Go value val. Available bindings
// for Go to PHP types are:
//
// int -> integer
// float64 -> double
// bool -> boolean
// string -> string
// slice -> indexed array
// int -> integer
// float64 -> double
// bool -> boolean
// string -> string
// slice -> indexed array
// map[int|string] -> associative array
// struct -> object
// struct -> object
//
// Bindings for functions and method receivers to PHP functions and classes are
// only available in the engine scope, and must be predeclared before context