#include "value-labels.h"
#include "variable.h"
#include <libpspp/version.h>
+#include <minmax.h>
#include "gettext.h"
#define _(msgid) gettext (msgid)
int compress; /* 1=compressed, 0=not compressed. */
int case_cnt; /* Number of cases written so far. */
size_t flt64_cnt; /* Number of flt64 elements in case. */
+ bool has_vls; /* Does the dict have very long strings? */
/* Compression buffering. */
flt64 *buf; /* Buffered data. */
const struct dictionary *dict);
static void write_documents (struct sfm_writer *, const struct dictionary *);
-static int does_dict_need_translation (const struct dictionary *);
static inline int
var_flt64_cnt (const struct variable *v)
w->fh = fh;
w->file = fdopen (fd, "w");
- w->needs_translation = does_dict_need_translation (d);
+ w->needs_translation = dict_compacting_would_change (d);
w->compress = opts.compress;
w->case_cnt = 0;
w->flt64_cnt = 0;
+ w->has_vls = false;
w->buf = w->end = w->ptr = NULL;
w->x = w->y = NULL;
sv->width = dv->width;
/* spss compatibility nonsense */
if ( dv->width > MAX_LONG_STRING )
- sv->width = (dv->width / MAX_LONG_STRING) * (MAX_LONG_STRING + 1)
- + (dv->width % MAX_LONG_STRING) ;
+ w->has_vls = true;
+
sv->fv = dv->fv;
sv->flt64_cnt = var_flt64_cnt (dv);
}
goto error;
}
-/* Returns zero if dictionary D's cases are ordered in the
- natural manner, with the first variable followed by the
- second, and so on,
- nonzero otherwise. */
-static int
-does_dict_need_translation (const struct dictionary *d)
-{
- size_t case_idx;
- size_t i;
-
- case_idx = 0;
- for (i = 0; i < dict_get_var_cnt (d); i++)
- {
- struct variable *v = dict_get_var (d, i);
- if (v->fv != case_idx)
- return 1;
- case_idx += v->nv;
- }
- return 0;
-}
-
/* Returns value of X truncated to two least-significant digits. */
static int
rerange (int x)
struct string vls_length_map;
- ds_init (&vls_length_map, 12 * dict_get_var_cnt (dict));
+ ds_init_empty (&vls_length_map);
vls_hdr.rec_type = 7;
vls_hdr.subtype = 14;
if ( v->width <= MAX_LONG_STRING )
continue;
- ds_printf (&vls_length_map, "%s=%05d", v->short_name, v->width);
- ds_putc (&vls_length_map, '\0');
- ds_putc (&vls_length_map, '\t');
+ ds_put_format (&vls_length_map, "%s=%05d", v->short_name, v->width);
+ ds_put_char (&vls_length_map, '\0');
+ ds_put_char (&vls_length_map, '\t');
}
vls_hdr.n_elem = ds_length (&vls_length_map);
struct string long_name_map;
size_t i;
- ds_init (&long_name_map, 10 * dict_get_var_cnt (dict));
+ ds_init_empty (&long_name_map);
for (i = 0; i < dict_get_var_cnt (dict); i++)
{
struct variable *v = dict_get_var (dict, i);
if (i)
- ds_putc (&long_name_map, '\t');
- ds_printf (&long_name_map, "%s=%s", v->short_name, v->name);
+ ds_put_char (&long_name_map, '\t');
+ ds_put_format (&long_name_map, "%s=%s", v->short_name, v->name);
}
lv_hdr.rec_type = 7;
w->case_cnt++;
if (!w->needs_translation && !w->compress
- && sizeof (flt64) == sizeof (union value))
+ && sizeof (flt64) == sizeof (union value) && ! w->has_vls )
{
/* Fast path: external and internal representations are the
same and the dictionary is properly ordered. Write
memset(bounce_cur, ' ', v->flt64_cnt * sizeof (flt64));
if (v->width == 0)
- *bounce_cur = case_num (c, v->fv);
- else
{
- buf_copy_rpad((char*)bounce_cur, v->flt64_cnt * sizeof (flt64),
- case_data(c, v->fv)->s,
- v->width);
+ *bounce_cur = case_num (c, v->fv);
+ bounce_cur += v->flt64_cnt;
+ }
+ else
+ { int ofs = 0;
+ while (ofs < v->width)
+ {
+ int chunk = MIN (MAX_LONG_STRING, v->width - ofs);
+ int nv = DIV_RND_UP (chunk, sizeof (flt64));
+ buf_copy_rpad ((char *) bounce_cur, nv * sizeof (flt64),
+ case_data (c, v->fv)->s + ofs, chunk);
+ bounce_cur += nv;
+ ofs += chunk;
+ }
}
- bounce_cur += v->flt64_cnt;
+
}
if (!w->compress)