#include <libpspp/pool.h>
#include <libpspp/str.h>
+#include "minmax.h"
#include "xalloc.h"
#include "gettext.h"
char *trans; /* 256-byte character set translation table. */
int var_cnt; /* Number of variables. */
int weight_index; /* 0-based index of weight variable, or -1. */
- int *widths; /* Variable widths, 0 for numeric. */
- size_t value_cnt; /* Number of `value's per case. */
+ struct caseproto *proto; /* Format of output cases. */
bool ok; /* Set false on I/O error. */
};
r->weight_index = -1;
r->trans = NULL;
r->var_cnt = 0;
- r->widths = NULL;
- r->value_cnt = 0;
+ r->proto = NULL;
r->ok = true;
if (setjmp (r->bail_out))
goto error;
if (!match (r, 'F'))
error (r, _("Data record expected."));
- r->value_cnt = dict_get_next_value_idx (*dict);
- return casereader_create_sequential (NULL, r->value_cnt, CASENUMBER_MAX,
+ r->proto = caseproto_ref_pool (dict_get_proto (*dict), r->pool);
+ return casereader_create_sequential (NULL, r->proto, CASENUMBER_MAX,
&por_file_casereader_class, r);
error:
return fmt_default_for_width (var_get_width (v));
}
-static union value parse_value (struct pfm_reader *, struct variable *);
+static void parse_value (struct pfm_reader *, int width, union value *);
/* Read information on all the variables. */
static void
r->var_cnt = read_int (r);
if (r->var_cnt <= 0)
error (r, _("Invalid number of variables %d."), r->var_cnt);
- r->widths = pool_nalloc (r->pool, r->var_cnt, sizeof *r->widths);
/* Purpose of this value is unknown. It is typically 161. */
read_int (r);
width = read_int (r);
if (width < 0)
error (r, _("Invalid variable width %d."), width);
- r->widths[i] = width;
read_string (r, name);
for (j = 0; j < 6; j++)
var_set_write_format (v, &write);
/* Range missing values. */
- mv_init (&miss, var_get_width (v));
+ mv_init (&miss, width);
if (match (r, 'B'))
{
double x = read_float (r);
/* Single missing values. */
while (match (r, '8'))
{
- union value value = parse_value (r, v);
+ int mv_width = MIN (width, 8);
+ union value value;
+
+ parse_value (r, mv_width, &value);
+ value_resize (&value, mv_width, width);
mv_add_value (&miss, &value);
+ value_destroy (&value, width);
}
var_set_missing_values (v, &miss);
+ mv_destroy (&miss);
if (match (r, 'C'))
{
}
}
-/* Parse a value for variable VV into value V. */
-static union value
-parse_value (struct pfm_reader *r, struct variable *vv)
+/* Parse a value of with WIDTH into value V. */
+static void
+parse_value (struct pfm_reader *r, int width, union value *v)
{
- union value v;
-
- if (var_is_alpha (vv))
+ value_init (v, width);
+ if (width > 0)
{
char string[256];
read_string (r, string);
- buf_copy_str_rpad (v.s, 8, string);
+ value_copy_str_rpad (v, width, string, ' ');
}
else
- v.f = read_float (r);
-
- return v;
+ v->f = read_float (r);
}
/* Parse a value label record and return success. */
char label[256];
int j;
- val = parse_value (r, v[0]);
+ parse_value (r, var_get_width (v[0]), &val);
read_string (r, label);
/* Assign the value label to each variable. */
for (j = 0; j < nv; j++)
- {
- struct variable *var = v[j];
+ var_replace_value_label (v[j], &val, label);
- if (!var_is_long_string (var))
- var_replace_value_label (var, &val, label);
- }
+ value_destroy (&val, var_get_width (v[0]));
}
}
struct pfm_reader *r = r_;
struct ccase *volatile c;
size_t i;
- size_t idx;
- c = case_create (casereader_get_value_cnt (reader));
+ c = case_create (r->proto);
setjmp (r->bail_out);
if (!r->ok)
{
return NULL;
}
- idx = 0;
for (i = 0; i < r->var_cnt; i++)
{
- int width = r->widths[i];
+ int width = caseproto_get_width (r->proto, i);
if (width == 0)
- {
- case_data_rw_idx (c, idx)->f = read_float (r);
- idx++;
- }
+ case_data_rw_idx (c, i)->f = read_float (r);
else
{
char string[256];
read_string (r, string);
- buf_copy_str_rpad (case_data_rw_idx (c, idx)->s, width, string);
- idx += DIV_RND_UP (width, MAX_SHORT_STRING);
+ buf_copy_str_rpad (case_str_rw_idx (c, i), width, string, ' ');
}
}