diff --git a/includes/parsing.h b/includes/parsing.h new file mode 100644 index 0000000..9a24dc0 --- /dev/null +++ b/includes/parsing.h @@ -0,0 +1,44 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parsing.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: apago +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/04 18:22:11 by apago #+# #+# */ +/* Updated: 2023/04/04 18:28:44 by apago ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PARSING_H +# define PARSING_H + +# include "fcntl.h" +# include "stdio.h" +# include "stdlib.h" +# include "unistd.h" + +typedef struct Meta +{ + char empty; + char obstacle; + char full; + int height; + int width; +} t_meta; + +typedef struct Map +{ + t_meta meta; + char *data; +} t_map; + +char *read_file(int file); +size_t read_uint(char *str); +int parse_valid_uint(char *str, size_t len); +int read_char(char *str, char *dst); +int printable(char c); +size_t count_first_line(char *line); +int read_fname(char *name, t_map *map); + +#endif \ No newline at end of file diff --git a/srcs/io.c b/srcs/io.c new file mode 100644 index 0000000..ddcfa03 --- /dev/null +++ b/srcs/io.c @@ -0,0 +1,73 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* io.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: apago +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/04 18:23:57 by apago #+# #+# */ +/* Updated: 2023/04/04 18:24:50 by apago ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parsing.h" + +void copy_bytes(char *dst, char *src, size_t bytes) +{ + size_t i; + + i = 0; + while (i < bytes) + { + dst[i] = src[i]; + i++; + } +} + +int push_bytes(size_t n_read, char **res, size_t *offset, size_t *size) +{ + char *new_res; + + if (n_read <= 0) + return (n_read); + *offset += n_read; + if (*offset == *size) + { + new_res = malloc(*size * 2); + if (!new_res) + return (-1); + copy_bytes(new_res, *res, *size); + free(*res); + *res = new_res; + *size *= 2; + } + return (n_read); +} + +char *read_file(int file) +{ + size_t size; + size_t offset; + size_t n_read; + char *res; + + offset = 0; + size = 1024; + res = malloc(size); + if (!res) + return (0); + while (1) + { + n_read = read(file, &res[offset], size - offset); + n_read = push_bytes(n_read, &res, &offset, &size); + if (!n_read) + break ; + if (n_read < 0) + { + free(res); + return (0); + } + } + res[offset] = 0; + return (res); +} diff --git a/srcs/parsing.c b/srcs/parsing.c new file mode 100644 index 0000000..eaed3e8 --- /dev/null +++ b/srcs/parsing.c @@ -0,0 +1,123 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parsing.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: apago +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/04 16:19:27 by apago #+# #+# */ +/* Updated: 2023/04/04 18:26:39 by apago ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parsing.h" + +int parse_meta(char *str, t_meta *meta) +{ + int read_bytes; + + read_bytes = read_uint(str); + meta->height = parse_valid_uint(str, read_bytes); + if (meta->height < 1) + return (0); + if (!read_char(&str[read_bytes++], &meta->empty)) + return (0); + if (!read_char(&str[read_bytes++], &meta->obstacle)) + return (0); + if (!read_char(&str[read_bytes++], &meta->full)) + return (0); + if (!printable(meta->empty) || !printable(meta->obstacle) + || !printable(meta->full)) + return (0); + if ((meta->empty == meta->obstacle) || (meta->obstacle == meta->full)) + return (0); + if (str[read_bytes++] != '\n') + return (0); + return (read_bytes); +} + +size_t parse_line(char *line, char *dst, t_meta *meta) +{ + int i; + + i = 0; + while (i < meta->width) + { + if (!line[i]) + return (0); + if (line[i] == meta->empty) + dst[i] = '.'; + else if (line[i] == meta->obstacle) + dst[i] = 'o'; + else + return (0); + i++; + } + if (line[i] != '\n') + return (0); + return (meta->width + 1); +} + +char *parse_data(char *data, t_meta *meta) +{ + char *res; + size_t offset; + size_t read_bytes; + int i; + + i = 0; + res = malloc(meta->width * meta->height * sizeof(char)); + if (!res) + return (0); + while (i < meta->height) + { + read_bytes = parse_line(data, res, meta); + if (!read_bytes) + { + free(res); + return (0); + } + data += read_bytes; + i++; + } + if (!*data) + return (res); + free(res); + return (0); +} + +int parse_input(char *str, t_map *map) +{ + size_t offset; + size_t read_bytes; + + read_bytes = parse_meta(str, &map->meta); + if (!read_bytes) + return (0); + offset = read_bytes; + map->meta.width = count_first_line(&str[offset]); + if (!map->meta.width) + return (0); + map->data = parse_data(&str[offset], &map->meta); + if (!map->data) + return (0); + return (1); +} + +int read_fname(char *name, t_map *map) +{ + int file; + char *text; + int res; + + file = open(name, O_RDONLY); + if (file == -1) + return (0); + text = read_file(file); + close(file); + if (!text) + return (0); + res = parse_input(text, map); + free(text); + return (res); +} diff --git a/srcs/parsing_simple.c b/srcs/parsing_simple.c new file mode 100644 index 0000000..7eb21ca --- /dev/null +++ b/srcs/parsing_simple.c @@ -0,0 +1,67 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parsing_simple.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: apago +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/04 18:25:47 by apago #+# #+# */ +/* Updated: 2023/04/04 18:28:51 by apago ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parsing.h" + +size_t read_uint(char *str) +{ + int i; + + i = 0; + while (*str >= '0' && *str <= '9') + { + str++; + i++; + } + return (i); +} + +int parse_valid_uint(char *str, size_t len) +{ + int res; + int i; + + res = 0; + i = 0; + while (i < len) + { + res = res * 10 + str[i] - '0'; + i++; + } + return (res); +} + +int read_char(char *str, char *dst) +{ + if (!*str) + return (0); + *dst = *str; + return (1); +} + +int printable(char c) +{ + return (c >= 32 && c <= 127); +} + +size_t count_first_line(char *line) +{ + size_t cnt; + + cnt = 0; + while (*line && *line != '\n') + { + line++; + cnt++; + } + return (cnt); +}