/* ***************************************************************************** * manage/mcsfile.c -- manage 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 /** * g1m_make_mcsfile: * Make an MCS file out of a head. * * Will allocate all of the required parts of the MCS file for it to be * filled later. * * @arg handle the file to allocate. * @arg rawhead the head to use. * @return the error (if any). */ int g1m_make_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *rawhead) { unsigned int y; int i, j; /* allocate the handle */ *handle = malloc(sizeof(g1m_mcsfile_t)); if (!handle) return (g1m_error_alloc); g1m_mcsfile_t *h = *handle; memset(h, 0, sizeof(g1m_mcsfile_t)); /* copy the head */ memcpy(&h->head, rawhead, sizeof(g1m_mcshead_t)); g1m_mcshead_t *head = &h->head; switch (head->type) { /* allocate the cells */ case g1m_mcstype_list: case g1m_mcstype_mat: case g1m_mcstype_vct: case g1m_mcstype_ssheet: log_info("Preparing %d*%d matrix", head->width, head->height); unsigned int wd = head->width, ht = head->height; if (wd && ht) { h->cells = malloc(sizeof(g1m_mcscell_t*) * ht); if (!h->cells) goto fail; h->cells[0] = malloc(sizeof(g1m_mcscell_t) * wd * ht); if (!h->cells[0]) { free(h->cells); goto fail; } for (y = 1; y < ht; y++) h->cells[y] = &h->cells[0][h->head.width * y]; } break; /* allocate the variables */ case g1m_mcstype_alphamem: if (head->count <= 1) h->vars = &h->var; else { h->vars = malloc(sizeof(g1m_mcscell_t) * head->count); if (!h->vars) goto fail; memset(h->vars, 0, sizeof(g1m_mcscell_t) * head->count); } break; /* allocate the set of pixels */ case g1m_mcstype_pict: case g1m_mcstype_capt: /* set count */ head->count = (head->type == g1m_mcstype_pict) ? 2 : 1; /* allocate directory */ if (head->count <= 1) h->pics = &h->pic; else { h->pics = malloc(sizeof(uint32_t**) * head->count); if (!h->pics) goto fail; } /* allocate */ for (i = 0; i < head->count; i++) { h->pics[i] = alloc_pixels(head->width, head->height); if (!h->pics[i]) { for (j = 0; j < i; j++) free(h->pics[j]); if (h->pics != &h->pic) free(h->pics); goto fail; } } /* prepare */ for (i = 0; i < head->count; i++) prepare_pixels(h->pics[i], head->width, head->height) break; /* allocate nothing */ case g1m_mcstype_end: case g1m_mcstype_setup: case g1m_mcstype_string: /* TEMPORARY XXX */ break; /* allocate raw content */ default: h->content = malloc(head->size); if (!h->content) goto fail; break; } /* finish */ return (0); fail: free(*handle); *handle = NULL; return (g1m_error_alloc); } /** * g1m_prepare_mcsfile_heads: * Prepare the heads from a general head. * * @arg head the main head. * @arg heads the heads to prepare. * @return the error (if any). */ int g1m_prepare_mcsfile_heads(g1m_mcshead_t *head, g1m_mcshead_t *heads) { int i; /* check if the head is a multiple head */ if (~head->flags & g1m_mcsflag_multiple) return (g1m_error_op); /* copy the data in each head */ for (i = 0; i < head->count; i++) { heads[i] = *head; heads[i].flags &= ~g1m_mcsflag_multiple; } /* no error */ return (0); } /** * g1m_free_mcsfile: * Free an MCS file handle content. * * @arg handle the handle which has the content to free. */ void g1m_free_mcsfile(g1m_mcsfile_t *handle) { int i; /* check if exists */ if (!handle) return ; switch (handle->head.type) { /* free the cells */ case g1m_mcstype_mat: case g1m_mcstype_vct: case g1m_mcstype_list: case g1m_mcstype_ssheet: if (handle->head.width && handle->head.height) { free(handle->cells[0]); free(handle->cells); } break; /* free the set of pixels */ case g1m_mcstype_pict: case g1m_mcstype_capt: for (i = 0; i < handle->head.count; i++) free(handle->pics[i]); if (handle->pics != &handle->pic) free(handle->pics); break; /* free the variables */ case g1m_mcstype_alphamem: if (handle->vars != &handle->var) free(handle->vars); break; /* free nothing */ case g1m_mcstype_end: case g1m_mcstype_setup: case g1m_mcstype_string: /* TEMPORARY XXX */ break; /* free the raw content */ default: free(handle->content); } /* free the content */ free(handle); }