changeset 39:9d1421c09dfb

core: add more utilities to improve code simplicity
author David Demelier <markand@malikania.fr>
date Tue, 14 Jan 2020 13:05:45 +0100
parents 83ae0e13c416
children 2a087210c0b8
files Makefile src/error.c src/error.h src/error_p.h src/font.c src/image.c src/main.c src/sys.c src/texture.c src/util.c src/util.h src/window.c
diffstat 12 files changed, 290 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Wed Jan 15 20:44:17 2020 +0100
+++ b/Makefile	Tue Jan 14 13:05:45 2020 +0100
@@ -24,16 +24,17 @@
 LIB=            libmolko.a
 SRCS=           src/animation.c \
                 src/clock.c \
+                src/error.c \
                 src/event.c \
-                src/error.c \
                 src/font.c \
+                src/image.c \
                 src/map.c \
                 src/message.c \
-                src/image.c \
+                src/painter.c \
                 src/sprite.c \
                 src/sys.c \
-                src/painter.c \
                 src/texture.c \
+                src/util.c \
                 src/window.c
 OBJS=           ${SRCS:.c=.o}
 DEPS=           ${SRCS:.c=.d}
--- a/src/error.c	Wed Jan 15 20:44:17 2020 +0100
+++ b/src/error.c	Tue Jan 14 13:05:45 2020 +0100
@@ -16,10 +16,15 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "error.h"
+#include "error_p.h"
+
+#include <SDL.h>
 
 static char buffer[2048];
 
@@ -29,7 +34,15 @@
 	return buffer;
 }
 
-void
+bool
+error_errno(void)
+{
+	error_printf("%s", strerror(errno));
+
+	return false;
+}
+
+bool
 error_printf(const char *fmt, ...)
 {
 	va_list ap;
@@ -37,12 +50,23 @@
 	va_start(ap, fmt);
 	error_vprintf(fmt, ap);
 	va_end(ap);
+
+	return false;
 }
 
-void
+bool
 error_vprintf(const char *fmt, va_list ap)
 {
 	vsnprintf(buffer, sizeof (buffer), fmt, ap);
+
+	return false;
+}
+
+noreturn void
+error_fatal(void)
+{
+	fprintf(stderr, "%s\n", buffer);
+	exit(1);
 }
 
 noreturn void
@@ -58,6 +82,16 @@
 noreturn void
 error_vfatalf(const char *fmt, va_list ap)
 {
-	error_vprintf(fmt, ap);
+	fprintf(stderr, fmt, ap);
 	exit(1);
 }
+
+/* private: error_p.h */
+
+bool
+error_sdl(void)
+{
+	error_printf("%s", SDL_GetError());
+
+	return false;
+}
--- a/src/error.h	Wed Jan 15 20:44:17 2020 +0100
+++ b/src/error.h	Tue Jan 14 13:05:45 2020 +0100
@@ -25,6 +25,7 @@
  */
 
 #include <stdarg.h>
+#include <stdbool.h>
 #include <stdnoreturn.h>
 
 /**
@@ -36,24 +37,41 @@
 error(void);
 
 /**
+ * Convenient handler that sets last error from global C errno and then return
+ * false.
+ *
+ * \return false
+ */
+bool
+error_errno(void);
+
+/**
  * Set the game error with a printf-like format.
  *
  * \param fmt the format string
+ * \return false
  */
-void
+bool
 error_printf(const char *fmt, ...);
 
 /**
- * \Similar to \a error_printf.
+ * Similar to \a error_printf.
  *
  * \param fmt the format stinrg
  * \param ap the variadic arguments pointer
+ * \return false
  */
-void
+bool
 error_vprintf(const char *fmt, va_list ap);
 
 /**
- * Similar to \a error_printf but close the application.
+ * Print last registered error and exit with code 1.
+ */
+noreturn void
+error_fatal(void);
+
+/**
+ * Prints an error to stderr and exit.
  *
  * \param fmt the format string
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/error_p.h	Tue Jan 14 13:05:45 2020 +0100
@@ -0,0 +1,33 @@
+/*
+ * error.h -- (PRIVATE) error routines
+ *
+ * Copyright (c) 2020 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MOLKO_ERROR_P_H
+#define MOLKO_ERROR_P_H
+
+#include <stdbool.h>
+
+/**
+ * Convenient handler that sets the game error to the last SDL error and then
+ * return false.
+ *
+ * \return false
+ */
+bool
+error_sdl(void);
+
+#endif /* !MOLKO_ERROR_P_H */
--- a/src/font.c	Wed Jan 15 20:44:17 2020 +0100
+++ b/src/font.c	Tue Jan 14 13:05:45 2020 +0100
@@ -23,8 +23,11 @@
 #include <SDL_ttf.h>
 
 #include "color.h"
