[libgxps] Add support for interleaved archives
- From: Carlos Garcia Campos <carlosgc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgxps] Add support for interleaved archives
- Date: Fri, 21 Dec 2012 11:11:01 +0000 (UTC)
commit bb7ddf8d9bfc6cd946d1db0a8a1aebd08a7c459e
Author: Carlos Garcia Campos <carlosgc gnome org>
Date: Fri Dec 21 12:07:24 2012 +0100
Add support for interleaved archives
libgxps/gxps-archive.c | 68 +++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 64 insertions(+), 4 deletions(-)
---
diff --git a/libgxps/gxps-archive.c b/libgxps/gxps-archive.c
index 235f37c..97d11c5 100644
--- a/libgxps/gxps-archive.c
+++ b/libgxps/gxps-archive.c
@@ -317,6 +317,8 @@ typedef struct _GXPSArchiveInputStream {
GInputStream parent;
ZipArchive *zip;
+ gboolean is_interleaved;
+ guint piece;
struct archive_entry *entry;
} GXPSArchiveInputStream;
@@ -336,22 +338,33 @@ gxps_archive_open (GXPSArchive *archive,
const gchar *path)
{
GXPSArchiveInputStream *stream;
+ gchar *first_piece_path = NULL;
if (path && path[0] == '/')
path++;
- if (!archive_has_entry (archive, path))
- return NULL;
+ if (!archive_has_entry (archive, path)) {
+ first_piece_path = g_build_filename (path, "[0].piece", NULL);
+ if (!archive_has_entry (archive, first_piece_path)) {
+ g_free (first_piece_path);
- stream = (GXPSArchiveInputStream *)g_object_new (GXPS_TYPE_ARCHIVE_INPUT_STREAM, NULL);
+ return NULL;
+ }
+ path = first_piece_path;
+ }
+ stream = (GXPSArchiveInputStream *)g_object_new (GXPS_TYPE_ARCHIVE_INPUT_STREAM, NULL);
stream->zip = gxps_zip_archive_create (archive->filename);
+ stream->is_interleaved = first_piece_path != NULL;
+
while (gxps_zip_archive_iter_next (stream->zip, &stream->entry)) {
if (g_ascii_strcasecmp (path, archive_entry_pathname (stream->entry)) == 0)
break;
archive_read_data_skip (stream->zip->archive);
}
+ g_free (first_piece_path);
+
return G_INPUT_STREAM (stream);
}
@@ -422,6 +435,44 @@ gxps_archive_read_entry (GXPSArchive *archive,
return retval;
}
+static gboolean
+gxps_archive_input_stream_is_last_piece (GXPSArchiveInputStream *stream)
+{
+ return g_str_has_suffix (archive_entry_pathname (stream->entry), ".last.piece");
+}
+
+static void
+gxps_archive_input_stream_next_piece (GXPSArchiveInputStream *stream)
+{
+ gchar *dirname;
+ gchar *prefix;
+ gint result;
+
+ if (!stream->is_interleaved)
+ return;
+
+ dirname = g_path_get_dirname (archive_entry_pathname (stream->entry));
+ if (!dirname)
+ return;
+
+ stream->piece++;
+ prefix = g_strdup_printf ("%s/[%u]", dirname, stream->piece);
+ g_free (dirname);
+
+ while (gxps_zip_archive_iter_next (stream->zip, &stream->entry)) {
+ if (g_str_has_prefix (archive_entry_pathname (stream->entry), prefix)) {
+ const gchar *suffix = archive_entry_pathname (stream->entry) + strlen (prefix);
+
+ if (g_ascii_strcasecmp (suffix, ".piece") == 0 ||
+ g_ascii_strcasecmp (suffix, ".last.piece") == 0)
+ break;
+ }
+ archive_read_data_skip (stream->zip->archive);
+ }
+
+ g_free (prefix);
+}
+
static gssize
gxps_archive_input_stream_read (GInputStream *stream,
void *buffer,
@@ -430,10 +481,19 @@ gxps_archive_input_stream_read (GInputStream *stream,
GError **error)
{
GXPSArchiveInputStream *istream = GXPS_ARCHIVE_INPUT_STREAM (stream);
+ gssize bytes_read;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return -1;
- return archive_read_data (istream->zip->archive, buffer, count);
+
+ bytes_read = archive_read_data (istream->zip->archive, buffer, count);
+ if (bytes_read == 0 && istream->is_interleaved && !gxps_archive_input_stream_is_last_piece (istream)) {
+ /* Read next piece */
+ gxps_archive_input_stream_next_piece (istream);
+ bytes_read = gxps_archive_input_stream_read (stream, buffer, count, cancellable, error);
+ }
+
+ return bytes_read;
}
static gssize
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]