Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  regprefix.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * regprefix.c
 *   Extract a common prefix, if any, from a compiled regex.
 *
 *
 * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1998, 1999 Henry Spencer
 *
 * IDENTIFICATION
 *   src/backend/regex/regprefix.c
 *
 *-------------------------------------------------------------------------
 */


#include "regex/regguts.h"


/*
 * forward declarations
 */

static int findprefix(struct cnfa *cnfa, struct colormap *cm,
        chr *string, size_t *slength);


/*
 * pg_regprefix - get common prefix for regular expression
 *
 * Returns one of:
 * REG_NOMATCH: there is no common prefix of strings matching the regex
 * REG_PREFIX: there is a common prefix of strings matching the regex
 * REG_EXACT: all strings satisfying the regex must match the same string
 * or a REG_XXX error code
 *
 * In the non-failure cases, *string is set to a palloc'd string containing
 * the common prefix or exact value, of length *slength (measured in chrs
 * not bytes!).
 *
 * This function does not analyze all complex cases (such as lookaround
 * constraints) exactly.  Therefore it is possible that some strings matching
 * the reported prefix or exact-match string do not satisfy the regex.  But
 * it should never be the case that a string satisfying the regex does not
 * match the reported prefix or exact-match string.
 */

int
pg_regprefix(regex_t *re,
    chr **string,
    size_t *slength)
{
 struct guts *g;
 struct cnfa *cnfa;
 int   st;

 /* sanity checks */
 if (string == NULL || slength == NULL)
  return REG_INVARG;
 *string = NULL;    /* initialize for failure cases */
 *slength = 0;
 if (re == NULL || re->re_magic != REMAGIC)
  return REG_INVARG;
 if (re->re_csize != sizeof(chr))
  return REG_MIXED;

 /* Initialize locale-dependent support */
 pg_set_regex_collation(re->re_collation);

 /* setup */
 g = (struct guts *) re->re_guts;
 if (g->info & REG_UIMPOSSIBLE)
  return REG_NOMATCH;

 /*
  * This implementation considers only the search NFA for the topmost regex
  * tree node.  Therefore, constraints such as backrefs are not fully
  * applied, which is allowed per the function's API spec.
 */

 assert(g->tree != NULL);
 cnfa = &g->tree->cnfa;

 /* matchall NFAs never have a fixed prefix */
 if (cnfa->flags & MATCHALL)
  return REG_NOMATCH;

 /*
  * Since a correct NFA should never contain any exit-free loops, it should
  * not be possible for our traversal to return to a previously visited NFA
  * state.  Hence we need at most nstates chrs in the output string.
 */

 *string = (chr *) MALLOC(cnfa->nstates * sizeof(chr));
 if (*string == NULL)
  return REG_ESPACE;

 /* do it */
 st = findprefix(cnfa, &g->cmap, *string, slength);

 assert(*slength <= cnfa->nstates);

 /* clean up */
 if (st != REG_PREFIX && st != REG_EXACT)
 {
  FREE(*string);
  *string = NULL;
  *slength = 0;
 }

 return st;
}

/*
 * findprefix - extract common prefix from cNFA
 *
 * Results are returned into the preallocated chr array string[], with
 * *slength (which must be preset to zero) incremented for each chr.
 */

