[Pcre-svn] [138] code/trunk: Preliminary substitute function…

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [138] code/trunk: Preliminary substitute function ( not yet tested or documented).
Revision: 138
          http://www.exim.org/viewvc/pcre2?view=rev&revision=138
Author:   ph10
Date:     2014-11-08 16:09:24 +0000 (Sat, 08 Nov 2014)


Log Message:
-----------
Preliminary substitute function (not yet tested or documented).

Modified Paths:
--------------
    code/trunk/Makefile.am
    code/trunk/doc/pcre2_match_data_create_from_pattern.3
    code/trunk/doc/pcre2api.3
    code/trunk/src/pcre2.h.in
    code/trunk/src/pcre2_match_data.c
    code/trunk/src/pcre2_substring.c


Added Paths:
-----------
    code/trunk/src/pcre2_substitute.c


Modified: code/trunk/Makefile.am
===================================================================
--- code/trunk/Makefile.am    2014-11-08 16:07:30 UTC (rev 137)
+++ code/trunk/Makefile.am    2014-11-08 16:09:24 UTC (rev 138)
@@ -314,6 +314,7 @@
   src/pcre2_pattern_info.c \
   src/pcre2_string_utils.c \
   src/pcre2_study.c \
+  src/pcre2_substitute.c \
   src/pcre2_substring.c \
   src/pcre2_tables.c \
   src/pcre2_ucd.c \


Modified: code/trunk/doc/pcre2_match_data_create_from_pattern.3
===================================================================
--- code/trunk/doc/pcre2_match_data_create_from_pattern.3    2014-11-08 16:07:30 UTC (rev 137)
+++ code/trunk/doc/pcre2_match_data_create_from_pattern.3    2014-11-08 16:09:24 UTC (rev 138)
@@ -7,7 +7,7 @@
 .B #include <pcre2.h>
 .PP
 .nf
