{
struct matrix_state *state;
struct file_handle *file;
+ char *encoding;
struct stringi_set rowtypes;
}
mget;
for (size_t j = 0; j < sizeof values / sizeof *values; j++)
pivot_table_put2 (table, j, i, pivot_value_new_integer (values[j]));
}
+ free (vars);
pivot_table_submit (table);
}
\f
}
static void
-matrix_cmd_execute_get__ (struct get_command *get,
- const struct dictionary *dict,
- struct casereader *reader)
+matrix_cmd_execute_get__ (struct get_command *get, struct casereader *reader,
+ const struct dictionary *dict)
{
struct variable **vars;
size_t n_vars = 0;
free (vars);
}
-static void
-matrix_cmd_execute_get (struct get_command *get)
+static bool
+matrix_open_casereader (const char *command_name,
+ struct file_handle *file, const char *encoding,
+ struct dataset *dataset,
+ struct casereader **readerp, struct dictionary **dictp)
{
- struct dictionary *dict;
- struct casereader *reader;
- if (get->file)
+ if (file)
{
- reader = any_reader_open_and_decode (get->file, get->encoding,
- &dict, NULL);
- if (!reader)
- return;
+ *readerp = any_reader_open_and_decode (file, encoding, dictp, NULL);
+ return *readerp != NULL;
}
else
{
- if (dict_get_var_cnt (dataset_dict (get->dataset)) == 0)
+ if (dict_get_var_cnt (dataset_dict (dataset)) == 0)
{
- msg (ME, _("GET cannot read empty active file."));
- return;
+ msg (ME, _("The %s command cannot read empty active file."),
+ command_name);
+ return false;
}
- reader = proc_open (get->dataset);
- dict = dict_ref (dataset_dict (get->dataset));
+ *readerp = proc_open (dataset);
+ *dictp = dict_ref (dataset_dict (dataset));
+ return true;
}
+}
- matrix_cmd_execute_get__ (get, dict, reader);
-
+static void
+matrix_close_casereader (struct file_handle *file, struct dataset *dataset,
+ struct casereader *reader, struct dictionary *dict)
+{
dict_unref (dict);
casereader_destroy (reader);
- if (!get->file)
- proc_commit (get->dataset);
+ if (!file)
+ proc_commit (dataset);
+}
+
+static void
+matrix_cmd_execute_get (struct get_command *get)
+{
+ struct casereader *r;
+ struct dictionary *d;
+ if (matrix_open_casereader ("GET", get->file, get->encoding, get->dataset,
+ &r, &d))
+ {
+ matrix_cmd_execute_get__ (get, r, d);
+ matrix_close_casereader (get->file, get->dataset, r, d);
+ }
}
\f
static const char *
matrix_parse_mget (struct matrix_state *s)
{
struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
- *cmd = (struct matrix_cmd) { .type = MCMD_MGET, .mget = { .state = s } };
+ *cmd = (struct matrix_cmd) {
+ .type = MCMD_MGET,
+ .mget = {
+ .state = s,
+ .rowtypes = STRINGI_SET_INITIALIZER (cmd->mget.rowtypes),
+ },
+ };
struct mget_command *mget = &cmd->mget;
- for (;;)
+ while (lex_token (s->lexer) != T_ENDCMD)
{
if (lex_match_id (s->lexer, "FILE"))
{
if (!mget->file)
goto error;
}
+ else if (lex_match_id (s->lexer, "ENCODING"))
+ {
+ lex_match (s->lexer, T_EQUALS);
+ if (!lex_force_string (s->lexer))
+ goto error;
+
+ free (mget->encoding);
+ mget->encoding = ss_xstrdup (lex_tokss (s->lexer));
+
+ lex_get (s->lexer);
+ }
else if (lex_match_id (s->lexer, "TYPE"))
{
lex_match (s->lexer, T_EQUALS);
lex_error_expecting (s->lexer, "FILE", "TYPE");
goto error;
}
- if (lex_token (s->lexer) == T_ENDCMD)
- break;
-
- if (!lex_force_match (s->lexer, T_SLASH))
- goto error;
+ lex_match (s->lexer, T_SLASH);
}
return cmd;
const struct dictionary *d,
const struct variable *rowtype_var,
struct matrix_state *s, size_t si, size_t fi,
- size_t cs, size_t cn)
+ size_t cs, size_t cn,
+ struct pivot_table *pt,
+ struct pivot_dimension *var_dimension)
{
if (!n_rows)
return;
}
}
+ int var_index = pivot_category_create_leaf (
+ var_dimension->root, pivot_value_new_user_text (ds_cstr (&name), SIZE_MAX));
+ double values[] = { n_rows, cn };
+ for (size_t j = 0; j < sizeof values / sizeof *values; j++)
+ pivot_table_put2 (pt, j, var_index, pivot_value_new_integer (values[j]));
+
if (n_missing)
msg (SE, ngettext ("Matrix data file variable %s contains a missing "
"value, which was treated as zero.",
var_changed (const struct ccase *ca, const struct ccase *cb,
const struct variable *var)
{
- return !value_equal (case_data (ca, var), case_data (cb, var),
- var_get_width (var));
+ return (ca && cb
+ ? !value_equal (case_data (ca, var), case_data (cb, var),
+ var_get_width (var))
+ : ca || cb);
}
static bool
}
static void
-matrix_cmd_execute_mget (struct mget_command *mget)
+matrix_cmd_execute_mget__ (struct mget_command *mget,
+ struct casereader *r, const struct dictionary *d,
+ struct pivot_table *pt,
+ struct pivot_dimension *var_dimension)
{
- struct dictionary *d;
- struct casereader *r = any_reader_open_and_decode (mget->file, "UTF-8",
- &d, NULL);
- if (!r)
- return;
-
const struct variable *rowtype_ = get_a8_var (d, "ROWTYPE_");
const struct variable *varname_ = get_a8_var (d, "VARNAME_");
if (!rowtype_ || !varname_)
- goto exit;
+ return;
if (var_get_dict_index (rowtype_) >= var_get_dict_index (varname_))
{
msg (SE, _("ROWTYPE_ must precede VARNAME_ in matrix data file."));
- goto exit;
+ return;
}
if (var_get_dict_index (varname_) + 1 >= dict_get_var_cnt (d))
{
msg (SE, _("Matrix data file contains no continuous variables."));
- goto exit;
+ return;
}
for (size_t i = 0; i < dict_get_var_cnt (d); i++)
msg (SE,
_("Matrix data file contains unexpected string variable %s."),
var_get_name (v));
- goto exit;
+ return;
}
}
struct ccase *c;
while ((c = casereader_read (r)) != NULL)
{
- bool sd = vars_changed (sc, c, d, ss, sn);
- bool fd = sd || vars_changed (fc, c, d, fs, fn);
- bool md = fd || !cc || var_changed (cc, c, rowtype_) || var_changed (cc, c, varname_);
- if (sd)
- {
- si++;
- case_unref (sc);
- sc = case_ref (c);
- }
- if (fd)
+ enum
{
- fi++;
- case_unref (fc);
- fc = case_ref (c);
+ SPLITS_CHANGED,
+ FACTORS_CHANGED,
+ ROWTYPE_CHANGED,
+ NOTHING_CHANGED
}
- if (md)
+ change
+ = (sn && (!sc || vars_changed (sc, c, d, ss, sn)) ? SPLITS_CHANGED
+ : fn && (!fc || vars_changed (fc, c, d, fs, fn)) ? FACTORS_CHANGED
+ : !cc || var_changed (cc, c, rowtype_) ? ROWTYPE_CHANGED
+ : NOTHING_CHANGED);
+
+ if (change != NOTHING_CHANGED)
{
matrix_mget_commit_var (rows, n_rows, d, rowtype_,
- mget->state, si, fi, cs, cn);
+ mget->state, si, fi, cs, cn,
+ pt, var_dimension);
n_rows = 0;
case_unref (cc);
cc = case_ref (c);
if (n_rows >= allocated_rows)
rows = x2nrealloc (rows, &allocated_rows, sizeof *rows);
rows[n_rows++] = c;
+
+ if (change == SPLITS_CHANGED)
+ {
+ si++;
+ case_unref (sc);
+ sc = case_ref (c);
+
+ /* Reset the factor number, if there are factors. */
+ if (fn)
+ {
+ fi = 1;
+ case_unref (fc);
+ fc = case_ref (c);
+ }
+ }
+ else if (change == FACTORS_CHANGED)
+ {
+ fi++;
+ case_unref (fc);
+ fc = case_ref (c);
+ }
}
matrix_mget_commit_var (rows, n_rows, d, rowtype_,
- mget->state, si, fi, cs, cn);
+ mget->state, si, fi, cs, cn,
+ pt, var_dimension);
free (rows);
-exit:
- casereader_destroy (r);
+ case_unref (sc);
+ case_unref (fc);
+ case_unref (cc);
+}
+
+static void
+matrix_cmd_execute_mget (struct mget_command *mget)
+{
+ struct casereader *r;
+ struct dictionary *d;
+ if (matrix_open_casereader ("MGET", mget->file, mget->encoding,
+ mget->state->dataset, &r, &d))
+ {
+ struct pivot_table *pt = pivot_table_create (
+ N_("Matrix Variables Created by MGET"));
+ pivot_dimension_create (pt, PIVOT_AXIS_COLUMN, N_("Dimension"),
+ N_("Rows"), N_("Columns"));
+ struct pivot_dimension *var_dimension = pivot_dimension_create (
+ pt, PIVOT_AXIS_ROW, N_("Variable"));
+ matrix_cmd_execute_mget__ (mget, r, d, pt, var_dimension);
+ if (var_dimension->n_leaves)
+ pivot_table_submit (pt);
+ else
+ pivot_table_unref (pt);
+
+ matrix_close_casereader (mget->file, mget->state->dataset, r, d);
+ }
}
\f
static bool