Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
SammyK committed May 17, 2020
0 parents commit 682bbe0
Show file tree
Hide file tree
Showing 10 changed files with 386 additions and 0 deletions.
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
*.lo
*.la
.libs
acinclude.m4
aclocal.m4
autom4te.cache
build
config.guess
config.h
config.h.in
config.log
config.nice
config.status
config.sub
configure
configure.ac
configure.in
include
install-sh
libtool
ltmain.sh
Makefile
Makefile.fragments
Makefile.global
Makefile.objects
missing
mkinstalldirs
modules
run-tests.php
tests/*/*.diff
tests/*/*.out
tests/*/*.php
tests/*/*.exp
tests/*/*.log
tests/*/*.sh
2 changes: 2 additions & 0 deletions CREDITS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cereal
Sammy Kaye Powers <[email protected]>
Empty file added EXPERIMENTAL
Empty file.
160 changes: 160 additions & 0 deletions cereal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/* cereal extension for PHP (c) 2020 Sammy Kaye Powers <[email protected]> */

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "php.h"
#include "ext/standard/info.h"
#include "php_cereal.h"
#include "cereal_arginfo.h"

#define CEREAL_ARENA_SIZE 1024 // TODO Figure out how much we need

ZEND_DECLARE_MODULE_GLOBALS(cereal)

typedef struct cereal_obj {
zend_object *obj;
struct cereal_obj *prev;
} cereal_obj;

ZEND_TLS cereal_obj *cereals;
ZEND_TLS zend_arena *cereal_arena;

zend_class_entry *cereal_ce_ptr;

static zend_object *_cereal_obj_create(zend_class_entry *ce)
{
zend_object *obj;
cereal_obj *c;

if (CEREAL_G(use_arena) == 1) {
obj = zend_arena_calloc(&cereal_arena, 1, sizeof(zend_object) + zend_object_properties_size(ce));
zend_object_std_init(obj, ce);
object_properties_init(obj, ce);
obj->handlers = &std_object_handlers;
c = zend_arena_calloc(&cereal_arena, 1, sizeof(cereal_obj));
} else {
obj = zend_objects_new(ce);
object_properties_init(obj, ce);
c = (cereal_obj *) ecalloc(1, sizeof(cereal_obj));
}

c->obj = obj;
c->prev = cereals;
cereals = c;

GC_ADDREF(obj);

return obj;
}

static void php_cereal_init_globals(zend_cereal_globals *cereal_globals)
{
cereal_globals->use_arena = 0;
}

/* For compatibility with older PHP versions */
#ifndef ZEND_PARSE_PARAMETERS_NONE
#define ZEND_PARSE_PARAMETERS_NONE() \
ZEND_PARSE_PARAMETERS_START(0, 0) \
ZEND_PARSE_PARAMETERS_END()
#endif

PHP_FUNCTION(get_cereal)
{
ZEND_PARSE_PARAMETERS_NONE();

ZVAL_OBJ(return_value, cereal_ce_ptr->create_object(cereal_ce_ptr));
}

PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("cereal.use_arena", "0", PHP_INI_SYSTEM, OnUpdateBool, use_arena, zend_cereal_globals, cereal_globals)
PHP_INI_END()

static PHP_MINIT_FUNCTION(cereal)
{
#if defined(ZTS) && defined(COMPILE_DL_CEREAL)
ZEND_TSRMLS_CACHE_UPDATE();
#endif
ZEND_INIT_MODULE_GLOBALS(cereal, php_cereal_init_globals, NULL);
REGISTER_INI_ENTRIES();

zend_class_entry _ce;
INIT_CLASS_ENTRY(_ce, "Cereal", class_Cereal_methods);
_ce.create_object = _cereal_obj_create;
cereal_ce_ptr = zend_register_internal_class_ex(&_ce, NULL);
cereal_ce_ptr->ce_flags |= ZEND_ACC_FINAL;
zend_declare_property_string(cereal_ce_ptr, ZEND_STRL("name"), "", ZEND_ACC_PUBLIC);
zend_declare_property_string(cereal_ce_ptr, ZEND_STRL("milk"), "", ZEND_ACC_PUBLIC);

return SUCCESS;
}

