aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/args.c89
-rw-r--r--src/args.h31
-rw-r--r--src/filter/filter.h15
-rw-r--r--src/filter/uniq.c0
-rw-r--r--src/filter/uniq.h12
-rw-r--r--src/io/io.c13
-rw-r--r--src/io/io.h24
-rw-r--r--src/io/svg.c52
-rw-r--r--src/io/svg.h10
-rw-r--r--src/io/text.c10
-rw-r--r--src/io/text.h10
-rw-r--r--src/main.c72
-rw-r--r--src/pattern/next.c79
-rw-r--r--src/pattern/next.h9
-rw-r--r--src/pattern/pattern.c83
-rw-r--r--src/pattern/pattern.h93
-rw-r--r--src/pattern/random.c1
-rw-r--r--src/pattern/random.h5
-rw-r--r--src/utils/args.c83
-rw-r--r--src/utils/args.h28
-rw-r--r--src/utils/utilities.c68
-rw-r--r--src/utils/utilities.h42
22 files changed, 829 insertions, 0 deletions
diff --git a/src/args.c b/src/args.c
new file mode 100644
index 0000000..fb73e6c
--- /dev/null
+++ b/src/args.c
@@ -0,0 +1,89 @@
+#include "args.h"
+#include <string.h>
+#include <stdlib.h>
+#include "pattern/next.h"
+#include "io/text.h"
+#include "io/svg.h"
+
+/*
+ * Options start.
+ */
+
+#define OPTIONS \
+ { \
+ {"w", "wait", false, wait}, \
+ {"n", "num", true, num}, \
+ {"p", "print", true, print}, \
+ {"os", "outputs", true, outputs}, \
+ {"fn", "from-num", true, fn}, \
+ {"tn", "to-num", true, tn}, \
+ }
+
+void wait(void *args, const char *str)
+{
+ ((struct args *)args)->wait = true;
+}
+
+void num(void *args, const char *str)
+{
+ ((struct args *)args)->gen_count = atoi(str);
+}
+
+void fn(void *args, const char *str)
+{
+ ((struct args *)args)->from_count = atoi(str);
+}
+
+void tn(void *args, const char *str)
+{
+ ((struct args *)args)->to_count = atoi(str);
+}
+
+void print(void *args, const char *str)
+{
+ ((struct args *)args)->print = str[0] == 's' ? print_pattern_svg : print_pattern_text;
+}
+
+void outputs(void *args, const char *str)
+{
+ struct args *args_ = (struct args *)args;
+ args_->standard_output = false;
+ args_->single_output = false;
+ strcpy(args_->output, str);
+}
+
+/*
+ * Options end.
+ */
+
+void load_defaults(struct args *args)
+{
+ // Pattern
+ args->pattern.length = 0;
+ args->pattern.type = gen_pattern_type(3, 4, -1);
+ // Params
+ args->params.aggregated = false;
+ args->params.count = 0;
+ args->params.print_author = true;
+ args->params.print_code = true;
+ args->params.print_count = true;
+ // Egyéb
+ args->gen_count = -1;
+ args->from_count = -1;
+ args->to_count = -1;
+ args->gen = next_point;
+ args->print = print_pattern_text;
+ args->single_output = true;
+ args->standard_output = true;
+ args->wait = false;
+}
+
+enum alr load_args(int argc, char **argv, struct args *args)
+{
+ // Init
+ load_defaults(args);
+ struct option options[] = OPTIONS;
+ int opt_length = sizeof(options) / sizeof(struct option);
+ // Process
+ return process_args(argc, argv, options, opt_length, args);
+} \ No newline at end of file
diff --git a/src/args.h b/src/args.h
new file mode 100644
index 0000000..780a621
--- /dev/null
+++ b/src/args.h
@@ -0,0 +1,31 @@
+#ifndef PLOC_GEN_ARGS_H
+#define PLOC_GEN_ARGS_H
+
+#include <stdbool.h>
+#include "pattern/pattern.h"
+#include "io/io.h"
+#include "utils/args.h"
+#include <stdio.h>
+
+struct args
+{
+ struct pattern pattern;
+ /*
+ * Negative value means unlimited.
+ */
+ int gen_count;
+ int from_count;
+ int to_count;
+ bool (*gen)(struct pattern *);
+ void (*print)(FILE *, struct print_params, struct pattern *);
+ struct print_params params;
+ bool wait;
+
+ bool single_output;
+ bool standard_output;
+ char output[512];
+};
+
+enum alr load_args(int argc, char **argv, struct args *args);
+
+#endif \ No newline at end of file
diff --git a/src/filter/filter.h b/src/filter/filter.h
new file mode 100644
index 0000000..7cdb640
--- /dev/null
+++ b/src/filter/filter.h
@@ -0,0 +1,15 @@
+#ifndef PLOC_GEN_FILTER_H
+#define PLOC_GEN_FILTER_H
+
+#include "stdbool.h"
+#include "pattern/pattern.h"
+
+struct filter
+{
+ void *state;
+ void *(*create)();
+ void (*free)(void *);
+ bool (*filter)(void *, struct pattern *);
+};
+
+#endif \ No newline at end of file
diff --git a/src/filter/uniq.c b/src/filter/uniq.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/filter/uniq.c
diff --git a/src/filter/uniq.h b/src/filter/uniq.h
new file mode 100644
index 0000000..fa235a5
--- /dev/null
+++ b/src/filter/uniq.h
@@ -0,0 +1,12 @@
+#ifndef PLOC_GEN_FILTER_UNIQ_H
+#define PLOC_GEN_FILTER_UNIQ_H
+
+#include "stdbool.h"
+#include "pattern/pattern.h"
+
+void *create_uniq();
+void free_uniq(void *state);
+
+bool uniq(void *state, struct pattern *pattern);
+
+#endif \ No newline at end of file
diff --git a/src/io/io.c b/src/io/io.c
new file mode 100644
index 0000000..e9f4fb8
--- /dev/null
+++ b/src/io/io.c
@@ -0,0 +1,13 @@
+#include "io.h"
+#include "stdio.h"
+
+void pattern_nums_to_str(char *str, struct pattern *pattern)
+{
+ str[0] = 0;
+ if (pattern->length >= 1)
+ str += sprintf(str, "%d", pattern_point_to_index(pattern, 0));
+ for (int i = 1; i < pattern->length; i++)
+ {
+ str += sprintf(str, ",%d", pattern_point_to_index(pattern, i));
+ }
+} \ No newline at end of file
diff --git a/src/io/io.h b/src/io/io.h
new file mode 100644
index 0000000..97af398
--- /dev/null
+++ b/src/io/io.h
@@ -0,0 +1,24 @@
+#ifndef PLOC_GEN_IO_H
+#define PLOC_GEN_IO_H
+
+#include "pattern/pattern.h"
+
+/*
+ * Print parameters.
+ */
+struct print_params
+{
+ unsigned int count;
+ /*
+ * aggregated is true, if the print function gets called on the
+ * same file over and over again.
+ */
+ bool aggregated;
+ bool print_count;
+ bool print_code;
+ bool print_author;
+};
+
+void pattern_nums_to_str(char *str, struct pattern *pattern);
+
+#endif \ No newline at end of file
diff --git a/src/io/svg.c b/src/io/svg.c
new file mode 100644
index 0000000..a8e2129
--- /dev/null
+++ b/src/io/svg.c
@@ -0,0 +1,52 @@
+#include "svg.h"
+
+void print_pattern_svg(FILE *out, struct print_params params, struct pattern *pattern)
+{
+ // Init variables.
+ double horizontal = 100 / (pattern->type.height + 1);
+ double vertical = 100 / (pattern->type.width + 1);
+ int hd = horizontal; // Horizontal distance
+ int vd = vertical; // Vertical distance
+ // Print
+ fprintf(out, "<svg width=\"500\" height=\"500\" style=\"background-color:black\">");
+ fprintf(out, "<rect width=\"100%%\" height=\"100%%\" fill=\"black\" />");
+
+ if (params.print_code)
+ {
+ char code[128];
+ pattern_nums_to_str(code, pattern);
+ fprintf(out, "<text x=\"0\" y=\"1em\" font-size=\"2em\" fill=\"white\">Code:%s</text>", code);
+ }
+ if (params.print_count)
+ fprintf(out, "<text x=\"0\" y=\"2em\" font-size=\"2em\" fill=\"white\">Count:%d</text>", params.count);
+ if (params.print_author)
+ fprintf(out, "<text x=\"500\" y=\"500\" font-size=\"1em\" fill=\"white\" text-anchor=\"end\">adriansopar.hu</text>");
+
+ // TODO: Print text!
+ // Print points.
+ for (int y = 0; y < pattern->type.height; y++)
+ {
+ for (int x = 0; x < pattern->type.width; x++)
+ {
+ fprintf(out,
+ "<circle cx=\"%f%%\" cy=\"%f%%\" r=\"%d%%\" fill=\"white\" />",
+ (double)(x + 1) * hd, (double)(y + 1) * vd, 3);
+ }
+ }
+ // Print pattern.
+ struct coord prev;
+ for (int i = 0; i < pattern->length; i++)
+ {
+ struct coord current = pattern->path[i];
+ fprintf(out,
+ "<circle cx=\"%f%%\" cy=\"%f%%\" r=\"6%%\" stroke=\"#00ff00\" stroke-width=\"2\" fill=\"none\" />",
+ (double)(current.x + 1) * hd, (double)(current.y + 1) * vd);
+ if (i > 0)
+ fprintf(out,
+ "<line x1=\"%f%%\" y1=\"%f%%\" x2=\"%f%%\" y2=\"%f%%\" stroke=\"white\" stroke-width=\"6%%\" stroke-opacity=\"0.5\" />",
+ (double)(prev.x + 1) * hd, (double)(prev.y + 1) * vd,
+ (double)(current.x + 1) * hd, (double)(current.y + 1) * vd);
+ prev = current;
+ }
+ fprintf(out, "</svg>");
+} \ No newline at end of file
diff --git a/src/io/svg.h b/src/io/svg.h
new file mode 100644
index 0000000..75559a2
--- /dev/null
+++ b/src/io/svg.h
@@ -0,0 +1,10 @@
+#ifndef PLOC_GEN_IO_SVG_H
+#define PLOC_GEN_IO_SVG_H
+
+#include <stdio.h>
+#include "pattern/pattern.h"
+#include "io.h"
+
+void print_pattern_svg(FILE *out, struct print_params params, struct pattern *pattern);
+
+#endif \ No newline at end of file
diff --git a/src/io/text.c b/src/io/text.c
new file mode 100644
index 0000000..a035cc5
--- /dev/null
+++ b/src/io/text.c
@@ -0,0 +1,10 @@
+#include "text.h"
+
+void print_pattern_text(FILE *out, struct print_params params, struct pattern *pattern)
+{
+ for (int i = 0; i < pattern->length; i++)
+ {
+ fprintf(out, "%d,", pattern_point_to_index(pattern, i));
+ }
+ fprintf(out, "\n");
+} \ No newline at end of file
diff --git a/src/io/text.h b/src/io/text.h
new file mode 100644
index 0000000..435294d
--- /dev/null
+++ b/src/io/text.h
@@ -0,0 +1,10 @@
+#ifndef PLOC_GEN_IO_TEXT_H
+#define PLOC_GEN_IO_TEXT_H
+
+#include <stdio.h>
+#include "pattern/pattern.h"
+#include "io.h"
+
+void print_pattern_text(FILE *out, struct print_params params, struct pattern *pattern);
+
+#endif \ No newline at end of file
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..7f961e7
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include "args.h"
+#include "pattern/pattern.h"
+#include "io/text.h"
+#include "io/svg.h"
+
+/*
+ * EX stands for EXIT STATUS and
+ * EXE stands for EXIT STATUS ERROR
+ */
+#define EX_OK 0
+#define EXE_ARGS 1
+#define EXE_IO 2
+
+int main(int argc, char **argv)
+{
+ struct args args;
+ enum alr alr = load_args(argc, argv, &args);
+ if (alr != ALR_OK)
+ {
+ if (alr == ALR_INVALID_OPTION)
+ fprintf(stderr, "Invalid option!");
+ else
+ fprintf(stderr, "Args processing error!\n");
+ return EXE_ARGS;
+ }
+ struct pattern *pattern = &args.pattern;
+ struct coord path[16];
+ pattern->path = path;
+
+ args.params.count = 0;
+ FILE *out = stdout;
+ if (!args.standard_output && args.single_output)
+ {
+ if ((out = fopen(args.output, "w")) == NULL)
+ {
+ fprintf(stderr, "%s file cannot be opened.", args.output);
+ return EXE_IO;
+ }
+ }
+ while (args.gen(pattern) && (args.gen_count < 0 || args.params.count < args.gen_count))
+ {
+ args.params.count++;
+ if ((args.from_count <= (int)args.params.count) && (((int)args.params.count <= args.to_count) || (args.to_count < 0)))
+ {
+ if (!args.standard_output && !args.single_output)
+ {
+ char file_path[512];
+ sprintf(file_path, args.output, args.params.count);
+ if ((out = fopen(file_path, "w")) == NULL)
+ {
+ fprintf(stderr, "%s file cannot be opened.", file_path);
+ return EXE_IO;
+ }
+ }
+
+ args.print(out, args.params, pattern);
+ if (args.wait)
+ {
+ char c;
+ getchar();
+ }
+
+ if (!args.standard_output && !args.single_output)
+ fclose(out);
+ }
+ }
+ if (!args.standard_output && args.single_output)
+ fclose(out);
+
+ return EX_OK;
+} \ No newline at end of file
diff --git a/src/pattern/next.c b/src/pattern/next.c
new file mode 100644
index 0000000..10261bc
--- /dev/null
+++ b/src/pattern/next.c
@@ -0,0 +1,79 @@
+#include "next.h"
+#include <stdlib.h>
+
+/*
+ * It gives the first point that:
+ * - Isn't part of pattern->path
+ * - Its index the lowest possible, but minimum min_index
+ * - There isn't any point in-line between it and the last of the path
+ * Returns true if such a point exsist, otherwise returns false.
+ */
+bool free_point(struct pattern *pattern, int min_index, struct coord *new_point)
+{
+ //printf("min_index=%d\n", min_index);
+ struct coord result = index_to_coord(pattern->type.width, min_index);
+ struct coord *last = pattern->length > 0 ? &pattern->path[pattern->length - 1] : NULL;
+ while (result.y < pattern->type.height)
+ {
+ while (result.x < pattern->type.width)
+ {
+ if (last == NULL)
+ {
+ *new_point = result;
+ return true;
+ }
+ else if (find_in_pattern(pattern, &result) < 0 &&
+ nothing_inbetween(pattern, &result))
+ {
+ //printf("fp(%d;%d)\n", result.x, result.y);
+ *new_point = result;
+ return true;
+ }
+ result.x++;
+ }
+ result.y++;
+ result.x = 0;
+ }
+ return false;
+}
+
+/*
+ * Changes pattern->path to the next possible pattern.
+ * It returns false if there's no possible pattern left,
+ * otherwise it returns true.
+ */
+bool next_point(struct pattern *pattern)
+{
+ struct coord next_point;
+ if (len_is_max(pattern))
+ {
+ do
+ {
+ if (pattern->length == 0)
+ return false; //Nincs több minta
+ next_point = pattern->path[--pattern->length];
+ } while (!free_point(
+ pattern,
+ coord_to_index(pattern->type.width, next_point) + 1,
+ &next_point));
+ //printf("(%d;%d)\n", next_point.x, next_point.y);
+ pattern->path[pattern->length++] = next_point;
+ if (pattern->length >= pattern->type.min_length)
+ return true;
+ }
+
+ do
+ {
+ if (free_point(pattern, 0, &next_point))
+ {
+ pattern->path[pattern->length++] = next_point;
+ //return true;
+ }
+ } while (pattern->length < pattern->type.min_length);
+
+ return true;
+
+ // Ha visszalépés volt, akkor az első újra előrelépésnél, csak nagyobb indexű
+ // elemre szabad lépni.
+ // Ha előrelépés volt, akkor a legkissebb indexű szabad elemre kell lépni.
+}
diff --git a/src/pattern/next.h b/src/pattern/next.h
new file mode 100644
index 0000000..c6aa380
--- /dev/null
+++ b/src/pattern/next.h
@@ -0,0 +1,9 @@
+#ifndef PLOC_GEN_PATTERN_NEXT_H
+#define PLOC_GEN_PATTERN_NEXT_H
+
+#include <stdbool.h>
+#include "pattern.h"
+
+bool next_point(struct pattern *pattern);
+
+#endif \ No newline at end of file
diff --git a/src/pattern/pattern.c b/src/pattern/pattern.c
new file mode 100644
index 0000000..85e21c7
--- /dev/null
+++ b/src/pattern/pattern.c
@@ -0,0 +1,83 @@
+#include "pattern.h"
+#include <stdlib.h>
+#include "utils/utilities.h"
+
+/*
+ * Inline functions
+ */
+bool len_is_max(struct pattern *pattern);
+bool len_is_min(struct pattern *pattern);
+int coord_to_index(int width, struct coord point);
+struct coord index_to_coord(int width, int index);
+int pattern_point_to_index(struct pattern *pattern, int index);
+
+struct pattern_type gen_pattern_type(int side_len, int min, int max)
+{
+ struct pattern_type result;
+ result.width = side_len;
+ result.height = side_len;
+
+ int max_possible = side_len * side_len;
+ result.min_length = min >= 0 ? min : max_possible;
+ if (max >= 0 && max <= max_possible)
+ result.max_length = max;
+ else
+ result.max_length = max_possible;
+ return result;
+}
+
+int coord_cmp(const void *a, const void *b)
+{
+ const struct coord *ac = a;
+ const struct coord *bc = b;
+ if (ac->x == bc->x && ac->y == bc->y)
+ return 0;
+ //TODO: Handle when the inputs are not equal!
+ return -1;
+}
+
+bool is_in_line(struct coord a, struct coord c, struct coord b)
+{
+ if (!(monotonic(a.x, b.x, c.x) && monotonic(a.y, b.y, c.y)))
+ return false;
+ return ((b.x - a.x) * (c.y - a.y)) + ((b.y - a.y) * (a.x - c.x)) == 0;
+}
+
+int find_in_pattern(struct pattern *pattern, struct coord *coord)
+{
+ for (int i = 0; i < pattern->length; i++)
+ {
+ struct coord *current = &pattern->path[i];
+ if (current->x == coord->x && current->y == coord->y)
+ return i;
+ }
+ return -1;
+}
+
+int inbetween(int width, int height, struct coord *from, struct coord *to, struct coord *arr)
+{
+ int length = 0;
+ struct coord current;
+ for (current.y = 0; current.y < height; current.y++)
+ for (current.x = 0; current.x < width; current.x++)
+ if ((current.x != from->x || current.y != from->y) &&
+ (current.x != to->x || current.y != to->y))
+ if (is_in_line(*from, *to, current))
+ arr[length++] = current;
+ return length;
+}
+
+bool nothing_inbetween(struct pattern *pattern, struct coord *next)
+{
+ if (pattern->length == 0)
+ return true;
+ struct coord *last = &pattern->path[pattern->length - 1];
+ struct coord arr[pattern->type.width * pattern->type.height];
+ size_t length = inbetween(pattern->type.width, pattern->type.height, last, next, arr);
+ if (length > pattern->length)
+ return false;
+ for (int i = 0; i < length; i++)
+ if (find_in_pattern(pattern, &arr[i]) < 0)
+ return false;
+ return true;
+}
diff --git a/src/pattern/pattern.h b/src/pattern/pattern.h
new file mode 100644
index 0000000..d53576e
--- /dev/null
+++ b/src/pattern/pattern.h
@@ -0,0 +1,93 @@
+#ifndef PLOC_GEN_PATTERN_PATTERN_H
+#define PLOC_GEN_PATTERN_PATTERN_H
+
+#include <stdbool.h>
+
+struct coord
+{
+ int x;
+ int y;
+};
+
+struct pattern_type
+{
+ int width;
+ int height;
+ int min_length;
+ int max_length;
+};
+
+struct pattern
+{
+ struct pattern_type type;
+ struct coord *path;
+ int length;
+};
+
+/*
+ * Creates a pattern_type.
+ * If max has an invalid value the max_length is set to the
+ * maximum possible length.
+ */
+struct pattern_type gen_pattern_type(int side_len, int min, int max);
+
+/*
+ * Returns 0 if a equals b.
+ */
+int coord_cmp(const void *a, const void *b);
+
+/*
+ * If the point happend to be on the line that connects start and end,
+ * the result is true, otherwise is false.
+ */
+bool is_in_line(struct coord a, struct coord c, struct coord b);
+
+/*
+ * Returns the index of coord in pattern->path.
+ * The return value is negative if coord not found in pattern->path.
+ */
+int find_in_pattern(struct pattern *pattern, struct coord *coord);
+
+/*
+ * Gives back the points in arr, that are between from and to.
+ */
+int inbetween(int width, int height, struct coord *from, struct coord *to, struct coord *arr);
+
+/*
+ * Returns true if there's no unvisited point between
+ * the last point of path and next.
+ */
+bool nothing_inbetween(struct pattern *pattern, struct coord *next);
+
+/*
+ * Inline functions.
+ */
+inline bool len_is_max(struct pattern *pattern)
+{
+ return pattern->length >= pattern->type.max_length;
+}
+
+inline bool len_is_min(struct pattern *pattern)
+{
+ return pattern->length <= pattern->type.min_length;
+}
+
+inline int coord_to_index(int width, struct coord point)
+{
+ return (point.y * width) + point.x;
+}
+
+inline struct coord index_to_coord(int width, int index)
+{
+ struct coord result;
+ result.y = index / width;
+ result.x = index % width;
+ return result;
+}
+
+inline int pattern_point_to_index(struct pattern *pattern, int index)
+{
+ return coord_to_index(pattern->type.width, pattern->path[index]);
+}
+
+#endif \ No newline at end of file
diff --git a/src/pattern/random.c b/src/pattern/random.c
new file mode 100644
index 0000000..b7dba62
--- /dev/null
+++ b/src/pattern/random.c
@@ -0,0 +1 @@
+#include "random.h"
diff --git a/src/pattern/random.h b/src/pattern/random.h
new file mode 100644
index 0000000..68aeddc
--- /dev/null
+++ b/src/pattern/random.h
@@ -0,0 +1,5 @@
+#ifndef PLOC_GEN_PATTERN_RANDOM_H
+#define PLOC_GEN_PATTERN_RANDOM_H
+
+
+#endif \ No newline at end of file
diff --git a/src/utils/args.c b/src/utils/args.c
new file mode 100644
index 0000000..e569b15
--- /dev/null
+++ b/src/utils/args.c
@@ -0,0 +1,83 @@
+#include "args.h"
+#include <stdlib.h>
+#include <string.h>
+#include "utilities.h"
+
+#include <stdio.h>
+enum alr process_args(int argc, char **argv, struct option *options, int opt_length, void *args)
+{
+ // Processing
+ for (int i = 1; i < argc; i++)
+ {
+ //printf("%d: Init variables.\n", i);
+ // Init variables.
+ char *arg_name = argv[i];
+ char *arg_param = NULL;
+ bool long_name = false;
+ //printf("%d: Extract name.\n", i);
+ // Extract name.
+ if (arg_name[0] == '-')
+ arg_name++;
+ if (arg_name[0] == '-')
+ {
+ arg_name++;
+ long_name = true;
+ }
+ if (arg_name[0] == 0)
+ {
+ // Syntax error
+ }
+
+ //printf("%d: Find option (%s)(%s).\n", i, arg_name, long_name ? "long" : "short");
+ // Find option.
+ struct option *option = NULL;
+ for (int i = 0; i < opt_length; i++)
+ {
+ //printf("option[i]: %s\n", options[i].short_name);
+ if (long_name)
+ {
+ if (cmpstr_tillchar(arg_name, options[i].name, '\0', '=') == 0)
+ option = &options[i];
+ }
+ else
+ {
+ if (cmpstr_tillchar(arg_name, options[i].short_name, '\0', '\0') == 0)
+ option = &options[i];
+ }
+ }
+ if (option == NULL)
+ return ALR_INVALID_OPTION;
+
+ //printf("%d: Find param.\n", i);
+ // Find param.
+ if (option->has_param)
+ {
+ if (long_name)
+ {
+ arg_param = strchr(arg_name, '=');
+ if (arg_param != NULL)
+ {
+ arg_param++;
+ if (arg_param[0] == '\0')
+ arg_param = NULL;
+ }
+ }
+ else
+ {
+ i++;
+ if (i < argc)
+ arg_param = argv[i];
+ }
+
+ if (arg_param == NULL)
+ {
+ // Error: Missing param.
+ }
+ }
+
+ //printf("%d: Process.\n", i);
+ // Process.
+ option->handle(args, arg_param);
+ }
+ return ALR_OK;
+} \ No newline at end of file
diff --git a/src/utils/args.h b/src/utils/args.h
new file mode 100644
index 0000000..ddf086d
--- /dev/null
+++ b/src/utils/args.h
@@ -0,0 +1,28 @@
+#ifndef UTILS_ARGS_H
+#define UTILS_ARGS_H
+
+#include <stdbool.h>
+
+struct option
+{
+ char short_name[16];
+ char name[32];
+ bool has_param;
+ // first: args struct; second: param;
+ void (*handle)(void *, const char *);
+};
+
+// ALR stands for Args Load Result
+enum alr
+{
+ ALR_OK,
+ ALR_INVALID_OPTION
+};
+
+/*
+ * opt_length: options length
+ * args: args struct
+ */
+enum alr process_args(int argc, char **argv, struct option *options, int opt_length, void *args);
+
+#endif \ No newline at end of file
diff --git a/src/utils/utilities.c b/src/utils/utilities.c
new file mode 100644
index 0000000..717dce0
--- /dev/null
+++ b/src/utils/utilities.c
@@ -0,0 +1,68 @@
+#include "utils/utilities.h"
+#include <string.h>
+#include <time.h>
+
+bool monotonic(int a, int b, int c);
+
+// TODO: Handle the case when they are not equal (greater or smaller)
+int cmpstr_tillchar(const char *a, const char *b, char a_until, char b_until)
+{
+ while (*a != 0 && *b != 0 && *a != a_until && *b != b_until)
+ {
+ if (*a != *b)
+ return -1;
+ a++;
+ b++;
+ }
+ return 0;
+}
+
+static unsigned int random_number(unsigned int max)
+{
+ return rand() / (RAND_MAX / max);
+}
+
+void shuffle(void *base, size_t nitems, size_t size)
+{
+ char *c_base = base;
+ char swap[size];
+ for (int i = 0; i < nitems; i++)
+ {
+ char *a = c_base + (i * size);
+ char *b = c_base + (random_number(nitems - 1) * size);
+ memcpy(swap, a, size);
+ memcpy(a, b, size);
+ memcpy(b, swap, size);
+ }
+}
+
+void init2d(void **array, size_t width, size_t height, size_t size)
+{
+ char **c_array = (char **)array;
+ char *start = (char *)array;
+ for (size_t x = 0; x < width; x++)
+ c_array[x] = start + (width * sizeof(int *)) + (x * height * size);
+}
+
+size_t sizeof_2d(size_t width, size_t height, size_t size)
+{
+ return (width * sizeof(char *)) + (width * height * size);
+}
+
+int find_lr_ints(char *text, char **left, char **right)
+{
+ *left = text;
+ while (**left != 0 && (**left < '0' || **left > '9'))
+ (*left)++;
+ if (**left == 0)
+ return 0;
+
+ *right = text + strlen(text);
+ while (**right < '0' || **right > '9')
+ (*right)--;
+
+ while (**right >= '0' && **right <= '9')
+ (*right)--;
+ (*right)++;
+ return 1;
+} \ No newline at end of file
diff --git a/src/utils/utilities.h b/src/utils/utilities.h
new file mode 100644
index 0000000..9447c1f
--- /dev/null
+++ b/src/utils/utilities.h
@@ -0,0 +1,42 @@
+#ifndef UTILS_UTILITIES_H
+#define UTILS_UTILITIES_H
+
+#include <stdlib.h>
+#include <stdbool.h>
+
+/*
+ * Compare the part a before a_until and
+ * the part b before b_until
+ */
+int cmpstr_tillchar(const char *a, const char *b, char a_until, char b_until);
+
+//int cmpstr_tillindex(const char *a, const char *b, int a_until, int b_until);
+
+void shuffle(void *base, size_t nitems, size_t size);
+
+void init2d(void **array, size_t width, size_t height, size_t size);
+
+size_t sizeof_2d(size_t width, size_t height, size_t size);
+
+/*
+ * Find the first integer numbers from the left and the right
+ * and sets the pointers *left, *right to the first digit of
+ * left and right numbers respectively.
+ */
+int find_lr_ints(char *text, char **left, char **right);
+
+/*
+ * Returns ture, if
+ * a <= b <= c OR
+ * a >= b >= c
+ */
+inline bool monotonic(int a, int b, int c)
+{
+ if (a <= b && b <= c)
+ return true;
+ if (a >= b && b >= c)
+ return true;
+ return false;
+}
+
+#endif \ No newline at end of file