summaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
authorMole Shang <[email protected]>2023-08-07 15:36:19 +0800
committerMole Shang <[email protected]>2023-08-07 15:47:37 +0800
commit93395705c40265c1893efd550b0f8404158eb86c (patch)
tree47aa1dc50729b2056d246a72c629905b8792e353 /src/utils
parent6055d641fff8502be8751eff42c8e59d0019592a (diff)
downloadhinata-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.c216
-rw-r--r--src/utils/utils.h63
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