cvs: embed /php-irssi ext-irssi.c

[email protected] ("Wez Furlong") Sat, 01 Feb 2003 04:46:56 -0000
Newsgroups php.embed.cvs
Message-ID <cvswez1044074816@cvsserver>
wez		Fri Jan 31 23:46:56 2003 EDT

  Modified files:              
    /embed/php-irssi	ext-irssi.c 
  Log:
  Implement irssi_signal_remove().
  
  
Index: embed/php-irssi/ext-irssi.c
diff -u embed/php-irssi/ext-irssi.c:1.5 embed/php-irssi/ext-irssi.c:1.6
--- embed/php-irssi/ext-irssi.c:1.5	Fri Jan 31 13:11:56 2003
+++ embed/php-irssi/ext-irssi.c	Fri Jan 31 23:46:56 2003
@@ -14,7 +14,7 @@
   +----------------------------------------------------------------------+
   | Author: Wez Furlong <[email protected]>                                    |
   +----------------------------------------------------------------------+
-  $Id: ext-irssi.c,v 1.5 2003/01/31 18:11:56 tal Exp $
+  $Id: ext-irssi.c,v 1.6 2003/02/01 04:46:56 wez Exp $
 */
 #include "php-irssi.h"
 #include "php-signals-list.h" /* generated by php during make */
@@ -24,12 +24,6 @@
  * Avoid stale pointer mess by keeping a copy of identifiers rather than
  * pointers to the actual records.  This may be slightly slower than holding
  * pointers, but at least it is safe.
- *
- * Make sure the OO works without needing (PHP) references as this causes
- * headaches.
- *
- * Use accessor functions rather than properties.
- * Could write overloaded objects where a property make sense.
  * */
 
 struct sig_record {
@@ -180,6 +174,39 @@
 	}
 }
 
+static char * signal_hash_key(char *signame, zval *callback TSRMLS_DC)
+{
+	char *key = NULL;
+	
+	if (Z_TYPE_P(callback) == IS_ARRAY) {
+		zval **obj = NULL, **func = NULL;
+
+		zend_hash_index_find(Z_ARRVAL_P(callback), 0, (void**)&obj);
+		zend_hash_index_find(Z_ARRVAL_P(callback), 1, (void**)&func);
+
+		if (obj == NULL || func == NULL) {
+			return NULL;
+		}
+
+		convert_to_string_ex(func);
+		
+		if (Z_TYPE_PP(obj) == IS_OBJECT) {
+			spprintf(&key, 0, "%s@%d@%s", signame, (*obj)->value.obj.handle, Z_STRVAL_PP(func));
+			return key;
+		}
+		
+		/* class name */
+		convert_to_string_ex(obj);
+		spprintf(&key, 0, "%s@%s@%s", signame, Z_STRVAL_PP(obj), Z_STRVAL_PP(func));
+		return key;
+	}
+	if (Z_TYPE_P(callback) == IS_STRING) {
+		spprintf(&key, 0, "%s@%s", signame, Z_STRVAL_P(callback));
+		return key;	
+	}
+	return NULL;
+}
+
 /* proto void irssi_signal_add(string signalname, mixed callback, [long priority, mixed sigarg])
    Binds a function to a signal. priority is one of the IRSSI_PRIORITY_XXX constants */
 PHP_FUNCTION(irssi_signal_add)
@@ -190,7 +217,8 @@
 	long priority = SIGNAL_PRIORITY_DEFAULT;
 	int sigid;
 	struct sig_record *rec;
-
+	char *sighash = NULL;
+	
 	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|lz!",
 				&signame, &signame_len,
 				&funcname,
@@ -200,6 +228,11 @@
 		return;
 	}
 	
+	sighash = signal_hash_key(signame, funcname TSRMLS_CC);
+	if (sighash == NULL) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash signal handler");
+	}
+	
 	rec = emalloc(sizeof(struct sig_record));
 	
 	sigid = signal_get_uniq_id(signame);
@@ -218,10 +251,16 @@
 		rec->arg = NULL;
 	}
 
-	zend_hash_next_index_insert(bound_signals, &rec, sizeof(rec), NULL);
+	if (sighash) {
+		zend_hash_update(bound_signals, sighash, strlen(sighash)+1, &rec, sizeof(rec), NULL);
+		efree(sighash);
+	} else {
+		zend_hash_next_index_insert(bound_signals, &rec, sizeof(rec), NULL);
+	}
 	
 	signal_add_full_id(MODULE_NAME, priority, sigid, sig_func, rec);
 
+	
 }
 
 /* fetches the optional arg registered when an event handler was bound */
@@ -242,6 +281,7 @@
 	
 }
 
+/* Trigger a signal */
 PHP_FUNCTION(irssi_signal_emit)
 {
 	const void *args[6];
@@ -287,7 +327,7 @@
 				args[i] = &Z_LVAL_PP(zargs[i+1]);
 				break;
 			case PIAT_ARRAY_OF_STRING:
-				/* make it into a GSList of char * */
+				/* TODO: make it into a GSList of char * */
 			default:
 				args[i] = NULL;
 		}
@@ -296,16 +336,49 @@
 			args[2], args[3], args[4], args[5]);
 }
 
+
+
+/* Un-bind a signal */
 PHP_FUNCTION(irssi_signal_remove)
 {
+	zval *sigarg = NULL, *funcname, *tmp;
+	char *signame;
+	long signame_len;
+	int sigid;
+	struct sig_record **rec;
+	char *sighash = NULL;
+	
+	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|z!",
+				&signame, &signame_len,
+				&funcname,
+				&sigarg
+				)) {
+		return;
+	}
+	
+	sighash = signal_hash_key(signame, funcname TSRMLS_CC);
+	if (sighash == NULL) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash signal handler");
+		RETURN_FALSE;
+	}
+	
+	if (FAILURE == zend_hash_find(bound_signals, sighash, strlen(sighash)+1, (void**)&rec)) {
+		/* Could not find this handler in our list */
+		RETURN_FALSE;
+	}
 
-}
+	signal_remove_id((*rec)->signal_id, sig_func, rec);
 
+	zend_hash_del(bound_signals, sighash, strlen(sighash)+1);
+	
+	efree(sighash);
 
+	RETURN_TRUE;
+}
 
 static void sig_rec_dtor(void *pDest)
 {
-	struct sig_record *rec = *(struct sig_record**)pDest;
+	struct sig_record *rec = *(struct sig_record **)pDest;
 
 	if (rec->handler) {
 		zval_ptr_dtor(&rec->handler);
@@ -318,6 +391,7 @@
 	efree(rec);
 }
 
+
 PHP_MINIT_FUNCTION(irssi)
 {
 	ALLOC_HASHTABLE(bound_signals);
@@ -360,6 +434,7 @@
 	REGISTER_LONG_CONSTANT("IRSSI_SIGNAL_PRIORITY_DEFAULT", SIGNAL_PRIORITY_DEFAULT, CONST_CS|CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("IRSSI_SIGNAL_PRIORITY_LOW", SIGNAL_PRIORITY_LOW, CONST_CS|CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("IRSSI_SIGNAL_PRIORITY_HIGH", SIGNAL_PRIORITY_HIGH, CONST_CS|CONST_PERSISTENT);
+
 	REGISTER_STRING_CONSTANT("PHP_IRSSI_VERSION", PHP_IRSSI_VERSION, CONST_CS|CONST_PERSISTENT);
 	
 	return SUCCESS;