"Fossies" - the Fresh Open Source Software Archive

Member "leafnode-1.12.0/pcre_extract.c" (28 Dec 2021, 5026 Bytes) of package /linux/misc/leafnode-1.12.0.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pcre_extract.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.11.12_vs_1.12.0.

    1 /* ln_pcre_extract.c -- compile and exec a PCRE and return captured strings
    2  * (C) 2002 - 2021 by Matthias Andree <matthias.andree@gmx.de>
    3  *
    4  * This library is free software; you can redistribute it and/or modify
    5  * it under the terms of version 2 of the GNU Lesser General Public License as
    6  * published by the Free Software Foundation.
    7  *
    8  * This library is distributed in the hope that it will be useful, but
    9  * WITHOUT ANY WARRANTY; without even the implied warranty of
   10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   11  * Lesser General Public License for more details.
   12  *
   13  * You should have received a copy of the GNU Lesser General Public
   14  * License along with this library (look for the COPYING.LGPL file); if
   15  * not, write to the Free Software Foundation, Inc., 59 Temple Place,
   16  * Suite 330, Boston, MA 02111-1307 USA
   17  */
   18 
   19 #include "leafnode.h"
   20 
   21 #include <string.h>
   22 #include <limits.h>
   23 #ifdef TEST
   24 #include <stdio.h>
   25 #endif
   26 
   27 #include "config.h"
   28 #include "critmem.h"
   29 #include "ln_log.h"
   30 #include "strlcpy.h"
   31 
   32 /* This function compiles and executes the regular expression in
   33  * "pattern" against the string in "input" and can optionally put the
   34  * matching string and captured substring into the output vector.
   35  *
   36  * Output may be NULL if and only if num is zero.
   37  *
   38  * If num is nonzero, the matching substring is strdup()ed into
   39  * output[0]. If num is > 1, ln_pcre_extract copies the first num - 1
   40  * captured substrings into output[...]. If a capturing subpattern did
   41  * not match, the corresponding output[] element is NULL.
   42  *
   43  * The return value is the same as that of pcre_exec. Short: 0 if num
   44  * too small to hold all captured strings, otherwise the number of
   45  * captured patterns, where the matching string is always captured, or
   46  * the PCRE error code.
   47  *
   48  * WARNING: if compiling the pattern fails, the program logs this
   49  * condition and aborts. This function is NOT safe to be used with
   50  * user-accessible patterns. Use constant patterns.
   51  *
   52  * You MUST free() the valid parts in your output[] vector yourself. You
   53  * can use ln_pcre_extract_free (which see) to do this.
   54  */
   55 int ln_pcre_extract(const unsigned char *input, const unsigned char *pattern, char **output, size_t num)
   56 {
   57     size_t errpos, i;
   58     int errcode, match;
   59     const int options = PCRE2_CASELESS|PCRE2_DOTALL|PCRE2_MULTILINE;
   60     PCRE2_SIZE *ovec;
   61     pcre2_code_8 *re;
   62     pcre2_match_data_8 *match_data;
   63 
   64     if (num > INT_MAX / 3) {
   65     ln_log(LNLOG_SERR, LNLOG_CTOP, "ln_pcre_extract: array size too large, aborting.");
   66     abort();
   67     }
   68 
   69     re = pcre2_compile_8(pattern, PCRE2_ZERO_TERMINATED, options, &errcode, &errpos, NULL);
   70     if (NULL == re) {
   71     unsigned char errstr[SIZE_lineout];
   72     int len = pcre2_get_error_message_8(errcode, errstr, sizeof(errstr));
   73     ln_log(LNLOG_SERR, LNLOG_CTOP, "ln_pcre_extract: cannot compile \"%s\": %s%s at pos. #%lu",
   74            pattern, errstr, len == PCRE2_ERROR_NOMEMORY ? "[...]" : "", (unsigned long)errpos);
   75     return -1;
   76     }
   77 
   78     match_data = pcre2_match_data_create_from_pattern_8(re, NULL);
   79     if (NULL == match_data) {
   80     ln_log(LNLOG_SERR, LNLOG_CTOP, "ln_pcre_extract: out of memory allocating match_data");
   81     return -1;
   82     }
   83 
   84     match = pcre2_match_8(re, input, PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL);
   85     if (match >= 0) {
   86     uint32_t ocnt = pcre2_get_ovector_count_8(match_data);
   87     ovec = pcre2_get_ovector_pointer_8(match_data);
   88     for (i = 0 ; i < num && i < ocnt ; i++) {
   89         size_t l = ovec[i*2 + 1] - ovec[i*2];
   90         if (ovec[i*2 + 1] < ovec[i * 2]) l = 0; /* can happen, for instance, with \K */
   91         output[i] = critmalloc(l + 1, "ln_pcre_extract");
   92         (void)memcpy(output[i], input + ovec[i*2], l);
   93         output[i][l] = '\0';
   94     }
   95     }
   96     pcre2_match_data_free_8(match_data);
   97     pcre2_code_free_8(re);
   98     return match;
   99 }
  100 
  101 /* free a vector as allocated by ln_pcre_extract
  102  * vec should be the same as output in ln_pcre_extract
  103  * count should be the value obtained from ln_pcre_extract
  104  * it is safe to pass a negative or zero count.
  105  *   
  106  * vec must NOT be NULL unless count is zero or negative.
  107  */
  108 void ln_pcre_extract_free(char **vec, int count)
  109 {
  110     int i;
  111 
  112     for (i = 0; i < count; i++) {
  113     if (vec[i]) {
  114         free(vec[i]);
  115         vec[i] = NULL;
  116     }
  117     }
  118 }
  119 
  120 #ifdef TEST
  121 #define MAX 30
  122 
  123 int debug = 0;
  124 int verbose = 0;
  125 
  126 /* test ln_pcre_extract capturing. */
  127 int main(int argc, char **argv)
  128 {
  129     char *out[MAX]; /* RATS: ignore */
  130     int rc, n = MAX;
  131 
  132     if (argc < 3 || argc > 4) {
  133     fprintf(stderr, "usage: %s string PCRE [num]\n", argv[0]);
  134     exit(1);
  135     }
  136 
  137     if (argc == 4) {
  138     n = atoi(argv[3]);
  139     if (n > MAX) {
  140         n = MAX;
  141         printf("warning: clamping max from %d to %d\n", n, MAX);
  142     }
  143     }
  144     rc = ln_pcre_extract((unsigned char *)argv[1], (unsigned char *)argv[2], out, argc == 4 ? atoi(argv[3]) : MAX);
  145     printf("ln_pcre_extract returned %d\n", rc);
  146     if (rc >= 0) {
  147     int i;
  148     for(i = 0; i < rc; i++) {
  149         printf("substring #%d: \"%s\"\n", i, out[i] ? out[i] : "(NULL)");
  150     }
  151     }
  152     ln_pcre_extract_free(out, rc);
  153 
  154     exit(0);
  155 }
  156 #endif