+#include "error.h"
+#include "error_p.h"
 #include "font.h"
 #include "texture_p.h"
+#include "util.h"
 
 struct font {
 	TTF_Font *handle;
@@ -37,9 +40,10 @@
 
 	struct font *f;
 
-	if (!(f = calloc(1, sizeof (struct font))))
-		return NULL;
+	f = ecalloc(1, sizeof (struct font));
+
 	if (!(f->handle = TTF_OpenFont(path, size))) {
+		error_sdl();
 		free(f);
 		return NULL;
 	}
@@ -50,25 +54,21 @@
 struct font *
 font_openb(const void *buffer, size_t buflen, unsigned size)
 {
+	assert(buffer);
+
 	struct font *f;
 	SDL_RWops *ops;
 
-	assert(buffer);
+	f = ecalloc(1, sizeof (struct font));
 
-	if (!(f = calloc(1, sizeof (struct font))))
-		return NULL;
-
-	if (!(ops = SDL_RWFromConstMem(buffer, buflen))) {
+	if (!(ops = SDL_RWFromConstMem(buffer, buflen)) ||
+	   (!(f->handle = TTF_OpenFontRW(ops, true, size)))) {
+		error_sdl();
 		free(f);
 		return NULL;
 	}
 
-	if (!(f->handle = TTF_OpenFontRW(ops, true, size))) {
-		free(f);
-		return NULL;
-	}
-
-	return NULL;
+	return f;
 }
 
 struct texture *
@@ -77,7 +77,6 @@
 	assert(font);
 	assert(text);
 
-	/* TODO: refactor this with window.c */
 	SDL_Color fg = {
 		.r = COLOR_R(color),
 		.g = COLOR_G(color),
@@ -85,12 +84,21 @@
 		.a = COLOR_A(color)
 	};
 
-	return texture_from_surface(TTF_RenderUTF8_Blended(font->handle, text, fg));
+	SDL_Surface *surface;
+
+	if (!(surface = TTF_RenderUTF8_Blended(font->handle, text, fg))) {
+		error_sdl();
+		return NULL;
+	}
+
+	return texture_from_surface(surface);
 }
 
 void
 font_close(struct font *font)
 {
+	assert(font);
+
 	TTF_CloseFont(font->handle);
 	free(font);
 }
--- a/src/image.c	Wed Jan 15 20:44:17 2020 +0100
+++ b/src/image.c	Tue Jan 14 13:05:45 2020 +0100
@@ -21,6 +21,7 @@
 
 #include <SDL_image.h>
 
+#include "error_p.h"
 #include "texture_p.h"
 
 struct texture *
@@ -28,7 +29,14 @@
 {
 	assert(path);
 
-	return texture_from_surface(IMG_Load(path));
+	SDL_Surface *surface = IMG_Load(path);
+
+	if (!surface) {
+		error_sdl();
+		return NULL;
+	}
+
+	return texture_from_surface(surface);
 }
 
 struct texture *
@@ -37,9 +45,12 @@
 	assert(buffer);
 
 	SDL_RWops *ops = SDL_RWFromConstMem(buffer, size);
+	SDL_Surface *surface;
 
-	if (!ops)
+	if (!ops || !(surface = IMG_Load_RW(ops, true))) {
+		error_sdl();
 		return NULL;
+	}
 
-	return texture_from_surface(IMG_Load_RW(ops, true));
+	return texture_from_surface(surface);
 }
--- a/src/main.c	Wed Jan 15 20:44:17 2020 +0100
+++ b/src/main.c	Tue Jan 14 13:05:45 2020 +0100
@@ -19,7 +19,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "clock.h"
+#include "error.h"
+#include "event.h"
+#include "painter.h"
 #include "sys.h"
+#include "window.h"
+#include "util.h"
 
 int
 main(int argc, char **argv)
@@ -27,7 +33,32 @@
 	(void)argc;
 	(void)argv;
 
-	printf("[%s]\n", sys_datapath("foo.map"));
+	struct clock clock;
+
+	if (!sys_init())
+		error_fatal();
+	if (!window_init("Molko's Adventure", 1024, 576))
+		error_fatal();
+
+	clock_start(&clock);
+
+	for (;;) {
+		/*uint64_t elapsed = clock_elapsed(&clock);*/
+		union event ev;
+
+		while (event_poll(&ev)) {
+			switch (ev.type) {
+			case EVENT_QUIT:
+				return 0;
+			default:
+				break;
+			}
+		}
+
+		painter_clear();
+		painter_present();
+		delay(50);
+	}
 
 	return 0;
 }
--- a/src/sys.c	Wed Jan 15 20:44:17 2020 +0100
+++ b/src/sys.c	Tue Jan 14 13:05:45 2020 +0100
@@ -28,6 +28,8 @@
 #	include <dirent.h>
 #endif
 
