cake
/
libg1m
Archived
1
0
Fork 0
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libg1m/src/decode/mcs/spreadsheet.c

125 lines
3.7 KiB
C

/* *****************************************************************************
* decode/mcs/spreadsheet.c -- decode an MCS spreadsheet.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* 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 <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* g1m_decode_mcs_spreadsheet:
* Decode a spreadsheet.
*
* @arg handle the handle to make.
* @arg buffer the buffer to read from.
* @arg head the pre-filled head to complete and use.
* @return the error code (0 if ok).
*/
int g1m_decode_mcs_spreadsheet(g1m_mcsfile_t **handle, g1m_buffer_t *buffer,
g1m_mcshead_t *head)
{
/* read header */
DREAD(hd, g1m_mcs_spreadsheet_header_s)
if (hd.g1m_mcs_spreadsheet_header_has_subheader != 0x01)
return (0);
/* read subheader */
DREAD(shd, g1m_mcs_spreadsheet_subheader_s)
uint_fast32_t colcount = hd.g1m_mcs_spreadsheet_header_column_count;
colcount = be32toh(colcount << 8);
shd.g1m_mcs_spreadsheet_subheader_defs_size =
be32toh(shd.g1m_mcs_spreadsheet_subheader_defs_size);
/* prepare */
g1m_mcscell_t cells[1000 * colcount];
bzero(cells, sizeof(g1m_mcscell_t) * 1000 * colcount);
int cells_count = 0;
uint_fast32_t rows = 0;
uint_fast32_t cols = 0;
/* log some info */
log_info("%" PRIuFAST32 " columns to read!", colcount);
if (colcount) {
/* get the column directory */
uint32_t column_directory[colcount];
READ(&column_directory, sizeof(uint32_t) * colcount)
/* browse columns */
for (uint_fast32_t c = 0; c < colcount; c++) {
/* check if column is empty */
if (!column_directory[c])
continue;
/* get the row directory */
uint8_t row_directory[0x80];
READ(&row_directory, (size_t)0x80)
/* initialize loop values */
uint8_t *rd = row_directory;
int bit = 1 << 7;
/* explore each cell */
for (uint_fast32_t i = 0; i < 1000; i++) {
/* check if used */
if (*rd & bit) {
/* get cell */
g1m_bcd_t cell;
DREAD(rawcell, g1m_mcsbcd_s)
g1m_bcd_frommcs(&rawcell, &cell);
/* store it */
cells[c * 1000 + i] = (g1m_mcscell_t){
.g1m_mcscell_real = cell,
.g1m_mcscell_imgn = (g1m_bcd_t){},
.g1m_mcscell_flags = g1m_mcscellflag_used
};
/* check things (max row, max col, cells count) */
rows = max(rows, i);
cols = c;
cells_count++;
}
/* iterate bit and rd */
rd += (bit & 1);
bit = (bit >> 1) | ((bit & 1) << 7);
}
}
}
/* we have max rows and columns, increment to have sizes */
rows++, cols++;
/* create final tab */
head->g1m_mcshead_width = 0; head->g1m_mcshead_height = 0;
if (cells_count) {
head->g1m_mcshead_width = cols;
head->g1m_mcshead_height = rows;
}
int err = g1m_make_mcsfile(handle, head);
if (err) return (err);
/* main copying loop */
g1m_mcscell_t **tab = (*handle)->g1m_mcsfile_cells;
for (uint_fast32_t y = 0; y < head->g1m_mcshead_height; y++)
for (uint_fast32_t x = 0; x < head->g1m_mcshead_width; x++)
tab[y][x] = cells[x * 1000 + y];
/* no error */
return (0);
}