merge: iobackend on dev

This commit is contained in:
Matteo Flebus 2026-01-13 11:08:36 +01:00
commit 9923ebc677
3 changed files with 218 additions and 17 deletions

View file

@ -1,35 +1,102 @@
#include "io_backend.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// === Static variables
static struct iob_context context;
static FILE *input;
static FILE *input = NULL;
static char *stream_buf = NULL;
static size_t stream_buf_size = 0;
static enum iob_state state = IOB_STATE_NOT_INITIALIZED;
// === Functions
int iob_init(struct iob_context *ctx)
{
if (state != IOB_STATE_NOT_INITIALIZED)
return IOB_ERROR_MODULE_ALREADY_INITIALIZED;
context = *ctx;
switch (context.mode)
{
case IOB_MODE_STDIN:
input = stdin;
state = IOB_STATE_READY;
return 0;
case IOB_MODE_SCRIPT:
if (context.args == NULL)
return -2;
return IOB_ERROR_BAD_ARG;
input = fopen(context.args, "r");
if (input == NULL)
return -4;
return IOB_ERROR_CANNOT_OPEN_FILE;
state = IOB_STATE_READY;
return 0;
case IOB_MODE_CMD:
if (context.args != NULL)
return -2;
else
return 0;
return IOB_ERROR_BAD_ARG;
state = IOB_STATE_READY;
return 0;
default:
return -1;
return IOB_ERROR_BAD_ARG;
}
}
void iob_close(void)
{
fclose(input);
if ((context.mode == IOB_MODE_STDIN || context.mode == IOB_MODE_SCRIPT)
&& stream_buf != NULL)
{
free(stream_buf);
stream_buf_size = 0;
}
state = IOB_STATE_NOT_INITIALIZED;
}
ssize_t stream_read(char **stream)
{
// Check args
if (stream == NULL)
return IOB_ERROR_BAD_ARG;
// Check env
if (state == IOB_STATE_NOT_INITIALIZED)
return IOB_ERROR_MODULE_NOT_INITIALIZED;
if (state == IOB_STATE_FINISHED)
return 0;
if (state == IOB_STATE_ERROR)
return IOB_ERROR_GENERIC;
// Use input
if (context.mode == IOB_MODE_STDIN || context.mode == IOB_MODE_SCRIPT)
{
ssize_t nread = getline(&stream_buf, &stream_buf_size, input);
if (nread == -1)
{
state = IOB_STATE_FINISHED;
return 0;
}
else if (nread < 0)
state = IOB_STATE_ERROR;
return nread;
}
// Use args
else if (context.mode == IOB_MODE_CMD)
{
*stream = context.args;
return strlen(context.args);
}
else
{
*stream = NULL;
return IOB_ERROR_GENERIC;
}
}

View file

@ -3,6 +3,13 @@
#include <sys/types.h>
// Error codes
#define IOB_ERROR_GENERIC -1
#define IOB_ERROR_BAD_ARG -2
#define IOB_ERROR_MODULE_NOT_INITIALIZED -3
#define IOB_ERROR_MODULE_ALREADY_INITIALIZED -4
#define IOB_ERROR_CANNOT_OPEN_FILE -5
enum iob_mode
{
IOB_MODE_NULL = 0,
@ -11,11 +18,19 @@ enum iob_mode
IOB_MODE_CMD
};
enum iob_state
{
IOB_STATE_NOT_INITIALIZED,
IOB_STATE_READY,
IOB_STATE_FINISHED,
IOB_STATE_ERROR
};
/* @struct iob_context
* @var mode
* @var args contains
* the script name when mode is set to IOB_SCRIPT,
* the command to execute when mode is set to IOB_CMD,
* the script name when mode is set to IOB_MODE_SCRIPT,
* the command to execute when mode is set to IOB_MODE_CMD
*/
struct iob_context
{
@ -31,17 +46,16 @@ struct iob_context
*/
int iob_init(struct iob_context *context);
/* TODO
*
*
*
/* @brief Closes the opened buffers and the module gracefully
*/
void iob_close();
void iob_close(void);
/*i TODO
*
*
/* @brief reads at most one line of the input and stores it into *stream
*
* @param stream is a pointer that will be set to a string to parse
* @return the number of read characters if positive,
* zero if finished (reached EOF),
* the error code otherwise
*/
ssize_t stream_read(char **stream);

View file

@ -0,0 +1,120 @@
#include <criterion/criterion.h>
#include <criterion/new/assert.h>
#include <io_backend/io_backend.h>
#include <stdio.h>
TestSuite(IO_Backend);
// IOB Init
Test(IO_Backend, init_null)
{
struct iob_context ctx =
{
.iob_mode = IOB_MODE_NULL;
.args = NULL;
};
int actual = iob_init(ctx);
int expected = IOB_ERROR_BAD_ARG;
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
}
Test(IO_Backend, init_stdin)
{
struct iob_context ctx =
{
.iob_mode = IOB_MODE_STDIN;
.args = NULL;
};
int actual = iob_init(ctx);
int expected = 0;
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
iob_close();
}
// WARNING: this one could fail because of iob_close in the previous test
// Same applies for other tests
Test(IO_Backend, init_script)
{
char *script_name = "script.tmp" struct iob_context ctx = {
.iob_mode = IOB_MODE_SCRIPT;
.args = script_name;
};
// Create file
FILE *f = fopen(script_name, "w");
fclose(f);
int actual = iob_init(ctx);
int expected = 0;
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
iob_close();
remove(script_name);
}
Test(IO_Backend, init_script_not_a_file)
{
char *script_name = "not_a_file.tmp" struct iob_context ctx = {
.iob_mode = IOB_MODE_SCRIPT;
.args = script_name;
};
int actual = iob_init(ctx);
int expected = IOB_ERROR_CANNOT_OPEN_FILE;
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
}
Test(IO_Backend, init_script_null)
{
struct iob_context ctx =
{
.iob_mode = IOB_MODE_SCRIPT;
.args = NULL;
};
int actual = iob_init(ctx);
int expected = IOB_ERROR_CANNOT_OPEN_FILE;
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
}
Test(IO_Backend, init_cmd)
{
char *cmd = "iamacommand --yesido" struct iob_context ctx = {
.iob_mode = IOB_MODE_CMD;
.args = cmd;
};
int actual = iob_init(ctx);
int expected = 0;
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
iob_close();
}
Test(IO_Backend, init_cmd_null)
{
struct iob_context ctx =
{
.iob_mode = IOB_MODE_CMD;
.args = NULL;
};
int actual = iob_init(ctx);
int expected = IOB_ERROR_BAD_ARG;
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
}
Test(IO_Backend, init_already_init)
{
char *cmd = "iamacommand --yesido" struct iob_context ctx = {
.iob_mode = IOB_MODE_CMD;
.args = cmd;
};
iob_init(ctx);
int actual = iob_init(ctx);
int expected = IOB_ERROR_ALREADY_INITIALIZED;
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
iob_close();
}
Test(IO_Backend, close_not_init)
{
iob_close(); // Shouldn't do anything
}
// IOB Stream
// TODO