#define _POSIX_C_SOURCE 200809L #include "io_backend.h" #include #include #include // === Static variables #include "../utils/args/args.h" static struct iob_context context; 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 IOB_ERROR_BAD_ARG; input = fopen(context.args, "r"); if (input == NULL) return IOB_ERROR_CANNOT_OPEN_FILE; state = IOB_STATE_READY; return 0; case IOB_MODE_CMD: if (context.args == NULL) return IOB_ERROR_BAD_ARG; state = IOB_STATE_READY; return 0; default: 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; // MAGNIFICO // malloc(1); *stream_buf = EOF; *stream = stream_buf; return 1; } else if (nread < 0) state = IOB_STATE_ERROR; *stream = stream_buf; return nread; } // Use args else if (context.mode == IOB_MODE_CMD) { *stream = context.args; size_t len = strlen(context.args); context.args[len] = EOF; return len + 1; } else { *stream = NULL; return IOB_ERROR_GENERIC; } } int iob_config_from_args(struct args_options *args, struct iob_context *ctx) { switch (args->type) { case INPUT_STDIN: ctx->mode = IOB_MODE_STDIN; ctx->args = NULL; break; case INPUT_FILE: ctx->mode = IOB_MODE_SCRIPT; ctx->args = (char *)args->input_source; break; case INPUT_CMD: ctx->mode = IOB_MODE_CMD; ctx->args = (char *)args->input_source; break; default: return IOB_ERROR_GENERIC; } return 0; }