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; 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) { void context_destroy(engine_context *context) {
php_request_shutdown((void *) 0); php_request_shutdown((void *) 0);

View File

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

View File

@ -11,13 +11,14 @@ typedef struct _engine_context {
#endif #endif
void *parent; // Pointer to parent Go context, used for passing to callbacks. 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;
engine_context *context_new(void *parent); engine_context *context_new(void *parent);
void context_exec(engine_context *context, char *filename); void context_exec(engine_context *context, char *filename);
void context_eval(engine_context *context, char *script); void context_eval(engine_context *context, char *script);
void context_bind(engine_context *context, char *name, void *zvalptr); 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); void context_destroy(engine_context *context);
#endif #endif

View File

@ -23,10 +23,10 @@ const char engine_ini_defaults[] =
"max_input_time = -1\n\0" "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); 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) { if (written != str_length) {
php_handle_aborted_connection(); php_handle_aborted_connection();
} }

View File

@ -16,18 +16,41 @@ import "C"
import ( import (
"fmt" "fmt"
"io"
"github.com/deuill/go-php/context"
) )
// Engine represents the core PHP engine bindings. // Engine represents the core PHP engine bindings.
type Engine struct { 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 // NewContext creates a new execution context on which scripts can be executed
// bindings. // 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() { func (e *Engine) Destroy() {
C.engine_shutdown(e.engine) for _, c := range e.contexts {
e = nil 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 // 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 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 package php
import ( import (
"io"
"github.com/deuill/go-php/context"
"github.com/deuill/go-php/engine" "github.com/deuill/go-php/engine"
) )
@ -19,10 +16,3 @@ import (
func New() (*engine.Engine, error) { func New() (*engine.Engine, error) {
return engine.New() 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() defer e.Destroy()
ctx, err := NewContext(os.Stdout) _, err = e.NewContext(os.Stdout)
if err != nil { if err != nil {
t.Errorf("NewContext(): %s", err) t.Errorf("NewContext(): %s", err)
} }
defer ctx.Destroy()
} }
var execTests = []struct { var execTests = []struct {
@ -68,10 +66,9 @@ func TestContextExec(t *testing.T) {
var w MockWriter var w MockWriter
e, _ := New() e, _ := New()
ctx, _ := NewContext(&w) ctx, _ := e.NewContext(&w)
defer e.Destroy() defer e.Destroy()
defer ctx.Destroy()
for _, tt := range execTests { for _, tt := range execTests {
file := path.Join(testDir, tt.file) file := path.Join(testDir, tt.file)
@ -94,16 +91,16 @@ var evalTests = []struct {
}{ }{
{"echo 'Hello World';", "Hello World"}, {"echo 'Hello World';", "Hello World"},
{"$i = 10; $d = 20; echo $i + $d;", "30"}, {"$i = 10; $d = 20; echo $i + $d;", "30"},
{"notascript{}!!*", ""},
} }
func TestContextEval(t *testing.T) { func TestContextEval(t *testing.T) {
var w MockWriter var w MockWriter
e, _ := New() e, _ := New()
ctx, _ := NewContext(&w) ctx, _ := e.NewContext(&w)
defer e.Destroy() defer e.Destroy()
defer ctx.Destroy()
for _, tt := range evalTests { for _, tt := range evalTests {
if err := ctx.Eval(tt.script); err != nil { if err := ctx.Eval(tt.script); err != nil {
@ -135,10 +132,9 @@ func TestContextBind(t *testing.T) {
var w MockWriter var w MockWriter
e, _ := New() e, _ := New()
ctx, _ := NewContext(&w) ctx, _ := e.NewContext(&w)
defer e.Destroy() defer e.Destroy()
defer ctx.Destroy()
for i, tt := range bindTests { for i, tt := range bindTests {
if err := ctx.Bind(strconv.FormatInt(int64(i), 10), tt.value); err != nil { 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 // Destroy removes all active references to the internal PHP value and frees
// any resources used. // any resources used.
func (v *Value) Destroy() { func (v *Value) Destroy() {
C.value_destroy(v.value) if v.value != nil {
v = nil C.value_destroy(v.value)
v.value = nil
}
} }
// New creates a PHP value representtion of a Go value val. Available bindings // New creates a PHP value representtion of a Go value val. Available bindings
// for Go to PHP types are: // for Go to PHP types are:
// //
// int -> integer // int -> integer
// float64 -> double // float64 -> double
// bool -> boolean // bool -> boolean
// string -> string // string -> string
// slice -> indexed array // slice -> indexed array
// map[int|string] -> associative array // map[int|string] -> associative array
// struct -> object // struct -> object
// //
// Bindings for functions and method receivers to PHP functions and classes are // Bindings for functions and method receivers to PHP functions and classes are
// only available in the engine scope, and must be predeclared before context // only available in the engine scope, and must be predeclared before context