Blame src/pcre2_substring.c

Packit 504f36
/*************************************************
Packit 504f36
*      Perl-Compatible Regular Expressions       *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/* PCRE is a library of functions to support regular expressions whose syntax
Packit 504f36
and semantics are as close as possible to those of the Perl 5 language.
Packit 504f36
Packit 504f36
                       Written by Philip Hazel
Packit 504f36
     Original API code Copyright (c) 1997-2012 University of Cambridge
Packit 504f36
          New API code Copyright (c) 2016-2018 University of Cambridge
Packit 504f36
Packit 504f36
-----------------------------------------------------------------------------
Packit 504f36
Redistribution and use in source and binary forms, with or without
Packit 504f36
modification, are permitted provided that the following conditions are met:
Packit 504f36
Packit 504f36
    * Redistributions of source code must retain the above copyright notice,
Packit 504f36
      this list of conditions and the following disclaimer.
Packit 504f36
Packit 504f36
    * Redistributions in binary form must reproduce the above copyright
Packit 504f36
      notice, this list of conditions and the following disclaimer in the
Packit 504f36
      documentation and/or other materials provided with the distribution.
Packit 504f36
Packit 504f36
    * Neither the name of the University of Cambridge nor the names of its
Packit 504f36
      contributors may be used to endorse or promote products derived from
Packit 504f36
      this software without specific prior written permission.
Packit 504f36
Packit 504f36
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 504f36
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 504f36
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 504f36
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
Packit 504f36
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit 504f36
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit 504f36
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit 504f36
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Packit 504f36
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit 504f36
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit 504f36
POSSIBILITY OF SUCH DAMAGE.
Packit 504f36
-----------------------------------------------------------------------------
Packit 504f36
*/
Packit 504f36
Packit 504f36
Packit 504f36
#ifdef HAVE_CONFIG_H
Packit 504f36
#include "config.h"
Packit 504f36
#endif
Packit 504f36
Packit 504f36
#include "pcre2_internal.h"
Packit 504f36
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*   Copy named captured string to given buffer   *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/* This function copies a single captured substring into a given buffer,
Packit 504f36
identifying it by name. If the regex permits duplicate names, the first
Packit 504f36
substring that is set is chosen.
Packit 504f36
Packit 504f36
Arguments:
Packit 504f36
  match_data     points to the match data
Packit 504f36
  stringname     the name of the required substring
Packit 504f36
  buffer         where to put the substring
Packit 504f36
  sizeptr        the size of the buffer, updated to the size of the substring
Packit 504f36
Packit 504f36
Returns:         if successful: zero
Packit 504f36
                 if not successful, a negative error code:
Packit 504f36
                   (1) an error from nametable_scan()
Packit 504f36
                   (2) an error from copy_bynumber()
Packit 504f36
                   (3) PCRE2_ERROR_UNAVAILABLE: no group is in ovector
Packit 504f36
                   (4) PCRE2_ERROR_UNSET: all named groups in ovector are unset
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_copy_byname(pcre2_match_data *match_data, PCRE2_SPTR stringname,
Packit 504f36
  PCRE2_UCHAR *buffer, PCRE2_SIZE *sizeptr)
Packit 504f36
{
Packit 504f36
PCRE2_SPTR first, last, entry;
Packit 504f36
int failrc, entrysize;
Packit 504f36
if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)
Packit 504f36
  return PCRE2_ERROR_DFA_UFUNC;
Packit 504f36
entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,
Packit 504f36
  &first, &last);
Packit 504f36
if (entrysize < 0) return entrysize;
Packit 504f36
failrc = PCRE2_ERROR_UNAVAILABLE;
Packit 504f36
for (entry = first; entry <= last; entry += entrysize)
Packit 504f36
  {
Packit 504f36
  uint32_t n = GET2(entry, 0);
Packit 504f36
  if (n < match_data->oveccount)
Packit 504f36
    {
Packit 504f36
    if (match_data->ovector[n*2] != PCRE2_UNSET)
Packit 504f36
      return pcre2_substring_copy_bynumber(match_data, n, buffer, sizeptr);
Packit 504f36
    failrc = PCRE2_ERROR_UNSET;
Packit 504f36
    }
Packit 504f36
  }
Packit 504f36
return failrc;
Packit 504f36
}
Packit 504f36
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*  Copy numbered captured string to given buffer *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/* This function copies a single captured substring into a given buffer,
Packit 504f36
identifying it by number.
Packit 504f36
Packit 504f36
Arguments:
Packit 504f36
  match_data     points to the match data
Packit 504f36
  stringnumber   the number of the required substring
Packit 504f36
  buffer         where to put the substring
Packit 504f36
  sizeptr        the size of the buffer, updated to the size of the substring
Packit 504f36
Packit 504f36
Returns:         if successful: 0
Packit 504f36
                 if not successful, a negative error code:
Packit 504f36
                   PCRE2_ERROR_NOMEMORY: buffer too small
Packit 504f36
                   PCRE2_ERROR_NOSUBSTRING: no such substring
Packit 504f36
                   PCRE2_ERROR_UNAVAILABLE: ovector too small
Packit 504f36
                   PCRE2_ERROR_UNSET: substring is not set
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_copy_bynumber(pcre2_match_data *match_data,
Packit 504f36
  uint32_t stringnumber, PCRE2_UCHAR *buffer, PCRE2_SIZE *sizeptr)
Packit 504f36
{
Packit 504f36
int rc;
Packit 504f36
PCRE2_SIZE size;
Packit 504f36
rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size);
Packit 504f36
if (rc < 0) return rc;
Packit 504f36
if (size + 1 > *sizeptr) return PCRE2_ERROR_NOMEMORY;
Packit 504f36
memcpy(buffer, match_data->subject + match_data->ovector[stringnumber*2],
Packit 504f36
  CU2BYTES(size));
Packit 504f36
buffer[size] = 0;
Packit 504f36
*sizeptr = size;
Packit 504f36
return 0;
Packit 504f36
}
Packit 504f36
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*          Extract named captured string         *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/* This function copies a single captured substring, identified by name, into
Packit 504f36
new memory. If the regex permits duplicate names, the first substring that is
Packit 504f36
set is chosen.
Packit 504f36
Packit 504f36
Arguments:
Packit 504f36
  match_data     pointer to match_data
Packit 504f36
  stringname     the name of the required substring
Packit 504f36
  stringptr      where to put the pointer to the new memory
Packit 504f36
  sizeptr        where to put the length of the substring
Packit 504f36
Packit 504f36
Returns:         if successful: zero
Packit 504f36
                 if not successful, a negative value:
Packit 504f36
                   (1) an error from nametable_scan()
Packit 504f36
                   (2) an error from get_bynumber()
Packit 504f36
                   (3) PCRE2_ERROR_UNAVAILABLE: no group is in ovector
Packit 504f36
                   (4) PCRE2_ERROR_UNSET: all named groups in ovector are unset
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_get_byname(pcre2_match_data *match_data,
Packit 504f36
  PCRE2_SPTR stringname, PCRE2_UCHAR **stringptr, PCRE2_SIZE *sizeptr)
Packit 504f36
{
Packit 504f36
PCRE2_SPTR first, last, entry;
Packit 504f36
int failrc, entrysize;
Packit 504f36
if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)
Packit 504f36
  return PCRE2_ERROR_DFA_UFUNC;
Packit 504f36
entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,
Packit 504f36
  &first, &last);
Packit 504f36
if (entrysize < 0) return entrysize;
Packit 504f36
failrc = PCRE2_ERROR_UNAVAILABLE;
Packit 504f36
for (entry = first; entry <= last; entry += entrysize)
Packit 504f36
  {
Packit 504f36
  uint32_t n = GET2(entry, 0);
Packit 504f36
  if (n < match_data->oveccount)
Packit 504f36
    {
Packit 504f36
    if (match_data->ovector[n*2] != PCRE2_UNSET)
Packit 504f36
      return pcre2_substring_get_bynumber(match_data, n, stringptr, sizeptr);
Packit 504f36
    failrc = PCRE2_ERROR_UNSET;
Packit 504f36
    }
Packit 504f36
  }
Packit 504f36
return failrc;
Packit 504f36
}
Packit 504f36
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*      Extract captured string to new memory     *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/* This function copies a single captured substring into a piece of new
Packit 504f36
memory.
Packit 504f36
Packit 504f36
Arguments:
Packit 504f36
  match_data     points to match data
Packit 504f36
  stringnumber   the number of the required substring
Packit 504f36
  stringptr      where to put a pointer to the new memory
Packit 504f36
  sizeptr        where to put the size of the substring
Packit 504f36
Packit 504f36
Returns:         if successful: 0
Packit 504f36
                 if not successful, a negative error code:
Packit 504f36
                   PCRE2_ERROR_NOMEMORY: failed to get memory
Packit 504f36
                   PCRE2_ERROR_NOSUBSTRING: no such substring
Packit 504f36
                   PCRE2_ERROR_UNAVAILABLE: ovector too small
Packit 504f36
                   PCRE2_ERROR_UNSET: substring is not set
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_get_bynumber(pcre2_match_data *match_data,
Packit 504f36
  uint32_t stringnumber, PCRE2_UCHAR **stringptr, PCRE2_SIZE *sizeptr)
Packit 504f36
{
Packit 504f36
int rc;
Packit 504f36
PCRE2_SIZE size;
Packit 504f36
PCRE2_UCHAR *yield;
Packit 504f36
rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size);
Packit 504f36
if (rc < 0) return rc;
Packit 504f36
yield = PRIV(memctl_malloc)(sizeof(pcre2_memctl) +
Packit 504f36
  (size + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)match_data);
Packit 504f36
if (yield == NULL) return PCRE2_ERROR_NOMEMORY;
Packit 504f36
yield = (PCRE2_UCHAR *)(((char *)yield) + sizeof(pcre2_memctl));
Packit 504f36
memcpy(yield, match_data->subject + match_data->ovector[stringnumber*2],
Packit 504f36
  CU2BYTES(size));
Packit 504f36
yield[size] = 0;
Packit 504f36
*stringptr = yield;
Packit 504f36
*sizeptr = size;
Packit 504f36
return 0;
Packit 504f36
}
Packit 504f36
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*       Free memory obtained by get_substring    *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/*
Packit 504f36
Argument:     the result of a previous pcre2_substring_get_byxxx()
Packit 504f36
Returns:      nothing
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_free(PCRE2_UCHAR *string)
Packit 504f36
{
Packit 504f36
if (string != NULL)
Packit 504f36
  {
Packit 504f36
  pcre2_memctl *memctl = (pcre2_memctl *)((char *)string - sizeof(pcre2_memctl));
Packit 504f36
  memctl->free(memctl, memctl->memory_data);
Packit 504f36
  }
Packit 504f36
}
Packit 504f36
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*         Get length of a named substring        *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/* This function returns the length of a named captured substring. If the regex
Packit 504f36
permits duplicate names, the first substring that is set is chosen.
Packit 504f36
Packit 504f36
Arguments:
Packit 504f36
  match_data      pointer to match data
Packit 504f36
  stringname      the name of the required substring
Packit 504f36
  sizeptr         where to put the length
Packit 504f36
Packit 504f36
Returns:          0 if successful, else a negative error number
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_length_byname(pcre2_match_data *match_data,
Packit 504f36
  PCRE2_SPTR stringname, PCRE2_SIZE *sizeptr)
Packit 504f36
{
Packit 504f36
PCRE2_SPTR first, last, entry;
Packit 504f36
int failrc, entrysize;
Packit 504f36
if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)
Packit 504f36
  return PCRE2_ERROR_DFA_UFUNC;
Packit 504f36
entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,
Packit 504f36
  &first, &last);
Packit 504f36
if (entrysize < 0) return entrysize;
Packit 504f36
failrc = PCRE2_ERROR_UNAVAILABLE;
Packit 504f36
for (entry = first; entry <= last; entry += entrysize)
Packit 504f36
  {
Packit 504f36
  uint32_t n = GET2(entry, 0);
Packit 504f36
  if (n < match_data->oveccount)
Packit 504f36
    {
Packit 504f36
    if (match_data->ovector[n*2] != PCRE2_UNSET)
Packit 504f36
      return pcre2_substring_length_bynumber(match_data, n, sizeptr);
Packit 504f36
    failrc = PCRE2_ERROR_UNSET;
Packit 504f36
    }
Packit 504f36
  }
Packit 504f36
return failrc;
Packit 504f36
}
Packit 504f36
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*        Get length of a numbered substring      *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/* This function returns the length of a captured substring. If the start is
Packit 504f36
beyond the end (which can happen when \K is used in an assertion), it sets the
Packit 504f36
length to zero.
Packit 504f36
Packit 504f36
Arguments:
Packit 504f36
  match_data      pointer to match data
Packit 504f36
  stringnumber    the number of the required substring
Packit 504f36
  sizeptr         where to put the length, if not NULL
Packit 504f36
Packit 504f36
Returns:         if successful: 0
Packit 504f36
                 if not successful, a negative error code:
Packit 504f36
                   PCRE2_ERROR_NOSUBSTRING: no such substring
Packit 504f36
                   PCRE2_ERROR_UNAVAILABLE: ovector is too small
Packit 504f36
                   PCRE2_ERROR_UNSET: substring is not set
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_length_bynumber(pcre2_match_data *match_data,
Packit 504f36
  uint32_t stringnumber, PCRE2_SIZE *sizeptr)
Packit 504f36
{
Packit 504f36
PCRE2_SIZE left, right;
Packit 504f36
int count = match_data->rc;
Packit 504f36
if (count == PCRE2_ERROR_PARTIAL)
Packit 504f36
  {
Packit 504f36
  if (stringnumber > 0) return PCRE2_ERROR_PARTIAL;
Packit 504f36
  count = 0;
Packit 504f36
  }
Packit 504f36
else if (count < 0) return count;            /* Match failed */
Packit 504f36
Packit 504f36
if (match_data->matchedby != PCRE2_MATCHEDBY_DFA_INTERPRETER)
Packit 504f36
  {
Packit 504f36
  if (stringnumber > match_data->code->top_bracket)
Packit 504f36
    return PCRE2_ERROR_NOSUBSTRING;
Packit 504f36
  if (stringnumber >= match_data->oveccount)
Packit 504f36
    return PCRE2_ERROR_UNAVAILABLE;
Packit 504f36
  if (match_data->ovector[stringnumber*2] == PCRE2_UNSET)
Packit 504f36
    return PCRE2_ERROR_UNSET;
Packit 504f36
  }
