casereader-translator: Add a class for casereader translators.
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 20 Feb 2023 23:47:52 +0000 (15:47 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 21 Feb 2023 04:01:26 +0000 (20:01 -0800)
This will make it easier to pass these around from one function to another.

src/data/case-map.c
src/data/casereader-project.c
src/data/casereader-provider.h
src/data/casereader-translator.c
src/data/casereader.c
src/data/casereader.h

index 87174f1fb3a4e37eb90064b5ab3f78f81aa9d894..2e1507edca750d0cc650d922168c8f1902e301b4 100644 (file)
@@ -131,11 +131,12 @@ struct casereader *
 case_map_create_input_translator (struct case_map *map,
                                   struct casereader *subreader)
 {
-    return casereader_create_translator (subreader,
-                                         case_map_get_proto (map),
-                                         translate_case,
-                                         destroy_case_map,
-                                         map);
+  static const struct casereader_translator_class class = {
+    translate_case, destroy_case_map,
+  };
+  return casereader_create_translator (subreader,
+                                       case_map_get_proto (map),
+                                       &class, map);
 }
 
 /* Creates and returns a new casewriter.  Cases written to the
index 2798eeb80cdfe4fa23f63275d21005dfb7ba25e9..55a8993bab93f297bd84855caade6f9dd3fe239a 100644 (file)
@@ -44,7 +44,7 @@ struct casereader_project
   };
 
 static struct ccase *
-project_case (struct ccase *old, casenumber idx UNUSED, const void *project_)
+project_case (struct ccase *old, void *project_)
 {
   const struct casereader_project *project = project_;
   struct ccase *new = case_create (subcase_get_proto (&project->new_sc));
@@ -81,9 +81,12 @@ casereader_project (struct casereader *subreader, const struct subcase *sc)
       subcase_init_empty (&project->new_sc);
       subcase_add_proto_always (&project->new_sc, proto);
 
+      static const struct casereader_translator_class class = {
+        project_case, destroy_projection,
+      };
+
       return casereader_translate_stateless (subreader, proto,
-                                             project_case, destroy_projection,
-                                             project);
+                                             &class, project);
     }
 }
 
index 2069eb678de9b652d5bb16cd91f399850be1b163..37bde24310c76e1a1c5c6facd49c439968c9272c 100644 (file)
@@ -148,7 +148,7 @@ struct casereader_random_class
        function should call casereader_force_error on READER. */
     void (*destroy) (struct casereader *reader, void *aux);
 
-    /* Mandatory.
+    /* Optional.
 
        A call to this function tells the callee that the N
        cases at the beginning of READER will never be read again.
index 996dc24f5a55a6bcdf94a526bca2744c42d6fe23..5c8b9f4209929f335c702f47e6f96312d8f1fabe 100644 (file)
@@ -33,9 +33,7 @@
 struct casereader_translator
   {
     struct casereader *subreader; /* Source of input cases. */
-
-    struct ccase *(*translate) (struct ccase *input, void *aux);
-    bool (*destroy) (void *aux);
+    const struct casereader_translator_class *class;
     void *aux;
   };
 
@@ -63,18 +61,17 @@ static const struct casereader_class casereader_translator_class;
 struct casereader *
 casereader_create_translator (struct casereader *subreader,
                               const struct caseproto *output_proto,
-                              struct ccase *(*translate) (struct ccase *input,
-                                                          void *aux),
-                              bool (*destroy) (void *aux),
+                              const struct casereader_translator_class *class,
                               void *aux)
 {
   struct casereader_translator *ct = xmalloc (sizeof *ct);
-  struct casereader *reader;
-  ct->subreader = casereader_rename (subreader);
-  ct->translate = translate;
-  ct->destroy = destroy;
-  ct->aux = aux;
-  reader = casereader_create_sequential (
+  *ct = (struct casereader_translator) {
+    .subreader = casereader_rename (subreader),
+    .class = class,
+    .aux = aux,
+  };
+
+  struct casereader *reader = casereader_create_sequential (
     NULL, output_proto, casereader_get_n_cases (ct->subreader),
     &casereader_translator_class, ct);
   taint_propagate (casereader_get_taint (ct->subreader),
@@ -90,7 +87,7 @@ casereader_translator_read (struct casereader *reader UNUSED,
   struct casereader_translator *ct = ct_;
   struct ccase *tmp = casereader_read (ct->subreader);
   if (tmp)
-    tmp = ct->translate (tmp, ct->aux);
+    tmp = ct->class->translate (tmp, ct->aux);
   return tmp;
 }
 
@@ -100,7 +97,7 @@ casereader_translator_destroy (struct casereader *reader UNUSED, void *ct_)
 {
   struct casereader_translator *ct = ct_;
   casereader_destroy (ct->subreader);
-  ct->destroy (ct->aux);
+  ct->class->destroy (ct->aux);
   free (ct);
 }
 
@@ -122,9 +119,7 @@ struct casereader_stateless_translator
     struct casereader *subreader; /* Source of input cases. */
 
     casenumber case_offset;
-    struct ccase *(*translate) (struct ccase *input, casenumber,
-                                const void *aux);
-    bool (*destroy) (void *aux);
+    const struct casereader_translator_class *class;
     void *aux;
   };
 
@@ -142,10 +137,6 @@ casereader_stateless_translator_class;
    cases may be skipped and never retrieved at all.  If TRANSLATE is stateful,
    use casereader_create_translator instead.
 
-   The casenumber argument to the TRANSLATE function is the absolute case
-   number in SUBREADER, that is, 0 when the first case in SUBREADER is being
-   translated, 1 when the second case is being translated, and so on.
-
    The cases returned by TRANSLATE must match OUTPUT_PROTO.
 
    When the stateless translating casereader is destroyed, DESTROY will be
@@ -158,18 +149,16 @@ struct casereader *
 casereader_translate_stateless (
   struct casereader *subreader,
   const struct caseproto *output_proto,
-  struct ccase *(*translate) (struct ccase *input, casenumber,
-                              const void *aux),
-  bool (*destroy) (void *aux),
+  const struct casereader_translator_class *class,
   void *aux)
 {
   struct casereader_stateless_translator *cst = xmalloc (sizeof *cst);
-  struct casereader *reader;
-  cst->subreader = casereader_rename (subreader);
-  cst->translate = translate;
-  cst->destroy = destroy;
-  cst->aux = aux;
-  reader = casereader_create_random (
+  *cst = (struct casereader_stateless_translator) {
+    .subreader = casereader_rename (subreader),
+    .class = class,
+    .aux = aux,
+  };
+  struct casereader *reader = casereader_create_random (
     output_proto, casereader_get_n_cases (cst->subreader),
     &casereader_stateless_translator_class, cst);
   taint_propagate (casereader_get_taint (cst->subreader),
@@ -185,7 +174,7 @@ casereader_stateless_translator_read (struct casereader *reader UNUSED,
   struct casereader_stateless_translator *cst = cst_;
   struct ccase *tmp = casereader_peek (cst->subreader, idx);
   if (tmp != NULL)
-    tmp = cst->translate (tmp, cst->case_offset + idx, cst->aux);
+    tmp = cst->class->translate (tmp, cst->aux);
   return tmp;
 }
 
@@ -196,7 +185,7 @@ casereader_stateless_translator_destroy (struct casereader *reader UNUSED,
 {
   struct casereader_stateless_translator *cst = cst_;
   casereader_destroy (cst->subreader);
-  cst->destroy (cst->aux);
+  cst->class->destroy (cst->aux);
   free (cst);
 }
 
@@ -253,8 +242,11 @@ casereader_create_append_numeric (struct casereader *subreader,
   can->aux = aux;
   can->func = func;
   can->destroy = destroy;
-  return casereader_create_translator (subreader, can->proto,
-                                       can_translate, can_destroy, can);
+
+  static const struct casereader_translator_class class = {
+    can_translate, can_destroy,
+  };
+  return casereader_create_translator (subreader, can->proto, &class, can);
 }
 
 
@@ -385,8 +377,10 @@ casereader_create_append_rank (struct casereader *subreader,
   car->err = err;
   car->prev_value = SYSMIS;
 
-  return casereader_create_translator (subreader, car->proto,
-                                       car_translate, car_destroy, car);
+  static const struct casereader_translator_class class = {
+    car_translate, car_destroy
+  };
+  return casereader_create_translator (subreader, car->proto, &class, car);
 }
 
 
@@ -576,7 +570,6 @@ casereader_create_distinct (struct casereader *input,
                                               const struct variable *weight)
 {
   struct casereader *u ;
-  struct casereader *ud ;
   struct caseproto *output_proto = caseproto_ref (casereader_get_proto (input));
 
   struct consolidator *cdr = xmalloc (sizeof (*cdr));
@@ -595,12 +588,9 @@ casereader_create_distinct (struct casereader *input,
   u = casereader_create_filter_func (input, uniquify,
                                     NULL, cdr, NULL);
 
-  ud = casereader_create_translator (u,
-                                    output_proto,
-                                    consolodate_weight,
-                                    uniquify_destroy,
-                                    cdr);
-
-  return ud;
+  static const struct casereader_translator_class class = {
+    consolodate_weight, uniquify_destroy,
+  };
+  return casereader_create_translator (u, output_proto, &class, cdr);
 }
 
index 1b06f42e8ab399b9b0ad4a3b76f1a3ea82a10bea..a410afcbcbfab2c826735d9ef94e4daffdca10f5 100644 (file)
@@ -501,7 +501,8 @@ advance_random_reader (struct casereader *reader,
   if (new > old)
     {
       shared->min_offset = new;
-      shared->class->advance (reader, shared->aux, new - old);
+      if (shared->class->advance)
+        shared->class->advance (reader, shared->aux, new - old);
     }
 }
 
index da4eaa2f3bcdb827a1e41bcfe64cd98b86b7d8e6..06f7a7b13a2cf872644cc9b8fc62d23c291ad3d1 100644 (file)
@@ -107,21 +107,20 @@ struct casereader *
 casereader_create_counter (struct casereader *, casenumber *counter,
                            casenumber initial_value);
 
+struct casereader_translator_class
+  {
+    struct ccase *(*translate) (struct ccase *, void *aux);
+    bool (*destroy) (void *aux);
+  };
 struct casereader *
 casereader_create_translator (struct casereader *,
                               const struct caseproto *output_proto,
-                              struct ccase *(*translate) (struct ccase *,
-                                                          void *aux),
-                              bool (*destroy) (void *aux),
+                              const struct casereader_translator_class *,
                               void *aux);
-
 struct casereader *
 casereader_translate_stateless (struct casereader *,
                                 const struct caseproto *output_proto,
-                                struct ccase *(*translate) (struct ccase *,
-                                                            casenumber idx,
-                                                            const void *aux),
-                                bool (*destroy) (void *aux),
+                                const struct casereader_translator_class *,
                                 void *aux);
 
 struct casereader *casereader_project (struct casereader *,