diff options
Diffstat (limited to 'src/Common/libzip/zip_progress.c')
-rw-r--r-- | src/Common/libzip/zip_progress.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/Common/libzip/zip_progress.c b/src/Common/libzip/zip_progress.c new file mode 100644 index 00000000..46c8bb81 --- /dev/null +++ b/src/Common/libzip/zip_progress.c @@ -0,0 +1,183 @@ +/* + zip_progress.c -- progress reporting + Copyright (C) 2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include <stdlib.h> + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + +struct zip_progress { + zip_t *za; + zip_progress_callback callback; + void (*ud_free)(void *); + + void *ud; + + double precision; + + /* state */ + double last_update; /* last value callback function was called with */ + + double start; /* start of sub-progress section */ + double end; /* end of sub-progress section */ +}; + + +void +_zip_progress_end(zip_progress_t *progress) { + _zip_progress_update(progress, 1.0); +} + + +void +_zip_progress_free(zip_progress_t *progress) { + if (progress == NULL) { + return; + } + + if (progress->ud_free) { + progress->ud_free(progress->ud); + } + + free(progress); +} + + +zip_progress_t * +_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) { + zip_progress_t *progress = (zip_progress_t *)malloc(sizeof(*progress)); + + if (progress == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + progress->za = za; + progress->callback = callback; + progress->ud_free = ud_free; + progress->ud = ud; + progress->precision = precision; + + return progress; +} + + +void +_zip_progress_start(zip_progress_t *progress) { + if (progress == NULL) { + return; + } + + progress->last_update = 0.0; + progress->callback(progress->za, 0.0, progress->ud); +} + + +void +_zip_progress_subrange(zip_progress_t *progress, double start, double end) { + if (progress == NULL) { + return; + } + + progress->start = start; + progress->end = end; + + _zip_progress_update(progress, 0.0); +} + +void +_zip_progress_update(zip_progress_t *progress, double sub_current) { + double current; + + if (progress == NULL) { + return; + } + + current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start; + + if (current - progress->last_update > progress->precision) { + progress->callback(progress->za, current, progress->ud); + progress->last_update = current; + } +} + + +ZIP_EXTERN int +zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) { + zip_progress_t *progress = NULL; + + if (callback != NULL) { + if ((progress = _zip_progress_new(za, precision, callback, ud_free, ud)) == NULL) { + return -1; + } + } + + _zip_progress_free(za->progress); + za->progress = progress; + + return 0; +} + + +struct legacy_ud { + zip_progress_callback_t callback; +}; + + +static void +_zip_legacy_progress_callback(zip_t *za, double progress, void *vud) { + struct legacy_ud *ud = (struct legacy_ud *)vud; + + ud->callback(progress); +} + +ZIP_EXTERN void +zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback) { + struct legacy_ud *ud; + + if (progress_callback == NULL) { + zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL); + } + + if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) { + return; + } + + ud->callback = progress_callback; + + if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) { + free(ud); + } +} |