Commits

Ruslan Osmanov committed dca6f13

Add: EventBuffer::setPosition method
Add: EventBufferPosition class

  • Participants
  • Parent commits 560bbc9

Comments (0)

Files changed (16)

 		return;
 	}
 
-	PHP_EVENT_FETCH_BASE(b, zbase)
+	PHP_EVENT_FETCH_BASE(b, zbase);
 
 	RETVAL_LONG(event_base_get_features(b->base));
 }
 #include "src/util.h"
 #include "src/priv.h"
 
-extern int le_event_buffer_pos;
-
-/* {{{ proto resource EventBuffer::__construct(void); */
+/* {{{ proto EventBuffer EventBuffer::__construct(void); */
 PHP_METHOD(EventBuffer, __construct)
 {
 	php_event_buffer_t *b;
  */
 PHP_METHOD(EventBuffer, search)
 {
-	zval                *zbuf       = getThis();
-	zval                *zstart_pos = NULL;
-	zval                *zend_pos   = NULL;
-	zval                *zwhat;
-	php_event_buffer_t  *b;
-	struct evbuffer_ptr *start_pos  = NULL;
-	struct evbuffer_ptr *end_pos    = NULL;
-	struct evbuffer_ptr *res_pos;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r!r!",
-				&zwhat, &zstart_pos, &zend_pos) == FAILURE) {
+	zval                   *zbuf       = getThis();
+	zval                   *zstart_pos = NULL;
+	zval                   *zend_pos   = NULL;
+	char                   *what;
+	int                     what_len;
+	php_event_buffer_t     *b;
+	php_event_buffer_pos_t *start_pos  = NULL;
+	php_event_buffer_pos_t *end_pos    = NULL;
+	php_event_buffer_pos_t *res_pos;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|O!O!",
+				&what, &what_len,
+				&zstart_pos, php_event_buffer_pos_ce,
+				&zend_pos, php_event_buffer_pos_ce) == FAILURE) {
 		return;
 	}
 
 	PHP_EVENT_FETCH_BUFFER(b, zbuf);
 
+	PHP_EVENT_INIT_CLASS_OBJECT(return_value, php_event_buffer_pos_ce);
+	PHP_EVENT_FETCH_BUFFER_POS(res_pos, return_value);
+
 	if (zstart_pos) {
 		PHP_EVENT_FETCH_BUFFER_POS(start_pos, zstart_pos);
 	}
 
-	res_pos = emalloc(sizeof(struct evbuffer_ptr));
-
 	if (zend_pos) {
 		PHP_EVENT_FETCH_BUFFER_POS(end_pos, zend_pos);
 
-		*res_pos = evbuffer_search(b->buf, Z_STRVAL_P(zwhat), (size_t) Z_STRLEN_P(zwhat), start_pos);
+		res_pos->p = evbuffer_search_range(b->buf, what, (size_t) what_len,
+				&start_pos->p, &end_pos->p);
 	} else {
-		*res_pos = evbuffer_search_range(b->buf, Z_STRVAL_P(zwhat), (size_t) Z_STRLEN_P(zwhat),
-				start_pos, end_pos);
+		res_pos->p = evbuffer_search(b->buf, what, (size_t) what_len, &start_pos->p);
 	}
 
-	if (res_pos->pos == -1) {
-		efree(res_pos);
+	if (res_pos->p.pos == -1) {
 		RETURN_NULL();
 	}
+}
+/* }}} */
+
+/* {{{ proto bool EventBuffer::setPosition(resource &pos, int value, int how);
+ *
+ * Manipulates the position pos within buffer. If how is EventBuffer::PTR_SET,
+ * the pointer is moved to an absolute position position within the buffer. If
+ * it is EventBuffer::PTR_ADD, the pointer moves position bytes forward.
+ */
+PHP_METHOD(EventBuffer, setPosition)
+{
+	zval                *zbuf  = getThis();
+	zval                *zpos;
+	long                 value;
+	long                 how;
+	php_event_buffer_t  *b;
+	php_event_buffer_pos_t *pos   = NULL;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oll",
+				&zpos, php_event_buffer_pos_ce, &value, &how) == FAILURE) {
+		return;
+	}
+
+	if (how & ~(EVBUFFER_PTR_SET | EVBUFFER_PTR_ADD)) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid mask");
+		RETURN_FALSE;
+	}
 
