Moriyoshi Koizumi
moriy****@users*****
2002年 10月 7日 (月) 06:59:22 JST
moriyoshi 02/10/07 06:59:22 Modified: ext/mbstring mbfunction.c Log: added binary safe version of strtok_r / strrchr Revision Changes Path 1.13 +158 -34 php4/ext/mbstring/mbfunction.c Index: mbfunction.c =================================================================== RCS file: /cvsroot/php-i18n/php4/ext/mbstring/mbfunction.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- mbfunction.c 6 Oct 2002 16:08:31 -0000 1.12 +++ mbfunction.c 6 Oct 2002 21:59:22 -0000 1.13 @@ -3144,7 +3144,7 @@ /* {{{ PHPAPI php_mbstr_mbchar_bytes_ex(const char *s, const php_mb_enc *enc) */ -PHPAPI int php_mb_mbchar_bytes_ex(const char *s, const php_mb_enc *enc) +PHPAPI size_t php_mb_mbchar_bytes_ex(const char *s, const php_mb_enc *enc) { if ( enc != NULL ) { if( enc->type & PHP_MB_ENCTYPE_MBCS ) { @@ -3161,57 +3161,181 @@ } /* }}} */ -/* {{{ php_mb_strtok_r_ex(char*, char*, char**, php_mb_enc *enc) */ -PHPAPI char *php_mb_strtok_r_ex(char *s1, const char *s2, char **last, php_mb_enc *enc) +/* {{{ php_mb_safe_strtok_r_ex(char*, char*, char**, size_t nbytes, php_mb_enc *enc) */ +PHPAPI char *php_mb_safe_strtok_r_ex(char *s1, size_t nbytes_s1, const char *s2, size_t nbytes_s2, php_mb_strtok_t *tok_d, php_mb_enc *enc) { - register char *p1; - register const char *p2; + char *p1; + char *retval = NULL; - int nbytes; + size_t nbytes_char; - if( s2 == NULL || last == NULL ) return NULL; + if( s2 == NULL || tok_d == NULL ) return NULL; + + if ( s1 != NULL ) { + p1 = s1; + } else { + if ( ( p1 = tok_d->last ) == NULL ) { + return NULL; + } + nbytes_s1 = tok_d->nbytes_left; + } - p1 = ( s1 ? s1 : *last ); if( p1 == NULL ) return NULL; retval = NULL; - *last = NULL; - while (*p1 != '\0') { - nbytes = php_mb_mbchar_bytes_ex( p1, enc ); - if (nbytes == 1) { - for (p2 = s2; *p2 != '\0' && *p1 == *p2; p2++); + tok_d->last = NULL; + tok_d->nbytes_left = 0; - if (*p1 != *p2) { + if ( nbytes_s1 == (size_t)-1 ) { + while (*p1 != '\0') { + register const char *p2; + register size_t bcnt_s2; + + nbytes_char = php_mb_mbchar_bytes_ex( p1, enc ); + if (nbytes_char == 1) { + if (nbytes_s2 == (size_t)-1) { + for (p2=s2; *p2!='\0' && *p1==*p2; p2++); + } else { + for (p2=s2, bcnt_s2=nbytes_s2; bcnt_s2>0 && *p1==*p2; p2++,bcnt_s2--); + } + if (*p1 != *p2) { + retval = p1; + break; + } + } else { retval = p1; break; + } + while (nbytes_char-- > 0) { + if( *(++p1) == '\0' ) goto out; } - } else { - retval = p1; - break; - } - while (--nbytes >= 0) { - if( *(++p1) == '\0' ) goto out; - } - } + } - while (*p1 != '\0') { - nbytes = php_mb_mbchar_bytes_ex( p1, enc ); - if (nbytes == 1) { - for (p2 = s2; *p2 != '\0'; p2++) { - if (*p1 == *p2) { - *p1 = '\0'; - *last = p1 + 1; - goto out; + while (*p1 != '\0') { + register const char *p2; + register size_t bcnt_s2; + + nbytes_char = php_mb_mbchar_bytes_ex( p1, enc ); + if (nbytes_char == 1) { + if (nbytes_s2 == (size_t)-1) { + for (p2=s2; *p2!='\0'; p2++) { + if (*p1 == *p2) { + *p1 = '\0'; + tok_d->last = p1 + 1; + goto out; + } + } + } else { + for (bcnt_s2=nbytes_s2,p2=s2; bcnt_s2>0; p2++,bcnt_s2--) { + if (*p1 == *p2) { + *p1 = '\0'; + tok_d->last = p1 + 1; + goto out; + } + } } } + while (nbytes_char-- >= 0) { + if( *(++p1) == '\0' ) goto out; + } + } + } else { + size_t bcnt_s1 = nbytes_s1; + + while (bcnt_s1 > 0) { + register const char *p2; + register size_t bcnt_s2; + + nbytes_char = php_mb_mbchar_bytes_ex( p1, enc ); + if (nbytes_char == 1) { + if (nbytes_s2 == (size_t)-1) { + for (p2=s2; *p2!='\0' && *p1==*p2; p2++); + } else { + for (p2=s2, bcnt_s2=nbytes_s2; bcnt_s2>0 && *p1==*p2; p2++,bcnt_s2--); + } + if (*p1 != *p2) { + retval = p1; + break; + } + } else { + retval = p1; + break; + } + if ( nbytes_char < bcnt_s1 ) { + return NULL; + } + bcnt_s1 -= nbytes_char; + if ( bcnt_s1 == 0 ) goto out; } - while (--nbytes >= 0) { - if( *(++p1) == '\0' ) goto out; - } - } + while (bcnt_s1 > 0) { + register const char *p2; + register size_t bcnt_s2; + + nbytes_char = php_mb_mbchar_bytes_ex( p1, enc ); + if (nbytes_char == 1) { + if (nbytes_s2 == (size_t)-1) { + for (p2=s2; *p2!='\0'; p2++) { + if (*p1 == *p2) { + *p1 = '\0'; + tok_d->last = p1 + 1; + tok_d->nbytes_left = bcnt_s1; + goto out; + } + } + } else { + for (bcnt_s2=nbytes_s2,p2=s2; bcnt_s2>0; p2++,bcnt_s2--) { + if (*p1 == *p2) { + *p1 = '\0'; + tok_d->last = p1 + 1; + tok_d->nbytes_left = bcnt_s1; + goto out; + } + } + } + } + if ( nbytes_char < bcnt_s1 ) { + return NULL; + } + bcnt_s1 -= nbytes_char; + if ( bcnt_s1 == 0 ) goto out; + } + } out: return retval; +} +/* }}} */ + +/* {{{ php_mb_safe_strrchr_ex(const char *s, char c, php_mb_enc *enc) + */ +PHPAPI char *php_mb_safe_strrchr_ex(const char *s, unsigned int c, size_t nbytes, php_mb_enc *enc) +{ + register const char *p = s; + char *last; + + if (nbytes == (size_t)-1) { + while ( *p != '\0') { + if (*p == c) { + last = (char *)p; + } + p += php_mb_mbchar_bytes_ex( p, enc ); + } + } else { + register size_t bcnt = nbytes; + register size_t nbytes_char; + while ( bcnt > 0 ) { + if (*p == c) { + last = (char *)p; + } + nbytes_char = php_mb_mbchar_bytes_ex( p, enc ); + if ( bcnt < nbytes_char ) { + return NULL; + } + p += nbytes_char; + bcnt -= nbytes_char; + } + } + return last; } /* }}} */