# HG changeset patch # User David Demelier # Date 1603208353 -7200 # Node ID eb0a7ab71023f132b4624478f089a416b6b82d4c # Parent aab824406d3d39e0cac0875e8a18de2911341f64 misc: extreme cleanup, closes #2506 While here, remove unneeded stuff. diff -r aab824406d3d -r eb0a7ab71023 doxygen/CMakeLists.txt --- a/doxygen/CMakeLists.txt Tue Oct 20 15:09:39 2020 +0200 +++ b/doxygen/CMakeLists.txt Tue Oct 20 17:39:13 2020 +0200 @@ -25,9 +25,12 @@ INPUT doxygen/groups.c doxygen/mainpage.c - doxygen/page-howto-initialization.c + doxygen/page-examples.c doxygen/page-faq.c - doxygen/page-examples.c + doxygen/page-howto-error.c + doxygen/page-howto-initialization.c + doxygen/page-howto-ownership.c + doxygen/page-portability.c libadventure libcore libui diff -r aab824406d3d -r eb0a7ab71023 doxygen/mainpage.c --- a/doxygen/mainpage.c Tue Oct 20 15:09:39 2020 +0200 +++ b/doxygen/mainpage.c Tue Oct 20 17:39:13 2020 +0200 @@ -26,9 +26,8 @@ * Molko's Adventure is a 2D solo RPG written in pure C, using SDL2 and SDL2 * addons. * - * As its heart, the game is split into two parts, the core (**src/core**) and - * the game data and scenario (**src/adventure**). It is then possible to anyone - * to create its own similar game using the same core. However please note that: + * As its heart, the game is split into multiple parts, libraries, game data and + * game code. * * - It is not a game engine! Many aspects in the core are still tightly coupled * with the original game design. We wanted the core to be kept simple without @@ -40,9 +39,8 @@ * * # Usage * - * If you plan to create your own game, simply copy the whole **src/core** - * directory to your project and add all .c files to the compilation process. No - * prior configuration is required, every features are detected using `#ifdef`s. + * If you plan to create your own game, simply copy the whole directory + * directory to your project and select which libraries you need. * * \note If you find a bug regarding your platform, feel free to send bug * reports and patches. @@ -51,111 +49,15 @@ * with _p.h are usually reserved for the implementation and should not be used * unless you know what you're doing. * - * # Documentation nomenclature - * - * Every modules are organized per files and referenced this way. For example, - * if you need to access the error handling, you just have to use \ref error.h - * file. - * - * ## Structures - * - * Almost every structure are exposed directly to the user and allocated on the - * stack. Each member is documented with the following prefix format (XYZ) - * where: - * - * The letter *X* defines the following restriction - * - * - `+`: The property is readable/editable by the user, - * - `-`: The property is readable by the user, - * - `*`: The property is not meant to be used directly by the user. - * - * The letter *Y* can be set to `&` in that case means it is only referenced - * and is not an owned property (usually a non-owning pointer). Which means - * user is responsible for deallocation if required. - * - * The finall letter *Z* can be set to `?` which means it is optional (like a - * nullable pointer). + * # Libraries * - * Examples: - * - * ```c - * struct foo { - * int x; // (+) Position in x. - * int y; // (+) Position in y. - * struct theme *th; // (+&?) Theme to use. - * unsigned int elapsed; // (-) Elapsed time since last frame. - * struct texture text; // (*) Texture used for rendering. - * }; - * ``` - * - * Within this structure, the fields `x` and `y` are completely accessible to - * the user for both reading/writing. The field `th` is an optional non-owning - * pointer to a theme which is also readable/writable. The field `elapsed` is - * readable but should not be modified. Finally, the field `text` is private - * and should not be touched by the user. - * - * ## Functions - * - * When functions needs to initialize and destroy objects, the following - * conventions is used: - * - * - `foo_init`: initialize the object, - * - `foo_finish`: dispose the object and possible owned allocations. + * The following libraries are available and built separately: * - * In case of opaque objects, the creation function is named under the module - * discretion (e.g. `foo_open`, `foo_new`) but the destruction function is - * usually named `foo_free`. - * - * # Usage conventions - * - * This chapter describes lots of aspects about using this core API. - * - * ## Memory and ownership - * - * Within the core, functions usually never take ownership of user objects. They - * mostly assume that objects are still alive during usage of the core API. If - * the opposite case happen, it is clearly stated in the documentation. Unless - * stated, user must always make sure objects are kept alive. - * - * If a function needs its own copy of something, it usually take a const - * pointer and copy it into its internals. But make sure that every member are - * still pointer to valid memory if this is a concern. - * - * Example: the \ref script.h modules is used to create a sequence of action, on - * its internal it stores a singly-linked list of \ref action that are copied - * from the user. But since the \ref action structure contains arbitrary data, - * those must be kept until the action is no longer used. - * - * \code - * struct action my_action action = { - * .data = my_action_data, - * .update = my_action_update - * }; - * struct script script; - * - * script_init(&script); - * script_append(&script, &action); - * \endcode - * - * Even though \ref script_append copy the action into an internal object, - * the *my_action_data* must still be valid until the script ended. - * - * ## Modules - * - * Whenever possible, functions that needs a structure context will always take - * it as first argument. - * - * This let the user to control lifetime and allocation storage for most of the - * API objects. - * - * Example: - * - * \code - * struct clock clock; - * - * clock_start(&clock); - * clock_elapsed(&clock); - * \endcode + * | Library | Description | Dependencies | + * |---------|----------------------------------------------|----------------------------------------| + * | libcore | Low level audio, video, windowing and input. | SDL2, SDL2_mixer, SDL2_ttf, SDL2_image | + * | libui | Minimalist UI routines to draw interfaces | libcore | + * | librpg | Group of modules related to RPG games | libcore, libui | * * ## Thread safety and reentrancy * @@ -166,10 +68,4 @@ * objects. * * \note This may change in the future. - * - * ## Error handling - * - * Functions that may fail usually return a boolean. If an error occured, it is - * stored in a global variable that are accessed through the \ref error.h - * module. */ diff -r aab824406d3d -r eb0a7ab71023 doxygen/page-faq.c --- a/doxygen/page-faq.c Tue Oct 20 15:09:39 2020 +0200 +++ b/doxygen/page-faq.c Tue Oct 20 17:39:13 2020 +0200 @@ -44,11 +44,11 @@ * happening under the hood without having to check if functions will generate * dynamic allocations or not. * - * However, we also love modernity and as such, C18 is the minimal requirement + * However, we also love modernity and as such, C11 is the minimal requirement * to build and run Molko's Adventure. * * \note The code does not make any assumption about the platform it runs, it - * expects to have a fully conformant C18 implementation. Microsoft MSVC + * expects to have a fully conformant C11 implementation. Microsoft MSVC * is known to **not** support this C version. * * # Can I make a MMORPG with that? diff -r aab824406d3d -r eb0a7ab71023 doxygen/page-howto-error.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doxygen/page-howto-error.c Tue Oct 20 17:39:13 2020 +0200 @@ -0,0 +1,76 @@ +/** + * \page howto-error Howto: error handling + * \tableofcontents + * + * How error handling is used within the API and the user code. + * + * # Synopsis + * + * Error handling is always a complicated task in the software development. In + * Molko's Adventure there is three kinds of errors: + * + * 1. Programming error. + * 2. Recoverable error at runtime. + * 3. Unexpected error at runtime. + * + * # Kind of errors + * + * ## Assertions + * + * One of the easiest errors to detect are about programming errors. In the + * Molko's Adventure API they are usually detected at runtime when you use a + * function with preconditions unmet. In that case standard C `assert` is used. + * + * For example, it happens when you: + * + * - Pass a NULL pointer where the function expects non-NULL, + * - Pass invalid arguments such as out of bounds indicies. + * + * Always read carefully preconditions that are annotated through the + * documentation. + * + * ## Recoverable errors + * + * Next, come recoverable errors. Those arise when you may expect a failure from + * the API and can do something else. + * + * For example, it happens when you: + * + * - Open a font file that is invalid, + * - Open a music file that is no longer on the disk. + * + * In these situations, the API indicates usually by a return code that the + * function was unable to complete correctly (and you can use \ref error to + * retrieve the specified error). In some case, you *MUST* not ignore the return + * value because if the function takes an input as argument it will be kept + * untouched. For example, the \ref texture_new function may fail to create a + * texture and in that case it is left untouched. + * + * ## Unexpected errors + * + * Finally, come what we call unexpected errors. Those happen while they are not + * supposed to. + * + * For example, it happens when there is a severe issue either in the kernel, + * graphics or any other library that aren't raised by the API itself. + * + * This includes (but not limited to): + * + * - A rendering error (caused by an internal issue). + * + * In these situations, the API calls the function \ref panic which definitely + * calls the \ref panic_handler. The default implementation prints an error and + * exit with a code of 1. User may pass a custom function but should quit the + * game because the API does not take care of deallocating data before calling + * panic. + * + * # Error handling in Molko's Adventure API + * + * The following table shows what is used and when. + * + * | | `assert` | Booleans | panic | Notes | + * |---------|--------------------|---------------------|-------------------------------------------|-----------------------------------| + * | libcore | Programming errors | As much as possible | Only in memory utilities from util.h | Never called from libcore itself. | + * | libui | Programming errors | When applicable | Mostly in rendering errors | None. | + * | librpg | Programming errors | When applicable | Mostly in rendering errors | None. | + */ diff -r aab824406d3d -r eb0a7ab71023 doxygen/page-howto-ownership.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doxygen/page-howto-ownership.c Tue Oct 20 17:39:13 2020 +0200 @@ -0,0 +1,120 @@ +/** + * \page howto-ownership Howto: ownership and memory management + * \tableofcontents + * + * How memory and ownership is used within Molko's Adventure API. + * + * # Synopsis + * + * In C, memory management can be a cumbersome issue and a major common complain + * when it comes to leak. + * + * As such, the API itself does not use dynamic allocations in most of the case. + * Instead it is kept to the user responsability to handle storage of data. In + * that manner the code stays simpler, stronger and more flexible. The API + * itself does not have to deal with memory management and deallocation, it only + * expect data from user and work with that. + * + * You can imagine a situation with a DVD player and some movies on DVDs. You + * have one DVD player where you put some DVDs inside but the DVD player never + * make its own copy, it simply reads your disc and you get it back afterwards. + * + * Following this philosophy, the Molko's Adventure API for this scenario would + * look like this: + * + * ```c + * struct dvd_player player; + * struct dvd dvd; + * + * dvd_open(&dvd, "/dev/sr0"); + * + * dvd_player_turn_on(); + * dvd_player_insert(&player, &dvd); + * dvd_player_play(&player); + * dvd_player_turn_off(); + * ``` + * + * # Memory handling + * + * ## Arrays + * + * Some modules in the API may require an array. Depending on the situation they + * can be passed as parameter or are usually of a fixed reasonable size in + * structures. + * + * They are always annotated with a macro to let the user flexibility over it if + * necessary. + * + * Example, a player has a set of spells. + * + * ```c + * #define PLAYER_SPELL_MAX (16) + * + * struct player { + * struct spell *spells[PLAYER_SPELL_MAX]; + * }; + * ``` + * + * ## Strings + * + * When dealing with strings, they are almost always referenced and not copied + * unless explicitly required. As such, no allocation/deallocation required + * either. + * + * ```c + * struct player { + * const char *name; // Not allocated, no deallocation + * ``` + * + * # Ownership + * + * Alongside the memory handling comes the ownership. Related to the DVD + * scenario explained above, not having to *own* a resource within a structure + * means no allocation/deallocation required. + * + * Also, since C does not have a scoped mechanism, all fields in structured are + * publicly available and to avoid allocating them on the heap they are always + * declared to the user even if they need internal data. + * + * As a documentation notice, fields are always annotated using (XYZ) prefix + * with some symbols to indicate whether user is allowed to touch or not. + * + * The letter *X* defines the following restriction + * + * - `+`: The property is readable/editable by the user, + * - `-`: The property is readable by the user, + * - `*`: The property is not meant to be used directly by the user. + * + * The letter *Y* can be set to `&` in that case means it is only referenced + * and is not an owned property (usually a non-owning pointer). Which means + * user is responsible for deallocation if required. + * + * The finall letter *Z* can be set to `?` which means it is optional (like a + * nullable pointer). + * + * Examples: + * + * ```c + * struct foo { + * int x; // (+) Position in x. + * int y; // (+) Position in y. + * struct theme *th; // (+&?) Theme to use. + * unsigned int elapsed; // (-) Elapsed time since last frame. + * struct texture text; // (*) Texture used for rendering. + * }; + * ``` + * + * Within this structure, the fields `x` and `y` are completely accessible to + * the user for both reading/writing. The field `th` is an optional non-owning + * pointer to a theme which is also readable/writable. The field `elapsed` is + * readable but should not be modified. Finally, the field `text` is private + * and should not be touched by the user. + * + * # Memory handling in Molko's Adventure API + * + * | | Dynamic allocation? | Notes | + * |---------|---------------------|---------------------------------------------------------| + * | libcore | None | The util.h provides convenient allocators for the user. | + * | libui | None | | + * | librpg | In map.h module | Maps are big chunk of data. | + */ diff -r aab824406d3d -r eb0a7ab71023 doxygen/page-portability.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doxygen/page-portability.c Tue Oct 20 17:39:13 2020 +0200 @@ -0,0 +1,34 @@ +/** + * \page portability Portability + * \tableofcontents + * + * A note about portability in Molko's Adventure API. + * + * # C standard used + * + * The code is based mostly written in C99 with a subset of C11. The following + * features from C11 are required: + * + * - `` header. + * + * # POSIX + * + * A few routines from the POSIX specification are also used: + * + * - `` header. + * - `read(2)` function. + * - `open(2)` function. + * - `getopt(3)`, + * - `fmemopen(3)`. + * + * Efforts are ongoing to provide fallback implementations for systems that lack + * those functionalities. + * + * # System tested + * + * - macOS (10.15 and later), + * - Linux (glibc and musl variants), + * - FreeBSD, NetBSD and OpenBSD. + * + * Windows is currently not supported right now but will be in the future. + */ diff -r aab824406d3d -r eb0a7ab71023 libcore/CMakeLists.txt --- a/libcore/CMakeLists.txt Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/CMakeLists.txt Tue Oct 20 17:39:13 2020 +0200 @@ -33,7 +33,6 @@ ${libcore_SOURCE_DIR}/core/drawable.h ${libcore_SOURCE_DIR}/core/error.c ${libcore_SOURCE_DIR}/core/error.h - ${libcore_SOURCE_DIR}/core/error_p.h ${libcore_SOURCE_DIR}/core/event.c ${libcore_SOURCE_DIR}/core/event.h ${libcore_SOURCE_DIR}/core/font.c @@ -53,8 +52,6 @@ ${libcore_SOURCE_DIR}/core/panic.c ${libcore_SOURCE_DIR}/core/panic.h ${libcore_SOURCE_DIR}/core/plat.h - ${libcore_SOURCE_DIR}/core/rbuf.c - ${libcore_SOURCE_DIR}/core/rbuf.h ${libcore_SOURCE_DIR}/core/save.c ${libcore_SOURCE_DIR}/core/save.h ${libcore_SOURCE_DIR}/core/script.c diff -r aab824406d3d -r eb0a7ab71023 libcore/core/action.h --- a/libcore/core/action.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/action.h Tue Oct 20 17:39:13 2020 +0200 @@ -115,6 +115,7 @@ * \pre act != NULL * \param act the action * \param ticks the number of milliseconds since last frame + * \return Status of act->update or false if act->update is NULL. */ bool action_update(struct action *act, unsigned int ticks); @@ -180,6 +181,7 @@ * \param st the stack * \param act the action * \note The pointer must be kept alive. + * \return True if the action was added correctly (enough space). */ bool action_stack_add(struct action_stack *st, struct action *act); @@ -201,7 +203,7 @@ * \pre st != NULL * \param st the stack * \param ticks the number of milliseconds since last frame - * \return true if all actions completed + * \return True if all actions completed. */ bool action_stack_update(struct action_stack *st, unsigned int ticks); @@ -220,7 +222,7 @@ * * \pre st != NULL * \param st the stack - * \return false if there is at least one action in the stack + * \return False if there is at least one action in the stack. */ bool action_stack_completed(const struct action_stack *st); diff -r aab824406d3d -r eb0a7ab71023 libcore/core/animation.c --- a/libcore/core/animation.c Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/animation.c Tue Oct 20 17:39:13 2020 +0200 @@ -32,7 +32,7 @@ static void draw(struct drawable *dw) { - return animation_draw(dw->data, dw->x, dw->y); + animation_draw(dw->data, dw->x, dw->y); } void @@ -85,10 +85,10 @@ an->column >= an->sprite->ncols; } -void +bool animation_draw(struct animation *an, int x, int y) { - sprite_draw(an->sprite, an->row, an->column, x, y); + return sprite_draw(an->sprite, an->row, an->column, x, y); } void diff -r aab824406d3d -r eb0a7ab71023 libcore/core/animation.h --- a/libcore/core/animation.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/animation.h Tue Oct 20 17:39:13 2020 +0200 @@ -74,7 +74,7 @@ * \pre an != NULL * \param an the animation * \param ticks the elapsed ticks since the last call - * \return true if the animation is complete + * \return True if the animation is complete. */ bool animation_update(struct animation *an, unsigned int ticks); @@ -86,8 +86,9 @@ * \param an the animation * \param x the X coordinate * \param y the Y coordinate + * \return False in case of rendering error. */ -void +bool animation_draw(struct animation *an, int x, int y); /** diff -r aab824406d3d -r eb0a7ab71023 libcore/core/drawable.h --- a/libcore/core/drawable.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/drawable.h Tue Oct 20 17:39:13 2020 +0200 @@ -141,8 +141,7 @@ * \pre dw != NULL * \param st the stack * \param dw the drawable to reference - * \return true if the drawable was placed correctly and false if there wasn't - * enough room. + * \return True if the drawable was added correctly (enough space). */ bool drawable_stack_add(struct drawable_stack *st, struct drawable *dw); @@ -155,7 +154,7 @@ * \pre st != NULL * \param st the drawable stack * \param ticks the number of ticks since last frame - * \return true if all drawable were rendered + * \return True if all drawable were rendered. */ bool drawable_stack_update(struct drawable_stack *st, unsigned int ticks); @@ -174,7 +173,7 @@ * * \pre st != NULL * \param st the stack - * \return false if there is at least one drawable in the stack + * \return False if there is at least one drawable in the stack. */ bool drawable_stack_completed(const struct drawable_stack *st); diff -r aab824406d3d -r eb0a7ab71023 libcore/core/error.c --- a/libcore/core/error.c Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/error.c Tue Oct 20 17:39:13 2020 +0200 @@ -17,13 +17,9 @@ */ #include -#include #include -#include -#include #include "error.h" -#include "error_p.h" #include @@ -58,21 +54,3 @@ return false; } - -bool -error_errno(void) -{ - errorf("%s", strerror(errno)); - - return false; -} - -/* private: error_p.h */ - -bool -error_sdl(void) -{ - errorf("%s", SDL_GetError()); - - return false; -} diff -r aab824406d3d -r eb0a7ab71023 libcore/core/error.h --- a/libcore/core/error.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/error.h Tue Oct 20 17:39:13 2020 +0200 @@ -59,13 +59,4 @@ bool verrorf(const char *fmt, va_list ap) PLAT_PRINTF(1, 0); -/** - * Convenient helper that sets last error from global C errno and then return - * false. - * - * \return Always false. - */ -bool -error_errno(void); - #endif /* !MOLKO_ERROR_H */ diff -r aab824406d3d -r eb0a7ab71023 libcore/core/error_p.h --- a/libcore/core/error_p.h Tue Oct 20 15:09:39 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * error.h -- (PRIVATE) error routines - * - * Copyright (c) 2020 David Demelier - * - * 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 - -/** - * 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 */ diff -r aab824406d3d -r eb0a7ab71023 libcore/core/event.h --- a/libcore/core/event.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/event.h Tue Oct 20 17:39:13 2020 +0200 @@ -84,7 +84,7 @@ * Fetch the next event or return false if there are not. * * \param ev the event - * \return true if the event was filled or false otherwise + * \return True if the event was filled or false otherwise. */ bool event_poll(union event *ev); diff -r aab824406d3d -r eb0a7ab71023 libcore/core/font.c --- a/libcore/core/font.c Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/font.c Tue Oct 20 17:39:13 2020 +0200 @@ -23,7 +23,6 @@ #include "color.h" #include "error.h" -#include "error_p.h" #include "font.h" #include "texture_p.h" #include "util.h" @@ -35,7 +34,7 @@ assert(path); if (!(font->handle = TTF_OpenFont(path, size))) - return error_sdl(); + return errorf("%s", SDL_GetError()); return true; } @@ -50,7 +49,7 @@ if (!(ops = SDL_RWFromConstMem(buffer, buflen)) || (!(font->handle = TTF_OpenFontRW(ops, true, size)))) - return error_sdl(); + return errorf("%s", SDL_GetError()); return true; } @@ -97,7 +96,7 @@ } if (!(surface = func(font->handle, text, fg))) - return error_sdl(); + return errorf("%s", SDL_GetError()); return texture_from_surface(tex, surface); } @@ -117,7 +116,7 @@ assert(text); if (TTF_SizeUTF8(font->handle, text, (int *)w, (int *)h) != 0) - return error_sdl(); + return errorf("%s", SDL_GetError()); return true; } diff -r aab824406d3d -r eb0a7ab71023 libcore/core/font.h --- a/libcore/core/font.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/font.h Tue Oct 20 17:39:13 2020 +0200 @@ -137,7 +137,7 @@ * \param text the UTF-8 text * \param w pointer to width (may be NULL) * \param h pointer to height (may be NULL) - * \return false in case of error and pointers to w and h are left unmodified + * \return False in case of error and pointers to w and h are left unmodified. */ bool font_query(const struct font *font, const char *text, unsigned int *w, unsigned int *h); diff -r aab824406d3d -r eb0a7ab71023 libcore/core/game.h --- a/libcore/core/game.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/game.h Tue Oct 20 17:39:13 2020 +0200 @@ -28,11 +28,6 @@ #include "inhibit.h" -/** - * \brief Max number of actions allowed at the same time. - */ -#define GAME_ACTIONS_MAX 128 - struct state; union event; diff -r aab824406d3d -r eb0a7ab71023 libcore/core/image.c --- a/libcore/core/image.c Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/image.c Tue Oct 20 17:39:13 2020 +0200 @@ -21,7 +21,7 @@ #include -#include "error_p.h" +#include "error.h" #include "texture.h" #include "window.h" #include "window_p.h" @@ -46,7 +46,7 @@ assert(path); if (!(tex->handle = IMG_LoadTexture(RENDERER(), path))) - return error_sdl(); + return errorf("%s", SDL_GetError()); dimensions(tex); @@ -61,7 +61,7 @@ SDL_RWops *ops = SDL_RWFromConstMem(buffer, size); if (!ops || !(tex->handle = IMG_LoadTexture_RW(RENDERER(), ops, true))) - return error_sdl(); + return errorf("%s", SDL_GetError()); dimensions(tex); diff -r aab824406d3d -r eb0a7ab71023 libcore/core/image.h --- a/libcore/core/image.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/image.h Tue Oct 20 17:39:13 2020 +0200 @@ -28,6 +28,8 @@ #include #include +#include "plat.h" + struct texture; /** @@ -40,7 +42,7 @@ * \return False on errors. */ bool -image_open(struct texture *tex, const char *path); +image_open(struct texture *tex, const char *path) PLAT_NODISCARD; /** * Open a file from a memory buffer. @@ -55,6 +57,6 @@ * \return False on errors. */ bool -image_openmem(struct texture *tex, const void *buffer, size_t size); +image_openmem(struct texture *tex, const void *buffer, size_t size) PLAT_NODISCARD; #endif /* !MOLKO_IMAGE_H */ diff -r aab824406d3d -r eb0a7ab71023 libcore/core/plat.h --- a/libcore/core/plat.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/plat.h Tue Oct 20 17:39:13 2020 +0200 @@ -36,10 +36,16 @@ */ #define PLAT_PRINTF(p1, p2) +/** + * Annotate a function when the result must never be discarded. + */ +#define PLAT_NODISCARD + #else #if defined(__GNUC__) || defined(__clang__) # define PLAT_PRINTF(p1, p2) __attribute__ ((format (printf, p1, p2))) +# define PLAT_NODISCARD __attribute__ ((warn_unused_result)) #else # define PLAT_PRINTF(p1, p2) #endif diff -r aab824406d3d -r eb0a7ab71023 libcore/core/rbuf.c --- a/libcore/core/rbuf.c Tue Oct 20 15:09:39 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * rbuf.c -- basic utility for reading input buffers - * - * Copyright (c) 2020 David Demelier - * - * 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 - -#include "rbuf.h" - -void -rbuf_open(struct rbuf *rb, const void *data, size_t datasz) -{ - assert(rb); - assert(data); - - rb->s = data; - rb->e = rb->s + datasz; -} - -bool -rbuf_readline(struct rbuf *rb, char *output, size_t outputsz) -{ - assert(rb); - assert(output); - assert(outputsz > 0); - - if (rb->s == rb->e) - return false; - - for (--outputsz; rb->s != rb->e && *rb->s != '\n' && outputsz; outputsz--) - *output++ = *rb->s++; - - /* Not enough space? */ - if (!outputsz && rb->s != rb->e && *rb->s != '\n') - return false; - - /* Remove this '\n' if still present. */ - if (rb->s != rb->e && *rb->s == '\n') - rb->s++; - - *output = '\0'; - - return true; -} diff -r aab824406d3d -r eb0a7ab71023 libcore/core/rbuf.h --- a/libcore/core/rbuf.h Tue Oct 20 15:09:39 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * rbuf.h -- basic utility for reading input buffers - * - * Copyright (c) 2020 David Demelier - * - * 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_RBUF_H -#define MOLKO_RBUF_H - -/** - * \file rbuf.h - * \brief Basic utility for reading input buffers. - */ - -#include -#include - -/** - * \brief Input object to store progression. - */ -struct rbuf { - const char *s; /*!< (-) Pointer to current character. */ - const char *e; /*!< (-) Pointer to end of array. */ -}; - -/** - * Open this input buffer. - * - * \pre rb != NULL - * \pre data != NULL - * \param rb the input object - * \param data the data to read - * \param datasz the size of buffer - */ -void -rbuf_open(struct rbuf *rb, const void *data, size_t datasz); - -/** - * Read the next line from the input. - * - * This function writes at most outputsz - 1 and is always NULL terminated - * unless the function returns false which indicates either end of buffer or - * too small output size. - * - * Example of use (`some_data` is assumed to be a buffer). - * - * \code - * struct rbuf rb; - * char line[1024]; - * - * rbuf_open(&rb, some_data, sizeof (some_data)); - * - * while (rbuf_readline(&rb, line, sizeof (line))) { - * printf("line contents: >[%s]<\n", line); - * } - * \endcode - * - * \pre rb != NULL - * \pre output != NULL - * \pre outputsz > 0 - * \param rb the input object - * \param output the output buffer - * \param outputsz the output buffer size - * \return true if a line was read correctly - */ -bool -rbuf_readline(struct rbuf *rb, char *output, size_t outputsz); - -#endif /* !MOLKO_RBUF_H */ diff -r aab824406d3d -r eb0a7ab71023 libcore/core/sound.c --- a/libcore/core/sound.c Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/sound.c Tue Oct 20 17:39:13 2020 +0200 @@ -21,8 +21,8 @@ #include +#include "error.h" #include "sound.h" -#include "error_p.h" bool sound_open(struct sound *snd, const char *path) @@ -31,7 +31,7 @@ assert(path); if (!(snd->handle = Mix_LoadMUS(path))) - return error_sdl(); + return errorf("%s", SDL_GetError()); return true; } @@ -46,7 +46,7 @@ if (!(ops = SDL_RWFromConstMem(buffer, buffersz)) || !(snd->handle = Mix_LoadMUS_RW(ops, true))) - return error_sdl(); + return errorf("%s", SDL_GetError()); return true; } @@ -61,7 +61,7 @@ if (snd->flags & SOUND_LOOP) n = -1; if (Mix_PlayMusic(snd->handle, n) < 0) - return error_sdl(); + return errorf("%s", SDL_GetError()); return true; } diff -r aab824406d3d -r eb0a7ab71023 libcore/core/sound.h --- a/libcore/core/sound.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/sound.h Tue Oct 20 17:39:13 2020 +0200 @@ -27,6 +27,8 @@ #include #include +#include "plat.h" + /** * \brief Sound flags. */ @@ -53,7 +55,7 @@ * \return False on errors. */ bool -sound_open(struct sound *snd, const char *path); +sound_open(struct sound *snd, const char *path) PLAT_NODISCARD; /** * Open a sound audio from a buffer. diff -r aab824406d3d -r eb0a7ab71023 libcore/core/sprite.c --- a/libcore/core/sprite.c Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/sprite.c Tue Oct 20 17:39:13 2020 +0200 @@ -46,14 +46,14 @@ return texture_ok(sprite->texture) && sprite->cellw != 0 && sprite->cellh != 0; } -void +bool sprite_draw(struct sprite *sprite, unsigned int r, unsigned int c, int x, int y) { assert(sprite_ok(sprite)); assert(r < sprite->nrows); assert(c < sprite->ncols); - texture_scale( + return texture_scale( sprite->texture, c * sprite->cellw, /* src y */ r * sprite->cellh, /* src x */ diff -r aab824406d3d -r eb0a7ab71023 libcore/core/sprite.h --- a/libcore/core/sprite.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/sprite.h Tue Oct 20 17:39:13 2020 +0200 @@ -87,7 +87,7 @@ * Tells if the sprite has a texture and isn't null sized. * * \param sprite the sprite to check (may be NULL) - * \return True if it is initialized correctly + * \return True if it is initialized correctly. */ bool sprite_ok(const struct sprite *sprite); @@ -103,8 +103,9 @@ * \param c the column number * \param x the X destination * \param y the Y destination + * \return False in case of rendering error. */ -void +bool sprite_draw(struct sprite *sprite, unsigned int r, unsigned int c, int x, int y); #endif /* !MOLKO_SPRITE_H */ diff -r aab824406d3d -r eb0a7ab71023 libcore/core/sys.c --- a/libcore/core/sys.c Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/sys.c Tue Oct 20 17:39:13 2020 +0200 @@ -32,7 +32,6 @@ #endif #include "error.h" -#include "error_p.h" #include "sys.h" #if defined(_WIN32) @@ -107,15 +106,15 @@ #endif if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) - return error_sdl(); + return errorf("%s", SDL_GetError()); if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) - return error_sdl(); + return errorf("%s", SDL_GetError()); if (TTF_Init() < 0) - return error_sdl(); + return errorf("%s", SDL_GetError()); if (Mix_Init(MIX_INIT_OGG) != MIX_INIT_OGG) - return error_sdl(); + return errorf("%s", SDL_GetError()); if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096) < 0) - return error_sdl(); + return errorf("%s", SDL_GetError()); return true; } diff -r aab824406d3d -r eb0a7ab71023 libcore/core/sys.h --- a/libcore/core/sys.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/sys.h Tue Oct 20 17:39:13 2020 +0200 @@ -39,7 +39,7 @@ * \return False on error. */ bool -sys_init(void); +sys_init(void) PLAT_NODISCARD; /** * Get the base system directory path. diff -r aab824406d3d -r eb0a7ab71023 libcore/core/texture.c --- a/libcore/core/texture.c Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/texture.c Tue Oct 20 17:39:13 2020 +0200 @@ -19,7 +19,6 @@ #include #include "error.h" -#include "error_p.h" #include "texture.h" #include "texture_p.h" #include "util.h" @@ -36,7 +35,7 @@ if (!tex->handle) { tex->w = tex->h = 0; - return error_sdl(); + return errorf("%s", SDL_GetError()); } tex->w = w; @@ -64,7 +63,7 @@ }; if (SDL_RenderCopy(RENDERER(), tex->handle, NULL, &dst) < 0) - return error_sdl(); + return errorf("%s", SDL_GetError()); return true; } @@ -95,7 +94,7 @@ }; if (SDL_RenderCopyEx(RENDERER(), tex->handle, &src, &dst, angle, NULL, SDL_FLIP_NONE) < 0) - return error_sdl(); + return errorf("%s", SDL_GetError()); return true; } @@ -121,7 +120,7 @@ if (!(tex->handle = SDL_CreateTextureFromSurface(RENDERER(), surface))) { tex->w = tex->h = 0; - return error_sdl(); + return errorf("%s", SDL_GetError()); } tex->w = surface->w; diff -r aab824406d3d -r eb0a7ab71023 libcore/core/texture.h --- a/libcore/core/texture.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/texture.h Tue Oct 20 17:39:13 2020 +0200 @@ -29,6 +29,8 @@ #include +#include "plat.h" + /** * \brief Texture object. */ @@ -48,7 +50,7 @@ * \return False on error. */ bool -texture_new(struct texture *tex, unsigned int w, unsigned int h); +texture_new(struct texture *tex, unsigned int w, unsigned int h) PLAT_NODISCARD; /** * Check if the texture is valid. diff -r aab824406d3d -r eb0a7ab71023 libcore/core/util.c --- a/libcore/core/util.c Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/util.c Tue Oct 20 17:39:13 2020 +0200 @@ -59,48 +59,6 @@ return memcpy(mem, ptr, size); } -char * -eprintf(const char *fmt, ...) -{ - assert(fmt); - - va_list ap; - char *ret; - - va_start(ap, fmt); - ret = evprintf(fmt, ap); - va_end(ap); - - return ret; -} - -char * -evprintf(const char *fmt, va_list args) -{ - assert(fmt); - - va_list ap; - int size; - char *ret; - - /* Count number of bytes required. */ - va_copy(ap, args); - - if ((size = vsnprintf(NULL, 0, fmt, ap)) < 0) - panicf("%s", strerror(errno)); - - /* Do actual copy. */ - ret = emalloc(size + 1); - va_copy(ap, args); - - if (vsnprintf(ret, size, fmt, ap) != size) { - free(ret); - panicf("%s", strerror(errno)); - } - - return ret; -} - void delay(unsigned int ms) { diff -r aab824406d3d -r eb0a7ab71023 libcore/core/util.h --- a/libcore/core/util.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/util.h Tue Oct 20 17:39:13 2020 +0200 @@ -51,7 +51,7 @@ * \post returned pointer will never be NULL */ void * -emalloc(size_t size); +emalloc(size_t size) PLAT_NODISCARD; /** * Wrapper around calloc(3) that exits on allocation failure. @@ -62,7 +62,7 @@ * \post returned pointer will never be NULL */ void * -ecalloc(size_t n, size_t size); +ecalloc(size_t n, size_t size) PLAT_NODISCARD; /** * Copy the region specified by ptr. @@ -74,25 +74,7 @@ * \post returned pointer will never be NULL */ void * -ememdup(const void *ptr, size_t size); - -/** - * Create a dynamically allocated string in the printf(3) format string. - * - * \pre fmt != NULL - * \return The heap allocated string. - * \post Returned string will never be NULL. - */ -char * -eprintf(const char *fmt, ...) PLAT_PRINTF(1, 2); - -/** - * Similar to \ref eprintf with arguments pointer. - * - * \copydoc eprintf - */ -char * -evprintf(const char *fmt, va_list ap) PLAT_PRINTF(1, 0); +ememdup(const void *ptr, size_t size) PLAT_NODISCARD; /** * Put the thread to sleep for a given amount of milliseconds. diff -r aab824406d3d -r eb0a7ab71023 libcore/core/window.c --- a/libcore/core/window.c Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/window.c Tue Oct 20 17:39:13 2020 +0200 @@ -21,7 +21,7 @@ #include -#include "error_p.h" +#include "error.h" #include "util.h" #include "window.h" #include "window_p.h" @@ -64,7 +64,7 @@ if (SDL_CreateWindowAndRenderer(w, h, SDL_WINDOW_OPENGL, &handle.win, &handle.renderer) < 0) - return error_sdl(); + return errorf("%s", SDL_GetError()); SDL_SetWindowTitle(handle.win, title); diff -r aab824406d3d -r eb0a7ab71023 libcore/core/window.h --- a/libcore/core/window.h Tue Oct 20 15:09:39 2020 +0200 +++ b/libcore/core/window.h Tue Oct 20 17:39:13 2020 +0200 @@ -27,6 +27,8 @@ #include +#include "plat.h" + /** * \brief Global exposed window structure. */ @@ -40,14 +42,14 @@ * \brief Window mouse cursor. */ enum window_cursor { - WINDOW_CURSOR_ARROW, - WINDOW_CURSOR_EDIT, - WINDOW_CURSOR_WAIT, - WINDOW_CURSOR_CROSSHAIR, - WINDOW_CURSOR_SIZE, - WINDOW_CURSOR_NO, - WINDOW_CURSOR_HAND, - WINDOW_CURSOR_LAST + WINDOW_CURSOR_ARROW, /*!< Standard arrow.*/ + WINDOW_CURSOR_EDIT, /*!< Text edit cursor "I". */ + WINDOW_CURSOR_WAIT, /*!< Busy cursor. */ + WINDOW_CURSOR_CROSSHAIR, /*!< Cross-hair for selection. */ + WINDOW_CURSOR_SIZE, /*!< Size/moving. */ + WINDOW_CURSOR_NO, /*!< Action forbidden. */ + WINDOW_CURSOR_HAND, /*!< Hand. */ + WINDOW_CURSOR_LAST /*!< Number of cursors. */ }; /** @@ -65,7 +67,7 @@ * \return true on success */ bool -window_open(const char *title, unsigned int width, unsigned int height); +window_open(const char *title, unsigned int width, unsigned int height) PLAT_NODISCARD; /** * Change the window cursor. diff -r aab824406d3d -r eb0a7ab71023 librpg/rpg/map.c --- a/librpg/rpg/map.c Tue Oct 20 15:09:39 2020 +0200 +++ b/librpg/rpg/map.c Tue Oct 20 17:39:13 2020 +0200 @@ -22,7 +22,6 @@ #include #include -#include #include #include #include diff -r aab824406d3d -r eb0a7ab71023 tests/CMakeLists.txt --- a/tests/CMakeLists.txt Tue Oct 20 15:09:39 2020 +0200 +++ b/tests/CMakeLists.txt Tue Oct 20 17:39:13 2020 +0200 @@ -34,7 +34,6 @@ ${tests_SOURCE_DIR}/assets/maps/error-width.map ${tests_SOURCE_DIR}/assets/maps/sample-map.map ) -molko_define_test(TARGET rbuf SOURCES test-rbuf.c) molko_define_test(TARGET save SOURCES test-save.c) molko_define_test(TARGET state SOURCES test-state.c) molko_define_test(TARGET drawable SOURCES test-drawable.c) diff -r aab824406d3d -r eb0a7ab71023 tests/test-rbuf.c --- a/tests/test-rbuf.c Tue Oct 20 15:09:39 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -/* - * test-rbuf.c -- test error routines - * - * Copyright (c) 2020 David Demelier - * - * 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. - */ - -#define GREATEST_USE_ABBREVS 0 -#include - -#include - -/* Don't use "" to avoid '\0' */ -const char data1[] = { 'a', 'b', 'c', '\n', 'd', 'e', 'f', '\n' }; -const char data2[] = { 'a', 'b', 'c', '\n', 'd', 'e', 'f' }; -const char data3[] = { 'a', 'b', 'c', '\n', '\n', 'd', 'e', 'f', '\n' }; -const char data4[] = { 'a', 'b', 'c', '\n', 'd', 'e', 'f', 'g', 'h', '\n' }; - -GREATEST_TEST -simple(void) -{ - struct rbuf rb; - char line[128]; - - rbuf_open(&rb, data1, sizeof (data1)); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(rbuf_readline(&rb, line, sizeof (line))); - GREATEST_ASSERT_STR_EQ("abc", line); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(rbuf_readline(&rb, line, sizeof (line))); - GREATEST_ASSERT_STR_EQ("def", line); - - GREATEST_PASS(); -} - -GREATEST_TEST -simple_noeol(void) -{ - struct rbuf rb; - char line[128]; - - rbuf_open(&rb, data2, sizeof (data2)); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(rbuf_readline(&rb, line, sizeof (line))); - GREATEST_ASSERT_STR_EQ("abc", line); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(rbuf_readline(&rb, line, sizeof (line))); - GREATEST_ASSERT_STR_EQ("def", line); - - GREATEST_PASS(); -} - -GREATEST_TEST -simple_emptylines(void) -{ - struct rbuf rb; - char line[128]; - - rbuf_open(&rb, data3, sizeof (data3)); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(rbuf_readline(&rb, line, sizeof (line))); - GREATEST_ASSERT_STR_EQ("abc", line); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(rbuf_readline(&rb, line, sizeof (line))); - GREATEST_ASSERT_STR_EQ("", line); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(rbuf_readline(&rb, line, sizeof (line))); - GREATEST_ASSERT_STR_EQ("def", line); - - GREATEST_PASS(); -} - -GREATEST_SUITE(simple_suite) -{ - GREATEST_RUN_TEST(simple); - GREATEST_RUN_TEST(simple_noeol); - GREATEST_RUN_TEST(simple_emptylines); -} - -GREATEST_TEST -fail_toosmall(void) -{ - struct rbuf rb; - char line[4]; - - rbuf_open(&rb, data4, sizeof (data4)); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(rbuf_readline(&rb, line, sizeof (line))); - GREATEST_ASSERT_STR_EQ("abc", line); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(!rbuf_readline(&rb, line, sizeof (line))); - - GREATEST_PASS(); -} - -GREATEST_TEST -fail_end(void) -{ - struct rbuf rb; - char line[128]; - - rbuf_open(&rb, data1, sizeof (data1)); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(rbuf_readline(&rb, line, sizeof (line))); - GREATEST_ASSERT_STR_EQ("abc", line); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(rbuf_readline(&rb, line, sizeof (line))); - GREATEST_ASSERT_STR_EQ("def", line); - - memset(line, '?', sizeof (line)); - GREATEST_ASSERT(!rbuf_readline(&rb, line, sizeof (line))); - - GREATEST_PASS(); -} - -GREATEST_SUITE(fail_suite) -{ - GREATEST_RUN_TEST(fail_toosmall); - GREATEST_RUN_TEST(fail_end); -} - -GREATEST_MAIN_DEFS(); - -int -main(int argc, char **argv) -{ - GREATEST_MAIN_BEGIN(); - GREATEST_RUN_SUITE(simple_suite); - GREATEST_RUN_SUITE(fail_suite); - GREATEST_MAIN_END(); -}