summaryrefslogtreecommitdiff
path: root/src/utils/utils.c
blob: 16d39d9bd599834620d190d10b881115bd242485 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <pcre2.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../logger.h"
#include "utils.h"

int regex_match(const char *subject, str_array_t patterns,
                str_array_t *results) {
  pcre2_code *re;

  int errornumber;
  int rc = PCRE2_ERROR_NOMATCH;

  PCRE2_SIZE subject_len = strlen(subject);
  PCRE2_SIZE offset = 0, erroroffset;
  PCRE2_SIZE *ovector;

  pcre2_match_data *match_data;
  for (unsigned short i = 0; i < patterns.n; i++) {
    DEBUG_PRINT("Gets pattern: %s\n", patterns.str[i]);
    re = pcre2_compile((PCRE2_SPTR)patterns.str[i], PCRE2_ZERO_TERMINATED, 0,
                       &errornumber, &erroroffset, NULL);

    if (re == NULL) {
      PCRE2_UCHAR buffer[256];
      pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
      LOG("PCRE2", "compilation failed at offset %d: %s\n", (int)erroroffset,
          buffer);
      return 1;
    }

    match_data = pcre2_match_data_create_from_pattern(re, NULL);

    unsigned char i = 0;
    while (offset < subject_len &&
           (rc = pcre2_match(re, (PCRE2_SPTR)subject, (PCRE2_SIZE)subject_len,
                             offset, 0, match_data, NULL)) > 0) {

      // results->str = realloc(results->str, sizeof(char *) * (rc +
      // results->n));
      resize_str_array(results, rc + i);

      ovector = pcre2_get_ovector_pointer(match_data);
      DEBUG_PRINT("Get %d captures.\n", rc - 1);
      DEBUG_PRINT("Match succeeded at offset %d.\n", (int)ovector[0]);

      for (unsigned short j = 1; j < rc; j++) {
        PCRE2_SIZE substring_length = ovector[2 * j + 1] - ovector[2 * j];
        PCRE2_SPTR substring = (PCRE2_SPTR)subject + ovector[2 * j];
        /* Here we need to manually control the str array,
         * as PCRE2_SPTR == const unsigned char
         * (which cannot be directly casted) */
        results->str[j] = malloc(substring_length + 1);
        sprintf(results->str[j], "%.*s", (int)substring_length, substring);
        DEBUG_PRINT("index: %2d, substring_length: %d\n", j,
                    (int)substring_length);
      }
      offset = ovector[1];
      DEBUG_PRINT("offset: %zu, subject_len: %zu\n", offset, subject_len);
      i++;
    }
    pcre2_match_data_free(match_data);
    pcre2_code_free(re);
    if (rc <= 0) {

      switch (rc) {
      case PCRE2_ERROR_NOMATCH:
        DEBUG_PRINT("No match found.\n");
        return 0;
        break;
      case 0:
        LOG("PCRE2",
            "ovector was not big enough for all the captured substrings\n");
        break;
      default:
        LOG("PCRE2", "Matching error %d\n", rc);
        return 1;
      }
    }
  }
  return 0;
}

int repchr(char *str, char t, char r) {
  int c = 0;
  for (size_t i = 0; str[i] != '\0'; i++) {
    if (str[i] == t) {
      str[i] = r;
      c++;
    }
  }
  return c;
}


void free_and_nullify(void *p) {
  if (p) {
    free(p);
    p = NULL;
  }
}