+#include "error.h"
+#include "error_p.h"
 #include "sys.h"
 
 #if defined(_WIN32)
@@ -96,13 +98,13 @@
 sys_init(void)
 {
 	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
-		return false;
+		return error_sdl();
 	if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG)
-		return false;
+		return error_sdl();
 	if (TTF_Init() < 0)
-		return false;
+		return error_sdl();
 	if (Mix_Init(MIX_INIT_OGG) != MIX_INIT_OGG)
-		return false;
+		return error_sdl();
 
 	return true;
 }
--- a/src/texture.c	Wed Jan 15 20:44:17 2020 +0100
+++ b/src/texture.c	Tue Jan 14 13:05:45 2020 +0100
@@ -18,19 +18,21 @@
 
 #include <assert.h>
 
+#include "error.h"
+#include "error_p.h"
 #include "texture.h"
 #include "texture_p.h"
+#include "util.h"
 #include "window_p.h"
 
 struct texture *
 texture_new(uint16_t w, uint16_t h)
 {
-	struct texture *tex;
+	struct texture *tex = emalloc(sizeof (struct texture));
 
-	if (!(tex = malloc(sizeof (struct texture))))
-		return NULL;
 	if (!(tex->handle = SDL_CreateTexture(win.renderer,
 	    SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h))) {
+		error_sdl();
 		free(tex);
 		return NULL;
 	}
@@ -46,6 +48,7 @@
 	int rw, rh;
 
 	if (SDL_QueryTexture(tex->handle, NULL, NULL, &rw, &rh) < 0) {
+		error_sdl();
 		*w = 0;
 		*h = 0;
 		return false;
@@ -116,11 +119,12 @@
 struct texture *
 texture_from_surface(SDL_Surface *surface)
 {
-	struct texture *texture;
+	assert(surface);
 
-	if (!(texture = calloc(1, sizeof (struct texture))))
-		return NULL;
+	struct texture *texture = ecalloc(1, sizeof (struct texture));
+
 	if (!(texture->handle = SDL_CreateTextureFromSurface(win.renderer, surface))) {
+		error_sdl();
 		free(texture);
 		return NULL;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util.c	Tue Jan 14 13:05:45 2020 +0100
@@ -0,0 +1,54 @@
+/*
+ * util.c -- utilities
+ *
+ * Copyright (c) 2020 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <SDL.h>
+
+#include "util.h"
+#include "error.h"
+
+void *
+emalloc(size_t size)
+{
+	void *mem;
+
+	if (!(mem = malloc(size)))
+		error_fatalf("%s\n", strerror(errno));
+
+	return mem;
+}
+
+void *
+ecalloc(size_t n, size_t size)
+{
+	void *mem;
+
+	if (!(mem = calloc(n, size)))
+		error_fatalf("%s\n", strerror(errno));
+
+	return mem;
+}
+
+void
+delay(unsigned int ms)
+{
+	SDL_Delay(ms);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util.h	Tue Jan 14 13:05:45 2020 +0100
@@ -0,0 +1,53 @@
+/*
+ * util.h -- utilities
+ *
+ * Copyright (c) 2020 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MOLKO_UTIL_H
+#define MOLKO_UTIL_H
+
+#include <stddef.h>
+
+/**
+ * Wrapper around malloc(3) that exits on allocation failure.
+ *
+ * \param size the size
+ * \return a pointer
+ * \post returned pointer will never be NULL
+ */
+void *
+emalloc(size_t size);
+
+/**
+ * Wrapper around calloc(3) that exits on allocation failure.
+ *
+ * \param n the number of objects to allocate
+ * \param size the size per n
+ * \return a pointer
+ * \post returned pointer will never be NULL
+ */
+void *
+ecalloc(size_t n, size_t size);
+
+/**
+ * Put the thread to sleep for a given amount of milliseconds.
+ *
+ * \param ms the number of milliseconds to wait
+ */
+void
+delay(unsigned int ms);
+
+#endif /* !MOLKO_UTIL_H */
--- a/src/window.c	Wed Jan 15 20:44:17 2020 +0100
+++ b/src/window.c	Tue Jan 14 13:05:45 2020 +0100
@@ -20,6 +20,7 @@
 
 #include <SDL.h>
 
+#include "error_p.h"
 #include "window.h"
 #include "window_p.h"
 
@@ -36,7 +37,7 @@
 
 	if (SDL_CreateWindowAndRenderer(width, height, SDL_WINDOW_OPENGL,
 	    &win.win, &win.renderer) < 0)
-		return false;
+		return error_sdl();
 
 	SDL_SetWindowTitle(win.win, title);