quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

tool_cb_prg.c (7880B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 #include "tool_setup.h"
     25 
     26 #include "tool_cfgable.h"
     27 #include "tool_cb_prg.h"
     28 #include "tool_util.h"
     29 #include "tool_operate.h"
     30 #include "terminal.h"
     31 
     32 #include "memdebug.h" /* keep this as LAST include */
     33 
     34 #define MAX_BARLENGTH 400
     35 #define MIN_BARLENGTH 20
     36 
     37 /* 200 values generated by this perl code:
     38 
     39    my $pi = 3.1415;
     40    foreach my $i (1 .. 200) {
     41      printf "%d, ", sin($i/200 * 2 * $pi) * 500000 + 500000;
     42    }
     43 */
     44 static const int sinus[] = {
     45   515704, 531394, 547052, 562664, 578214, 593687, 609068, 624341, 639491,
     46   654504, 669364, 684057, 698568, 712883, 726989, 740870, 754513, 767906,
     47   781034, 793885, 806445, 818704, 830647, 842265, 853545, 864476, 875047,
     48   885248, 895069, 904500, 913532, 922156, 930363, 938145, 945495, 952406,
     49   958870, 964881, 970434, 975522, 980141, 984286, 987954, 991139, 993840,
     50   996054, 997778, 999011, 999752, 999999, 999754, 999014, 997783, 996060,
     51   993848, 991148, 987964, 984298, 980154, 975536, 970449, 964898, 958888,
     52   952426, 945516, 938168, 930386, 922180, 913558, 904527, 895097, 885277,
     53   875077, 864507, 853577, 842299, 830682, 818739, 806482, 793922, 781072,
     54   767945, 754553, 740910, 727030, 712925, 698610, 684100, 669407, 654548,
     55   639536, 624386, 609113, 593733, 578260, 562710, 547098, 531440, 515751,
     56   500046, 484341, 468651, 452993, 437381, 421830, 406357, 390976, 375703,
     57   360552, 345539, 330679, 315985, 301474, 287158, 273052, 259170, 245525,
     58   232132, 219003, 206152, 193590, 181331, 169386, 157768, 146487, 135555,
     59   124983, 114781, 104959, 95526, 86493, 77868, 69660, 61876, 54525, 47613,
     60   41147, 35135, 29581, 24491, 19871, 15724, 12056, 8868, 6166, 3951, 2225,
     61   990, 248, 0, 244, 982, 2212, 3933, 6144, 8842, 12025, 15690, 19832, 24448,
     62   29534, 35084, 41092, 47554, 54462, 61809, 69589, 77794, 86415, 95445,
     63   104873, 114692, 124891, 135460, 146389, 157667, 169282, 181224, 193480,
     64   206039, 218888, 232015, 245406, 259048, 272928, 287032, 301346, 315856,
     65   330548, 345407, 360419, 375568, 390841, 406221, 421693, 437243, 452854,
     66   468513, 484202, 499907
     67 };
     68 
     69 static void fly(struct ProgressData *bar, bool moved)
     70 {
     71   char buf[MAX_BARLENGTH + 2];
     72   int pos;
     73   int check = bar->width - 2;
     74 
     75   /* bar->width is range checked when assigned */
     76   DEBUGASSERT(bar->width <= MAX_BARLENGTH);
     77   buf[0] = '\r';
     78   memset(&buf[1], ' ', bar->width);
     79   buf[bar->width + 1] = '\0';
     80 
     81   memcpy(&buf[bar->bar + 1], "-=O=-", 5);
     82 
     83   pos = sinus[bar->tick%200] / (1000000 / check) + 1;
     84   buf[pos] = '#';
     85   pos = sinus[(bar->tick + 5)%200] / (1000000 / check) + 1;
     86   buf[pos] = '#';
     87   pos = sinus[(bar->tick + 10)%200] / (1000000 / check) + 1;
     88   buf[pos] = '#';
     89   pos = sinus[(bar->tick + 15)%200] / (1000000 / check) + 1;
     90   buf[pos] = '#';
     91 
     92   fputs(buf, bar->out);
     93   bar->tick += 2;
     94   if(bar->tick >= 200)
     95     bar->tick -= 200;
     96 
     97   bar->bar += (moved ? bar->barmove : 0);
     98   if(bar->bar >= (bar->width - 6)) {
     99     bar->barmove = -1;
    100     bar->bar = bar->width - 6;
    101   }
    102   else if(bar->bar < 0) {
    103     bar->barmove = 1;
    104     bar->bar = 0;
    105   }
    106 }
    107 
    108 /*
    109 ** callback for CURLOPT_XFERINFOFUNCTION
    110 */
    111 
    112 #if (SIZEOF_CURL_OFF_T < 8)
    113 #error "too small curl_off_t"
    114 #else
    115    /* assume SIZEOF_CURL_OFF_T == 8 */
    116 #  define CURL_OFF_T_MAX 0x7FFFFFFFFFFFFFFF
    117 #endif
    118 
    119 static void update_width(struct ProgressData *bar)
    120 {
    121   int cols = get_terminal_columns();
    122   if(cols > MAX_BARLENGTH)
    123     bar->width = MAX_BARLENGTH;
    124   else if(cols > MIN_BARLENGTH)
    125     bar->width = (int)cols;
    126   else
    127     bar->width = MIN_BARLENGTH;
    128 }
    129 
    130 int tool_progress_cb(void *clientp,
    131                      curl_off_t dltotal, curl_off_t dlnow,
    132                      curl_off_t ultotal, curl_off_t ulnow)
    133 {
    134   struct curltime now = curlx_now();
    135   struct per_transfer *per = clientp;
    136   struct OperationConfig *config = per->config;
    137   struct ProgressData *bar = &per->progressbar;
    138   curl_off_t total;
    139   curl_off_t point;
    140 
    141   /* Calculate expected transfer size. initial_size can be less than zero when
    142      indicating that we are expecting to get the filesize from the remote */
    143   if(bar->initial_size < 0) {
    144     if(dltotal || ultotal)
    145       total = dltotal + ultotal;
    146     else
    147       total = CURL_OFF_T_MAX;
    148   }
    149   else if((CURL_OFF_T_MAX - bar->initial_size) < (dltotal + ultotal))
    150     total = CURL_OFF_T_MAX;
    151   else
    152     total = dltotal + ultotal + bar->initial_size;
    153 
    154   /* Calculate the current progress. initial_size can be less than zero when
    155      indicating that we are expecting to get the filesize from the remote */
    156   if(bar->initial_size < 0) {
    157     if(dltotal || ultotal)
    158       point = dlnow + ulnow;
    159     else
    160       point = CURL_OFF_T_MAX;
    161   }
    162   else if((CURL_OFF_T_MAX - bar->initial_size) < (dlnow + ulnow))
    163     point = CURL_OFF_T_MAX;
    164   else
    165     point = dlnow + ulnow + bar->initial_size;
    166 
    167   if(bar->calls) {
    168     /* after first call... */
    169     if(total) {
    170       /* we know the total data to get... */
    171       if(bar->prev == point)
    172         /* progress did not change since last invoke */
    173         return 0;
    174       else if((curlx_timediff(now, bar->prevtime) < 100L) && point < total)
    175         /* limit progress-bar updating to 10 Hz except when we are at 100% */
    176         return 0;
    177     }
    178     else {
    179       /* total is unknown */
    180       if(curlx_timediff(now, bar->prevtime) < 100L)
    181         /* limit progress-bar updating to 10 Hz */
    182         return 0;
    183       update_width(bar);
    184       fly(bar, point != bar->prev);
    185     }
    186   }
    187 
    188   /* simply count invokes */
    189   bar->calls++;
    190 
    191   update_width(bar);
    192   if((total > 0) && (point != bar->prev)) {
    193     char line[MAX_BARLENGTH + 1];
    194     char format[40];
    195     double frac;
    196     double percent;
    197     int barwidth;
    198     size_t num;
    199     if(point > total)
    200       /* we have got more than the expected total! */
    201       total = point;
    202 
    203     frac = (double)point / (double)total;
    204     percent = frac * 100.0;
    205     barwidth = bar->width - 7;
    206     num = (size_t) (((double)barwidth) * frac);
    207     if(num > MAX_BARLENGTH)
    208       num = MAX_BARLENGTH;
    209     memset(line, '#', num);
    210     line[num] = '\0';
    211     msnprintf(format, sizeof(format), "\r%%-%ds %%5.1f%%%%", barwidth);
    212 #ifdef __clang__
    213 #pragma clang diagnostic push
    214 #pragma clang diagnostic ignored "-Wformat-nonliteral"
    215 #endif
    216     fprintf(bar->out, format, line, percent);
    217 #ifdef __clang__
    218 #pragma clang diagnostic pop
    219 #endif
    220   }
    221   fflush(bar->out);
    222   bar->prev = point;
    223   bar->prevtime = now;
    224 
    225   if(config->readbusy) {
    226     config->readbusy = FALSE;
    227     curl_easy_pause(per->curl, CURLPAUSE_CONT);
    228   }
    229 
    230   return 0;
    231 }
    232 
    233 void progressbarinit(struct ProgressData *bar,
    234                      struct OperationConfig *config)
    235 {
    236   memset(bar, 0, sizeof(struct ProgressData));
    237 
    238   /* pass the resume from value through to the progress function so it can
    239    * display progress towards total file not just the part that is left. */
    240   if(config->use_resume)
    241     bar->initial_size = config->resume_from;
    242 
    243   update_width(bar);
    244 
    245   bar->out = tool_stderr;
    246   bar->tick = 150;
    247   bar->barmove = 1;
    248 }