Re: [PATCH] preg_match(_all) support for capturing offsets
| From: | Andrei Zmievski | Date: | Thu, 06 Jun 2002 17:52:54 +0000 |
| Subject: | Re: [PATCH] preg_match(_all) support for capturing offsets | ||
| References: | 1 | Groups: | php.dev |
| Request: | Send a blank email to php-dev+get-84956@lists.php.net to get a copy of this message | ||
I will take a look at this soon, thanks.
On Thu, 06 Jun 2002, David Brown wrote:
> Hi Andrei, all:
>
> (This is a re-send of a previous message that received no replies; my
> apologies if you've already seen/considered it)
>
> In a previous patch
> (http://news.php.net/article.php?group=php.dev&article=84281), support
> was added to preg_split for capturing offsets along with matches. The
> attached patch adds similar support to preg_match and preg_match_all via
> a new PREG_MATCH_OFFSET_CAPTURE flag.
>
> The code handles capturing offsets for both subpattern matches and whole
> pattern matches, using the previously-added add_offset_pair helper function.
>
> The flag is a new fourth (and optional) parameter for preg_match, and
> are or'd into the existing 'order' parameter for preg_match_all, above
> PREG_SET_ORDER and PREG_PATTERN_ORDER.
>
> The patch below is diffed against the CVS head - humbly sumbitted for
> application, rejection, suggestions, or extensive flaming. :)
>
>
> Thanks in advance,
>
> - Dave
> dave@codewhore.org
>
>
> --- ext/pcre/php_pcre.c.orig Tue Jun 4 13:02:50 2002
> +++ ext/pcre/php_pcre.c Tue Jun 4 13:12:10 2002
> @@ -35,7 +35,9 @@
> #define PREG_PATTERN_ORDER 0
> #define PREG_SET_ORDER 1
>
> -#define PREG_SPLIT_NO_EMPTY (1<<0)
> +#define PREG_MATCH_OFFSET_CAPTURE (1<<2)
> +
> +#define PREG_SPLIT_NO_EMPTY (1<<0)
> #define PREG_SPLIT_DELIM_CAPTURE (1<<1)
> #define PREG_SPLIT_OFFSET_CAPTURE (1<<2)
>
> @@ -99,6 +101,7 @@
>
> REGISTER_LONG_CONSTANT("PREG_PATTERN_ORDER", PREG_PATTERN_ORDER, CONST_CS |
> CONST_PERSISTENT);
> REGISTER_LONG_CONSTANT("PREG_SET_ORDER", PREG_SET_ORDER, CONST_CS |
> CONST_PERSISTENT);
> + REGISTER_LONG_CONSTANT("PREG_MATCH_OFFSET_CAPTURE", PREG_MATCH_OFFSET_CAPTURE,
> CONST_CS | CONST_PERSISTENT);
> REGISTER_LONG_CONSTANT("PREG_SPLIT_NO_EMPTY", PREG_SPLIT_NO_EMPTY, CONST_CS |
> CONST_PERSISTENT);
> REGISTER_LONG_CONSTANT("PREG_SPLIT_DELIM_CAPTURE", PREG_SPLIT_DELIM_CAPTURE,
> CONST_CS | CONST_PERSISTENT);
> REGISTER_LONG_CONSTANT("PREG_SPLIT_OFFSET_CAPTURE", PREG_SPLIT_OFFSET_CAPTURE,
> CONST_CS | CONST_PERSISTENT);
> @@ -310,6 +313,24 @@
> }
> /* }}} */
>
> +/* {{{ add_offset_pair
> + */
> +static inline void add_offset_pair(zval *result, char *str, int len, int offset)
> +{
> + zval *match_pair;
> +
> + ALLOC_ZVAL(match_pair);
> + array_init(match_pair);
> + INIT_PZVAL(match_pair);
> +
> + /* Add (match, offset) to the return value */
> + add_next_index_stringl(match_pair, str, len, 1);
> + add_next_index_long(match_pair, offset);
> +
> + zend_hash_next_index_insert(Z_ARRVAL_P(result), &match_pair, sizeof(zval *), NULL);
> +}
> +/* }}} */
> +
> /* {{{ php_pcre_match
> */
> static void php_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global)
> @@ -335,6 +356,7 @@
> int matched; /* Has anything matched */
> int i;
> int subpats_order_val = 0; /* Integer value of subpats_order */
> + int offset_capture = 0; /* If offsets should be captured */
> int g_notempty = 0; /* If the match should not be empty */
> const char **stringlist; /* Used to hold list of subpatterns */
> char *match; /* The current match */
> @@ -363,11 +385,17 @@
>
> /* Make sure subpats_order is a number */
> convert_to_long_ex(subpats_order);
> - subpats_order_val = Z_LVAL_PP(subpats_order);
> - if (subpats_order_val < PREG_PATTERN_ORDER ||
> - subpats_order_val > PREG_SET_ORDER) {
> - zend_error(E_WARNING, "Wrong value for parameter 4 in call to
> preg_match_all()");
> - }
> + offset_capture = (Z_LVAL_PP(subpats_order) & PREG_MATCH_OFFSET_CAPTURE);
> +
> + if (global) {
> + subpats_order_val = (Z_LVAL_PP(subpats_order) & 1UL);
> +
> + if ((subpats_order_val < PREG_PATTERN_ORDER) ||
> + (subpats_order_val > PREG_SET_ORDER)) {
> + zend_error(E_WARNING, "Wrong value for parameter 4 in call to
> preg_match_all()");
> + }
> + }
> +
> break;
>
> default:
> @@ -442,8 +470,13 @@
> if (subpats_order_val == PREG_PATTERN_ORDER) {
> /* For each subpattern, insert it into the appropriate array. */
> for (i = 0; i < count; i++) {
> - add_next_index_stringl(match_sets[i], (char *)stringlist[i],
> - offsets[(i<<1)+1] - offsets[i<<1], 1);
> + if (offset_capture) {
> + add_offset_pair(match_sets[i], (char *)stringlist[i],
> + offsets[(i<<1)+1] - offsets[i<<1], offsets[i<<1]);
> + } else {
> + add_next_index_stringl(match_sets[i], (char *)stringlist[i],
> + offsets[(i<<1)+1] - offsets[i<<1], 1);
> + }
> }
> /*
> * If the number of captured subpatterns on this run is
> @@ -463,8 +496,13 @@
>
> /* Add all the subpatterns to it */
> for (i = 0; i < count; i++) {
> - add_next_index_stringl(result_set, (char *)stringlist[i],
> - offsets[(i<<1)+1] - offsets[i<<1], 1);
> + if (offset_capture) {
> + add_offset_pair(result_set, (char *)stringlist[i],
> + offsets[(i<<1)+1] - offsets[i<<1], offsets[i<<1]);
> + } else {
> + add_next_index_stringl(result_set, (char *)stringlist[i],
> + offsets[(i<<1)+1] - offsets[i<<1], 1);
> + }
> }
> /* And add it to the output array */
> zend_hash_next_index_insert(Z_ARRVAL_PP(subpats), &result_set,
> @@ -474,8 +512,13 @@
> else { /* single pattern matching */
> /* For each subpattern, insert it into the subpatterns array. */
> for (i = 0; i < count; i++) {
> - add_next_index_stringl((*subpats), (char *)stringlist[i],
> - offsets[(i<<1)+1] - offsets[i<<1], 1);
> + if (offset_capture) {
> + add_offset_pair((*subpats), (char *)stringlist[i],
> + offsets[(i<<1)+1] - offsets[i<<1], offsets[i<<1]);
> + } else {
> + add_next_index_stringl((*subpats), (char *)stringlist[i],
> + offsets[(i<<1)+1] - offsets[i<<1], 1);
> + }
> }
> }
>
> @@ -518,7 +561,7 @@
> }
> /* }}} */
>
> -/* {{{ proto int preg_match(string pattern, string subject [, array subpatterns])
> +/* {{{ proto int preg_match(string pattern, string subject [, array matches [, int flags]])
> Perform a Perl-style regular expression match */
> PHP_FUNCTION(preg_match)
> {
> @@ -1063,21 +1106,6 @@
> preg_replace_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
> }
> /* }}} */
> -
> -static inline void add_offset_pair(zval *result, char *str, int len, int offset)
> -{
> - zval *match_pair;
> -
> - ALLOC_ZVAL(match_pair);
> - array_init(match_pair);
> - INIT_PZVAL(match_pair);
> -
> - /* Add (match, offset) to the return value */
> - add_next_index_stringl(match_pair, str, len, 1);
> - add_next_index_long(match_pair, offset);
> -
> - zend_hash_next_index_insert(Z_ARRVAL_P(result), &match_pair, sizeof(zval *), NULL);
> -}
>
> /* {{{ proto array preg_split(string pattern, string subject [, int limit [, int flags]])
> Split string into an array using a perl-style regular expression as a delimiter */
>
-Andrei http://www.gravitonic.com/
* DOS is, quite possibly, the worst text-adventure game ever. *