casereader: Add a class for casereader translators.
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 20 Feb 2023 23:48:59 +0000 (15:48 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 20 Feb 2023 23:48:59 +0000 (15:48 -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-translator.c
src/data/casereader.h

index 5d2a347472df7e185461dbe372f77aefb63682f2..c7249c7a7acc84245bf383225eae8e4e68312cb2 100644 (file)
@@ -147,11 +147,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..4dbfb7b3ac903a9cf8a96141ff680b231e28ff27 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));
@@ -63,6 +63,12 @@ destroy_projection (void *project_)
   return true;
 }
 
+static const struct casereader_translator_class projection_class =
+  {
+    project_case,
+    destroy_projection,
+  };
+
 /* Returns a casereader in which each row is obtained by extracting the subcase
    SC from the corresponding row of SUBREADER. */
 struct casereader *
@@ -82,8 +88,7 @@ casereader_project (struct casereader *subreader, const struct subcase *sc)
       subcase_add_proto_always (&project->new_sc, proto);
 
       return casereader_translate_stateless (subreader, proto,
-                                             project_case, destroy_projection,
-                                             project);
+                                             &projection_class, project);
     }
 }
 
index 996dc24f5a55a6bcdf94a526bca2744c42d6fe23..31ee82c1f627e19b19f6846aff860d6f1c450463 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);
 }
 
@@ -116,18 +113,6 @@ static const struct casereader_class casereader_translator_class =
 /* Casereader that applies a user-supplied function to translate
    each case into another in a stateless fashion. */
 
-/* A statelessly translating casereader. */
-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);
-    void *aux;
-  };
-
 static const struct casereader_random_class
 casereader_stateless_translator_class;
 
@@ -142,10 +127,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,21 +139,20 @@ 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 (
-    output_proto, casereader_get_n_cases (cst->subreader),
-    &casereader_stateless_translator_class, cst);
-  taint_propagate (casereader_get_taint (cst->subreader),
+  struct casereader_translator *ct = xmalloc (sizeof *ct);
+  *ct = (struct casereader_translator) {
+    .subreader = casereader_rename (subreader),
+    .class = class,
+    .aux = aux,
+  };
+
+  struct casereader *reader = casereader_create_random (
+    output_proto, casereader_get_n_cases (ct->subreader),
+    &casereader_stateless_translator_class, ct);
+  taint_propagate (casereader_get_taint (ct->subreader),
                    casereader_get_taint (reader));
   return reader;
 }
@@ -180,32 +160,24 @@ casereader_translate_stateless (
 /* Internal read function for stateless translating casereader. */
 static struct ccase *
 casereader_stateless_translator_read (struct casereader *reader UNUSED,
-                                      void *cst_, casenumber idx)
+                                      void *ct_, casenumber idx)
 {
-  struct casereader_stateless_translator *cst = cst_;
-  struct ccase *tmp = casereader_peek (cst->subreader, idx);
+  struct casereader_translator *ct = ct_;
+  struct ccase *tmp = casereader_peek (ct->subreader, idx);
   if (tmp != NULL)
-    tmp = cst->translate (tmp, cst->case_offset + idx, cst->aux);
+    tmp = ct->class->translate (tmp, ct->aux);
   return tmp;
 }
 
 /* Internal destroy function for translating casereader. */
 static void
 casereader_stateless_translator_destroy (struct casereader *reader UNUSED,
-                                         void *cst_)
+                                         void *ct_)
 {
-  struct casereader_stateless_translator *cst = cst_;
-  casereader_destroy (cst->subreader);
-  cst->destroy (cst->aux);
-  free (cst);
-}
-
-static void
-casereader_stateless_translator_advance (struct casereader *reader UNUSED,
-                                         void *cst_, casenumber n)
-{
-  struct casereader_stateless_translator *cst = cst_;
-  cst->case_offset += casereader_advance (cst->subreader, n);
+  struct casereader_translator *ct = ct_;
+  casereader_destroy (ct->subreader);
+  ct->class->destroy (ct->aux);
+  free (ct);
 }
 
 /* Casereader class for stateless translating casereader. */
@@ -214,7 +186,7 @@ casereader_stateless_translator_class =
   {
     casereader_stateless_translator_read,
     casereader_stateless_translator_destroy,
-    casereader_stateless_translator_advance,
+    NULL,
   };
 \f
 
@@ -253,8 +225,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 +360,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 +553,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 +571,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 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 *,