+\f
+struct caseinit_translator
+ {
+ struct init_list reinit_values;
+ struct caseproto *proto;
+ };
+
+static struct ccase *
+translate_caseinit (struct ccase *c, void *cit_)
+{
+ const struct caseinit_translator *cit = cit_;
+
+ c = case_unshare_and_resize (c, cit->proto);
+ init_list_init (&cit->reinit_values, c);
+ return c;
+}
+
+static bool
+translate_destroy (void *cit_)
+{
+ struct caseinit_translator *cit = cit_;
+
+ init_list_destroy (&cit->reinit_values);
+ caseproto_unref (cit->proto);
+ free (cit);
+
+ return true;
+}
+
+/* Returns a new casereader that yields each case from R, resized to match
+ OUTPUT_PROTO and initialized from CI as if with caseinit_init_vars(). Takes
+ ownership of R.
+
+ OUTPUT_PROTO must be conformable with R's prototype. */
+struct casereader *
+caseinit_translate_casereader_to_init_vars (struct caseinit *ci,
+ const struct caseproto *output_proto,
+ struct casereader *r)
+{
+ assert (caseproto_is_conformable (casereader_get_proto (r), output_proto));
+ if (caseproto_equal (output_proto, casereader_get_proto (r))
+ && ci->reinit_values.n == 0)
+ return casereader_rename (r);
+
+ struct caseinit_translator *cit = xmalloc (sizeof *cit);
+ *cit = (struct caseinit_translator) {
+ .reinit_values = init_list_clone (&ci->reinit_values),
+ .proto = caseproto_ref (output_proto),
+ };
+
+ static const struct casereader_translator_class class = {
+ .translate = translate_caseinit,
+ .destroy = translate_destroy,
+ };
+ return casereader_translate_stateless (r, output_proto, &class, cit);
+}