Skip to content

Commit

Permalink
Improve progress callback.
Browse files Browse the repository at this point in the history
- Pass zip archive and user provided context (void pointer) into callback.
- Optional free function for context.
  • Loading branch information
dillof committed May 2, 2017
1 parent 677f980 commit 9729dc3
Show file tree
Hide file tree
Showing 11 changed files with 229 additions and 67 deletions.
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ SET(LIBZIP_SOURCES
zip_name_locate.c
zip_new.c
zip_open.c
zip_progress.c
zip_rename.c
zip_replace.c
zip_set_archive_comment.c
Expand Down
1 change: 1 addition & 0 deletions lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ libzip_la_SOURCES=\
zip_name_locate.c \
zip_new.c \
zip_open.c \
zip_progress.c \
zip_rename.c \
zip_replace.c \
zip_set_archive_comment.c \
Expand Down
8 changes: 5 additions & 3 deletions lib/zip.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,12 @@ typedef struct zip_stat zip_stat_t;
typedef zip_uint32_t zip_flags_t;

typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, zip_source_cmd_t);
typedef void (*zip_progress_callback_t)(double);

typedef void (*zip_progress_callback)(zip_t *, double, void *);

#ifndef ZIP_DISABLE_DEPRECATED
typedef void (*zip_progress_callback_t)(double);
ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t);

ZIP_EXTERN zip_int64_t zip_add(zip_t *, const char *, zip_source_t *); /* use zip_file_add */
ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *, const char *); /* use zip_dir_add */
ZIP_EXTERN const char *zip_get_file_comment(zip_t *, zip_uint64_t, int *, int); /* use zip_file_get_comment */
Expand Down Expand Up @@ -378,7 +380,7 @@ ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *, zip_flags_t);
ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *, const char *, zip_flags_t);
ZIP_EXTERN zip_t *zip_open(const char *, int, int *);
ZIP_EXTERN zip_t *zip_open_from_source(zip_source_t *, int, zip_error_t *);
ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t);
ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *, double, zip_progress_callback, void (*)(void *), void *);
ZIP_EXTERN int zip_set_archive_comment(zip_t *, const char *, zip_uint16_t);
ZIP_EXTERN int zip_set_archive_flag(zip_t *, zip_flags_t, int);
ZIP_EXTERN int zip_set_default_password(zip_t *, const char *);
Expand Down
71 changes: 17 additions & 54 deletions lib/zip_close.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,10 @@
#endif


typedef struct {
double last_update; /* last value callback function was called with */

double start; /* start of sub-progress setcion */
double end; /* end of sub-progress setcion */
} progress_state_t;

static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, progress_state_t *);
static int copy_data(zip_t *, zip_uint64_t, progress_state_t *);
static int copy_source(zip_t *, zip_source_t *, progress_state_t *, zip_int64_t);
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
static int copy_data(zip_t *, zip_uint64_t);
static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
static void _zip_progress(zip_t *, progress_state_t *, double);

ZIP_EXTERN int
zip_close(zip_t *za)
Expand All @@ -72,7 +64,6 @@ zip_close(zip_t *za)
int error;
zip_filelist_t *filelist;
int changed;
progress_state_t progress_state;

if (za == NULL)
return -1;
Expand Down Expand Up @@ -129,22 +120,15 @@ zip_close(zip_t *za)
free(filelist);
return -1;
}

if (za->progress_callback) {
progress_state.last_update = 0.0;
za->progress_callback(0.0);
}

_zip_progress_start(za->progress);
error = 0;
for (j=0; j<survivors; j++) {
int new_data;
zip_entry_t *entry;
zip_dirent_t *de;

if (za->progress_callback) {
progress_state.start = (double)j / (double)survivors;
progress_state.end = (double)(j+1) / (double)survivors;
_zip_progress(za, &progress_state, 0.0);
}
_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j+1) / (double)survivors);

i = filelist[j].idx;
entry = za->entry+i;
Expand Down Expand Up @@ -184,7 +168,7 @@ zip_close(zip_t *za)
}

