#include "data/short-names.h"
#include "data/value-labels.h"
#include "data/variable.h"
+#include "data/varset.h"
#include "libpspp/float-format.h"
#include "libpspp/i18n.h"
#include "libpspp/integer-format.h"
struct replace_file *rf; /* Ticket for replacing output file. */
enum any_compression compression;
- casenumber case_cnt; /* Number of cases written so far. */
+ casenumber n_cases; /* Number of cases written so far. */
uint8_t space; /* ' ' in the file's character encoding. */
/* Simple compression buffering.
/* Variables. */
struct sfm_var *sfm_vars; /* Variables. */
- size_t sfm_var_cnt; /* Number of variables. */
- size_t segment_cnt; /* Number of variables including extra segments
+ size_t sfm_n_vars; /* Number of variables. */
+ size_t n_segments; /* Number of variables including extra segments
for long string variables. */
};
static void write_long_string_missing_values (struct sfm_writer *,
const struct dictionary *);
+static void write_varsets (struct sfm_writer *, const struct dictionary *);
static void write_mrsets (struct sfm_writer *, const struct dictionary *,
bool pre_v14);
struct sfm_write_options opts)
{
struct encoding_info encoding_info;
- struct sfm_writer *w;
mode_t mode;
int i;
}
/* Create and initialize writer. */
- w = xzalloc (sizeof *w);
+ struct sfm_writer *w = XZALLOC (struct sfm_writer);
w->fh = fh_ref (fh);
w->lock = NULL;
w->file = NULL;
&& is_encoding_ebcdic_compatible (dict_get_encoding (d)))
w->compression = ANY_COMP_SIMPLE;
- w->case_cnt = 0;
+ w->n_cases = 0;
w->n_opcodes = w->n_elements = 0;
memset (w->cbuf[0], 0, 8);
data. Also count the number of segments. Very long strings
occupy multiple segments, otherwise each variable only takes
one segment. */
- w->segment_cnt = sfm_dictionary_to_sfm_vars (d, &w->sfm_vars,
- &w->sfm_var_cnt);
+ w->n_segments = sfm_dictionary_to_sfm_vars (d, &w->sfm_vars, &w->sfm_n_vars);
/* Open file handle as an exclusive writer. */
/* TRANSLATORS: this fragment will be interpolated into
/* Write basic variable info. */
short_names_assign (d);
- for (i = 0; i < dict_get_var_cnt (d); i++)
+ for (i = 0; i < dict_get_n_vars (d); i++)
write_variable (w, dict_get_var (d, i));
write_value_labels (w, d);
- if (dict_get_document_line_cnt (d) > 0)
+ if (dict_get_document_n_lines (d) > 0)
write_documents (w, d);
write_integer_info_record (w, d);
write_float_info_record (w);
+ write_varsets (w, d);
write_mrsets (w, d, true);
write_variable_display_parameters (w, d);
int i;
oct_idx = 0;
- for (i = 0; i < dict_get_var_cnt (d); i++)
+ for (i = 0; i < dict_get_n_vars (d); i++)
{
struct variable *var = dict_get_var (d, i);
if (var == target_var)
if (time (&t) == (time_t) -1)
{
creation_date = xstrdup ("01 Jan 70");
- creation_time = xstrdup ( "00:00:00");
+ creation_time = xstrdup ("00:00:00");
}
else
{
static void
write_format (struct sfm_writer *w, struct fmt_spec fmt, int width)
{
- assert (fmt_check_output (&fmt));
+ assert (fmt_check_output (fmt));
assert (sfm_width_to_segments (width) == 1);
if (width > 0)
write_variable (struct sfm_writer *w, const struct variable *v)
{
int width = var_get_width (v);
- int segment_cnt = sfm_width_to_segments (width);
+ int n_segments = sfm_width_to_segments (width);
int seg0_width = sfm_segment_alloc_width (width, 0);
const char *encoding = var_get_encoding (v);
int i;
Missing values for long string variables are written in a separate
record. */
+ enum { MAX_SHORT_STRING = 8 };
if (width <= MAX_SHORT_STRING)
{
const struct missing_values *mv = var_get_missing_values (v);
write_int (w, 0);
/* Print and write formats. */
- write_format (w, *var_get_print_format (v), seg0_width);
- write_format (w, *var_get_write_format (v), seg0_width);
+ write_format (w, var_get_print_format (v), seg0_width);
+ write_format (w, var_get_write_format (v), seg0_width);
/* Short name.
The full name is in a translation table written
write_variable_continuation_records (w, seg0_width);
/* Write additional segments for very long string variables. */
- for (i = 1; i < segment_cnt; i++)
+ for (i = 1; i < n_segments; i++)
{
int seg_width = sfm_segment_alloc_width (width, i);
struct fmt_spec fmt = fmt_for_output (FMT_A, MAX (seg_width, 1), 0);
hmap_init (&same_sets);
idx = 0;
- for (i = 0; i < dict_get_var_cnt (d); i++)
+ for (i = 0; i < dict_get_n_vars (d); i++)
{
struct variable *v = dict_get_var (d, i);
write_variable_attributes (struct sfm_writer *w, const struct dictionary *d)
{
struct string s = DS_EMPTY_INITIALIZER;
- size_t n_vars = dict_get_var_cnt (d);
+ size_t n_vars = dict_get_n_vars (d);
size_t n_attrsets = 0;
size_t i;
ds_destroy (&s);
}
+/* Write variable sets. */
+static void
+write_varsets (struct sfm_writer *w, const struct dictionary *dict)
+{
+ const char *encoding = dict_get_encoding (dict);
+
+ if (is_encoding_ebcdic_compatible (encoding))
+ {
+ /* FIXME. */
+ return;
+ }
+
+ size_t n_varsets = dict_get_n_varsets (dict);
+ if (n_varsets == 0)
+ return;
+
+ struct string s = DS_EMPTY_INITIALIZER;
+ for (size_t i = 0; i < n_varsets; i++)
+ {
+ const struct varset *varset = dict_get_varset (dict, i);
+
+ char *name = recode_string (encoding, "UTF-8", varset->name, -1);
+ ds_put_format (&s, "%s= ", name);
+ free (name);
+
+ for (size_t j = 0; j < varset->n_vars; j++)
+ {
+ if (j)
+ ds_put_byte (&s, ' ');
+
+ const char *name_utf8 = var_get_name (varset->vars[j]);
+ char *name = recode_string (encoding, "UTF-8", name_utf8, -1);
+ ds_put_cstr (&s, name);
+ free (name);
+ }
+ ds_put_byte (&s, '\n');
+ }
+
+ if (!ds_is_empty (&s))
+ write_string_record (w, ds_ss (&s), 5);
+ ds_destroy (&s);
+}
+
/* Write multiple response sets. If PRE_V14 is true, writes sets supported by
SPSS before release 14, otherwise writes sets supported only by later
versions. */
if (mrset->width == 0)
counted = xasprintf ("%.0f", mrset->counted.f);
else
- counted = xmemdup0 (value_str (&mrset->counted, mrset->width),
- mrset->width);
+ counted = xmemdup0 (mrset->counted.s, mrset->width);
ds_put_format (&s, "%zu %s", strlen (counted), counted);
free (counted);
}
write_int (w, 7); /* Record type. */
write_int (w, 11); /* Record subtype. */
write_int (w, 4); /* Data item (int32) size. */
- write_int (w, w->segment_cnt * 3); /* Number of data items. */
+ write_int (w, w->n_segments * 3); /* Number of data items. */
- for (i = 0; i < dict_get_var_cnt (dict); ++i)
+ for (i = 0; i < dict_get_n_vars (dict); ++i)
{
struct variable *v = dict_get_var (dict, i);
int width = var_get_width (v);
- int segment_cnt = sfm_width_to_segments (width);
+ int n_segments = sfm_width_to_segments (width);
int measure = (var_get_measure (v) == MEASURE_NOMINAL ? 1
: var_get_measure (v) == MEASURE_ORDINAL ? 2
: 3);
: 2);
int i;
- for (i = 0; i < segment_cnt; i++)
+ for (i = 0; i < n_segments; i++)
{
int width_left = width - sfm_segment_effective_offset (width, i);
write_int (w, measure);
int i;
ds_init_empty (&map);
- for (i = 0; i < dict_get_var_cnt (dict); ++i)
+ for (i = 0; i < dict_get_n_vars (dict); ++i)
{
const struct variable *v = dict_get_var (dict, i);
if (sfm_width_to_segments (var_get_width (v)) > 1)
const struct dictionary *dict)
{
const char *encoding = dict_get_encoding (dict);
- size_t n_vars = dict_get_var_cnt (dict);
+ size_t n_vars = dict_get_n_vars (dict);
size_t size, i;
- off_t start UNUSED;
/* Figure out the size in advance. */
size = 0;
write_int (w, 1); /* Data item (byte) size. */
write_int (w, size); /* Number of data items. */
- start = ftello (w->file);
for (i = 0; i < n_vars; i++)
{
struct variable *var = dict_get_var (dict, i);
size_t len;
write_int (w, width);
- write_bytes (w, value_str (val_lab_get_value (val_lab), width),
- width);
+ write_bytes (w, val_lab_get_value (val_lab)->s, width);
label = recode_string (var_get_encoding (var), "UTF-8",
val_lab_get_escaped_label (val_lab), -1);
free (label);
}
}
- assert (ftello (w->file) == start + size);
}
static void
const struct dictionary *dict)
{
const char *encoding = dict_get_encoding (dict);
- size_t n_vars = dict_get_var_cnt (dict);
+ size_t n_vars = dict_get_n_vars (dict);
size_t size, i;
- off_t start UNUSED;
/* Figure out the size in advance. */
size = 0;
size += 4;
size += recode_string_len (encoding, "UTF-8", var_get_name (var), -1);
size += 1;
- size += mv_n_values (mv) * (4 + 8);
+ size += 4;
+ size += mv_n_values (mv) * 8;
}
if (size == 0)
return;
write_int (w, 1); /* Data item (byte) size. */
write_int (w, size); /* Number of data items. */
- start = ftello (w->file);
for (i = 0; i < n_vars; i++)
{
struct variable *var = dict_get_var (dict, i);
n_missing_values = mv_n_values (mv);
write_bytes (w, &n_missing_values, 1);
+ write_int (w, 8);
+
for (j = 0; j < n_missing_values; j++)
{
const union value *value = mv_get_value (mv, j);
-
- write_int (w, 8);
- write_bytes (w, value_str (value, width), 8);
+ write_bytes (w, value->s, 8);
}
}
- assert (ftello (w->file) == start + size);
}
static void
size_t i;
ds_init_empty (&map);
- for (i = 0; i < dict_get_var_cnt (dict); i++)
+ for (i = 0; i < dict_get_n_vars (dict); i++)
{
struct variable *v = dict_get_var (dict, i);
if (i)
return;
}
- w->case_cnt++;
+ w->n_cases++;
if (w->compression == ANY_COMP_NONE)
write_case_uncompressed (w, c);
/* Seek back to the beginning and update the number of cases.
This is just a courtesy to later readers, so there's no need
to check return values or report errors. */
- if (ok && w->case_cnt <= INT32_MAX && !fseeko (w->file, 80, SEEK_SET))
+ if (ok && w->n_cases <= INT32_MAX && !fseeko (w->file, 80, SEEK_SET))
{
- write_int (w, w->case_cnt);
+ write_int (w, w->n_cases);
clearerr (w->file);
}
{
size_t i;
- for (i = 0; i < w->sfm_var_cnt; i++)
+ for (i = 0; i < w->sfm_n_vars; i++)
{
struct sfm_var *v = &w->sfm_vars[i];
{
size_t i;
- for (i = 0; i < w->sfm_var_cnt; i++)
+ for (i = 0; i < w->sfm_n_vars; i++)
{
struct sfm_var *v = &w->sfm_vars[i];
write_float (w, value->f);
else
{
- write_bytes (w, value_str (value, width), width);
+ write_bytes (w, value->s, width);
write_zeros (w, 8 - width);
}
}