Last active
December 15, 2015 18:38
-
-
Save krakjoe/5304945 to your computer and use it in GitHub Desktop.
a (completely untested) unified php api, perhaps, just the "gist" ... its correct "enough" ...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* +----------------------------------------------------------------------+ | |
| 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 | | |
| [email protected] so we can mail you a copy immediately. | | |
+----------------------------------------------------------------------+ | |
| Author: Sara Golemon ([email protected]) | | |
| Author: Joe Watkins ([email protected]) | | |
+----------------------------------------------------------------------+ | |
*/ | |
#ifndef PHP_API_H | |
#define PHP_API_H | |
#include "zend_execute.h" | |
#include "zend_API.h" | |
#include "zend_operators.h" | |
#include "zend_hash.h" | |
#include "zend_list.h" | |
/** | |
* All APIs in this file follow a general format: | |
* | |
* php_{$verb}{$modifier}_{$type}(zval *pzval, ...) | |
* | |
* $verb is one of: | |
* exists - Boolean check whether the array offset exists | |
* fetch - Retrieve the value at $pzval[$key] | |
* unset - Delete the named offset | |
* | |
* $modifier specifies what type of offset (key) is being used: | |
* <no modifer> - NULL terminated string variable, unknown length | |
* l - NULL terminated string variable, known length | |
* l_safe - String variable of known length, not necessarily NULL terminated | |
* n - Long (integer) offset | |
* c - NULL terminated string literal (e.g. "foo" rather than foo) | |
* z - zval* offset, type should be NULL, BOOL, LONG, DOUBLE, or STRING | |
* | |
* $type is specific to the "fetch" verb: | |
* <no type> - Fetch a zval* of any type | |
* bool - Fetch a zend_bool (converting as needed) | |
* long - Fetch a long (converting as needed) | |
* double - Fetch a double (converting as needed) | |
* string - Fetch a string (converting as needed, caller may need to free) | |
* array - Fetch an array (no conversion from other types) | |
* object - Fetch an object (no conversion, type spec optional) | |
* resource - Fetch a resource (no conversion, type spec mandatory) | |
* | |
* See the specific subsection for additional details | |
*/ | |
/* isset($pzval[$key]) - Check for the existence of a key within an array | |
* | |
* zend_bool php_exists(zval *pzval, const char *key) | |
* zend_bool php_existsc(zval *pzval, const char *litstr) | |
* zend_bool php_existsl(zval *pzval, const char *key, int key_len) | |
* zend_bool php_existsl_safe(zval *pzval, const char *key, int key_len) | |
* zend_bool php_existsn(zval *pzval, ulong idx) | |
* zend_bool php_existsz(zval *pzval, zval *key) | |
*/ | |
static inline | |
zend_bool php_api_exists(zval *pzval, const char *key, size_t keylen, zend_ulong idx, zend_bool safe TSRMLS_DC) { | |
zend_bool exists = 0; | |
char *ukey = NULL; | |
size_t ulen = keylen; | |
/* perform safety for key */ | |
if (safe) { | |
ukey = estrndup(key); | |
} else ukey = (char*) key; | |
/* just an idea, but it might be nice in debug/some other mode | |
to warn the user of the unexpected */ | |
#if defined(PHP_API_PEDANTIC) | |
/* we expect null terminated strings */ | |
if (ulen != 0L && | |
ukey[ulen] != '\0') { | |
/* free key if copied */ | |
if (safe) { | |
efree(ukey); | |
} | |
/* copy key, null terminate and correct length */ | |
ukey = emalloc( | |
ulen + 1); | |
memcpy(ukey, key, ulen); | |
ukey[++ulen] = '\0'; | |
/* mark as safe to efree key */ | |
safe = 1; | |
/* output a warning in this mode for developer */ | |
} | |
/* anything else ?? */ | |
#endif | |
switch (Z_TYPE(pzval)) { | |
case IS_ARRAY: | |
/* normal array_exists/isset */ | |
if (ulen == 0L) { | |
exists = zend_hash_index_exists(Z_ARRVAL_P(pzval), idx); | |
} else exists = zend_hash_exists(Z_ARRVAL_P(pzval), ukey, ulen); | |
break; | |
case IS_OBJECT: { | |
/* attempt to use handlers where they are set */ | |
zend_object_has_property_t handle = Z_OBJ_HT_P(pzval)->has_property; | |
if (handle) { | |
/* if we are using indexes then create a key from the index */ | |
if (ulen == 0L) { | |
/* calculate length of key */ | |
ulen = snprintf( | |
NULL, 0, "%lu", idx); | |
/* allocate and format key */ | |
ukey = emalloc(ulen + 1); | |
if (ukey) { | |
snprintf( | |
ukey, ulen, "%lu", idx); | |
} | |
/* mark safe to efree key */ | |
safe = 1; | |
} | |
/* perform call to handler */ | |
exists = handle(pzval, ukey, ulen, 2 NULL TSRMLS_CC); | |
} else { | |
/* fallback on std properties */ | |
HashTable *properties = Z_OBJPROP_P(pzval); | |
/* check so we can report the unexpected */ | |
if (properties) { | |
if (ulen == 0L) { | |
exists = zend_hash_index_exists(properties, idx); | |
} else exists = zend_hash_exists(properties, ukey, ulen); | |
} | |
#if defined(PHP_API_PEDANTIC) | |
else { | |
/* do something, we do not expect null property tables */ | |
} | |
#endif | |
} | |
} | |
} | |
/* perform safety cleanup */ | |
if (safe) { | |
efree(ukey); | |
} | |
return exists; | |
} | |
#define php_exists(p, k)\ | |
php_api_exists(p, k, strlen(k)+1, 0L, 0 TSRMLS_CC) | |
#define php_existsc(p, k)\ | |
php_api_exists(p, k, sizeof(k), 0L, 0 TSRMLS_CC) | |
#define php_existsl(p, k, l)\ | |
php_exists_api(p, k, l+1, 0L, 0 TSRMLS_CC) | |
#define php_existsl_safe(p, k, l, s)\ | |
php_api_exists(p, k, l, 0L, s TSRMLS_CC) | |
#define php_existsn(p, k)\ | |
php_api_exists(p, NULL, 0L, idx, 0 TSRMLS_CC) | |
static inline | |
zend_bool php_api_existsz(zval *pzval, zval *key TSRMLS_DC) { | |
switch (Z_TYPE_P(key)) { | |
case IS_NULL: | |
return php_api_exists(pzval, "", 1, 0L, 0 TSRMLS_CC); | |
case IS_BOOL: | |
case IS_LONG: | |
return php_api_exists(pzval, NULL, 0L, Z_LVAL_P(key), 0 TSRMLS_CC); | |
case IS_DOUBLE: | |
return php_api_exists(pzval, NULL, 0L, zend_dval_to_lval(Z_DVAL_P(key)), 0 TSRMLS_CC); | |
case IS_STRING: | |
return php_api_exists(pzval, Z_STRVAL_P(key), Z_STRLEN_P(key)+1, 0L, 0 TSRMLS_CC); | |
default: | |
return 0; | |
} | |
} | |
#endif /* PHP_API_H */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment