Tried to implement CAS file groups.
This commit is contained in:
parent
dfca7ea255
commit
795c9638c6
|
@ -19,8 +19,9 @@
|
|||
* WARNING: Do NOT include this header using <libg1m-(version)/libg1m.h>!
|
||||
*
|
||||
* Compile using one of these:
|
||||
* libg1m-config --cflags
|
||||
* pkg-config libg1m --cflags
|
||||
*
|
||||
* libg1m-config --cflags
|
||||
* pkg-config libg1m --cflags
|
||||
*
|
||||
* and include using <libg1m.h>.
|
||||
* ************************************************************************** */
|
||||
|
@ -73,9 +74,10 @@ extern const char *g1m_error_strings[];
|
|||
/* ************************************************************************** */
|
||||
/* Main functions */
|
||||
/* ************************************************************************** */
|
||||
/* open a handle */
|
||||
/* open and free a handle */
|
||||
int g1m_decode(g1m_t *handle, const char *path, g1m_buffer_t *buffer,
|
||||
g1m_type_t expected_type);
|
||||
void g1m_free(g1m_t *handle);
|
||||
|
||||
/* open a handle using FILEs */
|
||||
#ifndef G1M_DISABLED_FILE
|
||||
|
@ -85,8 +87,13 @@ int g1m_fopen(g1m_t **handle, const char *path, FILE *stream,
|
|||
g1m_type_t expected_type);
|
||||
#endif
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Main MCS functions */
|
||||
/* ************************************************************************** */
|
||||
/* make an MCS file out of a head */
|
||||
int g1m_make_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *rawhead);
|
||||
int g1m_prepare_mcsfile_heads(g1m_mcshead_t *head, g1m_mcshead_t *heads);
|
||||
void g1m_free_mcsfile(g1m_mcsfile_t *handle);
|
||||
|
||||
/* open MCS head for decoding, correct it for encoding */
|
||||
int g1m_decode_mcsfile_head(g1m_mcshead_t *head,
|
||||
|
@ -103,19 +110,18 @@ int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle,
|
|||
|
||||
/* open CAS head for decoding
|
||||
* --------------------------
|
||||
* if the head corresponds to something you want as a file (e.g. g1m_mcstype_end
|
||||
* then you should make the file using `g1m_make_mcsfile`, and call
|
||||
* `g1m_decode_casfile_part` while the `g1m_mcsflag_unfinished` flag is set.
|
||||
* if the head corresponds to something you want as a file (e.g.
|
||||
* not `g1m_mcstype_end`), then you should make the file using
|
||||
* `g1m_make_mcsfile`, and call `g1m_decode_casfile_part` while the
|
||||
* `g1m_mcsflag_unfinished` flag is set.
|
||||
* Warning: there could be no parts to read! (e.g. unset variable) */
|
||||
int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer);
|
||||
int g1m_decode_casfiles_part(g1m_mcshead_t *head, g1m_mcshead_t *heads,
|
||||
g1m_buffer_t *buffer);
|
||||
int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer);
|
||||
|
||||
/* free handles */
|
||||
void g1m_free(g1m_t *handle);
|
||||
void g1m_free_mcsfile(g1m_mcsfile_t *handle);
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* MCS file manipulation */
|
||||
/* MCS archive management */
|
||||
/* ************************************************************************** */
|
||||
/* add MCS files */
|
||||
int g1m_putmcs_program(g1m_t *handle, g1m_mcsfile_t **pfile,
|
||||
|
|
|
@ -146,9 +146,13 @@ G1M_MCSFUNC(string)
|
|||
/* ************************************************************************** */
|
||||
# define G1M_CASFUNC(NAME) \
|
||||
int g1m_decode_caspart_##NAME(g1m_mcsfile_t *handle, g1m_buffer_t *buffer);
|
||||
# define G1M_CASHFUNC(NAME) \
|
||||
int g1m_decode_cashpart_##NAME(g1m_mcshead_t *head, g1m_mcshead_t *heads, \
|
||||
g1m_buffer_t *buffer);
|
||||
|
||||
G1M_CASFUNC(var)
|
||||
G1M_CASFUNC(program)
|
||||
G1M_CASHFUNC(program)
|
||||
/* ************************************************************************** */
|
||||
/* Picture utilities */
|
||||
/* ************************************************************************** */
|
||||
|
@ -171,7 +175,6 @@ G1M_CASFUNC(program)
|
|||
G1M_PROTOTYPE_PIX(packed1bit)
|
||||
G1M_PROTOTYPE_PIX(packed4bits)
|
||||
G1M_PROTOTYPE_PIX(16bits)
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Utilities */
|
||||
/* ************************************************************************** */
|
||||
|
@ -180,7 +183,6 @@ int g1m_make_mcs(g1m_t **h);
|
|||
|
||||
/* Free-ing */
|
||||
void g1m_free_content(g1m_t *handle);
|
||||
void g1m_free_mcsfile_content(g1m_mcsfile_t *handle);
|
||||
void g1m_free_mcs(g1m_t *handle);
|
||||
void g1m_free_line_content(g1m_line_t *line);
|
||||
|
||||
|
|
|
@ -81,16 +81,17 @@ typedef struct g1m_mcs_cell_s {
|
|||
/* ************************************************************************** */
|
||||
/* mcs file head flags */
|
||||
# define g1m_mcsflag_unfinished 0x8000 /* is there still parts to read? */
|
||||
# define g1m_mcsflag_multiple 0x4000 /* is a group */
|
||||
# define g1m_mcsflag_complex 0x0001 /* is a complex variable */
|
||||
|
||||
/* mcs file type -- what type of raw information is there
|
||||
* e.g. `head.flags & g1m_mcsmask_info == g1m_mcsinfo_g1m` */
|
||||
# define g1m_mcsinfo(H) ((H)->flags & g1m_mcsmask_info)
|
||||
# define g1m_mcsmask_info 0x6000
|
||||
# define g1m_mcsmask_info 0x0600
|
||||
# define g1m_mcsinfo_none 0x0000
|
||||
# define g1m_mcsinfo_mcs 0x2000
|
||||
# define g1m_mcsinfo_cas 0x4000
|
||||
# define g1m_mcsinfo_caspro 0x6000
|
||||
# define g1m_mcsinfo_mcs 0x0200
|
||||
# define g1m_mcsinfo_cas 0x0400
|
||||
# define g1m_mcsinfo_caspro 0x0600
|
||||
|
||||
/* mcs file head */
|
||||
typedef struct g1m_mcshead_s {
|
||||
|
|
|
@ -41,60 +41,6 @@ void g1m_free_line_content(g1m_line_t *line)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_free_mcsfile_content:
|
||||
* Free an MCS file handle content.
|
||||
*
|
||||
* @arg handle the handle which has the content to free.
|
||||
*/
|
||||
|
||||
void g1m_free_mcsfile_content(g1m_mcsfile_t *handle)
|
||||
{
|
||||
unsigned int type = handle->head.type;
|
||||
|
||||
/* free content for unknown files */
|
||||
if (!type)
|
||||
free(handle->content);
|
||||
|
||||
/* free cells */
|
||||
if (type & (g1m_mcstype_mat | g1m_mcstype_vct | g1m_mcstype_list
|
||||
| g1m_mcstype_spreadsheet)
|
||||
&& handle->head.width && handle->head.height) {
|
||||
free(handle->cells[0]);
|
||||
free(handle->cells);
|
||||
}
|
||||
|
||||
/* free the images */
|
||||
if ((type & (g1m_mcstype_pict | g1m_mcstype_capt))) {
|
||||
for (int i = 0; i < handle->head.count; i++)
|
||||
free(handle->pics[i]);
|
||||
if (handle->pics != &handle->pic)
|
||||
free(handle->pics);
|
||||
}
|
||||
|
||||
/* free the vars */
|
||||
if ((type & g1m_mcstype_alphamem)
|
||||
&& handle->vars != &handle->var)
|
||||
free(handle->vars);
|
||||
|
||||
/* free the content */
|
||||
if (type & (g1m_mcstype_program | g1m_mcstype_setup))
|
||||
free(handle->content);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_free_mcsfile:
|
||||
* Free an MCS file handle.
|
||||
*
|
||||
* @arg handle the handle to free.
|
||||
*/
|
||||
|
||||
void g1m_free_mcsfile(g1m_mcsfile_t *handle)
|
||||
{
|
||||
g1m_free_mcsfile_content(handle);
|
||||
free(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_free_mcs:
|
||||
* Free all of the MCS.
|
||||
|
|
118
src/decode/cas.c
118
src/decode/cas.c
|
@ -21,24 +21,32 @@
|
|||
* ************************************************************************** */
|
||||
#include <libg1m/internals.h>
|
||||
#define FUNC(NAME) g1m_decode_caspart_##NAME
|
||||
#define HFUNC(NAME) g1m_decode_cashpart_##NAME
|
||||
#define READCOLON() { \
|
||||
uint8_t colon; GREAD(&colon, 1) \
|
||||
err = g1m_error_magic; \
|
||||
if (colon != ':') goto fail; }
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Type correspondance list */
|
||||
/* ************************************************************************** */
|
||||
/* Part parsing function type */
|
||||
typedef int (*cas_decode_function)(g1m_mcsfile_t*, g1m_buffer_t*);
|
||||
typedef int (*cas_heads_decode_function)(g1m_mcshead_t *head,
|
||||
g1m_mcshead_t *heads, g1m_buffer_t *buffer);
|
||||
|
||||
/* Correspondance type */
|
||||
struct cas_corresp {
|
||||
unsigned int type;
|
||||
cas_decode_function decode;
|
||||
cas_heads_decode_function hdecode;
|
||||
};
|
||||
|
||||
/* All correspondances */
|
||||
#define TTERM {0, NULL}
|
||||
#define TTERM {0, NULL, NULL}
|
||||
static struct cas_corresp cas_types[] = {
|
||||
{g1m_mcstype_var, FUNC(var)},
|
||||
{g1m_mcstype_program, FUNC(program)},
|
||||
{g1m_mcstype_var, FUNC(var), NULL},
|
||||
{g1m_mcstype_program, FUNC(program), HFUNC(program)},
|
||||
TTERM
|
||||
};
|
||||
|
||||
|
@ -50,7 +58,7 @@ static struct cas_corresp cas_types[] = {
|
|||
* @return the function (NULL if not found).
|
||||
*/
|
||||
|
||||
static cas_decode_function lookup_cas_decode(g1m_mcstype_t type)
|
||||
static void *lookup_cas_decode(g1m_mcstype_t type, int heads)
|
||||
{
|
||||
/* lookup for the type */
|
||||
struct cas_corresp *c = cas_types;
|
||||
|
@ -61,7 +69,7 @@ static cas_decode_function lookup_cas_decode(g1m_mcstype_t type)
|
|||
}
|
||||
|
||||
/* return the function */
|
||||
return (c->decode);
|
||||
return (heads ? (void*)c->hdecode : (void*)c->decode);
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
|
@ -126,6 +134,7 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer)
|
|||
{
|
||||
/* check that the head exists */
|
||||
if (!head) return (-1);
|
||||
memset(head, 0, sizeof(g1m_mcshead_t));
|
||||
|
||||
/* read beginning of the header, try to guess a newer header */
|
||||
uint8_t buf[49]; READ(buf, 7)
|
||||
|
@ -160,6 +169,30 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer)
|
|||
/* ************************************************************************** */
|
||||
/* Part decoding functions */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* g1m_decode_casfiles_part:
|
||||
* Decode the CASIOLINK group parts.
|
||||
*
|
||||
* @arg head the general head.
|
||||
* @arg heads the heads to contribute to.
|
||||
* @arg buffer the buffer to read from.
|
||||
* @return the error that occurred (0 if ok).
|
||||
*/
|
||||
|
||||
int g1m_decode_casfiles_part(g1m_mcshead_t *head, g1m_mcshead_t *heads,
|
||||
g1m_buffer_t *buffer)
|
||||
{
|
||||
/* look for the decoding function */
|
||||
cas_heads_decode_function decode = (void*)lookup_cas_decode(head->type, 1);
|
||||
if (!decode) {
|
||||
log_error("No dedicated decoding function was found for this type!");
|
||||
return (g1m_error_unknown);
|
||||
}
|
||||
|
||||
/* decode the part */
|
||||
return ((*decode)(head, heads, buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_decode_casfile_part:
|
||||
* Decode a CASIOLINK Protocol content part.
|
||||
|
@ -175,7 +208,7 @@ int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer)
|
|||
if (!file) return (g1m_error_op);
|
||||
|
||||
/* look for the decoding function */
|
||||
cas_decode_function decode = lookup_cas_decode(file->head.type);
|
||||
cas_decode_function decode = (void*)lookup_cas_decode(file->head.type, 0);
|
||||
if (!decode) {
|
||||
log_error("No dedicated decoding function was found for this type!");
|
||||
return (g1m_error_unknown);
|
||||
|
@ -192,7 +225,8 @@ int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer)
|
|||
* g1m_decode_cas:
|
||||
* Decode a CAS file. TODO.
|
||||
*
|
||||
* The colon ':' (0x3A) is already read at this point.
|
||||
* Is also sort of a guide for using the CAS MCS files.
|
||||
* The colon ':' (0x3A) is already read at this point (CAS file id.).
|
||||
*
|
||||
* @arg handle the handle to create.
|
||||
* @arg buffer the buffer to read from.
|
||||
|
@ -213,14 +247,32 @@ int g1m_decode_cas(g1m_t *handle, g1m_buffer_t *buffer,
|
|||
/* read each */
|
||||
for (handle->count = 0;;) {
|
||||
/* read the head */
|
||||
log_info("Reading file head #%d", handle->count);
|
||||
g1m_mcshead_t head;
|
||||
log_info("Reading the next head.");
|
||||
g1m_mcshead_t head = {};
|
||||
if ((err = g1m_decode_casfile_head(&head, buffer))) goto fail;
|
||||
if (head.type == g1m_mcstype_end) break;
|
||||
|
||||
/* heads up! */
|
||||
int numheads = head.flags & g1m_mcsflag_multiple ? head.count : 1;
|
||||
g1m_mcshead_t heads[numheads];
|
||||
if (head.flags & g1m_mcsflag_multiple) {
|
||||
log_info("Is a head for multiple files!");
|
||||
g1m_prepare_mcsfile_heads(&head, heads);
|
||||
while (head.flags & g1m_mcsflag_unfinished) {
|
||||
READCOLON()
|
||||
|
||||
/* decode a general part */
|
||||
err = g1m_decode_casfiles_part(&head, heads, buffer);
|
||||
if (err) goto fail;
|
||||
}
|
||||
} else
|
||||
heads[0] = head;
|
||||
|
||||
/* prepare space in the index */
|
||||
if (handle->count == handle->_size) {
|
||||
int newsize = handle->_size + 4;
|
||||
int required_size = handle->count
|
||||
+ (head.flags & g1m_mcsflag_multiple) ? head.count : 1;
|
||||
if (required_size > handle->_size) {
|
||||
int newsize = required_size + 2;
|
||||
log_info("index not big enough, allocating from %d to %d slots",
|
||||
handle->_size, newsize);
|
||||
|
||||
|
@ -238,33 +290,31 @@ int g1m_decode_cas(g1m_t *handle, g1m_buffer_t *buffer,
|
|||
handle->_size = newsize;
|
||||
}
|
||||
|
||||
/* prepare the file */
|
||||
log_info("Preparing the file.");
|
||||
err = g1m_make_mcsfile(&handle->files[handle->count], &head);
|
||||
if (err) goto fail;
|
||||
|
||||
/* read each part */
|
||||
g1m_mcsfile_t *file = handle->files[handle->count]; handle->count++;
|
||||
#if LOGLEVEL <= ll_info
|
||||
for (int j = 1; file->head.flags & g1m_mcsflag_unfinished; j++) {
|
||||
#else
|
||||
while (file->head.flags & g1m_mcsflag_unfinished) {
|
||||
#endif
|
||||
log_info("Reading part #%d", j);
|
||||
/* read the colon */
|
||||
uint8_t colon; GREAD(&colon, 1)
|
||||
err = g1m_error_magic;
|
||||
if (colon != ':') goto fail;
|
||||
|
||||
/* read the part */
|
||||
err = g1m_decode_casfile_part(file, buffer);
|
||||
for (int i = 0; i < numheads; i++) {
|
||||
/* prepare the file */
|
||||
log_info("Preparing the group file #%d", i);
|
||||
err = g1m_make_mcsfile(&handle->files[handle->count], &heads[i]);
|
||||
if (err) goto fail;
|
||||
g1m_mcsfile_t *file = handle->files[handle->count]; handle->count++;
|
||||
|
||||
/* read each part */
|
||||
#if LOGLEVEL <= ll_info
|
||||
for (int j = 1; file->head.flags & g1m_mcsflag_unfinished; j++) {
|
||||
#else
|
||||
while (file->head.flags & g1m_mcsflag_unfinished) {
|
||||
#endif
|
||||
/* initialize */
|
||||
log_info("Reading part #%d", j);
|
||||
READCOLON()
|
||||
|
||||
/* read the part */
|
||||
err = g1m_decode_casfile_part(file, buffer);
|
||||
if (err) goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* read first colon of the next part */
|
||||
err = g1m_error_magic;
|
||||
uint8_t nextcolon; GREAD(&nextcolon, 1)
|
||||
if (nextcolon != ':') goto fail;
|
||||
READCOLON()
|
||||
}
|
||||
|
||||
/* everything went well :) */
|
||||
|
|
|
@ -80,11 +80,18 @@ int g1m_decode_mcs_matrix(g1m_mcsfile_t **handle, g1m_buffer_t *buffer,
|
|||
for (uint_fast32_t y = 0; y < h; y++)
|
||||
for (uint_fast32_t x = 0; x < w; x++) {
|
||||
g1m_bcdtoa(&tab[y][x].real, rbuf, G1M_BCD_GOODBUFSIZE);
|
||||
|
||||
if (g1m_bcd_has_special(&tab[y][x].real)) {
|
||||
g1m_bcdtoa(&tab[y][x].imgn, ibuf, G1M_BCD_GOODBUFSIZE);
|
||||
log_info("[%" PRIuFAST32 "] %si + %s", y, ibuf, rbuf);
|
||||
g1m_bcd_t ibcd = tab[y][x].imgn;
|
||||
int ch = g1m_bcd_is_negative(&ibcd) ? '-' : '+';
|
||||
ibcd.flags &= ~g1m_bcdflag_neg;
|
||||
|
||||
g1m_bcdtoa(&ibcd, ibuf, G1M_BCD_GOODBUFSIZE);
|
||||
log_info("[%" PRIuFAST32 "][%" PRIuFAST32 "] %s %c %si",
|
||||
y, x, rbuf, ch, ibuf);
|
||||
} else
|
||||
log_info("[%" PRIuFAST32 "] %s", y, rbuf);
|
||||
log_info("[%" PRIuFAST32 "][%" PRIuFAST32 "] %s",
|
||||
y, x, rbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -59,6 +59,41 @@ fail:
|
|||
return (err);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_decode_cashpart_program:
|
||||
* Decode a CAS heads program part.
|
||||
*
|
||||
* @arg head the general head.
|
||||
* @arg heads the heads to contribute to.
|
||||
* @arg buffer the buffer to read from.
|
||||
* @return the error code (0 if ok).
|
||||
*/
|
||||
|
||||
int g1m_decode_cashpart_program(g1m_mcshead_t *head, g1m_mcshead_t *heads,
|
||||
g1m_buffer_t *buffer)
|
||||
{
|
||||
/* get content */
|
||||
struct cas_spe_program headers[head->count];
|
||||
READ(headers, sizeof(struct cas_spe_program) * head->count)
|
||||
|
||||
/* check the sum */
|
||||
uint8_t checksum; READ(&checksum, 1)
|
||||
uint8_t csum = ~g1m_checksum8(headers,
|
||||
sizeof(struct cas_spe_program) * head->count) + 1;
|
||||
if (csum != checksum)
|
||||
return (g1m_error_checksum);
|
||||
|
||||
/* initialize */
|
||||
for (int i = 0; i < head->count; i++) {
|
||||
heads[i].size = be16toh(headers[i].length);
|
||||
/* program type? */
|
||||
}
|
||||
|
||||
/* everything went well :D */
|
||||
head->flags &= ~g1m_mcsflag_unfinished;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_decode_caspart_program:
|
||||
* Decode a CAS program part.
|
||||
|
|
102
src/manage/mcs.c
102
src/manage/mcs.c
|
@ -19,108 +19,6 @@
|
|||
#include <libg1m/internals.h>
|
||||
#define MCS_CHUNK_SIZE 16
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Allocate files and content */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* act differently according to the context */
|
||||
switch (head->type) {
|
||||
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_mcs_cell_t*) * ht);
|
||||
if (!h->cells) goto fail;
|
||||
h->cells[0] = malloc(sizeof(g1m_mcs_cell_t) * wd * ht);
|
||||
if (!h->cells[0]) { free(h->cells); goto fail; }
|
||||
|
||||
for (unsigned int y = 1; y < ht; y++)
|
||||
h->cells[y] = &h->cells[0][h->head.width * y];
|
||||
}
|
||||
break;
|
||||
|
||||
case g1m_mcstype_var:
|
||||
if (head->count <= 1) h->vars = &h->var;
|
||||
else {
|
||||
h->vars = malloc(sizeof(g1m_mcs_cell_t) * head->count);
|
||||
if (!h->vars) goto fail;
|
||||
memset(h->vars, 0, sizeof(g1m_mcs_cell_t) * head->count);
|
||||
}
|
||||
break;
|
||||
|
||||
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 (int i = 0; i < head->count; i++) {
|
||||
h->pics[i] = alloc_pixels(head->width, head->height);
|
||||
if (!h->pics[i]) {
|
||||
for (int j = 0; j < i; j++)
|
||||
free(h->pics[j]);
|
||||
if (h->pics != &h->pic)
|
||||
free(h->pics);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* prepare */
|
||||
for (int i = 0; i < head->count; i++)
|
||||
prepare_pixels(h->pics[i], head->width, head->height)
|
||||
break;
|
||||
|
||||
case g1m_mcstype_end:
|
||||
break;
|
||||
|
||||
/* those are TEMPORARY XXX */
|
||||
case g1m_mcstype_string:
|
||||
break;
|
||||
|
||||
default:
|
||||
h->content = malloc(head->size);
|
||||
if (!h->content) goto fail;
|
||||
break;
|
||||
}
|
||||
|
||||
/* finish */
|
||||
return (0);
|
||||
fail:
|
||||
free(h);
|
||||
*handle = NULL;
|
||||
return (g1m_error_alloc);
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Internal functions */
|
||||
/* ************************************************************************** */
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
/* *****************************************************************************
|
||||
* manage/mcsfile.c -- manage an MCS file.
|
||||
* 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_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)
|
||||
{
|
||||
/* 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_mcs_cell_t*) * ht);
|
||||
if (!h->cells) goto fail;
|
||||
h->cells[0] = malloc(sizeof(g1m_mcs_cell_t) * wd * ht);
|
||||
if (!h->cells[0]) { free(h->cells); goto fail; }
|
||||
|
||||
for (unsigned int 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_mcs_cell_t) * head->count);
|
||||
if (!h->vars) goto fail;
|
||||
memset(h->vars, 0, sizeof(g1m_mcs_cell_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 (int i = 0; i < head->count; i++) {
|
||||
h->pics[i] = alloc_pixels(head->width, head->height);
|
||||
if (!h->pics[i]) {
|
||||
for (int j = 0; j < i; j++)
|
||||
free(h->pics[j]);
|
||||
if (h->pics != &h->pic)
|
||||
free(h->pics);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* prepare */
|
||||
for (int 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_string: /* TEMPORARY XXX */
|
||||
break;
|
||||
|
||||
/* allocate raw content */
|
||||
default:
|
||||
h->content = malloc(head->size);
|
||||
if (!h->content) goto fail;
|
||||
break;
|
||||
}
|
||||
|
||||
/* finish */
|
||||
return (0);
|
||||
fail:
|
||||
free(h);
|
||||
*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)
|
||||
{
|
||||
/* 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 (int 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)
|
||||
{
|
||||
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 (int 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_string: /* TEMPORARY XXX */
|
||||
break;
|
||||
|
||||
/* free the raw content */
|
||||
default:
|
||||
free(handle->content);
|
||||
}
|
||||
|
||||
/* free the content */
|
||||
free(handle);
|
||||
}
|
|
@ -26,43 +26,46 @@ struct type_corresp {
|
|||
/* identification */
|
||||
const char *datatype;
|
||||
|
||||
/* libg1m MCS file type */
|
||||
/* libg1m MCS file type, flags */
|
||||
g1m_mcstype_t type;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Correspondances */
|
||||
/* ************************************************************************** */
|
||||
/* All correspondances. Remarks:
|
||||
/* All correspondances found by Tom Wheeley and Tom Lynn. Remarks:
|
||||
* - Correspondances with a NULL data type means the data type isn't to be
|
||||
* read. */
|
||||
|
||||
#define TTERM {NULL, 0}
|
||||
#define TTERM {NULL, 0, 0}
|
||||
static struct type_corresp cas_groups[] = {
|
||||
/* not implemented yet types, described by Tom Wheeley and Tom Lynn */
|
||||
{"AA", 0}, // dynamic graph functions
|
||||
{"AD", 0}, // variable memory
|
||||
{"AL", 0}, // all
|
||||
{"AM", 0}, // alpha variable memory
|
||||
{"BU", 0}, // backup
|
||||
{"DM", 0}, // defined memory
|
||||
{"DD", 0}, // screenshot
|
||||
{"EN", 0}, // one editor file
|
||||
{"FN", 0}, // set of editor files
|
||||
{"F1", 0}, // one function memory
|
||||
{"F6", 0}, // set of function memories
|
||||
{"GA", 0}, // set of graph functions
|
||||
{"GF", 0}, // graph zoom factor (graph function?)
|
||||
{"GR", 0}, // graph range
|
||||
{"GT", 0}, // function table
|
||||
{"MA", 0}, // set of matrices
|
||||
{"PD", 0}, // polynomial equations
|
||||
{"P1", 0}, // one program
|
||||
{"PZ", 0}, // set of programs
|
||||
{"RT", 0}, // recursion table
|
||||
{"SD", 0}, // simultaneous equations
|
||||
{"SR", 0}, // linear regression data
|
||||
{"SS", 0}, // standard deviation data
|
||||
/* implemented */
|
||||
{"P1", g1m_mcstype_program, 0}, // one program
|
||||
{"PZ", g1m_mcstype_program, g1m_mcsflag_multiple}, // set of programs
|
||||
|
||||
/* not implemented yet */
|
||||
{"AA", 0, 0}, // dynamic graph functions
|
||||
{"AD", 0, 0}, // variable memory
|
||||
{"AL", 0, 0}, // all
|
||||
{"AM", 0, 0}, // alpha variable memory
|
||||
{"BU", 0, 0}, // backup
|
||||
{"DM", 0, 0}, // defined memory
|
||||
{"DD", 0, 0}, // screenshot
|
||||
{"EN", 0, 0}, // one editor file
|
||||
{"FN", 0, 0}, // set of editor files
|
||||
{"F1", 0, 0}, // one function memory
|
||||
{"F6", 0, 0}, // set of function memories
|
||||
{"GA", 0, 0}, // set of graph functions
|
||||
{"GF", 0, 0}, // graph zoom factor (graph function?)
|
||||
{"GR", 0, 0}, // graph range
|
||||
{"GT", 0, 0}, // function table
|
||||
{"MA", 0, 0}, // set of matrices
|
||||
{"PD", 0, 0}, // polynomial equations
|
||||
{"RT", 0, 0}, // recursion table
|
||||
{"SD", 0, 0}, // simultaneous equations
|
||||
{"SR", 0, 0}, // linear regression data
|
||||
{"SS", 0, 0}, // standard deviation data
|
||||
|
||||
/* terminating entry */
|
||||
TTERM
|
||||
|
@ -99,6 +102,7 @@ int g1m_maketype_cas(g1m_mcshead_t *head, const char *datatype)
|
|||
|
||||
/* fill in info and return */
|
||||
head->type = c->type;
|
||||
head->flags |= c->flags;
|
||||
return (0);
|
||||
|
||||
notfound:
|
||||
|
|
Reference in New Issue