/* PSPP - computes sample statistics.
Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
- Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
#include <data/case-source.h>
#include <data/case.h>
#include <data/casefile.h>
+#include <data/casefile-factory.h>
#include "xalloc.h"
-/* Information about storage sink or source. */
-struct storage_stream_info
+/* Storage sink. */
+
+/* Information about storage sink. */
+struct storage_sink_info
{
struct casefile *casefile; /* Storage. */
};
-\f
-/* Storage sink. */
+
+static struct storage_sink_info *
+get_storage_sink_info (struct case_sink *sink)
+{
+ assert (sink->class == &storage_sink_class);
+ return sink->aux;
+}
/* Initializes a storage sink. */
static void
storage_sink_open (struct case_sink *sink)
{
- struct storage_stream_info *info;
+ struct storage_sink_info *info;
sink->aux = info = xmalloc (sizeof *info);
- info->casefile = casefile_create (sink->value_cnt);
-}
-
-/* Destroys storage stream represented by INFO. */
-static void
-destroy_storage_stream_info (struct storage_stream_info *info)
-{
- if (info != NULL)
- {
- casefile_destroy (info->casefile);
- free (info);
- }
+ info->casefile = sink->factory->create_casefile (sink->factory,
+ sink->value_cnt);
}
/* Writes case C to the storage sink SINK.
static bool
storage_sink_write (struct case_sink *sink, const struct ccase *c)
{
- struct storage_stream_info *info = sink->aux;
-
+ struct storage_sink_info *info = get_storage_sink_info (sink);
return casefile_append (info->casefile, c);
}
static void
storage_sink_destroy (struct case_sink *sink)
{
- destroy_storage_stream_info (sink->aux);
+ struct storage_sink_info *info = get_storage_sink_info (sink);
+ casefile_destroy (info->casefile);
+ free (info);
}
/* Closes the sink and returns a storage source to read back the
static struct case_source *
storage_sink_make_source (struct case_sink *sink)
{
- struct case_source *source
- = create_case_source (&storage_source_class, sink->aux);
- sink->aux = NULL;
+ struct storage_sink_info *info = get_storage_sink_info (sink);
+ struct case_source *source = storage_source_create (info->casefile);
+ info->casefile = NULL;
return source;
}
\f
/* Storage source. */
+struct storage_source_info
+ {
+ struct casefile *casefile; /* Storage. */
+ struct casereader *reader; /* Reader. */
+ };
+
+static struct storage_source_info *
+get_storage_source_info (const struct case_source *source)
+{
+ assert (source->class == &storage_source_class);
+ return source->aux;
+}
+
/* Returns the number of cases that will be read by
storage_source_read(). */
static int
storage_source_count (const struct case_source *source)
{
- struct storage_stream_info *info = source->aux;
-
+ struct storage_source_info *info = get_storage_source_info (source);
return casefile_get_case_cnt (info->casefile);
}
-/* Reads all cases from the storage source and passes them one by one to
- write_case(). */
+/* Reads one case into OUTPUT_CASE.
+ Returns true if successful, false at end of file or if an
+ I/O error occurred. */
static bool
-storage_source_read (struct case_source *source,
- struct ccase *output_case,
- write_case_func *write_case, write_case_data wc_data)
+storage_source_read (struct case_source *source, struct ccase *output_case)
{
- struct storage_stream_info *info = source->aux;
+ struct storage_source_info *info = get_storage_source_info (source);
struct ccase casefile_case;
- struct casereader *reader;
- bool ok = true;
- for (reader = casefile_get_reader (info->casefile);
- ok && casereader_read (reader, &casefile_case);
- case_destroy (&casefile_case))
+ if (info->reader == NULL)
+ info->reader = casefile_get_reader (info->casefile, NULL);
+
+ if (casereader_read (info->reader, &casefile_case))
{
case_copy (output_case, 0,
&casefile_case, 0,
casefile_get_value_cnt (info->casefile));
- ok = write_case (wc_data);
+ return true;
}
- casereader_destroy (reader);
-
- return ok;
+ else
+ return false;
}
-/* Destroys the source's internal data. */
-static void
+/* Destroys the source.
+ Returns true if successful read, false if an I/O occurred
+ during destruction or previously. */
+static bool
storage_source_destroy (struct case_source *source)
{
- destroy_storage_stream_info (source->aux);
+ struct storage_source_info *info = get_storage_source_info (source);
+ bool ok = true;
+ if (info->casefile)
+ {
+ ok = !casefile_error (info->casefile);
+ casefile_destroy (info->casefile);
+ }
+ free (info);
+ return ok;
}
-/* Storage source. */
-const struct case_source_class storage_source_class =
- {
- "storage",
- storage_source_count,
- storage_source_read,
- storage_source_destroy,
- };
-
/* Returns the casefile encapsulated by SOURCE. */
struct casefile *
storage_source_get_casefile (struct case_source *source)
{
- struct storage_stream_info *info = source->aux;
-
- assert (source->class == &storage_source_class);
+ struct storage_source_info *info = get_storage_source_info (source);
return info->casefile;
}
struct casefile *
storage_source_decapsulate (struct case_source *source)
{
- struct storage_stream_info *info = source->aux;
- struct casefile *casefile;
-
- assert (source->class == &storage_source_class);
- casefile = info->casefile;
+ struct storage_source_info *info = get_storage_source_info (source);
+ struct casefile *casefile = info->casefile;
+ assert (info->reader == NULL);
info->casefile = NULL;
free_case_source (source);
return casefile;
}
-/* Creates and returns a new storage stream that encapsulates
+/* Creates and returns a new storage source that encapsulates
CASEFILE. */
struct case_source *
storage_source_create (struct casefile *casefile)
{
- struct storage_stream_info *info;
+ struct storage_source_info *info;
info = xmalloc (sizeof *info);
info->casefile = casefile;
+ info->reader = NULL;
return create_case_source (&storage_source_class, info);
}
+
+/* Storage source. */
+const struct case_source_class storage_source_class =
+ {
+ "storage",
+ storage_source_count,
+ storage_source_read,
+ storage_source_destroy,
+ };