From: Andrei Zmievski Date: Fri, 4 Aug 2006 18:09:46 +0000 (+0000) Subject: Upgrade dirname() to support IS_UNICODE. X-Git-Tag: RELEASE_1_0_0RC1~2093 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9ff2107cc17ee6ad6aa19b2c2cb0b72eabc8c819;p=php Upgrade dirname() to support IS_UNICODE. --- diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index a63dc32bcd..bd87a3be66 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -129,8 +129,10 @@ PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int freeit, PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC); PHPAPI void php_u_stripslashes(UChar *str, int *len TSRMLS_DC); PHPAPI void php_stripcslashes(char *str, int *len); -PHPAPI void php_basename(char *s, size_t len, char *suffix, size_t sufflen, char **p_ret, size_t *p_len TSRMLS_DC); -PHPAPI size_t php_dirname(char *str, size_t len); +PHPAPI void php_u_basename(UChar *s, int len, UChar *suffix, int sufflen, UChar **p_ret, int *p_len TSRMLS_DC); +PHPAPI void php_basename(char *s, int len, char *suffix, int sufflen, char **p_ret, int *p_len TSRMLS_DC); +PHPAPI int php_u_dirname(UChar *str, int len); +PHPAPI int php_dirname(char *str, int len); PHPAPI UChar *php_u_stristr(UChar *s, UChar *t, int s_len, int t_len); PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len); PHPAPI int php_u_strspn(UChar *s1, UChar *s2, UChar *s1_end, UChar *s2_end); diff --git a/ext/standard/string.c b/ext/standard/string.c index 16d6fc4330..f76988408b 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1739,7 +1739,7 @@ PHPAPI void php_u_basename(UChar *s, int len, UChar *suffix, int sufflen, UChar /* {{{ php_basename */ -PHPAPI void php_basename(char *s, size_t len, char *suffix, size_t sufflen, char **p_ret, size_t *p_len TSRMLS_DC) +PHPAPI void php_basename(char *s, int len, char *suffix, int sufflen, char **p_ret, int *p_len TSRMLS_DC) { char *ret = NULL, *c, *comp, *cend; size_t inc_len, cnt; @@ -1833,9 +1833,104 @@ PHP_FUNCTION(basename) } /* }}} */ +/* {{{ php_u_dirname + Returns directory name component of path */ +PHPAPI int php_u_dirname(UChar *path, int len) +{ + register UChar *end = path + len - 1; + unsigned int len_adjust = 0; + +#ifdef PHP_WIN32 + /* Note that on Win32 CWD is per drive (heritage from CP/M). + * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive. + */ + if ((2 <= len) && u_isalpha((UChar32)path[0]) && ((UChar)0x3a /*':'*/ == path[1])) { + /* Skip over the drive spec (if any) so as not to change */ + path += 2; + len_adjust += 2; + if (2 == len) { + /* Return "c:" on Win32 for dirname("c:"). + * It would be more consistent to return "c:." + * but that would require making the string *longer*. + */ + return len; + } + } +#elif defined(NETWARE) + /* + * Find the first occurence of : from the left + * move the path pointer to the position just after : + * increment the len_adjust to the length of path till colon character(inclusive) + * If there is no character beyond : simple return len + */ + UChar *colonpos = NULL; + colonpos = u_strchr(path, (UChar) 0x3a /*':'*/); + if(colonpos != NULL) { + len_adjust = ((colonpos - path) + 1); + path += len_adjust; + if(len_adjust == len) { + return len; + } + } +#endif + + if (len == 0) { + /* Illegal use of this function */ + return 0; + } + + /* Strip trailing slashes */ + while (end >= path && IS_U_SLASH_P(end)) { + end--; + } + if (end < path) { + /* The path only contained slashes */ + path[0] = DEFAULT_U_SLASH; + path[1] = 0; + return 1 + len_adjust; + } + + /* Strip filename */ + while (end >= path && !IS_U_SLASH_P(end)) { + end--; + } + if (end < path) { + /* No slash found, therefore return '.' */ +#ifdef NETWARE + if(len_adjust == 0) { + path[0] = (UChar) 0x2e /*'.'*/; + path[1] = 0; + return 1; //only one character + } + else { + path[0] = 0; + return len_adjust; + } +#else + path[0] = (UChar) 0x2e /*'.'*/; + path[1] = 0; + return 1 + len_adjust; +#endif + } + + /* Strip slashes which came before the file name */ + while (end >= path && IS_U_SLASH_P(end)) { + end--; + } + if (end < path) { + path[0] = DEFAULT_U_SLASH; + path[1] = 0; + return 1 + len_adjust; + } + *(end+1) = 0; + + return (size_t)(end + 1 - path) + len_adjust; +} +/* }}} */ + /* {{{ php_dirname Returns directory name component of path */ -PHPAPI size_t php_dirname(char *path, size_t len) +PHPAPI int php_dirname(char *path, int len) { register char *end = path + len - 1; unsigned int len_adjust = 0; @@ -1928,26 +2023,30 @@ PHPAPI size_t php_dirname(char *path, size_t len) } /* }}} */ -/* {{{ proto string dirname(string path) +/* {{{ proto string dirname(string path) U Returns the directory name component of the path */ PHP_FUNCTION(dirname) { - zval **str; - char *ret; - size_t ret_len; + zstr str; + int str_len; + zend_uchar str_type; + zstr ret; + int ret_len; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &str, &str_len, + &str_type) == FAILURE) { + return; } - convert_to_string_ex(str); - - ret = estrndup(Z_STRVAL_PP(str), Z_STRLEN_PP(str)); - ret_len = php_dirname(ret, Z_STRLEN_PP(str)); - RETVAL_RT_STRINGL(ret, ret_len, 0); - if (UG(unicode)) { - efree(ret); + if (str_type == IS_UNICODE) { + ret.u = eustrndup(str.u, str_len); + ret_len = php_u_dirname(ret.u, str_len); + } else { + ret.s = estrndup(str.s, str_len); + ret_len = php_dirname(ret.s, str_len); } + + RETURN_ZSTRL(ret, ret_len, str_type, 0); } /* }}} */ @@ -3048,7 +3147,6 @@ PHP_FUNCTION(substr) } /* }}} */ - /* {{{ php_adjust_limits */ PHPAPI void php_adjust_limits(zval **str, int *f, int *l) @@ -3315,9 +3413,6 @@ PHP_FUNCTION(substr_replace) } /* }}} */ - - - /* {{{ proto string quotemeta(string str) Quotes meta characters */ PHP_FUNCTION(quotemeta)