Skip to content

New setNotifier() method #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,23 @@ public CSS3Processor::__construct(void) : CSS3Processor
* Throws exceptions on errors.


```
public CSS3Processor::setNotifier(int $type, callable $callback) : bool
```

* Registers a callback for the given token `$type` that will be called
during tokenisation. The callback gets an info array of the current
token and context.
* All return values from the callback are discarded.
* The parameter `$type` can be set to any of the `extcss3` Type Constants
listed below.
* If a Modifier is registered for the same token type, the Notifier is
allways called bevore the Modifier.
* Multiple notifier callbacks per token type are possible.
* Returns `true` on success.
* Throws exceptions on errors.


```
public CSS3Processor::setModifier(int $type, callable $callback) : bool
```
Expand Down
69 changes: 69 additions & 0 deletions extcss3/intern.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ extcss3_decl *extcss3_create_decl(void)
return (extcss3_decl *)calloc(1, sizeof(extcss3_decl));
}

extcss3_sig *extcss3_create_signal(void)
{
return (extcss3_sig *)calloc(1, sizeof(extcss3_sig));
}

/* ==================================================================================================== */

void extcss3_release_intern(extcss3_intern *intern)
Expand Down Expand Up @@ -86,6 +91,10 @@ void extcss3_release_intern(extcss3_intern *intern)
}
}

if (intern->notifier.base != NULL) {
extcss3_release_signals_list(&intern->notifier);
}

free(intern);
}

Expand Down Expand Up @@ -248,6 +257,36 @@ void extcss3_release_decls_list(extcss3_decl *list)
extcss3_release_decl(list);
}

void extcss3_release_signal(extcss3_not *notifier, extcss3_sig *signal)
{
if (signal == NULL) {
return;
}

if ((signal->callable != NULL) && (notifier != NULL) && (notifier->destructor != NULL)) {
notifier->destructor(signal->callable);
}

free(signal);
}

void extcss3_release_signals_list(extcss3_not *notifier)
{
extcss3_sig *next, *list = notifier->base;

if (list == NULL) {
return;
}

while (list->next != NULL) {
next = list->next->next;
extcss3_release_signal(notifier, list->next);
list->next = next;
}

extcss3_release_signal(notifier, list);
}

/* ==================================================================================================== */

bool extcss3_set_css_string(extcss3_intern *intern, char *css, size_t len, unsigned int *error)
Expand Down Expand Up @@ -298,6 +337,36 @@ bool extcss3_set_css_string(extcss3_intern *intern, char *css, size_t len, unsig
return EXTCSS3_SUCCESS;
}

bool extcss3_set_notifier(extcss3_intern *intern, unsigned int type, void *callable, unsigned int *error)
{
extcss3_sig *signal;

if ((intern == NULL) || (intern->notifier.destructor == NULL) || (intern->notifier.callback == NULL) || (callable == NULL)) {
*error = EXTCSS3_ERR_NULL_PTR;

return EXTCSS3_FAILURE;
}

if ((signal = extcss3_create_signal()) == NULL) {
*error = EXTCSS3_ERR_MEMORY;

return EXTCSS3_FAILURE;
}

signal->type = type;
signal->callable = callable;

if (intern->notifier.base == NULL) {
intern->notifier.base = signal;
} else {
intern->notifier.last->next = signal;
}

intern->notifier.last = signal;

return EXTCSS3_SUCCESS;
}

bool extcss3_set_modifier(extcss3_intern *intern, unsigned int type, void *callable, unsigned int *error)
{
if ((intern == NULL) || (intern->modifier.destructor == NULL) || (intern->modifier.callback == NULL) || (callable == NULL)) {
Expand Down
3 changes: 3 additions & 0 deletions extcss3/intern.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ void extcss3_release_rules_list(extcss3_rule *list);
void extcss3_release_block(extcss3_block *block);
void extcss3_release_decl(extcss3_decl *decl);
void extcss3_release_decls_list(extcss3_decl *list);
void extcss3_release_signal(extcss3_not *notifier, extcss3_sig *signal);
void extcss3_release_signals_list(extcss3_not *notifier);

bool extcss3_set_css_string(extcss3_intern *intern, char *css, size_t len, unsigned int *error);
bool extcss3_set_notifier(extcss3_intern *intern, unsigned int type, void *callable, unsigned int *error);
bool extcss3_set_modifier(extcss3_intern *intern, unsigned int type, void *callable, unsigned int *error);
bool extcss3_set_vendor_string(extcss3_intern *intern, char *name, size_t len, unsigned int *error);

Expand Down
21 changes: 20 additions & 1 deletion extcss3/tokenizer/tokenizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ bool extcss3_tokenize(extcss3_intern *intern, unsigned int *error)
} else if ((intern->base_token = token = extcss3_create_token()) == NULL) {
return _extcss3_cleanup_tokenizer(*error = EXTCSS3_ERR_MEMORY, NULL, false, false);
} else if (
EXTCSS3_HAS_MODIFIER(intern) &&
((intern->notifier.base != NULL) || EXTCSS3_HAS_MODIFIER(intern)) &&
((intern->base_ctxt = intern->last_ctxt = extcss3_create_ctxt()) == NULL)
) {
return _extcss3_cleanup_tokenizer(*error = EXTCSS3_ERR_MEMORY, intern, true, false);
Expand Down Expand Up @@ -396,6 +396,7 @@ static inline bool _extcss3_next_char(extcss3_intern *intern, unsigned int *erro
static inline bool _extcss3_token_add(extcss3_intern *intern, extcss3_token *token, unsigned int *error)
{
extcss3_token *prev;
extcss3_sig *signal;

if ((token->prev = intern->last_token) != NULL) {
intern->last_token->next = token;
Expand Down Expand Up @@ -431,6 +432,24 @@ static inline bool _extcss3_token_add(extcss3_intern *intern, extcss3_token *tok
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

if (intern->base_ctxt != NULL) {
/* Calling notifier(s) */
if (((signal = intern->notifier.base) != NULL) && (intern->notifier.callback != NULL)) {
while (signal != NULL) {
if (signal->type == token->type) {
intern->notifier.callback(intern, signal);

if ((token->user.str != NULL) || (token->user.len != 0)) {
*error = EXTCSS3_ERR_INV_VALUE;

return EXTCSS3_FAILURE;
}
}

signal = signal->next;
}
}

/* Calling modifier */
if (EXTCSS3_TYPE_IS_MODIFIABLE(token->type) && (intern->modifier.callback != NULL)) {
intern->modifier.callback(intern);

Expand Down
23 changes: 23 additions & 0 deletions extcss3/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define EXTCSS3_ERR_BYTES_CORRUPTION ((unsigned int)2)
#define EXTCSS3_ERR_NULL_PTR ((unsigned int)3)
#define EXTCSS3_ERR_INV_PARAM ((unsigned int)4)
#define EXTCSS3_ERR_INV_VALUE ((unsigned int)5)

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

Expand Down Expand Up @@ -125,6 +126,10 @@ typedef struct _extcss3_ctxt extcss3_ctxt;

typedef struct _extcss3_vendor extcss3_vendor;

typedef struct _extcss3_sig extcss3_sig;

typedef struct _extcss3_not extcss3_not;

typedef struct _extcss3_mod extcss3_mod;

typedef struct _extcss3_decl extcss3_decl;
Expand Down Expand Up @@ -181,6 +186,23 @@ struct _extcss3_vendor
extcss3_vendor *next;
};

struct _extcss3_sig
{
unsigned int type;
extcss3_sig *next;

void *callable;
};

struct _extcss3_not
{
extcss3_sig *base;
extcss3_sig *last;

void (*callback)(extcss3_intern *intern, extcss3_sig *signal);
void (*destructor)(void *callable);
};

struct _extcss3_mod
{
void *string;
Expand Down Expand Up @@ -242,6 +264,7 @@ struct _extcss3_intern
extcss3_vendor *base_vendor;
extcss3_vendor *last_vendor;

extcss3_not notifier;
extcss3_mod modifier;
};

Expand Down
73 changes: 70 additions & 3 deletions php_extcss3.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ static inline void php_extcss3_throw_exception(unsigned int error)
case EXTCSS3_ERR_INV_PARAM:
zend_throw_exception(zend_ce_exception, "extcss3: Invalid paramenter or parameter type given", EXTCSS3_ERR_INV_PARAM);
break;
case EXTCSS3_ERR_INV_VALUE:
zend_throw_exception(zend_ce_exception, "extcss3: Invalid, unallowed or unexpected value found", EXTCSS3_ERR_INV_VALUE);
break;
default:
zend_throw_exception(zend_ce_exception, "extcss3: Unknown internal error", 0);
}
Expand Down Expand Up @@ -138,6 +141,32 @@ static inline void php_extcss3_make_data_array(extcss3_intern *intern, zval *dat
zval_ptr_dtor(&empty);
}

static void php_extcss3_notifier_callback(extcss3_intern *intern, extcss3_sig *signal)
{
zval data, retval, *args, *callable;

if ((intern == NULL) || (intern->last_token == NULL) || (signal == NULL)) {
return;
}

if ((callable = signal->callable) == NULL) {
return;
}

php_extcss3_make_data_array(intern, &data);

args = safe_emalloc(sizeof(zval), 1, 0);
ZVAL_COPY(&args[0], &data);

call_user_function_ex(EG(function_table), NULL, callable, &retval, 1, args, 0, NULL);

zval_ptr_dtor(&data);
zval_ptr_dtor(&args[0]);
zval_ptr_dtor(&retval);

efree(args);
}

static void php_extcss3_modifier_callback(extcss3_intern *intern)
{
zval data, retval, *args, *callable = NULL;
Expand Down Expand Up @@ -191,9 +220,9 @@ static void php_extcss3_modifier_callback(extcss3_intern *intern)
efree(args);
}

static void php_extcss3_modifier_destructor(void *modifier)
static void php_extcss3_callable_destructor(void *callable)
{
zval *ptr = (zval *)modifier;
zval *ptr = (zval *)callable;

if (ptr == NULL) {
return;
Expand Down Expand Up @@ -232,8 +261,11 @@ PHP_METHOD(CSS3Processor, __construct)
if (intern == NULL) {
php_extcss3_throw_exception(EXTCSS3_ERR_MEMORY);
} else {
intern->notifier.callback = php_extcss3_notifier_callback;
intern->notifier.destructor = php_extcss3_callable_destructor;

intern->modifier.callback = php_extcss3_modifier_callback;
intern->modifier.destructor = php_extcss3_modifier_destructor;
intern->modifier.destructor = php_extcss3_callable_destructor;

object->intern = intern;
}
Expand Down Expand Up @@ -276,6 +308,40 @@ PHP_METHOD(CSS3Processor, setModifier)
RETURN_TRUE;
}

PHP_METHOD(CSS3Processor, setNotifier)
{
extcss3_object *object = extcss3_object_fetch(Z_OBJ_P(getThis()));
extcss3_intern *intern = object->intern;
zval *callable, *copy;
size_t type;
unsigned int error = 0;

if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "lz", &type, &callable)) {
return;
} else if (intern == NULL) {
php_extcss3_throw_exception(EXTCSS3_ERR_NULL_PTR);
return;
}

copy = (zval *)ecalloc(1, sizeof(zval));

if (copy == NULL) {
php_extcss3_throw_exception(EXTCSS3_ERR_MEMORY);
return;
}

ZVAL_COPY(copy, callable);

if (EXTCSS3_SUCCESS != extcss3_set_notifier(intern, type, copy, &error)) {
intern->notifier.destructor(copy);

php_extcss3_throw_exception(error);
return;
}

RETURN_TRUE;
}

PHP_METHOD(CSS3Processor, dump)
{
extcss3_object *object = extcss3_object_fetch(Z_OBJ_P(getThis()));
Expand Down Expand Up @@ -359,6 +425,7 @@ PHP_METHOD(CSS3Processor, minify)
zend_function_entry extcss3_methods[] = {
PHP_ME(CSS3Processor, __construct, arginfo_EXTCSS3_void, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
PHP_ME(CSS3Processor, setModifier, arginfo_EXTCSS3_setModifier, ZEND_ACC_PUBLIC)
PHP_ME(CSS3Processor, setNotifier, arginfo_EXTCSS3_setModifier, ZEND_ACC_PUBLIC)
PHP_ME(CSS3Processor, dump, arginfo_EXTCSS3_dump, ZEND_ACC_PUBLIC)
PHP_ME(CSS3Processor, minify, arginfo_EXTCSS3_minify, ZEND_ACC_PUBLIC)
PHP_FE_END
Expand Down
35 changes: 35 additions & 0 deletions tests/setNotifier.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
Test CSS3Processor::setNotifier() method
--FILE--
<?php

class Test_Notifier
{
public static function A(array $aData)
{
var_dump('A: ' . $aData['value']);
}

public static function B(array $aData)
{
var_dump('B: ' . $aData['value']);

return 'foo';
}
}

$oProcessor = new \CSS3Processor();

var_dump($oProcessor->setNotifier(CSS3Processor::TYPE_AT_KEYWORD, ['Test_Notifier', 'A']));
var_dump($oProcessor->setNotifier(CSS3Processor::TYPE_AT_KEYWORD, ['Test_Notifier', 'B']));

$oProcessor->dump('@charset "UTF-8";');

?>
===DONE===
--EXPECT--
bool(true)
bool(true)
string(11) "A: @charset"
string(11) "B: @charset"
===DONE===