diff options
author | Thies C. Arntzen <thies@php.net> | 1999-11-20 15:53:18 +0000 |
---|---|---|
committer | Thies C. Arntzen <thies@php.net> | 1999-11-20 15:53:18 +0000 |
commit | 2013026c14035c5356c2ca6fd9fd8bb8a872c0c3 (patch) | |
tree | 319ccd6143b8560c205cfd6aad213dd6b0712a26 | |
parent | 111c24b5b153a9c6d7c708839985de2fa72034cb (diff) | |
download | php-git-2013026c14035c5356c2ca6fd9fd8bb8a872c0c3.tar.gz |
@- Implemented 2-Arg version of strtr($str,$translation_array). This can be used
@ to revert what htmlspecialchars() did. (Thies)
(PHP strtr) new 2-Arg version.
-rw-r--r-- | ext/standard/string.c | 138 |
1 files changed, 125 insertions, 13 deletions
diff --git a/ext/standard/string.c b/ext/standard/string.c index 1c6e57df5d..bc3f5805b1 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1080,27 +1080,139 @@ PHPAPI char *php_strtr(char *string, int len, char *str_from, return string; } +static void php_strtr_array(zval *return_value,char *str,int slen,HashTable *hash) +{ + zval *entry; + char *string_key; + zval **trans; + zval ctmp; + ulong num_key; + int minlen = 128*1024; + int maxlen = 0, pos, len, newpos, newlen, found; + char *newstr, *key; + + zend_hash_internal_pointer_reset(hash); + while (zend_hash_get_current_data(hash, (void **)&entry) == SUCCESS) { + switch (zend_hash_get_current_key(hash, &string_key, &num_key)) { + case HASH_KEY_IS_STRING: + len = strlen(string_key); + if (len > maxlen) maxlen = len; + if (len < minlen) minlen = len; + efree(string_key); + break; + + case HASH_KEY_IS_LONG: + ctmp.type = IS_LONG; + ctmp.value.lval = num_key; + + convert_to_string(&ctmp); + len = ctmp.value.str.len; + zval_dtor(&ctmp); + + if (len > maxlen) maxlen = len; + if (len < minlen) minlen = len; + break; + } + zend_hash_move_forward(hash); + } + + key = emalloc(maxlen+1); + newstr = emalloc(8192); + newlen = 8192; + newpos = pos = 0; + + while (pos < slen) { + if ((pos + maxlen) > slen) { + maxlen = slen - pos; + } + + found = 0; + + for (len = maxlen; len >= minlen; len--) { + memcpy(key,str+pos,len); + key[ len ]=0; + + if (zend_hash_find(hash,key,len+1,(void**)&trans) == SUCCESS) { + char *tval; + int tlen; + zval tmp; + + if ((*trans)->type != IS_STRING) { + tmp = **trans; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + tval = tmp.value.str.val; + tlen = tmp.value.str.len; + } else { + tval = (*trans)->value.str.val; + tlen = (*trans)->value.str.len; + } + + if ((newpos + tlen + 1) > newlen) { + newlen = newpos + tlen + 1 + 8192; + newstr = realloc(newstr,newlen); + } + + memcpy(newstr+newpos,tval,tlen); + newpos += tlen; + pos += len; + found = 1; + + if ((*trans)->type != IS_STRING) { + zval_dtor(&tmp); + } + break; + } + } + + if (! found) { + if ((newpos + 1) > newlen) { + newlen = newpos + 1 + 8192; + newstr = realloc(newstr,newlen); + } + + newstr[ newpos++ ] = str[ pos++ ]; + } + } + + efree(key); + newstr[ newpos ] = 0; + RETURN_STRINGL(newstr,newpos,0); +} + /* {{{ proto string strtr(string str, string from, string to) Translate characters in str using given translation tables */ PHP_FUNCTION(strtr) { /* strtr(STRING,FROM,TO) */ pval **str, **from, **to; - - if (ARG_COUNT(ht) != 3 || getParametersEx(3, &str, &from, &to) == - FAILURE) { + int ac = ARG_COUNT(ht); + + if (ac < 2 || ac > 3 || getParametersEx(ac, &str, &from, &to) == FAILURE) { WRONG_PARAM_COUNT; } + + if (ac == 2 && (*from)->type != IS_ARRAY) { + php_error(E_WARNING,"arg2 must be passed an array"); + RETURN_FALSE; + } + convert_to_string_ex(str); - convert_to_string_ex(from); - convert_to_string_ex(to); - - *return_value=**str; - zval_copy_ctor(return_value); - php_strtr(return_value->value.str.val, - return_value->value.str.len, - (*from)->value.str.val, - (*to)->value.str.val, - MIN((*from)->value.str.len,(*to)->value.str.len)); + + if (ac == 2) { + php_strtr_array(return_value,(*str)->value.str.val,(*str)->value.str.len,HASH_OF(*from)); + } else { + convert_to_string_ex(from); + convert_to_string_ex(to); + + *return_value=**str; + zval_copy_ctor(return_value); + + php_strtr(return_value->value.str.val, + return_value->value.str.len, + (*from)->value.str.val, + (*to)->value.str.val, + MIN((*from)->value.str.len,(*to)->value.str.len)); + } } /* }}} */ |