static PHP_MSHUTDOWN_FUNCTION(cereal)
{
return SUCCESS;
}

static PHP_RINIT_FUNCTION(cereal)
{
cereals = NULL;
if (CEREAL_G(use_arena) == 1) {
cereal_arena = zend_arena_create(CEREAL_ARENA_SIZE);
}

return SUCCESS;
}

static PHP_RSHUTDOWN_FUNCTION(cereal)
{
if (CEREAL_G(use_arena) == 1) {
php_printf("Freeing arena (%p)\n", cereal_arena);
zend_arena_destroy(cereal_arena);
cereal_arena = NULL;
} else {
cereal_obj *c = cereals;
cereal_obj *tmp;

while (c) {
tmp = c->prev;
php_printf("Freeing cereal #%lu (%p)\n", (unsigned long) c->obj->handle, c);
GC_DELREF(c->obj);
zend_object_std_dtor(c->obj);
efree(c);
c = tmp;
}
cereals = NULL;
}

return SUCCESS;
}

static PHP_MINFO_FUNCTION(cereal)
{
php_info_print_table_start();
php_info_print_table_header(2, "cereal support", "enabled");
php_info_print_table_end();

DISPLAY_INI_ENTRIES();
}

zend_module_entry cereal_module_entry = {
STANDARD_MODULE_HEADER,
"cereal", /* Extension name */
ext_functions, /* zend_function_entry */
PHP_MINIT(cereal), /* PHP_MINIT - Module initialization */
PHP_MSHUTDOWN(cereal), /* PHP_MSHUTDOWN - Module shutdown */
PHP_RINIT(cereal), /* PHP_RINIT - Request initialization */
PHP_RSHUTDOWN(cereal), /* PHP_RSHUTDOWN - Request shutdown */
PHP_MINFO(cereal), /* PHP_MINFO - Module info */
PHP_CEREAL_VERSION, /* Version */
STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_CEREAL
# ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
# endif
ZEND_GET_MODULE(cereal)
#endif
11 changes: 11 additions & 0 deletions cereal.stub.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

/** @generate-function-entries */

/**
* @property string $name The name of the cereal
* @property string $milk The type of the milk
*/
class Cereal {}

function get_cereal(): Cereal {}
18 changes: 18 additions & 0 deletions cereal_arginfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* This is a generated file, edit the .stub.php file instead. */

ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_get_cereal, 0, 0, Cereal, 0)
ZEND_END_ARG_INFO()


ZEND_FUNCTION(get_cereal);


static const zend_function_entry ext_functions[] = {
ZEND_FE(get_cereal, arginfo_get_cereal)
ZEND_FE_END
};


static const zend_function_entry class_Cereal_methods[] = {
ZEND_FE_END
};
10 changes: 10 additions & 0 deletions config.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
PHP_ARG_ENABLE([cereal],
[whether to enable cereal support],
[AS_HELP_STRING([--enable-cereal],
[Enable cereal support])],
[no])

if test "$PHP_CEREAL" != "no"; then
AC_DEFINE(HAVE_CEREAL, 1, [ Have cereal support ])
PHP_NEW_EXTENSION(cereal, cereal.c, $ext_shared)
fi
25 changes: 25 additions & 0 deletions php_cereal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* cereal extension for PHP (c) 2020 Sammy Kaye Powers <[email protected]> */

#ifndef PHP_CEREAL_H
# define PHP_CEREAL_H

extern zend_module_entry cereal_module_entry;
# define phpext_cereal_ptr &cereal_module_entry

# define PHP_CEREAL_VERSION "0.1.0"

# if defined(ZTS) && defined(COMPILE_DL_CEREAL)
ZEND_TSRMLS_CACHE_EXTERN()
# endif

