2 zip_progress.c -- progress reporting
3 Copyright (C) 2017-2020 Dieter Baron and Thomas Klausner
5 This file is part of libzip, a library to manipulate ZIP archives.
6 The authors can be contacted at <info@libzip.org>
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in
15 the documentation and/or other materials provided with the
17 3. The names of the authors may not be used to endorse or promote
18 products derived from this software without specific prior
21 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #define _ZIP_COMPILING_DEPRECATED
44 zip_progress_callback callback_progress;
45 void (*ud_progress_free)(void *);
48 zip_cancel_callback callback_cancel;
49 void (*ud_cancel_free)(void *);
55 double last_update; /* last value callback function was called with */
57 double start; /* start of sub-progress section */
58 double end; /* end of sub-progress section */
61 static void _zip_progress_free_cancel_callback(zip_progress_t *progress);
62 static void _zip_progress_free_progress_callback(zip_progress_t *progress);
63 static zip_progress_t *_zip_progress_new(zip_t *za);
64 static void _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback callback, void (*ud_free)(void *), void *ud);
65 static void _zip_progress_set_progress_callback(zip_progress_t *progress, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud);
68 _zip_progress_end(zip_progress_t *progress) {
69 _zip_progress_update(progress, 1.0);
74 _zip_progress_free(zip_progress_t *progress) {
75 if (progress == NULL) {
79 _zip_progress_free_progress_callback(progress);
80 _zip_progress_free_cancel_callback(progress);
86 static zip_progress_t *
87 _zip_progress_new(zip_t *za) {
88 zip_progress_t *progress = (zip_progress_t *)malloc(sizeof(*progress));
90 if (progress == NULL) {
91 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
97 progress->callback_progress = NULL;
98 progress->ud_progress_free = NULL;
99 progress->ud_progress = NULL;
100 progress->precision = 0.0;
102 progress->callback_cancel = NULL;
103 progress->ud_cancel_free = NULL;
104 progress->ud_cancel = NULL;
110 _zip_progress_free_progress_callback(zip_progress_t *progress) {
111 if (progress->ud_progress_free) {
112 progress->ud_progress_free(progress->ud_progress);
115 progress->callback_progress = NULL;
116 progress->ud_progress = NULL;
117 progress->ud_progress_free = NULL;
121 _zip_progress_free_cancel_callback(zip_progress_t *progress) {
122 if (progress->ud_cancel_free) {
123 progress->ud_cancel_free(progress->ud_cancel);
126 progress->callback_cancel = NULL;
127 progress->ud_cancel = NULL;
128 progress->ud_cancel_free = NULL;
132 _zip_progress_set_progress_callback(zip_progress_t *progress, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
133 _zip_progress_free_progress_callback(progress);
135 progress->callback_progress = callback;
136 progress->ud_progress_free = ud_free;
137 progress->ud_progress = ud;
138 progress->precision = precision;
142 _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) {
143 _zip_progress_free_cancel_callback(progress);
145 progress->callback_cancel = callback;
146 progress->ud_cancel_free = ud_free;
147 progress->ud_cancel = ud;
151 _zip_progress_start(zip_progress_t *progress) {
152 if (progress == NULL) {
156 if (progress->callback_progress != NULL) {
157 progress->last_update = 0.0;
158 progress->callback_progress(progress->za, 0.0, progress->ud_progress);
161 if (progress->callback_cancel != NULL) {
162 if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
172 _zip_progress_subrange(zip_progress_t *progress, double start, double end) {
173 if (progress == NULL) {
177 progress->start = start;
180 return _zip_progress_update(progress, 0.0);
184 _zip_progress_update(zip_progress_t *progress, double sub_current) {
187 if (progress == NULL) {
191 if (progress->callback_progress != NULL) {
192 current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
194 if (current - progress->last_update > progress->precision) {
195 progress->callback_progress(progress->za, current, progress->ud_progress);
196 progress->last_update = current;
200 if (progress->callback_cancel != NULL) {
201 if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
211 zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
212 if (callback != NULL) {
213 if (za->progress == NULL) {
214 if ((za->progress = _zip_progress_new(za)) == NULL) {
219 _zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud);
222 if (za->progress != NULL) {
223 if (za->progress->callback_cancel == NULL) {
224 _zip_progress_free(za->progress);
228 _zip_progress_free_progress_callback(za->progress);
238 zip_register_cancel_callback_with_state(zip_t *za, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) {
239 if (callback != NULL) {
240 if (za->progress == NULL) {
241 if ((za->progress = _zip_progress_new(za)) == NULL) {
246 _zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud);
249 if (za->progress != NULL) {
250 if (za->progress->callback_progress == NULL) {
251 _zip_progress_free(za->progress);
255 _zip_progress_free_cancel_callback(za->progress);
265 zip_progress_callback_t callback;
270 _zip_legacy_progress_callback(zip_t *za, double progress, void *vud) {
271 struct legacy_ud *ud = (struct legacy_ud *)vud;
273 ud->callback(progress);
277 zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback) {
278 struct legacy_ud *ud;
280 if (progress_callback == NULL) {
281 zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
284 if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) {
288 ud->callback = progress_callback;
290 if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) {