#include #include #include #include #include #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; } generic_array_t create_array(size_t elem_size, size_t n) { generic_array_t array; array.data = n ? malloc(elem_size * n) : NULL; array.elem_size = elem_size; array.n = n; return array; } void free_array(generic_array_t *array) { free_and_nullify(array->data); array->n = 0; } void resize_array(generic_array_t *array, size_t new_size) { array->data = realloc(array->data, array->elem_size * new_size); array->n = new_size; } void *get_element(generic_array_t *array, size_t index) { if (index >= array->n) { return NULL; // Out of bounds } return (char *)array->data + index * array->elem_size; } /* A more specific impl, specially for string (char *) */ str_array_t create_str_array(size_t n) { str_array_t array; array.str = n ? malloc(n * sizeof(char *)) : NULL; array.n = n; for (size_t i = 0; i < n; i++) { array.str[i] = NULL; } return array; } void free_str_array(str_array_t *array) { for (size_t i = 0; i < array->n; i++) { free(array->str[i]); } free_and_nullify(array->str); array->n = 0; } void resize_str_array(str_array_t *array, size_t new_size) { array->str = realloc(array->str, sizeof(char *) * new_size); for (size_t i = array->n; i < new_size; i++) { array->str[i] = NULL; } array->n = new_size; } int set_str_element(str_array_t *array, size_t index, const char *value) { if (index >= array->n) { return 1; // Out of bounds } array->str[index] = malloc(strlen(value) + 1); strcpy(array->str[index], value); return 0; } const char *get_str_element(str_array_t *array, size_t index) { if (index >= array->n) { return NULL; // Out of bounds } return array->str[index]; } queue_t create_queue(void) { queue_t queue; queue.front = queue.rear = NULL; return queue; } int is_empty_queue(queue_t *queue) { return queue->front == NULL; } void enqueue(queue_t *queue, data_t data) { node_t *node = malloc(sizeof(node_t)); node->data = data; node->next = NULL; if (queue->rear == NULL) { queue->rear = queue->front = node; } else { queue->rear->next = node; queue->rear = node; } } data_t dequeue(queue_t *queue) { if (is_empty_queue(queue)) { DEBUG_PRINT("Queue is empty.\n"); return NULL; } node_t *temp = queue->front; data_t data = temp->data; queue->front = temp->next; free_and_nullify(temp); if (queue->front == NULL) { queue->rear = NULL; } return data; } void free_queue(queue_t *queue) { while (!is_empty_queue(queue)) { dequeue(queue); } } void free_and_nullify(void *p) { if (p) { free(p); p = NULL; } }