ZEND_BEGIN_MODULE_GLOBALS(cereal)
int use_arena;
ZEND_END_MODULE_GLOBALS(cereal)

#ifdef ZTS
#define CEREAL_G(v) TSRMG(cereal_globals_id, zend_cereal_globals *, v)
#else
#define CEREAL_G(v) (cereal_globals.v)
#endif

#endif /* PHP_CEREAL_H */
67 changes: 67 additions & 0 deletions tests/001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
--TEST--
Test non-arena functionality
--SKIPIF--
<?php if (!extension_loaded('cereal')) die('skip: cereal extension required'); ?>
--INI--
cereal.use_arena=0
--FILE--
<?php
echo 'Where are my Lucky Charms?' . PHP_EOL;
$cereal = new Cereal();
$cereal->name = 'Lucky Charms';
var_dump($cereal);

$cereal2 = get_cereal();
$cereal2->name = 'Cinnamon Toast Crunch';
$cereal2->milk = 'almond';
var_dump($cereal2);

function userlandCereals() {
foreach (range(0, 3) as $i) {
$c = new Cereal();
echo 'Made userland cereal #' . spl_object_id($c) . PHP_EOL;
}
}

function internalCereals() {
foreach (range(0, 3) as $i) {
$c = get_cereal();
echo 'Made internal cereal #' . spl_object_id($c) . PHP_EOL;
}
}

userlandCereals();
internalCereals();
?>
--EXPECTF--
Where are my Lucky Charms?
object(Cereal)#1 (2) {
["name"]=>
string(12) "Lucky Charms"
["milk"]=>
string(0) ""
}
object(Cereal)#2 (2) {
["name"]=>
string(21) "Cinnamon Toast Crunch"
["milk"]=>
string(6) "almond"
}
Made userland cereal #3
Made userland cereal #4
Made userland cereal #5
Made userland cereal #6
Made internal cereal #7
Made internal cereal #8
Made internal cereal #9
Made internal cereal #10
Freeing cereal #10 (%s)
Freeing cereal #9 (%s)
Freeing cereal #8 (%s)
Freeing cereal #7 (%s)
Freeing cereal #6 (%s)
Freeing cereal #5 (%s)
Freeing cereal #4 (%s)
Freeing cereal #3 (%s)
Freeing cereal #2 (%s)
Freeing cereal #1 (%s)
58 changes: 58 additions & 0 deletions tests/002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
--TEST--
Test arena functionality
--SKIPIF--
<?php if (!extension_loaded('cereal')) die('skip: cereal extension required'); ?>
--INI--
cereal.use_arena=1
--FILE--
<?php
echo 'Where are my Lucky Charms?' . PHP_EOL;
$cereal = new Cereal();
$cereal->name = 'Lucky Charms';
var_dump($cereal);

$cereal2 = get_cereal();
$cereal2->name = 'Cinnamon Toast Crunch';
$cereal2->milk = 'almond';
var_dump($cereal2);

function userlandCereals() {
foreach (range(0, 3) as $i) {
$c = new Cereal();
echo 'Made userland cereal #' . spl_object_id($c) . PHP_EOL;
}
}

function internalCereals() {
foreach (range(0, 3) as $i) {
$c = get_cereal();
echo 'Made internal cereal #' . spl_object_id($c) . PHP_EOL;
}
}

userlandCereals();
internalCereals();
?>
--EXPECTF--
Where are my Lucky Charms?
object(Cereal)#1 (2) {
["name"]=>
string(12) "Lucky Charms"
["milk"]=>
string(0) ""
}
object(Cereal)#2 (2) {
["name"]=>
string(21) "Cinnamon Toast Crunch"
["milk"]=>
string(6) "almond"
}
Made userland cereal #3
Made userland cereal #4
Made userland cereal #5
Made userland cereal #6
Made internal cereal #7
Made internal cereal #8
Made internal cereal #9
Made internal cereal #10
Freeing arena (%s)

0 comments on commit 682bbe0

Please sign in to comment.