From 1785ab6697b54a64b51a454852503eabeb8cbb4b Mon Sep 17 00:00:00 2001 From: "Thomas \"Cakeisalie5\" Touhey" Date: Tue, 11 Apr 2017 01:38:58 +0200 Subject: [PATCH] Tried things. --- include/libg1m.h | 9 ++++ src/encode/main.c | 5 +- src/encode/mcs.c | 127 +++++++++++++++++++++++++++++++++++++++++++++ src/utils/buffer.c | 18 +++++++ 4 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 src/encode/mcs.c diff --git a/include/libg1m.h b/include/libg1m.h index fa88e3a..2324d6d 100644 --- a/include/libg1m.h +++ b/include/libg1m.h @@ -135,6 +135,12 @@ extern int g1m_decode_mcsfile(g1m_mcsfile_t **handle, extern int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle, const g1m_mcshead_t *head, const unsigned char *data, size_t size); +/* encode an MCS file */ +extern int g1m_encode_mcsfile(g1m_mcsfile_t *handle, g1m_buffer_t *buffer); +# define g1m_announce_mcsfile(handle, size) \ + (g1m_encode_mcsfile(handle, (g1m_buffer_t[]){{ \ + .cookie = (size_t*)size, .announce = g1m_announce_callback }})) + /* open CAS head for decoding, correct it for encoding */ extern int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer); extern int g1m_decode_casfiles_part(g1m_mcshead_t *head, g1m_mcshead_t *heads, @@ -178,6 +184,9 @@ extern int g1m_check_date(const char *raw); extern int g1m_decode_date(const char *raw, time_t *date); extern int g1m_encode_date(const time_t *date, char *raw); +/* Announce callback that just contributes to a size_t. */ +extern int g1m_announce_callback(void *cookie, size_t size); + # ifdef __cplusplus } # endif diff --git a/src/encode/main.c b/src/encode/main.c index 388653b..3c3f2a9 100644 --- a/src/encode/main.c +++ b/src/encode/main.c @@ -67,8 +67,7 @@ int g1m_encode(g1m_handle_t *handle, g1m_buffer_t *buffer) if (c->platforms && !(c->platforms & handle->platform)) continue; break; - } - if (!c->encode) return (g1m_error_op); + } if (!c->encode) return (g1m_error_op); /* announce, if necessary */ if (buffer->announce) { @@ -81,7 +80,7 @@ int g1m_encode(g1m_handle_t *handle, g1m_buffer_t *buffer) /* encode */ if (buffer->write) { err = (*c->encode)(handle, buffer); - if (err) { + if (err && buffer->unannounce) { (*buffer->unannounce)(buffer->cookie); return (err); } diff --git a/src/encode/mcs.c b/src/encode/mcs.c new file mode 100644 index 0000000..fc8a4d4 --- /dev/null +++ b/src/encode/mcs.c @@ -0,0 +1,127 @@ +/* ***************************************************************************** + * encode/mcs.c -- encode an MCS file. + * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey + * + * This file is part of libg1m. + * libg1m is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3.0 of the License, + * or (at your option) any later version. + * + * libg1m is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libg1m; if not, see . + * ************************************************************************** */ +#include +#define FUNCS(name) g1m_announce_mcs_##name, g1m_encode_mcs_##name + +/* ************************************************************************** */ +/* Correspondances */ +/* ************************************************************************** */ +/* Types */ +typedef int (*announce_t)(const g1m_mcsfile_t*, size_t*); +typedef int (*encode_t)(const g1m_mcsfile_t*, g1m_buffer_t *buffer); +struct corresp { + /* 'identification' */ + g1m_mcstype_t types; + + /* functions */ + announce_t announce; + encode_t encode; +}; + +/* All correspondances */ +static const struct corresp encodings[] = { + {g1m_mcstype_list | g1m_mcstype_matrix, FUNCS(cells)}, + {g1m_mcstype_program, FUNCS(program)}, + {g1m_mcstype_alpha, FUNCS(var)}, + + /* sentinel */ + {0, NULL, NULL} +}; +/* ************************************************************************** */ +/* Default functions */ +/* ************************************************************************** */ +/** + * default_announce: + * Announce a file with no type. + * + * @arg handle the file handle. + * @arg sz the size to contribute to. + * @return the error code (0 if ok). + */ + +static int default_announce(const g1m_mcsfile_t *handle, size_t *sz) +{ + *sz += handle->head.size; + return (0); +} + +/** + * default_encode: + * 'Encode' a file with no type. + * + * @arg handle the file handle. + * @arg buffer the buffer to write to. + * @return the error code (0 if ok). + */ + +static int default_encode(const g1m_mcsfile_t *handle, g1m_buffer_t *buffer) +{ + WRITE(handle->content, handle->head.size) + return (0); +} + +/* default correspondance */ +static struct corresp default_corresp = { 0, default_announce, default_encode}; +/* ************************************************************************** */ +/* Main function */ +/* ************************************************************************** */ +/** + * g1m_encode_mcsfile: + * Encode an MCS file. + * + * @arg handle the file handle. + * @arg buffer the buffer to which to encode it. + * @return the error that occured (0 if ok). + */ + +int g1m_encode_mcsfile(g1m_mcsfile_t *handle, g1m_buffer_t *buffer) +{ + int err; + + /* find the announcement and encoding function */ + const struct corresp *c = encodings - 1; + if (!c->types) c = &default_corresp; + else { + while ((++c)->encode) { + if (c->types && !(c->types & handle->head.type)) + continue; + break; + } if (!c->encode) return (g1m_error_op); + } + + /* announce if necessary */ + if (buffer->announce) { + size_t size = 0; + if ((err = (*c->announce)(handle, &size)) + || (err = (*buffer->announce)(buffer->cookie, size))) + return (err); + } + + /* encode */ + if (buffer->write) { + err = (*c->encode)(handle, buffer); + if (err && buffer->unannounce) { + (*buffer->unannounce)(buffer->cookie); + return (err); + } + } + + /* everything went well! */ + return (0); +} diff --git a/src/utils/buffer.c b/src/utils/buffer.c index fc92a40..7deb0df 100644 --- a/src/utils/buffer.c +++ b/src/utils/buffer.c @@ -152,3 +152,21 @@ int g1m_empty_limbuffer(g1m_buffer_t *limbuffer) SKIP(lim->left) return (0); } +/* ************************************************************************** */ +/* The announce callback */ +/* ************************************************************************** */ +/** + * g1m_announce_callback: + * Main announce callback, that just contributes to a size. + * + * @arg vpsize the size_t pointer. + * @arg size the size to add. + * @return 0 because OK. + */ + +int g1m_announce_callback(void *vpsize, size_t size) +{ + size_t *psize = (void*)vpsize; + *psize += size; + return (0); +}