add map parsing and other things

This commit is contained in:
mcolonna 2024-10-04 15:32:12 +02:00
parent f04587cd62
commit 5bad24dcee
24 changed files with 974 additions and 15 deletions

1
.gitignore vendored
View file

@ -35,6 +35,7 @@
*.i*86
*.x86_64
*.hex
/cub3D
# Debug files
*.dSYM/

17
.vscode/c_cpp_properties.json vendored Normal file
View file

@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/clang",
"cStandard": "c17",
"cppStandard": "c++14",
"intelliSenseMode": "linux-clang-x64",
"configurationProvider": "ms-vscode.makefile-tools"
}
],
"version": 4
}

5
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"files.associations": {
"util.h": "c"
}
}

View file

@ -1,6 +1,6 @@
NAME = cub3D
CPP = gcc -Wall -Wextra -Werror $(FLAGS)
C_FILES = $(wildcard *.c)
CPP = gcc -Wall -Wextra -Werror -I include $(FLAGS)
C_FILES = $(wildcard **/*.c)
O_FILES = $(patsubst %.c,%.o,$(C_FILES))
ECHO = echoo(){ \
@ -33,14 +33,13 @@ $(NAME) : $(O_FILES)
@$(ECHO) "\t\t \e[0;92m\(^o^)/ \e[0;102;30;1m $(NAME) made! \e[0;92m \(^o^)/\e[0m"
@$(ECHO)
%.o : %.cpp
%.o : %.c
@$(ECHO)
@$(ECHO) "\e[30;47;1m $(NAME): making '$@'... \e[0m"
$(CPP) $(FLAGS_1) -c $< -o $@
check_headers :
@ERROR=0; \
echo $(wildcard **/*.h); \
for HEADER in $(wildcard **/*.h); \
do \
echo "check header $$HEADER..."; \
@ -51,13 +50,12 @@ check_headers :
if [ $$? -ne 0 ]; \
then \
ERROR=1; \
echo error \
break; \
echo " error \e[31m:(\e[0m"; \
fi; \
echo "good :)"; \
echo " good \e[32m:)\e[0m"; \
2> /dev/null rm -- "__tmp_check_header.out" "__tmp_check_header.c"; \
done; \
2> /dev/null rm __tmp_check_header.out __tmp_check_header.c; \
if [ $$ERROR -eq 0 ]; then true; else false; fi;
.PHONY : all clean fclean re check_headers
.PHONY : all clean fclean re check_headers

21
dev/cub.vim Normal file
View file

@ -0,0 +1,21 @@
function! CubSyntax()
if expand('%:e') == 'cub'
highlight cubParameter ctermfg=blue
syntax match cubParameter /^(NO|SO|WE|EA|F|C) .$/
highlight cubDefault ctermfg=white
syntax match cubDefault /./
highlight cub0 ctermfg=grey
syntax match cub0 /0/
highlight cub1 cterm=bold ctermfg=white
syntax match cub1 /1/
highlight cubP cterm=bold ctermfg=blue
syntax match cubP /[NSWE]/
endif
endfunction
autocmd BufReadPost * call CubSyntax()

30
include/color.h Normal file
View file

@ -0,0 +1,30 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* color.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/01 16:25:50 by mcolonna #+# #+# */
/* Updated: 2024/10/02 15:41:43 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef COLOR_H
# define COLOR_H
# include <linux/types.h>
// TODO Must the transparency be 0 or 255?
/// @brief Represents an TRGB color in 0xTTRRGGBB format.
typedef __u32 t_color;
/// @brief Convert a color from each color value to a t_color.
///
/// @param red Level of red from 0 to 255.
/// @param green Level of green from 0 to 255.
/// @param blue Level of blue from 0 to 255.
/// @return The result.
t_color color_from_rgb(int red, int green, int blue);
#endif

View file

@ -6,13 +6,16 @@
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/01 13:59:04 by mcolonna #+# #+# */
/* Updated: 2024/10/01 14:00:40 by mcolonna ### ########.fr */
/* Updated: 2024/10/04 13:13:04 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MAP_H
# define MAP_H
# include <stdbool.h>
# include "color.h"
/// @brief The type of a case.
typedef enum e_map_wall
{
@ -26,14 +29,20 @@ typedef enum e_map_wall
typedef struct s_object
{
/// @brief Function called when creating the object.
///
/// @param data Address of the s_object.data pointer.
void (*init)(void **data);
/// @brief Function called when destroying the object (to free everything).
/// @brief Function called when destroying the object (to avoid leaks).
///
/// @param data Address of the s_object.data pointer.
void (*destroy)(void **data);
/// @brief Function called each tick.
///
/// @param data Address of the s_object.data pointer.
void (*tick)(void **data);
/// @brief Pointer the object can use to save data.
void *data;
} t_object;
@ -43,6 +52,7 @@ typedef struct s_map_case
{
/// @brief Is the case empty or a wall?
t_map_wall wall;
/// @brief The object that appears on this case. If there is none,
/// every pointer of the struct will be NULL.
t_object object;
@ -51,14 +61,46 @@ typedef struct s_map_case
/// @brief Represents a map.
typedef struct s_map
{
/// @brief Color of the floor.
t_color color_floor;
/// @brief Color of the ceiling.
t_color color_ceiling;
/// @brief Path to the image file for the wall face north.
const char *texture_north;
/// @brief Path to the image file for the wall face south.
const char *texture_south;
/// @brief Path to the image file for the wall face west.
const char *texture_west;
/// @brief Path to the image file for the wall face east.
const char *texture_east;
/// @brief Width of the map.
int width;
unsigned int width;
/// @brief Height of the map.
int height;
unsigned int height;
/// @brief An 2D array of all the cases.
/// Syntax to get a case: cases[y][x]
///
/// Syntax to get a case: cases[y * width + x]
/// x is left to right, y is top to bottom.
t_map_case **cases;
t_map_case *cases;
} t_map;
#endif
/// @brief Create a t_map from the content of a .cub file.
///
/// @param dest Pointer to the t_map to set.
/// @param file .cub file to use to create the t_map.
/// It must be destroyed with mapDestroy to avoid leaks.
/// @return false if an error occured, otherwise true.
bool map_from_file(t_map *dest, const char *file);
/// @brief Destroy the map to avoid leaks.
void map_destroy(t_map *map);
#endif

31
include/map_mapping.h Normal file
View file

@ -0,0 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map_mapping.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/04 12:00:07 by mcolonna #+# #+# */
/* Updated: 2024/10/04 15:24:14 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MAP_MAPPING_H
# define MAP_MAPPING_H
# include "map.h"
/// @brief Each element of g_map_mapping. A case and its associated char.
typedef struct s_map_mapping_element
{
/// @brief char representing the case.
char name;
/// @brief associated case.
t_map_case value;
} t_map_mapping_element;
/// @brief List of each char and its according case.
/// Ended by an element with the name '\0'.
extern const t_map_mapping_element g_map_mapping[];
#endif

29
include/read_all_text.h Normal file
View file

@ -0,0 +1,29 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* read_all_text.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/02 15:39:02 by mcolonna #+# #+# */
/* Updated: 2024/10/02 17:04:33 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef READ_ALL_TEXT_H
# define READ_ALL_TEXT_H
/// @brief Size of buffer used in read_all_text().
# define BUFFER_SIZE 1000
/// @brief Read all the text of the given file.
///
/// If the last line isn't ended by a '\\n', add one.
///
/// If error, returns NULL and set errno accordingly.
///
/// @param fd File descriptor of the file.
/// @return Alloc'd string of the file content. NULL if error.
char *read_all_text(int fd);
#endif

54
include/stream.h Normal file
View file

@ -0,0 +1,54 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* stream.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/02 12:33:25 by mcolonna #+# #+# */
/* Updated: 2024/10/02 16:14:23 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef STREAM_H
# define STREAM_H
# include <stdbool.h>
/// @brief Represents a string and an associated cursor.
typedef struct s_stream
{
/// @brief Index of the cursor.
int i;
/// @brief Pointer to the string.
const char *str;
} t_stream;
/// @brief Read a specific string, error if it isn't the expected string.
///
/// @param str Expected string.
/// @param stream Stream to use.
/// @param err Set to true if an error occured.
/// If already true, the function won't do anything.
void read_expected_string(const char *str, t_stream *stream, bool *err);
/// @brief Read an unsigned int (which fits the pattern /[0-9]+/).
///
/// @param dest Will be set to the value of the unsigned integer.
/// @param stream Stream to use.
/// @param err Set to true if an error occured.
/// If already true, the function won't do anything.
void read_unsigned(unsigned int *dest, t_stream *stream, bool *err);
/// @brief Read a string until limit char or \0.
///
/// @param c Limit char.
/// @param dest Will be set to an alloc'd pointer to the read string.
/// NULL if alloc error.
/// @param stream Stream to use.
/// @param err Set to true if an error occured.
/// If already true, the function won't do anything.
void read_until(char c, char **dest, t_stream *stream, bool *err);
#endif

24
include/util.h Normal file
View file

@ -0,0 +1,24 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* util.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/03 14:19:03 by mc #+# #+# */
/* Updated: 2024/10/04 15:27:07 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef UTIL_H
# define UTIL_H
/// @brief Get the length of a string.
int getlen(const char *str);
/// @brief Write an error message on stderr.
///
/// @param str... All the strings to write. The last parameter MUST BE NULL.
void write_err(const char *str, ...);
#endif

18
src/color.c Normal file
View file

@ -0,0 +1,18 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* color.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/01 17:04:56 by mcolonna #+# #+# */
/* Updated: 2024/10/02 14:27:53 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "color.h"
t_color color_from_rgb(int red, int green, int blue)
{
return (red << 16 | green << 8 | blue);
}

34
src/main.c Normal file
View file

@ -0,0 +1,34 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/02 15:45:49 by mcolonna #+# #+# */
/* Updated: 2024/10/04 15:10:50 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map.h"
#include <stdio.h>
int main(int argc, char *argv[])
{
t_map map;
bool success;
if (argc != 2)
{
printf(":(\n");
return (1);
}
success = map_from_file(&map, argv[1]);
printf("--> Success: %i <--\n", success);
if (success)
printf("C 0x%08x\nF 0x%08x\nEA %s\nWE %s\nNO %s\nSO %s\n",
map.color_ceiling, map.color_floor,
map.texture_east, map.texture_west,
map.texture_north, map.texture_south);
map_destroy(&map);
}

55
src/map.c Normal file
View file

@ -0,0 +1,55 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/01 17:12:58 by mcolonna #+# #+# */
/* Updated: 2024/10/04 15:25:32 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map.h"
#include "map_utils.h"
#include "stream.h"
#include "read_all_text.h"
#include <util.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
bool map_from_file(t_map *dest, const char *file)
{
int fd;
t_stream stream;
bool err;
fd = open(file, O_RDONLY);
if (fd < 0)
{
write_err("Can't open '", file, "': ", strerror(errno), "\n",
NULL);
return (false);
}
stream.str = read_all_text(fd);
if (!stream.str)
{
write_err("Can't read file.\n", NULL);
return (false);
}
stream.i = 0;
err = read_map(dest, &stream);
free((void *)stream.str);
return (err);
}
void map_destroy(t_map *map)
{
free((void *)map->texture_east);
free((void *)map->texture_west);
free((void *)map->texture_north);
free((void *)map->texture_south);
free(map->cases);
}

24
src/map_mapping.c Normal file
View file

@ -0,0 +1,24 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map_mapping.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/04 12:05:21 by mcolonna #+# #+# */
/* Updated: 2024/10/04 15:23:28 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map_mapping.h"
#include <stdlib.h>
const t_map_mapping_element g_map_mapping[] = {
{' ', {EMPTY, {NULL, NULL, NULL, NULL}}},
{'0', {EMPTY, {NULL, NULL, NULL, NULL}}},
{'1', {WALL, {NULL, NULL, NULL, NULL}}},
{'N', {EMPTY, {NULL, NULL, NULL, NULL}}}, // TODO add player object
{'S', {EMPTY, {NULL, NULL, NULL, NULL}}}, // --
{'E', {EMPTY, {NULL, NULL, NULL, NULL}}}, // --
{'W', {EMPTY, {NULL, NULL, NULL, NULL}}}, // --
{'\0', {EMPTY, {NULL, NULL, NULL, NULL}}}};

80
src/map_utils.h Normal file
View file

@ -0,0 +1,80 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map_utils.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/03 15:05:13 by mc #+# #+# */
/* Updated: 2024/10/04 15:30:03 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MAP_UTILS_H
# define MAP_UTILS_H
# include "color.h"
# include "stream.h"
# include "map.h"
# include <stdbool.h>
# include <stddef.h>
/// @brief Read a parameter of the map which has a color as an argument.
/// Color format: [0-255],[0-255],[0-255]
/// @param name Name of the parameter.
/// @param dest Will be set to the value of the parameter.
/// Unchanged if error.
/// If success but *dest is not 0xFF000000, throws an error.
/// @param stream Stream to use.
/// Unchanged if error.
/// @param redefined Set to true if the parameter was already defined.
/// @return true if success or redefined, false if non-fatal error.
bool read_color_parameter(const char *name, t_color *dest,
t_stream *stream, bool *redefined);
/// @brief Read a parameter of the map which has a string as an argument.
/// @param name Name of the parameter.
/// @param dest Will be set to an alloc'd pointer to the value of the parameter.
/// Unchanged if error.
/// If success but *dest is not null, throws an error.
/// @param stream Stream to use.
/// Unchanged if error.
/// @param redefined Set to true if the parameter was already defined.
/// @return true if success or redefined, false if non-fatal error.
bool read_string_parameter(const char *name, const char **dest,
t_stream *stream, bool *redefined);
/// @brief Set the map to initial values. Every texture becomes NULL
/// and every color becomes 0xFF000000.
/// @param dest Map to reset.
void reset_map(t_map *dest);
/// @brief Read a map-formatted string.
/// If an error occurs, write an error message on stderr.
/// @param dest Will be set to the map.
/// @param stream Stream to use.
/// @return true if success, false if error.
bool read_map(t_map *dest, t_stream *stream);
/// @brief Get the case associated with the char.
///
/// @param dest Will be set to the char.
/// @param name Name of the case.
/// @return true if success, false if error.
bool get_case(t_map_case *dest, char name);
/// @brief Fill the pointer with 'size' null bytes.
///
/// @param dest The pointer to set.
/// @param size The number of bytes.
void fill_zeros(void *dest, size_t size);
/// @brief Read the map description part of the map.
/// Read until the end of the file.
///
/// @param map The .width, .height and .cases members will be set.
/// @param stream Stream to use.
/// @return true if success, false if error.
bool read_map_description(t_map *map, t_stream *stream);
#endif

116
src/map_utils1.c Normal file
View file

@ -0,0 +1,116 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map_utils1.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/03 15:02:09 by mc #+# #+# */
/* Updated: 2024/10/04 15:28:06 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map_utils.h"
#include "util.h"
#include "map_mapping.h"
#include <stdlib.h>
bool read_color_parameter(const char *name, t_color *dest,
t_stream *stream, bool *redefined)
{
unsigned int rgb[3];
bool err;
t_stream old;
old = *stream;
err = false;
read_expected_string(name, stream, &err);
read_expected_string(" ", stream, &err);
read_unsigned(&rgb[0], stream, &err);
read_expected_string(",", stream, &err);
read_unsigned(&rgb[1], stream, &err);
read_expected_string(",", stream, &err);
read_unsigned(&rgb[2], stream, &err);
read_expected_string("\n", stream, &err);
if (!err && *dest != 0xFF000000)
{
*redefined = true;
write_err("Parameter '", name, "' was defined several times\n",
NULL);
}
else if (!err)
*dest = color_from_rgb(rgb[0], rgb[1], rgb[2]);
else
*stream = old;
return (!err);
}
bool read_string_parameter(const char *name, const char **dest,
t_stream *stream, bool *redefined)
{
char *r;
bool err;
t_stream old;
old = *stream;
err = false;
r = NULL;
read_expected_string(name, stream, &err);
read_expected_string(" ", stream, &err);
read_until('\n', &r, stream, &err);
read_expected_string("\n", stream, &err);
if (!err && *dest)
{
*redefined = true;
write_err("Parameter '", name, "' was defined several times\n",
NULL);
}
if (err || (!err && *dest))
{
*stream = old;
free(r);
}
else
*dest = r;
return (!err);
}
void reset_map(t_map *dest)
{
dest->cases = NULL;
dest->color_ceiling = 0xFF000000;
dest->color_floor = 0xFF000000;
dest->texture_east = NULL;
dest->texture_west = NULL;
dest->texture_north = NULL;
dest->texture_south = NULL;
}
bool read_map(t_map *dest, t_stream *stream)
{
bool err;
bool rdf;
reset_map(dest);
err = false;
rdf = false;
while (!rdf && !err && stream->str[stream->i])
{
if (true
&& (read_expected_string("\n", stream, &err), err)
&& !read_string_parameter("NO", &dest->texture_north, stream, &rdf)
&& !read_string_parameter("SO", &dest->texture_south, stream, &rdf)
&& !read_string_parameter("WE", &dest->texture_west, stream, &rdf)
&& !read_string_parameter("EA", &dest->texture_east, stream, &rdf)
&& !read_color_parameter("F", &dest->color_floor, stream, &rdf)
&& !read_color_parameter("C", &dest->color_ceiling, stream, &rdf))
{
err = !read_map_description(dest, stream);
return (!err);
}
err = false;
}
if (!rdf && !dest->cases)
write_err("Map description missing\n", NULL);
return (!err && !rdf && dest->cases);
}

105
src/map_utils2.c Normal file
View file

@ -0,0 +1,105 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map_utils2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/04 15:12:08 by mcolonna #+# #+# */
/* Updated: 2024/10/04 15:25:52 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map_utils.h"
#include "map_mapping.h"
#include "util.h"
#include <stdlib.h>
/// @brief Read the map description to get the dimensions.
/// The map must be at least 1x1.
///
/// @param map The .width and .height members will be set.
/// @param stream Stream to use.
/// @return true if success, false if error.
static bool get_map_dimensions(t_map *map, t_stream *stream)
{
unsigned int x;
unsigned int y;
map->width = 0;
map->height = 0;
y = 0;
while (stream->str[stream->i])
{
x = 0;
while (stream->str[stream->i] && stream->str[stream->i] != '\n')
{
stream->i++;
x++;
}
if (x > map->width)
map->width = x;
if (stream->str[stream->i] == '\n')
stream->i++;
y++;
}
map->height = y;
return (map->width > 0 && map->height > 0);
}
bool get_case(t_map_case *dest, char name)
{
int i;
char tmp[2];
i = -1;
while (g_map_mapping[++i].name)
{
if (name == g_map_mapping[i].name)
{
*dest = g_map_mapping[i].value;
return (true);
}
}
tmp[0] = name;
tmp[1] = '\0';
write_err("Character '", tmp, "' unexpected\n", NULL);
return (false);
}
void fill_zeros(void *dest, size_t size)
{
size_t i;
i = -1;
while (++i < size)
((char *)dest)[i] = '\0';
}
bool read_map_description(t_map *map, t_stream *stream)
{
t_stream stream2;
unsigned int x;
unsigned int y;
stream2 = *stream;
if (!get_map_dimensions(map, &stream2))
return (false);
map->cases = malloc((map->width * map->height) * sizeof(t_map_case));
y = -1;
fill_zeros(map->cases, (map->width * map->height) * sizeof(t_map_case));
while (++y < map->height)
{
x = 0;
while (stream->str[stream->i] && stream->str[stream->i] != '\n')
{
if (!get_case(&map->cases[y * map->width + x],
stream->str[stream->i]))
return (false);
stream->i++;
x++;
}
stream->i++;
}
return (true);
}

94
src/read_all_text.c Normal file
View file

@ -0,0 +1,94 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* read_all_text.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mc <mc@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/02 16:18:35 by mcolonna #+# #+# */
/* Updated: 2024/10/03 14:20:37 by mc ### ########.fr */
/* */
/* ************************************************************************** */
#include "read_all_text.h"
#include "util.h"
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
/// @brief Concatenate *dest and src and put the result in *dest.
///
/// *dest is alloc'd to contain the result value.
///
/// the old *dest is freed only if the function succeds.
///
/// src doesn't have to be nul-terminated, instead n is the size of src.
///
/// @return true if success, false if error.
static bool strconcat(char **dest, char *src, int n)
{
const int len_dest = getlen(*dest);
char *old_dest;
int i;
old_dest = *dest;
*dest = malloc((len_dest + n + 1) * sizeof(char));
if (!*dest)
return (false);
i = -1;
while (old_dest[++i])
(*dest)[i] = old_dest[i];
while (i < len_dest + n)
{
(*dest)[i] = src[i - len_dest];
i++;
}
(*dest)[i] = '\0';
free(old_dest);
return (true);
}
/// @brief If the string isn't empty and isn't ended by a '\\n', add one and
/// return the result.
///
/// str is either returned directly, or another freeable pointer is returned
/// and str is freed.
///
/// @return Return the result or NULL if error.
static char *add_endline_if_necessary(char *str)
{
char *endline;
if (str[0] == '\0' || str[getlen(str) - 1] == '\n')
return (str);
endline = malloc(1 * sizeof(char));
if (!endline)
return (free(str), NULL);
endline[0] = '\n';
if (!strconcat(&str, endline, 1))
return (free(str), NULL);
return (str);
}
char *read_all_text(int fd)
{
char buf[BUFFER_SIZE];
int n;
char *r;
r = malloc(sizeof(char));
if (!r)
return (NULL);
r[0] = '\0';
n = 1;
while (n)
{
n = read(fd, buf, BUFFER_SIZE);
if (n < 0 || (n && !strconcat(&r, buf, n)))
{
free(r);
return (NULL);
}
}
return (add_endline_if_necessary(r));
}

89
src/stream.c Normal file
View file

@ -0,0 +1,89 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* stream.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/02 14:08:10 by mcolonna #+# #+# */
/* Updated: 2024/10/02 17:31:34 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "stream.h"
#include <stdlib.h>
void read_expected_string(const char *str, t_stream *stream, bool *err)
{
int i;
if (*err)
return ;
i = 0;
while (str[i])
{
if (str[i] != stream->str[stream->i])
{
*err = true;
return ;
}
i++;
stream->i++;
}
return ;
}
/// @brief Check if a character is a digit.
/// @param c Character to check.
/// @return true if the character is a digit, false if not.
/// false if the character is '\0'.
static bool is_digit(char c)
{
return (c >= '0' && c <= '9');
}
void read_unsigned(unsigned int *dest, t_stream *stream, bool *err)
{
int r;
if (*err)
return ;
if (!is_digit(stream->str[stream->i]))
{
*err = true;
return ;
}
r = 0;
while (is_digit(stream->str[stream->i]))
{
r = r * 10 + stream->str[stream->i] - '0';
stream->i++;
}
*dest = r;
}
void read_until(char c, char **dest, t_stream *stream, bool *err)
{
int len;
int i;
if (*err)
return ;
len = 0;
while (stream->str[stream->i + len] && stream->str[stream->i + len] != c)
len++;
*dest = malloc((len + 1) * sizeof(char));
if (!*dest)
{
*err = true;
return ;
}
i = 0;
while (stream->str[stream->i] && stream->str[stream->i] != c)
{
(*dest)[i] = stream->str[stream->i];
i++;
stream->i++;
}
(*dest)[i] = '\0';
}

38
src/util.c Normal file
View file

@ -0,0 +1,38 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* util.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/03 14:19:38 by mc #+# #+# */
/* Updated: 2024/10/04 15:26:32 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "util.h"
#include <stdarg.h>
#include <unistd.h>
int getlen(const char *str)
{
int i;
i = 0;
while (str[i])
i++;
return (i);
}
void write_err(const char *str, ...)
{
va_list args;
va_start(args, str);
write(2, "Error\n", 6);
while (str)
{
write(2, str, getlen(str));
str = va_arg(args, const char *);
}
}

19
testmaps/hdhd.cub Normal file
View file

@ -0,0 +1,19 @@
F 255,127,0
EA eastimage
NO theimageforthenorthwall
C 0,2,67
SO SOUTH!!!!!!1
SO jde:
WE weeeee
SO south2

15
testmaps/idid.cub Normal file
View file

@ -0,0 +1,15 @@
F 255,127,0
EA eastimage
NO theimageforthenorthwall
C 0,2,67
SO SOUTH!!!!!!1
WE weeeee

20
testmaps/jdjd.cub Normal file
View file

@ -0,0 +1,20 @@
F 255,127,0
EA eastimage
NO theimageforthenorthwall
C 0,2,67
SO SOUTH!!!!!!1
WE weeeee
1111111
1000001
10W0001
1000001
1111111