step->step_type = RECODE_BYTE_TO_STRING;
step->step_table = table;
+ step->step_table_term_routine = free;
return true;
}
#include "common.h"
#include "hash.h"
-/* FIXME: Cleanup memory at end of job, and softly report errors. */
+/* FIXME: Softly report errors. */
/* The satisfactory aspects are that Recode is now able to combine a set of
sequence of UCS-2 characters into single codes, or explode those single
return false;
step->step_type = RECODE_EXPLODE_STEP;
step->step_table = table;
+ step->step_table_term_routine = (void (*) (void *)) hash_free;
if (!data)
return true;
state_free (void *void_state)
{
struct state *state = (struct state *) void_state;
- struct state *shift = (struct state *) state->shift;
+ struct state *shift = state->shift;
while (shift != NULL)
{
struct state *next_shift = shift->next;
- free (shift);
+ state_free (shift);
shift = next_shift;
}
free (state);
return false;
step->step_type = RECODE_COMBINE_STEP;
step->step_table = table;
+ step->step_table_term_routine = (void (*) (void *)) hash_free;
if (!data)
return true;
step->step_table)
{
step->step_type = RECODE_BYTE_TO_BYTE;
+ step->step_table_term_routine = free;
return true;
}
else
step->step_table)
{
step->step_type = RECODE_BYTE_TO_BYTE;
+ step->step_table_term_routine = free;
return true;
}
else
step->step_table)
{
step->step_type = RECODE_BYTE_TO_BYTE;
+ step->step_table_term_routine = free;
return true;
}
else
step->step_type = RECODE_UCS2_TO_STRING;
step->step_table = table;
+ step->step_table_term_routine = (void (*) (void *)) hash_free;
return true;
}
step->step_type = RECODE_STRING_TO_UCS2;
step->step_table = table;
+ step->step_table_term_routine = (void (*) (void *)) hash_free;
return true;
}
free (check_output_buffer);
}
+
+ iconv_close (check_conversion);
}
/* Invalid or untranslatable input. Skip one byte. */
table[cursor->code] = cursor->string;
step->step_table = table;
+ step->step_table_term_routine = free;
return true;
}
step->step_type = RECODE_BYTE_TO_STRING;
step->step_table = table;
+ step->step_table_term_routine = free;
return true;
}
step->step_type = RECODE_BYTE_TO_STRING;
step->step_table = table;
+ step->step_table_term_routine = free;
return true;
}
table[cursor->code] = cursor->string;
step->step_table = table;
+ step->step_table_term_routine = free;
return true;
}
step->step_type = RECODE_BYTE_TO_STRING;
step->step_table = table;
+ step->step_table_term_routine = free;
return true;
}
step->step_type = RECODE_BYTE_TO_STRING;
step->step_table = table;
+ step->step_table_term_routine = free;
return true;
}
{
void *result;
- result = malloc (size);
+ result = calloc (1, size);
if (!result)
recode_error (outer, _("Virtual memory exhausted"));
memcpy (table, reverse ? right_table : left_table, 256);
step->step_type = RECODE_BYTE_TO_BYTE;
step->step_table = table;
+ step->step_table_term_routine = free;
/* Upgrade step quality to reversible. */
step->transform_routine = transform_byte_to_variable;
step->step_type = RECODE_BYTE_TO_STRING;
step->step_table = table2;
+ step->step_table_term_routine = free;
}
return true;
| Recode a file from double byte UCS-2 characters to one byte characters. |
`-------------------------------------------------------------------------*/
+struct ucs2_to_byte
+ {
+ recode_ucs2 code; /* UCS-2 value */
+ unsigned char byte; /* corresponding byte */
+ };
+
+struct ucs2_to_byte_local
+ {
+ Hash_table *table;
+ struct ucs2_to_byte *data;
+ };
+
static size_t
ucs2_to_byte_hash (const void *void_data, size_t table_size)
{
return first->code == second->code;
}
+static bool
+term_ucs2_to_byte (RECODE_STEP step)
+{
+ hash_free (((struct ucs2_to_byte_local *) step->local)->table);
+ free (((struct ucs2_to_byte_local *) step->local)->data);
+ free (step->local);
+ return true;
+}
+
bool
init_ucs2_to_byte (RECODE_STEP step,
RECODE_CONST_REQUEST request,
}
}
- step->local = table;
+ if (!ALLOC (step->local, 1, struct ucs2_to_byte_local))
+ {
+ hash_free (table);
+ free (data);
+ return false;
+ }
+ ((struct ucs2_to_byte_local *) step->local)->table = table;
+ ((struct ucs2_to_byte_local *) step->local)->data = data;
+
+ step->term_routine = term_ucs2_to_byte;
return true;
}
bool
transform_ucs2_to_byte (RECODE_SUBTASK subtask)
{
- Hash_table *table = (Hash_table *) subtask->step->local;
+ Hash_table *table = ((struct ucs2_to_byte_local *) subtask->step->local)->table;
struct ucs2_to_byte lookup;
struct ucs2_to_byte *entry;
unsigned input_value; /* current UCS-2 character */
typedef bool (*Recode_init) (RECODE_STEP, RECODE_CONST_REQUEST,
RECODE_CONST_OPTION_LIST,
RECODE_CONST_OPTION_LIST);
-typedef bool (*Recode_term) (RECODE_STEP, RECODE_CONST_REQUEST);
+typedef bool (*Recode_term) (RECODE_STEP);
typedef bool (*Recode_transform) (RECODE_SUBTASK);
typedef bool (*Recode_fallback) (RECODE_SUBTASK, unsigned);
/* Recoding table. */
void *step_table;
+ void (*step_table_term_routine)(void *);
/* Step specific variables. */
void *local;
const short offset[256 / STRIP_SIZE];
};
-struct ucs2_to_byte
- {
- recode_ucs2 code; /* UCS-2 value */
- unsigned char byte; /* corresponding byte */
- };
-
struct ucs2_to_string
{
recode_ucs2 code; /* UCS-2 value */
step->before = single->before;
step->after = single->after;
step->step_table = single->initial_step_table;
+ step->step_table_term_routine = NULL;
step->step_type
= step->step_table ? RECODE_COMBINE_EXPLODE : RECODE_NO_STEP_TABLE;
step->transform_routine = single->transform_routine;
step->fallback_routine = single->fallback_routine;
+ step->term_routine = NULL;
if (single->init_routine)
{
pair_array, pair_cursor - pair_array, false, reversed);
}
+static bool
+delete_compressed_one_to_many (RECODE_STEP step)
+{
+ free (step->local);
+ return true;
+}
+
+static void
+delete_step (RECODE_STEP step)
+{
+ /* Run step destructor, and delete step_table if allocated. */
+ if (step->term_routine)
+ (*step->term_routine) (step);
+
+ if (step->step_table_term_routine != NULL)
+ (*step->step_table_term_routine) (step->step_table);
+}
+
/*---------------------------------------------------------------------.
| Optimize a SEQUENCE of single steps by creating new single steps, if |
| this can be done by merging adjacent steps which are simple enough. |
&& in[1].before == outer->ucs2_charset
&& in[1].after->data_type == RECODE_STRIP_DATA)
{
+ /* Free old steps before overwriting anything. */
+ delete_step (in);
+ delete_step (in + 1);
+
/* This is a double UCS-2 step. */
out->before = in[0].before;
out->after = in[1].after;
&& in[0].after == outer->iconv_pivot
&& in[1].before == outer->iconv_pivot)
{
+ /* Free old steps before overwriting anything. */
+ delete_step (in);
+ delete_step (in + 1);
+
/* This is a double `iconv' step. */
out->before = in[0].before;
out->after = in[1].after;
out->before = in->before;
out->after = in->after;
out->quality = in->quality;
- in++;
+ delete_step (in++);
/* Merge in all consecutive one-to-one recodings. */
out->after = in->after;
merge_qualities (&out->quality, in->quality);
- in++;
+ delete_step (in++);
saved_steps++;
}
free (accum);
out->step_type = RECODE_BYTE_TO_STRING;
out->step_table = string;
+ if (in->step_table_term_routine)
+ {
+ out->local = (void *) table; /* Save reference to old table for destructor. */
+ out->term_routine = delete_compressed_one_to_many;
+ }
+ out->step_table_term_routine = free;
out->transform_routine = transform_byte_to_variable;
out->after = in->after;
merge_qualities (&out->quality, in->quality);
{
request->sequence_length = 0;
saved_steps++;
+ delete_step (in);
}
/* Tell the user if something changed. */
bool
recode_delete_request (RECODE_REQUEST request)
{
+ for (RECODE_STEP step = request->sequence_array;
+ step < request->sequence_array + request->sequence_length;
+ step++)
+ delete_step (step);
free (request->sequence_array);
free (request->work_string);
free (request);
| Initialise the steps. |
`-----------------------*/
+static bool
+term_rfc1345 (RECODE_STEP step)
+{
+ free (step->local);
+ return true;
+}
+
static bool
init_rfc1345 (RECODE_CONST_REQUEST request,
RECODE_STEP step,
local->intro = '&';
step->local = local;
+ step->term_routine = term_rfc1345;
return true;
}