Packit 504f36
else  /* Matched using pcre2_dfa_match() */
Packit 504f36
  {
Packit 504f36
  if (stringnumber >= match_data->oveccount) return PCRE2_ERROR_UNAVAILABLE;
Packit 504f36
  if (count != 0 && stringnumber >= (uint32_t)count) return PCRE2_ERROR_UNSET;
Packit 504f36
  }
Packit 504f36
Packit 504f36
left = match_data->ovector[stringnumber*2];
Packit 504f36
right = match_data->ovector[stringnumber*2+1];
Packit 504f36
if (sizeptr != NULL) *sizeptr = (left > right)? 0 : right - left;
Packit 504f36
return 0;
Packit 504f36
}
Packit 504f36
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*    Extract all captured strings to new memory  *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/* This function gets one chunk of memory and builds a list of pointers and all
Packit 504f36
the captured substrings in it. A NULL pointer is put on the end of the list.
Packit 504f36
The substrings are zero-terminated, but also, if the final argument is
Packit 504f36
non-NULL, a list of lengths is also returned. This allows binary data to be
Packit 504f36
handled.
Packit 504f36
Packit 504f36
Arguments:
Packit 504f36
  match_data     points to the match data
Packit 504f36
  listptr        set to point to the list of pointers
Packit 504f36
  lengthsptr     set to point to the list of lengths (may be NULL)
Packit 504f36
Packit 504f36
Returns:         if successful: 0
Packit 504f36
                 if not successful, a negative error code:
Packit 504f36
                   PCRE2_ERROR_NOMEMORY: failed to get memory,
Packit 504f36
                   or a match failure code
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_list_get(pcre2_match_data *match_data, PCRE2_UCHAR ***listptr,
Packit 504f36
  PCRE2_SIZE **lengthsptr)
Packit 504f36
{
Packit 504f36
int i, count, count2;
Packit 504f36
PCRE2_SIZE size;
Packit 504f36
PCRE2_SIZE *lensp;
Packit 504f36
pcre2_memctl *memp;
Packit 504f36
PCRE2_UCHAR **listp;
Packit 504f36
PCRE2_UCHAR *sp;
Packit 504f36
PCRE2_SIZE *ovector;
Packit 504f36
Packit 504f36
if ((count = match_data->rc) < 0) return count;   /* Match failed */
Packit 504f36
if (count == 0) count = match_data->oveccount;    /* Ovector too small */
Packit 504f36
Packit 504f36
count2 = 2*count;
Packit 504f36
ovector = match_data->ovector;
Packit 504f36
size = sizeof(pcre2_memctl) + sizeof(PCRE2_UCHAR *);      /* For final NULL */
Packit 504f36
if (lengthsptr != NULL) size += sizeof(PCRE2_SIZE) * count;  /* For lengths */
Packit 504f36
Packit 504f36
for (i = 0; i < count2; i += 2)
Packit 504f36
  {
Packit 504f36
  size += sizeof(PCRE2_UCHAR *) + CU2BYTES(1);
Packit 504f36
  if (ovector[i+1] > ovector[i]) size += CU2BYTES(ovector[i+1] - ovector[i]);
Packit 504f36
  }
Packit 504f36
Packit 504f36
memp = PRIV(memctl_malloc)(size, (pcre2_memctl *)match_data);
Packit 504f36
if (memp == NULL) return PCRE2_ERROR_NOMEMORY;
Packit 504f36
Packit 504f36
*listptr = listp = (PCRE2_UCHAR **)((char *)memp + sizeof(pcre2_memctl));
Packit 504f36
lensp = (PCRE2_SIZE *)((char *)listp + sizeof(PCRE2_UCHAR *) * (count + 1));
Packit 504f36
Packit 504f36
if (lengthsptr == NULL)
Packit 504f36
  {
Packit 504f36
  sp = (PCRE2_UCHAR *)lensp;
Packit 504f36
  lensp = NULL;
Packit 504f36
  }
Packit 504f36
else
Packit 504f36
  {
Packit 504f36
  *lengthsptr = lensp;
Packit 504f36
  sp = (PCRE2_UCHAR *)((char *)lensp + sizeof(PCRE2_SIZE) * count);
Packit 504f36
  }
Packit 504f36
Packit 504f36
for (i = 0; i < count2; i += 2)
Packit 504f36
  {
Packit 504f36
  size = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0;
Packit 504f36
Packit 504f36
  /* Size == 0 includes the case when the capture is unset. Avoid adding
Packit 504f36
  PCRE2_UNSET to match_data->subject because it overflows, even though with
Packit 504f36
  zero size calling memcpy() is harmless. */
Packit 504f36
Packit 504f36
  if (size != 0) memcpy(sp, match_data->subject + ovector[i], CU2BYTES(size));
Packit 504f36
  *listp++ = sp;
Packit 504f36
  if (lensp != NULL) *lensp++ = size;
Packit 504f36
  sp += size;
Packit 504f36
  *sp++ = 0;
Packit 504f36
  }
