⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 progress.c

📁 一个从网络上自动下载文件的自由工具
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Download progress.   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008   Free Software Foundation, Inc.This file is part of GNU Wget.GNU Wget is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 3 of the License, or(at your option) any later version.GNU Wget is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with Wget.  If not, see <http://www.gnu.org/licenses/>.Additional permission under GNU GPL version 3 section 7If you modify this program, or any covered work, by linking orcombining it with the OpenSSL project's OpenSSL library (or amodified version of that library), containing parts covered by theterms of the OpenSSL or SSLeay licenses, the Free Software Foundationgrants you additional permission to convey the resulting work.Corresponding Source for a non-source form of such a combinationshall include the source code for the parts of OpenSSL used as wellas that of the covered work.  */#include <config.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#include <signal.h>#include "wget.h"#include "progress.h"#include "utils.h"#include "retr.h"struct progress_implementation {  const char *name;  bool interactive;  void *(*create) (wgint, wgint);  void (*update) (void *, wgint, double);  void (*finish) (void *, double);  void (*set_params) (const char *);};/* Necessary forward declarations. */static void *dot_create (wgint, wgint);static void dot_update (void *, wgint, double);static void dot_finish (void *, double);static void dot_set_params (const char *);static void *bar_create (wgint, wgint);static void bar_update (void *, wgint, double);static void bar_finish (void *, double);static void bar_set_params (const char *);static struct progress_implementation implementations[] = {  { "dot", 0, dot_create, dot_update, dot_finish, dot_set_params },  { "bar", 1, bar_create, bar_update, bar_finish, bar_set_params }};static struct progress_implementation *current_impl;static int current_impl_locked;/* Progress implementation used by default.  Can be overriden in   wgetrc or by the fallback one.  */#define DEFAULT_PROGRESS_IMPLEMENTATION "bar"/* Fallback progress implementation should be something that works   under all display types.  If you put something other than "dot"   here, remember that bar_set_params tries to switch to this if we're   not running on a TTY.  So changing this to "bar" could cause   infloop.  */#define FALLBACK_PROGRESS_IMPLEMENTATION "dot"/* Return true if NAME names a valid progress bar implementation.  The   characters after the first : will be ignored.  */boolvalid_progress_implementation_p (const char *name){  int i;  struct progress_implementation *pi = implementations;  char *colon = strchr (name, ':');  int namelen = colon ? colon - name : strlen (name);  for (i = 0; i < countof (implementations); i++, pi++)    if (!strncmp (pi->name, name, namelen))      return true;  return false;}/* Set the progress implementation to NAME.  */voidset_progress_implementation (const char *name){  int i, namelen;  struct progress_implementation *pi = implementations;  const char *colon;  if (!name)    name = DEFAULT_PROGRESS_IMPLEMENTATION;  colon = strchr (name, ':');  namelen = colon ? colon - name : strlen (name);  for (i = 0; i < countof (implementations); i++, pi++)    if (!strncmp (pi->name, name, namelen))      {        current_impl = pi;        current_impl_locked = 0;        if (colon)          /* We call pi->set_params even if colon is NULL because we             want to give the implementation a chance to set up some             things it needs to run.  */          ++colon;        if (pi->set_params)          pi->set_params (colon);        return;      }  abort ();}static int output_redirected;voidprogress_schedule_redirect (void){  output_redirected = 1;}/* Create a progress gauge.  INITIAL is the number of bytes the   download starts from (zero if the download starts from scratch).   TOTAL is the expected total number of bytes in this download.  If   TOTAL is zero, it means that the download size is not known in   advance.  */void *progress_create (wgint initial, wgint total){  /* Check if the log status has changed under our feet. */  if (output_redirected)    {      if (!current_impl_locked)        set_progress_implementation (FALLBACK_PROGRESS_IMPLEMENTATION);      output_redirected = 0;    }  return current_impl->create (initial, total);}/* Return true if the progress gauge is "interactive", i.e. if it can   profit from being called regularly even in absence of data.  The   progress bar is interactive because it regularly updates the ETA   and current update.  */boolprogress_interactive_p (void *progress){  return current_impl->interactive;}/* Inform the progress gauge of newly received bytes.  DLTIME is the   time since the beginning of the download.  */voidprogress_update (void *progress, wgint howmuch, double dltime){  current_impl->update (progress, howmuch, dltime);}/* Tell the progress gauge to clean up.  Calling this will free the   PROGRESS object, the further use of which is not allowed.  */voidprogress_finish (void *progress, double dltime){  current_impl->finish (progress, dltime);}/* Dot-printing. */struct dot_progress {  wgint initial_length;         /* how many bytes have been downloaded                                   previously. */  wgint total_length;           /* expected total byte count when the                                   download finishes */  int accumulated;              /* number of bytes accumulated after                                   the last printed dot */  int rows;                     /* number of rows printed so far */  int dots;                     /* number of dots printed in this row */  double last_timer_value;};/* Dot-progress backend for progress_create. */static void *dot_create (wgint initial, wgint total){  struct dot_progress *dp = xnew0 (struct dot_progress);  dp->initial_length = initial;  dp->total_length   = total;  if (dp->initial_length)    {      int dot_bytes = opt.dot_bytes;      const wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;      int remainder = dp->initial_length % ROW_BYTES;      wgint skipped = dp->initial_length - remainder;      if (skipped)        {          wgint skipped_k = skipped / 1024; /* skipped amount in K */          int skipped_k_len = numdigit (skipped_k);          if (skipped_k_len < 6)            skipped_k_len = 6;          /* Align the [ skipping ... ] line with the dots.  To do             that, insert the number of spaces equal to the number of             digits in the skipped amount in K.  */          logprintf (LOG_VERBOSE, _("\n%*s[ skipping %sK ]"),                     2 + skipped_k_len, "",                     number_to_static_string (skipped_k));        }      logprintf (LOG_VERBOSE, "\n%6sK",                 number_to_static_string (skipped / 1024));      for (; remainder >= dot_bytes; remainder -= dot_bytes)        {          if (dp->dots % opt.dot_spacing == 0)            logputs (LOG_VERBOSE, " ");          logputs (LOG_VERBOSE, ",");          ++dp->dots;        }      assert (dp->dots < opt.dots_in_line);      dp->accumulated = remainder;      dp->rows = skipped / ROW_BYTES;    }  return dp;}static const char *eta_to_human_short (int, bool);/* Prints the stats (percentage of completion, speed, ETA) for current   row.  DLTIME is the time spent downloading the data in current   row.   #### This function is somewhat uglified by the fact that current   row and last row have somewhat different stats requirements.  It   might be worthwhile to split it to two different functions.  */static voidprint_row_stats (struct dot_progress *dp, double dltime, bool last){  const wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;  /* bytes_displayed is the number of bytes indicated to the user by     dots printed so far, includes the initially "skipped" amount */  wgint bytes_displayed = dp->rows * ROW_BYTES + dp->dots * opt.dot_bytes;  if (last)    /* For last row also count bytes accumulated after last dot */    bytes_displayed += dp->accumulated;  if (dp->total_length)    {      /* Round to floor value to provide gauge how much data *has*         been retrieved.  12.8% will round to 12% because the 13% mark         has not yet been reached.  100% is only shown when done.  */      int percentage = 100.0 * bytes_displayed / dp->total_length;      logprintf (LOG_VERBOSE, "%3d%%", percentage);    }  {    static char names[] = {' ', 'K', 'M', 'G'};    int units;    double rate;    wgint bytes_this_row;    if (!last)      bytes_this_row = ROW_BYTES;    else      /* For last row also include bytes accumulated after last dot.  */      bytes_this_row = dp->dots * opt.dot_bytes + dp->accumulated;    /* Don't count the portion of the row belonging to initial_length */    if (dp->rows == dp->initial_length / ROW_BYTES)      bytes_this_row -= dp->initial_length % ROW_BYTES;    rate = calc_rate (bytes_this_row, dltime - dp->last_timer_value, &units);    logprintf (LOG_VERBOSE, " %4.*f%c",               rate >= 99.95 ? 0 : rate >= 9.995 ? 1 : 2,               rate, names[units]);    dp->last_timer_value = dltime;  }  if (!last)    {      /* Display ETA based on average speed.  Inspired by Vladi         Belperchinov-Shabanski's "wget-new-percentage" patch.  */      if (dp->total_length)        {          wgint bytes_remaining = dp->total_length - bytes_displayed;          /* The quantity downloaded in this download run. */          wgint bytes_sofar = bytes_displayed - dp->initial_length;          double eta = dltime * bytes_remaining / bytes_sofar;          if (eta < INT_MAX - 1)            logprintf (LOG_VERBOSE, " %s",                       eta_to_human_short ((int) (eta + 0.5), true));        }    }  else    {      /* When done, print the total download time */      if (dltime >= 10)        logprintf (LOG_VERBOSE, "=%s",                   eta_to_human_short ((int) (dltime + 0.5), true));      else        logprintf (LOG_VERBOSE, "=%ss", print_decimal (dltime));    }}/* Dot-progress backend for progress_update. */static voiddot_update (void *progress, wgint howmuch, double dltime){  struct dot_progress *dp = progress;  int dot_bytes = opt.dot_bytes;  wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;  log_set_flush (false);  dp->accumulated += howmuch;  for (; dp->accumulated >= dot_bytes; dp->accumulated -= dot_bytes)    {      if (dp->dots == 0)        logprintf (LOG_VERBOSE, "\n%6sK",                   number_to_static_string (dp->rows * ROW_BYTES / 1024));      if (dp->dots % opt.dot_spacing == 0)        logputs (LOG_VERBOSE, " ");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -