diff options
author | Mole Shang <[email protected]> | 2023-08-07 15:36:19 +0800 |
---|---|---|
committer | Mole Shang <[email protected]> | 2023-08-07 15:47:37 +0800 |
commit | 93395705c40265c1893efd550b0f8404158eb86c (patch) | |
tree | 47aa1dc50729b2056d246a72c629905b8792e353 /src/utils | |
parent | 6055d641fff8502be8751eff42c8e59d0019592a (diff) | |
download | hinata-93395705c40265c1893efd550b0f8404158eb86c.tar.gz hinata-93395705c40265c1893efd550b0f8404158eb86c.tar.bz2 hinata-93395705c40265c1893efd550b0f8404158eb86c.zip |
utils: move to a separate folder
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/utils.c | 216 | ||||
-rw-r--r-- | src/utils/utils.h | 63 |
2 files changed, 279 insertions, 0 deletions
diff --git a/src/utils/utils.c b/src/utils/utils.c new file mode 100644 index 0000000..475f5e0 --- /dev/null +++ b/src/utils/utils.c @@ -0,0 +1,216 @@ +#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; +} + +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; + } +} diff --git a/src/utils/utils.h b/src/utils/utils.h new file mode 100644 index 0000000..79c58ca --- /dev/null +++ b/src/utils/utils.h @@ -0,0 +1,63 @@ +#ifndef UTILS_H_ +#define UTILS_H_ + +#include <stddef.h> + +typedef void *data_t; + +typedef struct str_array { + char **str; + size_t n; +} str_array_t; + +typedef struct generic_array { + void *data; + size_t elem_size; + size_t n; +} generic_array_t; + +typedef struct node { + data_t data; + struct node *next; +} node_t; + +typedef struct queue { + node_t *front; + node_t *rear; +} queue_t; + +int regex_match(const char *, str_array_t, str_array_t *); + +int repchr(char *str, char t, char r); + +generic_array_t create_array(size_t elem_size, size_t n); + +void free_array(generic_array_t *array); + +void resize_array(generic_array_t *array, size_t new_size); + +void *get_element(generic_array_t *array, size_t index); + +void free_and_nullify(void *p); + +str_array_t create_str_array(size_t n); + +void free_str_array(str_array_t *array); + +void resize_str_array(str_array_t *array, size_t new_size); + +int set_str_element(str_array_t *array, size_t index, const char *value); + +const char *get_str_element(str_array_t *array, size_t index); + +queue_t create_queue(void); + +int is_empty_queue(queue_t *queue); + +void enqueue(queue_t *queue, data_t data); + +data_t dequeue(queue_t *queue); + +void free_queue(queue_t *queue); + +#endif |