Packit 504f36
Packit 504f36
*listp = NULL;
Packit 504f36
return 0;
Packit 504f36
}
Packit 504f36
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*   Free memory obtained by substring_list_get   *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/*
Packit 504f36
Argument:     the result of a previous pcre2_substring_list_get()
Packit 504f36
Returns:      nothing
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_list_free(PCRE2_SPTR *list)
Packit 504f36
{
Packit 504f36
if (list != NULL)
Packit 504f36
  {
Packit 504f36
  pcre2_memctl *memctl = (pcre2_memctl *)((char *)list - sizeof(pcre2_memctl));
Packit 504f36
  memctl->free(memctl, memctl->memory_data);
Packit 504f36
  }
Packit 504f36
}
Packit 504f36
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*     Find (multiple) entries for named string   *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/* This function scans the nametable for a given name, using binary chop. It
Packit 504f36
returns either two pointers to the entries in the table, or, if no pointers are
Packit 504f36
given, the number of a unique group with the given name. If duplicate names are
Packit 504f36
permitted, and the name is not unique, an error is generated.
Packit 504f36
Packit 504f36
Arguments:
Packit 504f36
  code        the compiled regex
Packit 504f36
  stringname  the name whose entries required
Packit 504f36
  firstptr    where to put the pointer to the first entry
Packit 504f36
  lastptr     where to put the pointer to the last entry
Packit 504f36
Packit 504f36
Returns:      PCRE2_ERROR_NOSUBSTRING if the name is not found
Packit 504f36
              otherwise, if firstptr and lastptr are NULL:
Packit 504f36
                a group number for a unique substring
Packit 504f36
                else PCRE2_ERROR_NOUNIQUESUBSTRING
Packit 504f36
              otherwise:
Packit 504f36
                the length of each entry, having set firstptr and lastptr
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_nametable_scan(const pcre2_code *code, PCRE2_SPTR stringname,
Packit 504f36
  PCRE2_SPTR *firstptr, PCRE2_SPTR *lastptr)
Packit 504f36
{
Packit 504f36
uint16_t bot = 0;
Packit 504f36
uint16_t top = code->name_count;
Packit 504f36
uint16_t entrysize = code->name_entry_size;
Packit 504f36
PCRE2_SPTR nametable = (PCRE2_SPTR)((char *)code + sizeof(pcre2_real_code));
Packit 504f36
Packit 504f36
while (top > bot)
Packit 504f36
  {
Packit 504f36
  uint16_t mid = (top + bot) / 2;
Packit 504f36
  PCRE2_SPTR entry = nametable + entrysize*mid;
Packit 504f36
  int c = PRIV(strcmp)(stringname, entry + IMM2_SIZE);
Packit 504f36
  if (c == 0)
Packit 504f36
    {
Packit 504f36
    PCRE2_SPTR first;
Packit 504f36
    PCRE2_SPTR last;
Packit 504f36
    PCRE2_SPTR lastentry;
Packit 504f36
    lastentry = nametable + entrysize * (code->name_count - 1);
Packit 504f36
    first = last = entry;
Packit 504f36
    while (first > nametable)
Packit 504f36
      {
Packit 504f36
      if (PRIV(strcmp)(stringname, (first - entrysize + IMM2_SIZE)) != 0) break;
Packit 504f36
      first -= entrysize;
Packit 504f36
      }
Packit 504f36
    while (last < lastentry)
Packit 504f36
      {
Packit 504f36
      if (PRIV(strcmp)(stringname, (last + entrysize + IMM2_SIZE)) != 0) break;
Packit 504f36
      last += entrysize;
Packit 504f36
      }
Packit 504f36
    if (firstptr == NULL) return (first == last)?
Packit 504f36
      (int)GET2(entry, 0) : PCRE2_ERROR_NOUNIQUESUBSTRING;
Packit 504f36
    *firstptr = first;
Packit 504f36
    *lastptr = last;
Packit 504f36
    return entrysize;
Packit 504f36
    }
Packit 504f36
  if (c > 0) bot = mid + 1; else top = mid;
Packit 504f36
  }
Packit 504f36
Packit 504f36
return PCRE2_ERROR_NOSUBSTRING;
Packit 504f36
}
Packit 504f36
Packit 504f36
Packit 504f36
/*************************************************
Packit 504f36
*           Find number for named string         *
Packit 504f36
*************************************************/
Packit 504f36
Packit 504f36
/* This function is a convenience wrapper for pcre2_substring_nametable_scan()
Packit 504f36
when it is known that names are unique. If there are duplicate names, it is not
Packit 504f36
defined which number is returned.
Packit 504f36
Packit 504f36
Arguments:
Packit 504f36
  code        the compiled regex
Packit 504f36
  stringname  the name whose number is required
Packit 504f36
Packit 504f36
Returns:      the number of the named parenthesis, or a negative number
Packit 504f36
                PCRE2_ERROR_NOSUBSTRING if not found
Packit 504f36
                PCRE2_ERROR_NOUNIQUESUBSTRING if not unique
Packit 504f36
*/
Packit 504f36
Packit 504f36
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
Packit 504f36
pcre2_substring_number_from_name(const pcre2_code *code,
Packit 504f36
  PCRE2_SPTR stringname)
Packit 504f36
{
Packit 504f36
return pcre2_substring_nametable_scan(code, stringname, NULL, NULL);
Packit 504f36
}
Packit 504f36
Packit 504f36
/* End of pcre2_substring.c */