static int      /* regprefix return code */
findprefix(struct cnfa *cnfa,
     struct colormap *cm,
     chr *string,
     size_t *slength)
{
 int   st;
 int   nextst;
 color  thiscolor;
 chr   c;
 struct carc *ca;

 /*
  * The "pre" state must have only BOS/BOL outarcs, else pattern isn't
  * anchored left.  If we have both BOS and BOL, they must go to the same
  * next state.
 */

 st = cnfa->pre;
 nextst = -1;
 for (ca = cnfa->states[st]; ca->co != COLORLESS; ca++)
 {
  if (ca->co == cnfa->bos[0] || ca->co == cnfa->bos[1])
  {
   if (nextst == -1)
    nextst = ca->to;
   else if (nextst != ca->to)
    return REG_NOMATCH;
  }
  else
   return REG_NOMATCH;
 }
 if (nextst == -1)
  return REG_NOMATCH;

 /*
  * Scan through successive states, stopping as soon as we find one with
  * more than one acceptable transition character (either multiple colors
  * on out-arcs, or a color with more than one member chr).
  *
  * We could find a state with multiple out-arcs that are all labeled with
  * the same singleton color; this comes from patterns like "^ab(cde|cxy)".
  * In that case we add the chr "c" to the output string but then exit the
  * loop with nextst == -1.  This leaves a little bit on the table: if the
  * pattern is like "^ab(cde|cdy)", we won't notice that "d" could be added
  * to the prefix.  But chasing multiple parallel state chains doesn't seem
  * worth the trouble.
 */

 do
 {
  st = nextst;
  nextst = -1;
  thiscolor = COLORLESS;
  for (ca = cnfa->states[st]; ca->co != COLORLESS; ca++)
  {
   /* We can ignore BOS/BOL arcs */
   if (ca->co == cnfa->bos[0] || ca->co == cnfa->bos[1])
    continue;

   /*
    * ... but EOS/EOL arcs terminate the search, as do RAINBOW arcs
    * and LACONs
 */

   if (ca->co == cnfa->eos[0] || ca->co == cnfa->eos[1] ||
    ca->co == RAINBOW || ca->co >= cnfa->ncolors)
   {
    thiscolor = COLORLESS;
    break;
   }
   if (thiscolor == COLORLESS)
   {
    /* First plain outarc */
    thiscolor = ca->co;
    nextst = ca->to;
   }
   else if (thiscolor == ca->co)
   {
    /* Another plain outarc for same color */
    nextst = -1;
   }
   else
   {
    /* More than one plain outarc color terminates the search */
    thiscolor = COLORLESS;
    break;
   }
  }
  /* Done if we didn't find exactly one color on plain outarcs */
  if (thiscolor == COLORLESS)
   break;
  /* The color must be a singleton */
  if (cm->cd[thiscolor].nschrs != 1)
   break;
  /* Must not have any high-color-map entries */
  if (cm->cd[thiscolor].nuchrs != 0)
   break;

  /*
   * Identify the color's sole member chr and add it to the prefix
   * string.  In general the colormap data structure doesn't provide a
   * way to find color member chrs, except by trying GETCOLOR() on each
   * possible chr value, which won't do at all.  However, for the cases
   * we care about it should be sufficient to test the "firstchr" value,
   * that is the first chr ever added to the color.  There are cases
   * where this might no longer be a member of the color (so we do need
   * to test), but none of them are likely to arise for a character that
   * is a member of a common prefix.  If we do hit such a corner case,
   * we just fall out without adding anything to the prefix string.
 */

  c = cm->cd[thiscolor].firstchr;
  if (GETCOLOR(cm, c) != thiscolor)
   break;

  string[(*slength)++] = c;

  /* Advance to next state, but only if we have a unique next state */
 } while (nextst != -1);

 /*
  * If we ended at a state that only has EOS/EOL outarcs leading to the
  * "post" state, then we have an exact-match string.  Note this is true
  * even if the string is of zero length.
 */

 nextst = -1;
 for (ca = cnfa->states[st]; ca->co != COLORLESS; ca++)
 {
  if (ca->co == cnfa->eos[0] || ca->co == cnfa->eos[1])
  {
   if (nextst == -1)
    nextst = ca->to;
   else if (nextst != ca->to)
   {
    nextst = -1;
    break;
   }
  }
  else
  {
   nextst = -1;
   break;
  }
 }
 if (nextst == cnfa->post)
  return REG_EXACT;

 /*
  * Otherwise, if we were unable to identify any prefix characters, say
  * NOMATCH --- the pattern is anchored left, but doesn't specify any
  * particular first character.
 */

 if (*slength > 0)
  return REG_PREFIX;

 return REG_NOMATCH;
}

Messung V0.5 in Prozent
C=92 H=96 G=93

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002