// ----------------------------------------------------------------
static void handle_full_srec_assignment(
	mlr_dsl_cst_statement_t* pstatement,
	variables_t*             pvars,
	cst_outputs_t*           pcst_outputs)
{
	full_srec_assignment_state_t* pstate = pstatement->pvstate;

	lrec_t* poutrec = lrec_unbacked_alloc(); // pinrec might be part of the RHS.
	lhmsmv_t* pout_typed_overlay = lhmsmv_alloc();

	rxval_evaluator_t* prhs_xevaluator = pstate->prhs_xevaluator;
	boxed_xval_t boxed_xval = prhs_xevaluator->pprocess_func(prhs_xevaluator->pvstate, pvars);

	if (!boxed_xval.xval.is_terminal) {
		for (mlhmmv_level_entry_t* pe = boxed_xval.xval.pnext_level->phead; pe != NULL; pe = pe->pnext) {
			mv_t* pkey = &pe->level_key;
			mlhmmv_xvalue_t* pval = &pe->level_xvalue;

			if (pval->is_terminal) { // xxx else collapse-down using json separator?
				char* skey = mv_alloc_format_val(pkey);
				// xxx if we're going to transfer here *and* free below, this needs a nullptr poke
				// at the copy-from site
				//mv_t val = boxed_xval.is_ephemeral ? pval->terminal_mlrval : mv_copy(&pval->terminal_mlrval);
				mv_t val = mv_copy(&pval->terminal_mlrval);

				// Write typed mlrval output to the typed overlay rather than into the lrec
				// (which holds only string values).
				//
				// The rval_evaluator reads the overlay in preference to the lrec. E.g. if the
				// input had "x"=>"abc","y"=>"def" but a previous statement had set "y"=>7.4 and
				// "z"=>"ghi", then an expression right-hand side referring to $y would get the
				// floating-point value 7.4. So we don't need to lrec_put the value here, and
				// moreover should not for two reasons: (1) there is a performance hit of doing
				// throwaway number-to-string formatting -- it's better to do it once at the
				// end; (2) having the string values doubly owned by the typed overlay and the
				// lrec would result in double frees, or awkward bookkeeping. However, the NR
				// variable evaluator reads prec->field_count, so we need to put something here.
				// And putting something statically allocated minimizes copying/freeing.
				lhmsmv_put(pout_typed_overlay, mlr_strdup_or_die(skey), &val,
					FREE_ENTRY_KEY | FREE_ENTRY_VALUE);
				lrec_put(poutrec, skey, "bug", FREE_ENTRY_KEY);
			}
		}
		if (boxed_xval.is_ephemeral) {
			mlhmmv_xvalue_free(&boxed_xval.xval);
		}
	} else {
		mlhmmv_xvalue_free(&boxed_xval.xval);
	}
	lrec_free(pvars->pinrec);
	lhmsmv_free(pvars->ptyped_overlay);
	pvars->pinrec = poutrec;
	pvars->ptyped_overlay = pout_typed_overlay;
}
Ejemplo n.º 2
0
/* Shows the dialog box and sets default values */
void
missing_val_dialog_show (struct missing_val_dialog *dialog)
{
  gint i;
  g_return_if_fail (dialog);
  g_return_if_fail (dialog->pv);

  mv_copy (&dialog->mvl, var_get_missing_values (dialog->pv));

  /* Blank all entry boxes and make them insensitive */
  gtk_entry_set_text (GTK_ENTRY (dialog->low), "");
  gtk_entry_set_text (GTK_ENTRY (dialog->high), "");
  gtk_entry_set_text (GTK_ENTRY (dialog->discrete), "");
  gtk_widget_set_sensitive (dialog->low, FALSE);
  gtk_widget_set_sensitive (dialog->high, FALSE);
  gtk_widget_set_sensitive (dialog->discrete, FALSE);

  gtk_widget_set_sensitive (GTK_WIDGET (dialog->button_range),
			   var_is_numeric (dialog->pv));


  for (i = 0 ; i < 3 ; ++i )
    {
      gtk_entry_set_text (GTK_ENTRY (dialog->mv[i]), "");
      gtk_widget_set_sensitive (dialog->mv[i], FALSE);
    }

  if ( mv_has_range (&dialog->mvl))
    {
      union value low, high;
      gchar *low_text;
      gchar *high_text;
      mv_get_range (&dialog->mvl, &low.f, &high.f);


      low_text = value_to_text (low, dialog->pv);
      high_text = value_to_text (high, dialog->pv);

      gtk_entry_set_text (GTK_ENTRY (dialog->low), low_text);
      gtk_entry_set_text (GTK_ENTRY (dialog->high), high_text);
      g_free (low_text);
      g_free (high_text);

      if ( mv_has_value (&dialog->mvl))
	{
	  gchar *text;
	  text = value_to_text (*mv_get_value (&dialog->mvl, 0), dialog->pv);
	  gtk_entry_set_text (GTK_ENTRY (dialog->discrete), text);
	  g_free (text);
	}

      gtk_toggle_button_set_active (dialog->button_range, TRUE);
      gtk_widget_set_sensitive (dialog->low, TRUE);
      gtk_widget_set_sensitive (dialog->high, TRUE);
      gtk_widget_set_sensitive (dialog->discrete, TRUE);

    }
  else if ( mv_has_value (&dialog->mvl))
    {
      const int n = mv_n_values (&dialog->mvl);

      for (i = 0 ; i < 3 ; ++i )
	{
	  if ( i < n)
	    {
	      gchar *text ;

	      text = value_to_text (*mv_get_value (&dialog->mvl, i), dialog->pv);
	      gtk_entry_set_text (GTK_ENTRY (dialog->mv[i]), text);
	      g_free (text);
	    }
	  gtk_widget_set_sensitive (dialog->mv[i], TRUE);
	}
      gtk_toggle_button_set_active (dialog->button_discrete, TRUE);
    }
  else if ( mv_is_empty (&dialog->mvl))
    {
      gtk_toggle_button_set_active (dialog->button_none, TRUE);
    }

  gtk_widget_show (dialog->window);
}
Ejemplo n.º 3
0
/* Opens the CSV file designated by file handle FH for writing cases from
   dictionary DICT according to the given OPTS.

   No reference to D is retained, so it may be modified or
   destroyed at will after this function returns. */
struct casewriter *
csv_writer_open (struct file_handle *fh, const struct dictionary *dict,
                 const struct csv_writer_options *opts)
{
  struct csv_writer *w;
  int i;

  /* Create and initialize writer. */
  w = xmalloc (sizeof *w);
  w->fh = fh_ref (fh);
  w->lock = NULL;
  w->file = NULL;
  w->rf = NULL;

  w->opts = *opts;

  w->encoding = xstrdup (dict_get_encoding (dict));

  w->n_csv_vars = dict_get_var_cnt (dict);
  w->csv_vars = xnmalloc (w->n_csv_vars, sizeof *w->csv_vars);
  for (i = 0; i < w->n_csv_vars; i++)
    {
      const struct variable *var = dict_get_var (dict, i);
      struct csv_var *cv = &w->csv_vars[i];

      cv->width = var_get_width (var);
      cv->case_index = var_get_case_index (var);

      cv->format = *var_get_print_format (var);
      if (opts->recode_user_missing)
        mv_copy (&cv->missing, var_get_missing_values (var));
      else
        mv_init (&cv->missing, cv->width);

      if (opts->use_value_labels)
        cv->val_labs = val_labs_clone (var_get_value_labels (var));
      else
        cv->val_labs = NULL;
    }

  /* Open file handle as an exclusive writer. */
  /* TRANSLATORS: this fragment will be interpolated into messages in fh_lock()
     that identify types of files. */
  w->lock = fh_lock (fh, FH_REF_FILE, N_("CSV file"), FH_ACC_WRITE, true);
  if (w->lock == NULL)
    goto error;

  /* Create the file on disk. */
  w->rf = replace_file_start (fh_get_file_name (fh), "w", 0666,
                              &w->file, NULL);
  if (w->rf == NULL)
    {
      msg (ME, _("Error opening `%s' for writing as a system file: %s."),
           fh_get_file_name (fh), strerror (errno));
      goto error;
    }

  if (opts->include_var_names)
    write_var_names (w, dict);

  if (write_error (w))
    goto error;

  return casewriter_create (dict_get_proto (dict),
                            &csv_file_casewriter_class, w);

error:
  close_writer (w);
  return NULL;
}