/* add_data writes dirent */
if (add_data(za, zs ? zs : entry->source, de, &progress_state) < 0) {
if (add_data(za, zs ? zs : entry->source, de) < 0) {
error = 1;
if (zs)
zip_source_free(zs);
Expand All @@ -211,7 +195,7 @@ zip_close(zip_t *za)
error = 1;
break;
}
if (copy_data(za, de->comp_size, &progress_state) < 0) {
if (copy_data(za, de->comp_size) < 0) {
error = 1;
break;
}
Expand All @@ -237,9 +221,7 @@ zip_close(zip_t *za)
return -1;
}

if (za->progress_callback) {
_zip_progress(za, &progress_state, 1.0);
}
_zip_progress_end(za->progress);

zip_discard(za);

Expand All @@ -248,7 +230,7 @@ zip_close(zip_t *za)


static int
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, progress_state_t *progress_state)
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
{
zip_int64_t offstart, offdata, offend, data_length;
struct zip_stat st;
Expand Down Expand Up @@ -430,7 +412,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, progress_state_t *progr
return -1;
}

ret = copy_source(za, src_final, progress_state, data_length);
ret = copy_source(za, src_final, data_length);

if (zip_source_stat(src_final, &st) < 0) {
_zip_error_set_from_source(&za->error, src_final);
Expand Down Expand Up @@ -495,7 +477,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, progress_state_t *progr


static int
copy_data(zip_t *za, zip_uint64_t len, progress_state_t *progress_state)
copy_data(zip_t *za, zip_uint64_t len)
{
zip_uint8_t buf[BUFSIZE];
size_t n;
Expand All @@ -512,18 +494,16 @@ copy_data(zip_t *za, zip_uint64_t len, progress_state_t *progress_state)
}

len -= n;

if (za->progress_callback) {
_zip_progress(za, progress_state, (total - (double)len) / total);
}

_zip_progress_update(za->progress, (total - (double)len) / total);
}

return 0;
}


static int
copy_source(zip_t *za, zip_source_t *src, progress_state_t *progress_state, zip_int64_t data_length)
copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length)
{
zip_uint8_t buf[BUFSIZE];
zip_int64_t n, current;
Expand All @@ -541,9 +521,9 @@ copy_source(zip_t *za, zip_source_t *src, progress_state_t *progress_state, zip_
ret = -1;
break;
}
if (n == sizeof(buf) && za->progress_callback && data_length > 0) {
if (n == sizeof(buf) && za->progress && data_length > 0) {
current += n;
_zip_progress(za, progress_state, (double)current/(double)data_length);
_zip_progress_update(za->progress, (double)current/(double)data_length);
}
}

Expand Down Expand Up @@ -602,20 +582,3 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp)

return changed;
}

static void
_zip_progress(zip_t *za, progress_state_t *progress_state, double sub_current)
{
double current;

if (za->progress_callback == NULL) {
return;
}

current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress_state->end - progress_state->start) + progress_state->start;

if (current - progress_state->last_update > 0.001) {
za->progress_callback(current);
progress_state->last_update = current;
}
}
2 changes: 2 additions & 0 deletions lib/zip_discard.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ zip_discard(zip_t *za)
}
free(za->open_source);

_zip_progress_free(za->progress);

zip_error_fini(&za->error);

free(za);
Expand Down
2 changes: 1 addition & 1 deletion lib/zip_new.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ _zip_new(zip_error_t *error)
za->entry = NULL;
za->nopen_source = za->nopen_source_alloc = 0;
za->open_source = NULL;
za->progress_callback = NULL;
za->progress = NULL;

return za;
}
6 changes: 0 additions & 6 deletions lib/zip_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,6 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error)
}
}

ZIP_EXTERN void
zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback)
{
za->progress_callback = progress_callback;
}


zip_t *
_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
Expand Down
Loading

0 comments on commit 9729dc3

Please sign in to comment.