-.B pcre2_match_data_create_from_pattern(pcre2_code *\fIcode\fP,
+.B pcre2_match_data_create_from_pattern(const pcre2_code *\fIcode\fP,
 .B "  pcre2_general_context *\fIgcontext\fP);"
 .fi
 .


Modified: code/trunk/doc/pcre2api.3
===================================================================
--- code/trunk/doc/pcre2api.3    2014-11-08 16:07:30 UTC (rev 137)
+++ code/trunk/doc/pcre2api.3    2014-11-08 16:09:24 UTC (rev 138)
@@ -1,4 +1,4 @@
-.TH PCRE2API 3 "03 November 2014" "PCRE2 10.00"
+.TH PCRE2API 3 "08 November 2014" "PCRE2 10.00"
 .SH NAME
 PCRE2 - Perl-compatible regular expressions (revised API)
 .sp
@@ -25,7 +25,7 @@
 .B pcre2_match_data_create(uint32_t \fIovecsize\fP,
 .B "  pcre2_general_context *\fIgcontext\fP);"
 .sp
-.B pcre2_match_data_create_from_pattern(pcre2_code *\fIcode\fP,
+.B pcre2_match_data_create_from_pattern(const pcre2_code *\fIcode\fP,
 .B "  pcre2_general_context *\fIgcontext\fP);"
 .sp
 .B int pcre2_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
@@ -178,14 +178,14 @@
 .B int pcre2_jit_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
 .B "  PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
 .B "  uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
-.B "  pcre2_match_context *\fImcontext\fP, pcre2_jit_stack *\fIjit_stack\fP);"
+.B "  pcre2_match_context *\fImcontext\fP);"
 .sp
 .B void pcre2_jit_free_unused_memory(pcre2_general_context *\fIgcontext\fP);
 .sp
 .B pcre2_jit_stack *pcre2_jit_stack_create(pcre2_general_context *\fIgcontext\fP,
 .B "  PCRE2_SIZE \fIstartsize\fP, PCRE2_SIZE \fImaxsize\fP);"
 .sp
-.B void pcre2_jit_stack_assign(const pcre2_code *\fIcode\fP,
+.B void pcre2_jit_stack_assign(pcre2_match_context *\fImcontext\fP,
 .B "  pcre2_jit_callback \fIcallback_function\fP, void *\fIcallback_data\fP);"
 .sp
 .B void pcre2_jit_stack_free(pcre2_jit_stack *\fIjit_stack\fP);
@@ -783,8 +783,9 @@
 \fBpcre2_config()\fP with \fBwhere\fP set to NULL.) The buffer is filled with a
 string that contains the name of the architecture for which the JIT compiler is
 configured, for example "x86 32bit (little endian + unaligned)". If JIT support
-is not available, PCRE2_ERROR_BADOPTION is returned, otherwise the length of
-the string, in code units, is returned.
+is not available, PCRE2_ERROR_BADOPTION is returned, otherwise the number of
+code units used is returned. This is the length of the string, plus one unit
+for the terminating zero.
 .sp
   PCRE2_CONFIG_LINKSIZE
 .sp
@@ -851,8 +852,8 @@
 \fBpcre2_config()\fP with \fBwhere\fP set to NULL.) If PCRE2 has been compiled
 without Unicode support, the buffer is filled with the text "Unicode not
 supported". Otherwise, the Unicode version string (for example, "7.0.0") is
-inserted. The string is zero-terminated. The function returns the length of the
-string in code units.
+inserted. The number of code units used is returned. This is the length of the
+string plus one unit for the terminating zero.
 .sp
   PCRE2_CONFIG_UNICODE
 .sp
@@ -864,8 +865,9 @@
 The \fIwhere\fP argument should point to a buffer that is at least 12 code
 units long. (The exact length needed can be found by calling
 \fBpcre2_config()\fP with \fBwhere\fP set to NULL.) The buffer is filled with
-the PCRE2 version string, zero-terminated. The length of the string (in code
-units) is returned.
+the PCRE2 version string, zero-terminated. The number of code units used is 
+returned. This is the length of the string plus one unit for the terminating 
+zero.
 .
 .
 .\" HTML <a name="compiling"></a>
@@ -1261,14 +1263,14 @@
 .B int pcre2_jit_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
 .B "  PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
 .B "  uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
-.B "  pcre2_match_context *\fImcontext\fP, pcre2_jit_stack *\fIjit_stack\fP);"
+.B "  pcre2_match_context *\fImcontext\fP);"
 .sp
 .B void pcre2_jit_free_unused_memory(pcre2_general_context *\fIgcontext\fP);
 .sp
 .B pcre2_jit_stack *pcre2_jit_stack_create(pcre2_general_context *\fIgcontext\fP,
 .B "  PCRE2_SIZE \fIstartsize\fP, PCRE2_SIZE \fImaxsize\fP);"
 .sp
-.B void pcre2_jit_stack_assign(const pcre2_code *\fIcode\fP,
+.B void pcre2_jit_stack_assign(pcre2_match_context *\fImcontext\fP,
 .B "  pcre2_jit_callback \fIcallback_function\fP, void *\fIcallback_data\fP);"
 .sp
 .B void pcre2_jit_stack_free(pcre2_jit_stack *\fIjit_stack\fP);
@@ -1642,7 +1644,7 @@
 .B pcre2_match_data_create(uint32_t \fIovecsize\fP,
 .B "  pcre2_general_context *\fIgcontext\fP);"
 .sp
-.B pcre2_match_data_create_from_pattern(pcre2_code *\fIcode\fP,
+.B pcre2_match_data_create_from_pattern(const pcre2_code *\fIcode\fP,
 .B "  pcre2_general_context *\fIgcontext\fP);"
 .sp
 .B void pcre2_match_data_free(pcre2_match_data *\fImatch_data\fP);
@@ -2631,6 +2633,6 @@
 .rs
 .sp
 .nf
-Last updated: 03 November 2014
+Last updated: 08 November 2014
 Copyright (c) 1997-2014 University of Cambridge.
 .fi


Modified: code/trunk/src/pcre2.h.in
===================================================================
--- code/trunk/src/pcre2.h.in    2014-11-08 16:07:30 UTC (rev 137)
+++ code/trunk/src/pcre2.h.in    2014-11-08 16:09:24 UTC (rev 138)
@@ -125,8 +125,8 @@
 #define PCRE2_JIT_PARTIAL_HARD    0x00000004u


/* These are for pcre2_match() and pcre2_dfa_match(). Note that PCRE2_ANCHORED,
-PCRE2_NO_START_OPTIMIZE, and PCRE2_NO_UTF_CHECK can also be passed to these
-functions, so take care not to define synonyms by mistake. */
+and PCRE2_NO_UTF_CHECK can also be passed to these functions, so take care not
+to define synonyms by mistake. */

 #define PCRE2_NOTBOL              0x00000001u
 #define PCRE2_NOTEOL              0x00000002u
@@ -140,6 +140,10 @@
 #define PCRE2_DFA_RESTART         0x00000040u
 #define PCRE2_DFA_SHORTEST        0x00000080u


+/* This is an additional option for pcre2_substitute(). */
+
+#define PCRE2_SUBSTITUTE_GLOBAL   0x00000100u
+
 /* Newline and \R settings, for use in compile contexts. The newline values
 must be kept in step with values set in config.h and both sets must all be
 greater than zero. */
@@ -406,7 +410,8 @@
   pcre2_match_data        *pcre2_match_data_create(uint32_t, \
                              pcre2_general_context *); \
 PCRE2_EXP_DECL \
-  pcre2_match_data        *pcre2_match_data_create_from_pattern(pcre2_code *, \
+  pcre2_match_data        *pcre2_match_data_create_from_pattern(\
+                             const pcre2_code *, \
                              pcre2_general_context *); \
 PCRE2_EXP_DECL int         pcre2_dfa_match(const pcre2_code *, PCRE2_SPTR, \
                              PCRE2_SIZE, PCRE2_SIZE, uint32_t, \
@@ -447,6 +452,16 @@
                            PCRE2_UCHAR ***, PCRE2_SIZE **);



+/* Convenience function for match + substitute. */
+
+#define PCRE2_SUBSTITUTE_FUNCTION \
+PCRE2_EXP_DECL int       pcre2_substitute(const pcre2_code *, \
+                           PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, \
+                           pcre2_match_data *, pcre2_match_context *, \
+                           PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, \
+                           PCRE2_SIZE *);
+
+
 /* Functions for JIT processing */


 #define PCRE2_JIT_FUNCTIONS \
@@ -550,6 +565,7 @@
 #define pcre2_set_parens_nest_limit           PCRE2_SUFFIX(pcre2_set_parens_nest_limit_)
 #define pcre2_set_recursion_limit             PCRE2_SUFFIX(pcre2_set_recursion_limit_)
 #define pcre2_set_recursion_memory_management PCRE2_SUFFIX(pcre2_set_recursion_memory_management_)
+#define pcre2_substitute                      PCRE2_SUFFIX(pcre2_substitute_)
 #define pcre2_substring_copy_byname           PCRE2_SUFFIX(pcre2_substring_copy_byname_)
 #define pcre2_substring_copy_bynumber         PCRE2_SUFFIX(pcre2_substring_copy_bynumber_)
 #define pcre2_substring_free                  PCRE2_SUFFIX(pcre2_substring_free_)
@@ -576,6 +592,7 @@
 PCRE2_COMPILE_FUNCTIONS \
 PCRE2_PATTERN_INFO_FUNCTIONS \
 PCRE2_MATCH_FUNCTIONS \
+PCRE2_SUBSTITUTE_FUNCTION \
 PCRE2_SUBSTRING_FUNCTIONS \
 PCRE2_JIT_FUNCTIONS \
 PCRE2_OTHER_FUNCTIONS


Modified: code/trunk/src/pcre2_match_data.c
===================================================================
--- code/trunk/src/pcre2_match_data.c    2014-11-08 16:07:30 UTC (rev 137)
+++ code/trunk/src/pcre2_match_data.c    2014-11-08 16:09:24 UTC (rev 138)
@@ -73,7 +73,7 @@
 *************************************************/


PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION
-pcre2_match_data_create_from_pattern(pcre2_code *code,
+pcre2_match_data_create_from_pattern(const pcre2_code *code,
pcre2_general_context *gcontext)
{
return pcre2_match_data_create(((pcre2_real_code *)code)->top_bracket + 1,

Added: code/trunk/src/pcre2_substitute.c
===================================================================
--- code/trunk/src/pcre2_substitute.c                            (rev 0)
+++ code/trunk/src/pcre2_substitute.c    2014-11-08 16:09:24 UTC (rev 138)
@@ -0,0 +1,269 @@
+/*************************************************
+*      Perl-Compatible Regular Expressions       *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+                       Written by Philip Hazel
+     Original API code Copyright (c) 1997-2012 University of Cambridge
+         New API code Copyright (c) 2014 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the name of the University of Cambridge nor the names of its
+      contributors may be used to endorse or promote products derived from
+      this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre2_internal.h"
+
+
+/*************************************************
+*              Match and substitute              *
+*************************************************/
+
+/* This function applies a compiled re to a subject string and creates a new
+string with substitutione. The first 7 arguments are the same as for
+pcre2_match(). Either string length may be PCRE2_ZERO_TERMINATED.
+
+Arguments:
+  code            points to the compiled expression
+  subject         points to the subject string
+  length          length of subject string (may contain binary zeros)
+  start_offset    where to start in the subject string
+  options         option bits
+  match_data      points to a match_data block, or is NULL
+  context         points a PCRE2 context
+  replacement     points to the replacement string
+  rlength         length of replacement string
+  buffer          where to put the substituted string
+  blength         points to length of buffer; updated to length of string
+
+Returns:        > 0 number of substitutions made
+                < 0 an error code, including PCRE2_ERROR_NOMATCH if no match
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
+  PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,
+  pcre2_match_context *mcontext, PCRE2_SPTR replacement, PCRE2_SIZE rlength,
+  PCRE2_UCHAR *buffer, PCRE2_SIZE *blength)
+{
+int rc = 0;
+int subs = 0;
+uint32_t ovector_count;
+uint32_t goptions = 0;
+BOOL match_data_created = FALSE;
+BOOL global = FALSE;
+PCRE2_SIZE buff_offset, lengthleft, endlength;
+PCRE2_SIZE *ovector;
+
+/* If no match data block is provided, create one. */
+
+if (match_data == NULL)
+  {
+  pcre2_general_context *gcontext = (mcontext == NULL)?
+    (pcre2_general_context *)code :
+    (pcre2_general_context *)mcontext;
+  match_data = pcre2_match_data_create_from_pattern(code, gcontext);
+  if (match_data == NULL) return PCRE2_ERROR_NOMEMORY;
+  match_data_created = TRUE;
+  }
+ovector = pcre2_get_ovector_pointer(match_data);
+ovector_count = pcre2_get_ovector_count(match_data);
+
+/* Notice the global option and remove it from the options that are passed to
+pcre2_match(). */
+
+if ((options & PCRE2_SUBSTITUTE_GLOBAL) != 0)
+  {
+  options &= ~PCRE2_SUBSTITUTE_GLOBAL;
+  global = TRUE;
+  }
+
+/* Find lengths of zero-terminated strings. */
+
+if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);
+if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement);
+
+/* Copy up to the start offset */
+
+if (start_offset > *blength) goto NOROOM;
+memcpy(buffer, subject, start_offset * (PCRE2_CODE_UNIT_WIDTH/8));
+buff_offset = start_offset;
+lengthleft = *blength - start_offset;
+
+/* Loop for global substituting. */
+
+do
+  {
+  PCRE2_SIZE i;
+
+  rc = pcre2_match(code, subject, length, start_offset, options|goptions,
+    match_data, mcontext);
+
+  if (rc < 0)
+    {
+    if (goptions == 0 || rc != PCRE2_ERROR_NOMATCH || start_offset >= length)
+      break;
+    start_offset++;
+    if ((code->overall_options & PCRE2_UTF) != 0)
+      {
+#if PCRE2_CODE_UNIT_WIDTH == 8
+      while (start_offset < length && (subject[start_offset] & 0xc0) == 0x80)
+        start_offset++;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+      while (start_offset < length &&
+            (subject[start_offset] & 0xfc00) == 0xdc00)
+        start_offset++;
+#endif
+      }
+    goptions = 0;
+    continue;
+    }
+
+  subs++;
+  if (rc == 0) rc = ovector_count;
+  endlength = ovector[0] - start_offset;
+  if (endlength >= lengthleft) goto NOROOM;
+  memcpy(buffer + buff_offset, subject + start_offset, 
+    endlength*(PCRE2_CODE_UNIT_WIDTH/8));
+  buff_offset += endlength;
+  lengthleft -= endlength;
+
+  for (i = 0; i < rlength; i++)
+    {
+    if (replacement[i] == CHAR_DOLLAR_SIGN && i != rlength - 1)
+      {
+      int group = -1;
+      int n = 0;
+      BOOL inparens = FALSE;
+      PCRE2_SIZE j = i + 1;
+      PCRE2_SIZE sublength; 
+      PCRE2_UCHAR next = replacement[j];
+      PCRE2_UCHAR name[33];
+
+      if (next == CHAR_LEFT_CURLY_BRACKET)
+        {
+        if (j == rlength - 1) goto LITERAL;
+        inparens = TRUE;
+        next = replacement[++j];
+        }
+
+      if (next >= CHAR_0 && next <= CHAR_9)
+        {
+        group = next - CHAR_0;
+        while (j < rlength - 1)
+          {
+          next = replacement[++j];
+          if (next < CHAR_0 || next > CHAR_9) break;
+          group = group * 10 + next - CHAR_0;
+          }
+        }
+      else
+        {
+        const uint8_t *ctypes = code->tables + ctypes_offset;
+        while (MAX_255(next) && (ctypes[next] & ctype_word) != 0)
+          {
+          name[n++] = next;
+          if (n > 32) goto LITERAL;
+          if (j == rlength - 1) break;
+          next = replacement[++j];
+          }
+        name[n] = 0;
+        }
+
+      if (inparens)
+        {
+        if (j == rlength || next != CHAR_RIGHT_CURLY_BRACKET) goto LITERAL;
+        }
+      else j--;   /* Last code unit of name/number */
+
+      /* Have found a syntactically correct group number or name. */
+
+      i = j;   /* Where to continue from */
+
+      if (group < 0)
+        rc = pcre2_substring_copy_byname(match_data, name,
+          buffer + buff_offset, &sublength);
+      else
+        rc = pcre2_substring_copy_bynumber(match_data, group,
+          buffer + buff_offset, &sublength);
+
+      if (rc < 0) goto EXIT;
+      buff_offset += sublength;
+      lengthleft -= sublength;
+      }
+
+   /* Handle a literal code unit */
+
+   else
+      {
+      LITERAL:
+      if (lengthleft-- < 1) goto NOROOM;
+      buffer[buff_offset++] = replacement[i];
+      }
+    }
+
+  /* The replacement has been copied to the output. Update the start offset to
+  point to the rest of the subject string. If we matched an empty string,
+  do the magic for global matches. */
+
+  start_offset = ovector[1];
+  goptions = (ovector[0] != ovector[1])? 0 :
+    PCRE2_ANCHORED|PCRE2_NOTEMPTY_ATSTART;
+  } while (global);  /* Repeat "do" loop */
+
+/* No match is a "normal" end; copy the rest of the subject and return the
+number of substitutions. */
+
+if (rc == PCRE2_ERROR_NOMATCH)
+  {
+  rc = subs;
+  endlength = length - start_offset;
+  if (endlength + 1 >= lengthleft) goto NOROOM;
+  memcpy(buffer + buff_offset, subject + start_offset,
+    endlength*(PCRE2_CODE_UNIT_WIDTH/8));
+  buff_offset += endlength;
+  buffer[buff_offset] = 0;
+  *blength = buff_offset;
+  }
+
+EXIT:
+if (match_data_created) pcre2_match_data_free(match_data);
+return rc;
+
+NOROOM:
+rc = PCRE2_ERROR_NOMEMORY;
+goto EXIT;
+}
+
+/* End of pcre2_substitute.c */


Modified: code/trunk/src/pcre2_substring.c
===================================================================
--- code/trunk/src/pcre2_substring.c    2014-11-08 16:07:30 UTC (rev 137)
+++ code/trunk/src/pcre2_substring.c    2014-11-08 16:09:24 UTC (rev 138)
@@ -472,7 +472,8 @@
   stringname  the name whose number is required


 Returns:      the number of the named parenthesis, or a negative number
-                (PCRE2_ERROR_NOSUBSTRING) if not found
+                PCRE2_ERROR_NOSUBSTRING if not found
+                PCRE2_ERROR_NOUNIQUESUBSTRING if not unique 
 */


PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION