summaryrefslogtreecommitdiffstats
path: root/libmsi/libmsi-istream.c
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2012-12-18 14:35:14 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2013-01-09 13:56:07 +0100
commit0a97c9f43718d34aacc834c60f3ced60e9ce956f (patch)
tree7a5b5975cd92862283df669f9af62005fe63baa9 /libmsi/libmsi-istream.c
parent880b9016b1d751d480a282b9a8556c54701a86f4 (diff)
downloadmsitools-0a97c9f43718d34aacc834c60f3ced60e9ce956f.tar.gz
msitools-0a97c9f43718d34aacc834c60f3ced60e9ce956f.tar.xz
msitools-0a97c9f43718d34aacc834c60f3ced60e9ce956f.zip
record: add set_stream() and get_stream() using GIO
Use GInputStream for record stream manipulation
Diffstat (limited to 'libmsi/libmsi-istream.c')
-rw-r--r--libmsi/libmsi-istream.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/libmsi/libmsi-istream.c b/libmsi/libmsi-istream.c
new file mode 100644
index 0000000..85653e5
--- /dev/null
+++ b/libmsi/libmsi-istream.c
@@ -0,0 +1,155 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "msipriv.h"
+#include "libmsi-istream.h"
+
+struct _LibmsiIStream
+{
+ GInputStream parent;
+
+ GsfInput *input;
+};
+
+static void libmsi_seekable_iface_init (GSeekableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (LibmsiIStream, libmsi_istream, G_TYPE_INPUT_STREAM,
+ G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
+ libmsi_seekable_iface_init);
+ )
+
+static goffset
+libmsi_tell (GSeekable *seekable)
+{
+ g_return_val_if_fail (LIBMSI_IS_ISTREAM(seekable), FALSE);
+
+ return gsf_input_tell (LIBMSI_ISTREAM(seekable)->input);
+}
+
+static gboolean
+libmsi_can_seek (GSeekable *seekable)
+{
+ return TRUE;
+}
+
+static gboolean
+libmsi_seek (GSeekable *seekable, goffset offset,
+ GSeekType type, GCancellable *cancellable)
+{
+ g_return_val_if_fail (LIBMSI_IS_ISTREAM(seekable), FALSE);
+
+ return !gsf_input_seek (LIBMSI_ISTREAM(seekable)->input, offset, type);
+}
+
+static gboolean
+libmsi_can_truncate (GSeekable *seekable)
+{
+ return FALSE;
+}
+
+static void
+libmsi_seekable_iface_init (GSeekableIface *iface)
+{
+ iface->tell = libmsi_tell;
+ iface->can_seek = libmsi_can_seek;
+ iface->seek = libmsi_seek;
+ iface->can_truncate = libmsi_can_truncate;
+}
+
+static void
+libmsi_istream_init (LibmsiIStream *self)
+{
+}
+
+static void
+libmsi_istream_finalize (GObject *object)
+{
+ LibmsiIStream *self = LIBMSI_ISTREAM (object);
+
+ if (self->input)
+ g_object_unref (self->input);
+
+ G_OBJECT_CLASS (libmsi_istream_parent_class)->finalize (object);
+}
+
+static gssize
+input_stream_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ LibmsiIStream *self = LIBMSI_ISTREAM (stream);
+ gssize remaining = gsf_input_remaining (self->input);
+
+ if (remaining == 0)
+ return 0;
+
+ count = MIN(count, remaining);
+ if (!gsf_input_read (self->input, count, buffer))
+ return -1;
+
+ return count;
+}
+
+static gssize
+input_stream_skip (GInputStream *stream,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ LibmsiIStream *self = LIBMSI_ISTREAM (stream);
+
+ count = MIN (count, gsf_input_remaining (self->input));
+ if (!gsf_input_seek (self->input, count, G_SEEK_CUR))
+ return -1;
+
+ return count;
+}
+
+static gboolean
+input_stream_close (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return TRUE;
+}
+
+static void
+libmsi_istream_class_init (LibmsiIStreamClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ GInputStreamClass *istream_class;
+
+ object_class->finalize = libmsi_istream_finalize;
+
+ istream_class = G_INPUT_STREAM_CLASS (klass);
+ istream_class->read_fn = input_stream_read;
+ istream_class->skip = input_stream_skip;
+ istream_class->close_fn = input_stream_close;
+}
+
+G_GNUC_INTERNAL LibmsiIStream *
+libmsi_istream_new (GsfInput *input)
+{
+ GsfInput *dup = gsf_input_dup (input, NULL);
+ g_return_val_if_fail (dup, NULL);
+
+ LibmsiIStream *self = g_object_new (LIBMSI_TYPE_ISTREAM, NULL);
+ self->input = dup;
+
+ return self;
+}