/* ***************************************************************************** * 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); /* initialize the handle, copy the head */ g1m_mcsfile_t *h = *handle; memset(h, 0, sizeof(g1m_mcsfile_t)); memcpy(&h->g1m_mcsfile_head, rawhead, sizeof(g1m_mcshead_t)); g1m_mcshead_t *head = &h->g1m_mcsfile_head; switch (head->g1m_mcshead_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->g1m_mcshead_width, head->g1m_mcshead_height); unsigned int wd = head->g1m_mcshead_width; unsigned int ht = head->g1m_mcshead_height; if (wd && ht) { h->g1m_mcsfile_cells = malloc(sizeof(g1m_mcscell_t*) * ht); if (!h->g1m_mcsfile_cells) goto fail; h->g1m_mcsfile_cells[0] = malloc(sizeof(g1m_mcscell_t) * wd * ht); if (!h->g1m_mcsfile_cells[0]) { free(h->g1m_mcsfile_cells); goto fail; } for (y = 1; y < ht; y++) h->g1m_mcsfile_cells[y] = &h->g1m_mcsfile_cells [0][h->g1m_mcsfile_head.g1m_mcshead_width * y]; } break; /* allocate the variables */ case g1m_mcstype_alphamem: if (head->g1m_mcshead_count <= 1) h->g1m_mcsfile_vars = &h->g1m_mcsfile_var; else { h->g1m_mcsfile_vars = malloc(sizeof(g1m_mcscell_t) * head->g1m_mcshead_count); if (!h->g1m_mcsfile_vars) goto fail; memset(h->g1m_mcsfile_vars, 0, sizeof(g1m_mcscell_t) * head->g1m_mcshead_count); } break; /* allocate the set of pixels */ case g1m_mcstype_pict: case g1m_mcstype_capt: /* set count */ head->g1m_mcshead_count = (head->g1m_mcshead_type == g1m_mcstype_pict) ? 2 : 1; /* allocate directory */ if (head->g1m_mcshead_count <= 1) h->g1m_mcsfile_pics = &h->g1m_mcsfile_pic; else { h->g1m_mcsfile_pics = malloc(sizeof(uint32_t**) * head->g1m_mcshead_count); if (!h->g1m_mcsfile_pics) goto fail; } /* allocate */ for (i = 0; i < head->g1m_mcshead_count; i++) { h->g1m_mcsfile_pics[i] = alloc_pixels(head->g1m_mcshead_width, head->g1m_mcshead_height); if (!h->g1m_mcsfile_pics[i]) { for (j = 0; j < i; j++) free(h->g1m_mcsfile_pics[j]); if (h->g1m_mcsfile_pics != &h->g1m_mcsfile_pic) free(h->g1m_mcsfile_pics); goto fail; } } /* prepare */ for (i = 0; i < head->g1m_mcshead_count; i++) prepare_pixels(h->g1m_mcsfile_pics[i], head->g1m_mcshead_width, head->g1m_mcshead_height) break; /* allocate nothing */ case g1m_mcstype_end: case g1m_mcstype_setup: case g1m_mcstype_string: /* TEMPORARY XXX */ break; /* allocate raw content */ default: h->g1m_mcsfile_content = malloc(head->g1m_mcshead_size); if (!h->g1m_mcsfile_content) goto fail; break; } /* finish */ return (0); fail: free(*handle); *handle = NULL; return (g1m_error_alloc); } /** * 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->g1m_mcsfile_head.g1m_mcshead_type) { /* free the cells */ case g1m_mcstype_mat: case g1m_mcstype_vct: case g1m_mcstype_list: case g1m_mcstype_ssheet: if (handle->g1m_mcsfile_head.g1m_mcshead_width && handle->g1m_mcsfile_head.g1m_mcshead_height) { free(handle->g1m_mcsfile_cells[0]); free(handle->g1m_mcsfile_cells); } break; /* free the set of pixels */ case g1m_mcstype_pict: case g1m_mcstype_capt: for (i = 0; i < handle->g1m_mcsfile_head.g1m_mcshead_count; i++) free(handle->g1m_mcsfile_pics[i]); if (handle->g1m_mcsfile_pics != &handle->g1m_mcsfile_pic) free(handle->g1m_mcsfile_pics); break; /* free the variables */ case g1m_mcstype_alphamem: if (handle->g1m_mcsfile_vars != &handle->g1m_mcsfile_var) free(handle->g1m_mcsfile_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->g1m_mcsfile_content); } /* free the content */ free(handle); }