-	ZEND_REGISTER_RESOURCE(return_value, res_pos, le_event_buffer_pos);
+	PHP_EVENT_FETCH_BUFFER(b, zbuf);
+	PHP_EVENT_FETCH_BUFFER_POS(pos, zpos);
+
+	if (evbuffer_ptr_set(b->buf, &pos->p, value, how)) {
+		RETURN_FALSE;
+	}
+
+	RETVAL_TRUE;
 }
 /* }}} */
 

classes/buffer_pos.c

+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 5                                                        |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2013 The PHP Group                                |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Author: Ruslan Osmanov <osmanov@php.net>                             |
+   +----------------------------------------------------------------------+
+*/
+#include "src/common.h"
+#include "src/util.h"
+#include "src/priv.h"
+
+/* {{{ proto EventBufferPosition EventBufferPosition::__construct(void); */
+PHP_METHOD(EventBufferPosition, __construct)
+{
+	php_event_buffer_pos_t *p;
+
+	if (zend_parse_parameters_none() == FAILURE) {
+		return;
+	}
+
+	PHP_EVENT_FETCH_BUFFER_POS(p, getThis());
+	p->p.pos = 0;
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4 sts=4
+ */
     classes/event_config.c \
     classes/buffer_event.c \
     classes/buffer.c \
+    classes/buffer_pos.c \
     classes/event_util.c"
 
   dnl {{{ --with-event-extra

examples/buffer_position.php

+<?php
+
+/* Count total occurances of 'str' in 'buf' */
+function count_instances($buf, $str) {
+    $total = 0;
+	$p = new EventBufferPosition();
+
+    $buf->setPosition($p, 0, EventBuffer::PTR_SET);
+
+	$i = 0;
+    while (1) {
+        $p = $buf->search($str, $p);
+        if (!$p) {
+            break;
+		}
+        ++$total;
+        $buf->setPosition($p, 1, EventBuffer::PTR_ADD);
+    }
+
+    return $total;
+}
+
+$buf = new EventBuffer();
+$buf->add("Some string within a string inside another string");
+var_dump(count_instances($buf, "str"));
+
+?>

examples/httpv0client.php

 function readcb($bev, $base) {
 	$input = $bev->getInput();
 
+	$pos = $input->search("TTP");
+	var_dump($pos);
+
 	while (($n = $input->remove($buf, 1024)) > 0) {
 		echo $buf;
 	}
   <date>2013-02-06</date>
   <!--{{{ Current version -->
   <version>
-    <release>1.1.1</release>
+    <release>1.1.2</release>
     <api>1.1.0</api>
   </version>
   <stability>
   <notes><![CDATA[
   Fix: non-static zend_always_inline function failed to compile with some (non-zts) php setups
   Change: static EventBuffer::addBuffer made non-static with one argument
-  Add: EventBuffer expand, prepend, prependBuffer, drain, copyout, readLine, search methods
+  Add: EventBuffer expand, prepend, prependBuffer, drain, copyout, readLine, search,
+  setPosition methods
+  Add: EventBufferPosition class
+  Fix: configure error in FreeBSD
   ]]></notes>
   <!--}}}-->
   <!--{{{ Contents -->
   <!--{{{ 1.1.1-beta-->
   <release>
   <version>
-    <release>1.1.1</release>
+    <release>1.1.2</release>
     <api>1.1.0</api>
   </version>
   <stability>
   <notes><![CDATA[
   Fix: non-static zend_always_inline function failed to compile with some (non-zts) php setups
   Change: static EventBuffer::addBuffer made non-static with one argument
-  Add: EventBuffer expand, prepend, prependBuffer, drain, copyout, readLine, search methods
+  Add: EventBuffer expand, prepend, prependBuffer, drain, copyout, readLine, search,
+  setPosition methods
+  Add: EventBufferPosition class
+  Fix: configure error in FreeBSD
   ]]></notes>
   </release>
   <!--}}}-->
-
     <!--{{{ 1.1.1-devel -->
     <release>
       <version>
 zend_class_entry *php_event_bevent_ce;
 zend_class_entry *php_event_buffer_ce;
 zend_class_entry *php_event_util_ce;
+zend_class_entry *php_event_buffer_pos_ce;
 
 #if HAVE_EVENT_EXTRA_LIB
 zend_class_entry *php_event_dns_base_ce;
 static HashTable event_config_properties;
 static HashTable event_bevent_properties;
 static HashTable event_buffer_properties;
+static HashTable event_buffer_pos_properties;
 
 static zend_object_handlers object_handlers;
 
-int le_event_buffer_pos;
-
 static const zend_module_dep event_deps[] = {
 	ZEND_MOD_OPTIONAL("sockets")
 	{NULL, NULL, NULL}
 }
 /* }}} */
 
+/* {{{ event_buffer_pos_object_free_storage */
+static void event_buffer_pos_object_free_storage(void *ptr TSRMLS_DC)
+{
+	event_generic_object_free_storage(ptr TSRMLS_CC);
+}
+/* }}} */
+
 
 /* {{{ register_object */
 static zend_always_inline zend_object_value register_object(zend_class_entry *ce, void *obj, zend_objects_store_dtor_t func_dtor, zend_objects_free_object_storage_t func_free_storage TSRMLS_DC)
 }
 /* }}} */
 
+/* {{{ event_buffer_pos_object_create
+ * EventBufferPosition object ctor */
+static zend_object_value event_buffer_pos_object_create(zend_class_entry *ce TSRMLS_DC)
+{
+	php_event_abstract_object_t *obj = (php_event_abstract_object_t *) object_new(ce, sizeof(php_event_buffer_pos_t) TSRMLS_CC);
+
+	return register_object(ce, (void *) obj, (zend_objects_store_dtor_t) zend_objects_destroy_object,
+			event_buffer_pos_object_free_storage TSRMLS_CC);
+}
+/* }}} */
+
 #if HAVE_EVENT_EXTRA_LIB
 
 /* {{{ event_dns_base_object_create
 	PHP_EVENT_DECL_CLASS_PROPERTIES(ce, event_buffer_property_entry_info);
 	zend_hash_add(&classes, ce->name, ce->name_length + 1, &event_buffer_properties, sizeof(event_buffer_properties), NULL);
 
+	PHP_EVENT_REGISTER_CLASS("EventBufferPosition", event_buffer_pos_object_create, php_event_buffer_pos_ce,
+			php_event_buffer_pos_ce_functions);
+	ce = php_event_buffer_pos_ce;
+	ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
+	zend_hash_init(&event_buffer_pos_properties, 0, NULL, NULL, 1);
+	PHP_EVENT_ADD_CLASS_PROPERTIES(&event_buffer_pos_properties, event_buffer_pos_property_entries);
+	PHP_EVENT_DECL_CLASS_PROPERTIES(ce, event_buffer_pos_property_entry_info);
+	zend_hash_add(&classes, ce->name, ce->name_length + 1, &event_buffer_pos_properties, sizeof(event_buffer_pos_properties), NULL);
+
 #if HAVE_EVENT_EXTRA_LIB
 
 	PHP_EVENT_REGISTER_CLASS("EventDnsBase", event_dns_base_object_create, php_event_dns_base_ce,
 }
 /* }}} */
 
-/* {{{ php_event_buffer_pos_dtor */
-static void php_event_buffer_pos_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
-	struct evbuffer_ptr *p = (struct evbuffer_ptr *) rsrc->ptr;
-
-	efree(p);
-}
-/* }}} */
-
 /* Private functions }}} */
 
 
 /* {{{ PHP_MINIT_FUNCTION */
 PHP_MINIT_FUNCTION(event)
 {
-	le_event_buffer_pos = zend_register_list_destructors_ex(php_event_buffer_pos_dtor, NULL, PHP_EVENT_BUFFER_POS_RES_NAME, module_number);
-
 	zend_object_handlers *std_hnd = zend_get_std_object_handlers();
 
 	memcpy(&object_handlers, std_hnd, sizeof(zend_object_handlers));
 #if LIBEVENT_VERSION_NUMBER >= 0x02010100
 	REGISTER_EVENT_CLASS_CONST_LONG(php_event_buffer_ce, EOL_NUL,         EVBUFFER_EOL_NUL);
 #endif
+	REGISTER_EVENT_CLASS_CONST_LONG(php_event_buffer_ce, PTR_SET,         EVBUFFER_PTR_SET);
+	REGISTER_EVENT_CLASS_CONST_LONG(php_event_buffer_ce, PTR_ADD,         EVBUFFER_PTR_ADD);
 
 	/* Handle libevent's error logging more gracefully than it's default
 	 * logging to stderr, or calling abort()/exit() */
 #ifndef PHP_EVENT_H
 #define PHP_EVENT_H
 
-#define PHP_EVENT_VERSION "1.1.1-beta"
+#define PHP_EVENT_VERSION "1.1.2-beta"
 
 
 extern zend_module_entry event_module_entry;
 
 #include "src/common.h"
 
-#define PHP_EVENT_BUFFER_POS_RES_NAME "EventBuffer Position"
-
 PHP_MINIT_FUNCTION(event);
 PHP_MSHUTDOWN_FUNCTION(event);
 PHP_RINIT_FUNCTION(event);
 	ZEND_ARG_INFO(0, end)
 ZEND_END_ARG_INFO();
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_evbuffer_set_position, 0, 0, 3)
+	ZEND_ARG_INFO(1, pos)
+	ZEND_ARG_INFO(0, value)
+	ZEND_ARG_INFO(0, how)
+ZEND_END_ARG_INFO();
+
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_event_socket_1, 0, 0, 0)
 	ZEND_ARG_INFO(0, socket)
 	PHP_ME(EventBuffer, copyout,       arginfo_evbuffer_remove,        ZEND_ACC_PUBLIC)
 	PHP_ME(EventBuffer, readLine,      arginfo_evbuffer_read_line,     ZEND_ACC_PUBLIC)
 	PHP_ME(EventBuffer, search,        arginfo_evbuffer_search,        ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, setPosition,   arginfo_evbuffer_set_position,  ZEND_ACC_PUBLIC)
 
 	PHP_FE_END
 };
 };
 /* }}} */
 
+const zend_function_entry php_event_buffer_pos_ce_functions[] = {/* {{{ */
+	PHP_ME(EventBufferPosition, __construct, arginfo_event__void, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+
+	PHP_FE_END
+};
+/* }}} */
+
 #if HAVE_EVENT_EXTRA_LIB
 /* {{{ Extra API */
 
 PHP_METHOD(EventBuffer, copyout);
 PHP_METHOD(EventBuffer, readLine);
 PHP_METHOD(EventBuffer, search);
+PHP_METHOD(EventBuffer, setPosition);
 
 PHP_METHOD(EventUtil, getLastSocketErrno);
 PHP_METHOD(EventUtil, getLastSocketError);
 
+PHP_METHOD(EventBufferPosition, __construct);
+
 #if HAVE_EVENT_EXTRA_LIB
 /* {{{ Extra API */
 
 }
 /* }}} */
 
+/* {{{ event_buffer_pos_position_prop_read */
+static int event_buffer_pos_position_prop_read(php_event_abstract_object_t *obj, zval **retval TSRMLS_DC)
+{
+	php_event_buffer_pos_t *pos = (php_event_buffer_pos_t *) obj;
+
+	MAKE_STD_ZVAL(*retval);
+	ZVAL_LONG(*retval, pos->p.pos);
+
+	return SUCCESS;
+}
+/* }}} */
+
 /* {{{ event_bevent_priority_write */
 static int event_bevent_priority_write(php_event_abstract_object_t *obj, zval *value TSRMLS_DC)
 {
 	{"contiguous_space", sizeof("contiguous_space") - 1, event_buffer_contiguous_space_prop_read, NULL, NULL},
     {NULL, 0, NULL, NULL, NULL}
 };
-const php_event_property_entry_t event_util_property_entries[] = {
+const php_event_property_entry_t event_buffer_pos_property_entries[] = {
+	{"position", sizeof("position") - 1, event_buffer_pos_position_prop_read, NULL, NULL},
     {NULL, 0, NULL, NULL, NULL}
 };
 
 	{ZEND_ACC_PUBLIC, "contiguous_space", sizeof("contiguous_space") - 1, -1, 0, NULL, 0, NULL},
 	{0, NULL, 0, -1, 0, NULL, 0, NULL}
 };
-const zend_property_info event_util_property_entry_info[] = {
+const zend_property_info event_buffer_pos_property_entry_info[] = {
+	{ZEND_ACC_PUBLIC, "position", sizeof("position") - 1, -1, 0, NULL, 0, NULL},
 	{0, NULL, 0, -1, 0, NULL, 0, NULL}
 };
 
 extern const zend_function_entry php_event_bevent_ce_functions[];
 extern const zend_function_entry php_event_buffer_ce_functions[];
 extern const zend_function_entry php_event_util_ce_functions[];
+extern const zend_function_entry php_event_buffer_pos_ce_functions[];
 
 extern zend_class_entry *php_event_ce;
 extern zend_class_entry *php_event_base_ce;
 extern zend_class_entry *php_event_config_ce;
 extern zend_class_entry *php_event_bevent_ce;
 extern zend_class_entry *php_event_buffer_ce;
+extern zend_class_entry *php_event_buffer_pos_ce;
 extern zend_class_entry *php_event_util_ce;
 
 extern const php_event_property_entry_t event_property_entries[];
 extern const php_event_property_entry_t event_config_property_entries[];
 extern const php_event_property_entry_t event_bevent_property_entries[];
 extern const php_event_property_entry_t event_buffer_property_entries[];
-extern const php_event_property_entry_t event_util_property_entries[];
+extern const php_event_property_entry_t event_buffer_pos_property_entries[];
 
 extern const zend_property_info event_property_entry_info[];
 extern const zend_property_info event_base_property_entry_info[];
 extern const zend_property_info event_config_property_entry_info[];
 extern const zend_property_info event_bevent_property_entry_info[];
 extern const zend_property_info event_buffer_property_entry_info[];
-extern const zend_property_info event_util_property_entry_info[];
+extern const zend_property_info event_buffer_pos_property_entry_info[];
 
 #if HAVE_EVENT_EXTRA_LIB
 
 
 #endif/* HAVE_EVENT_EXTRA_LIB }}} */
 
+typedef struct {
+	PHP_EVENT_OBJECT_HEAD;
+
+	struct evbuffer_ptr p;
+} php_event_buffer_pos_t;
+
 typedef double php_event_timestamp_t;
 
 typedef int (*php_event_prop_read_t)(php_event_abstract_object_t *obj, zval **retval TSRMLS_DC);
         Z_SET_ISREF_P((pz))
 
 #define PHP_EVENT_FETCH_EVENT(e, ze) \
-	e = (php_event_t *) zend_object_store_get_object(ze TSRMLS_CC);
+	e = (php_event_t *) zend_object_store_get_object(ze TSRMLS_CC)
 
 #define PHP_EVENT_FETCH_BASE(base, zbase) \
-	base = (php_event_base_t *) zend_object_store_get_object(zbase TSRMLS_CC);
+	base = (php_event_base_t *) zend_object_store_get_object(zbase TSRMLS_CC)
 
 #define PHP_EVENT_FETCH_CONFIG(cfg, zcfg) \
-	cfg = (php_event_config_t *) zend_object_store_get_object(zcfg TSRMLS_CC);
+	cfg = (php_event_config_t *) zend_object_store_get_object(zcfg TSRMLS_CC)
 
 #define PHP_EVENT_FETCH_BEVENT(b, zb) \
-	b = (php_event_bevent_t *) zend_object_store_get_object(zb TSRMLS_CC);
+	b = (php_event_bevent_t *) zend_object_store_get_object(zb TSRMLS_CC)
 
 #define PHP_EVENT_FETCH_BUFFER(b, zb) \
-	b = (php_event_buffer_t *) zend_object_store_get_object(zb TSRMLS_CC);
+	b = (php_event_buffer_t *) zend_object_store_get_object(zb TSRMLS_CC)
 
 #define PHP_EVENT_FETCH_DNS_BASE(b, zb) \
-	b = (php_event_dns_base_t *) zend_object_store_get_object(zb TSRMLS_CC);
+	b = (php_event_dns_base_t *) zend_object_store_get_object(zb TSRMLS_CC)
 
 #define PHP_EVENT_FETCH_LISTENER(b, zb) \
-	b = (php_event_listener_t *) zend_object_store_get_object(zb TSRMLS_CC);
+	b = (php_event_listener_t *) zend_object_store_get_object(zb TSRMLS_CC)
 
 #define PHP_EVENT_FETCH_HTTP_CONN(b, zb) \
-	b = (php_event_http_conn_t *) zend_object_store_get_object(zb TSRMLS_CC);
+	b = (php_event_http_conn_t *) zend_object_store_get_object(zb TSRMLS_CC)
 
 #define PHP_EVENT_FETCH_HTTP(b, zb) \
-	b = (php_event_http_t *) zend_object_store_get_object(zb TSRMLS_CC);
+	b = (php_event_http_t *) zend_object_store_get_object(zb TSRMLS_CC)
 
 #define PHP_EVENT_FETCH_BUFFER_POS(p, zp) \
-	ZEND_FETCH_RESOURCE((p), struct evbuffer_ptr *, &(zp), -1, PHP_EVENT_BUFFER_POS_RES_NAME, le_event_buffer_pos)
+	p = (php_event_buffer_pos_t *) zend_object_store_get_object(zp TSRMLS_CC)
 
 #define PHP_EVENT_TIMEVAL_SET(tv, t)                     \
         do {                                             \

tests/05-buffer-pos.phpt

+--TEST--
+Check for manupulation with buffer position
+--FILE--
+<?php
+/* Count total occurances of 'str' in 'buf' */
+function count_instances($buf, $str) {
+    $total = 0;
+	$p = new EventBufferPosition();
+
+    $buf->setPosition($p, 0, EventBuffer::PTR_SET);
+
+	$i = 0;
+    while (1) {
+        $p = $buf->search($str, $p);
+        if (!$p) {
+            break;
+		}
+        ++$total;
+        $buf->setPosition($p, 1, EventBuffer::PTR_ADD);
+    }
+
+    return $total;
+}
+
+// 1 12 123 1234 .. 123..9
+$i = 1;
+$s = "";
+$a = "";
+while ($i < 10) {
+	$s .= $i;
+	$a .= $s ." ";
+	++$i;
+}
+
+$buf = new EventBuffer();
+$buf->add($a);
+
+while (--$i > 0) {
+	echo $i, " - ", count_instances($buf, $i), PHP_EOL;
+}
+?>
+--EXPECT--
+9 - 1
+8 - 2
+7 - 3
+6 - 4
+5 - 5
+4 - 6
+3 - 7
+2 - 8
+1 - 9
+