File: progress.h

package info (click to toggle)
r-cran-cli 3.6.5-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,300 kB
  • sloc: ansic: 16,412; cpp: 37; sh: 13; makefile: 2
file content (413 lines) | stat: -rw-r--r-- 11,772 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
#ifndef R_CLI_PROGRESS_H
#define R_CLI_PROGRESS_H

#include <R_ext/Rdynload.h>
#include <stdarg.h>

#ifdef __cplusplus
extern "C" {
#endif

// ----------------------------------------------------------------------
// Public API
// ----------------------------------------------------------------------

//' ### `CLI_SHOULD_TICK`
//'
//' A macro that evaluates to (int) 1 if a cli progress bar update is due,
//' and to (int) 0 otherwise. If the timer hasn't been initialized in this
//' compilation unit yet, then it is always 0. To initialize the timer,
//' call `cli_progress_init_timer()` or create a progress bar with
//' `cli_progress_bar()`.

#define CLI_SHOULD_TICK

//' ### `cli_progress_add()`
//'
//' ```c
//' void cli_progress_add(SEXP bar, double inc);
//' ```
//'
//' Add a number of progress units to the progress bar. It will also
//' trigger an update if an update is due.
//'
//' * `bar`: progress bar object.
//' * `inc`: progress increment.

static R_INLINE void cli_progress_add(SEXP bar, double inc);

//' ### `cli_progress_bar()`
//'
//' ```c
//' SEXP cli_progress_bar(double total, SEXP config);
//' ```
//'
//'  Create a new progress bar object. The returned progress bar object
//'  must be `PROTECT()`-ed.
//'
//' * `total`: Total number of progress units. Use `NA_REAL` if it is not
//'   known.
//' * `config`: R named list object of additional parameters. May be `NULL`
//'   (the C `NULL~) or `R_NilValue` (the R `NULL`) for the defaults.
//'
//' `config` may contain the following entries:
//'
//' * `name`: progress bar name.
//' * `status`: (initial) progress bar status.
//' * `type`: progress bar type.
//' * `total`: total number of progress units.
//' * `show_after`: show the progress bar after the specified number of
//'    seconds. This overrides the global `show_after` option.
//' * `format`: format string, must be specified for custom progress bars.
//' * `format_done`: format string for successful termination.
//' * `format_failed`: format string for unsuccessful termination.
//' * `clear`: whether to remove the progress bar from the screen after
//'   termination.
//' * `auto_terminate`: whether to terminate the progress bar when the
//'   number of current units equals the number of total progress units.
//'
//' #### Example
//'
//' ```c
//' #include <cli/progress.h>
//' SEXP progress_test1() {
//'   int i;
//'   SEXP bar = PROTECT(cli_progress_bar(1000, NULL));
//'   for (i = 0; i < 1000; i++) {
//'     cli_progress_sleep(0, 4 * 1000 * 1000);
//'     if (CLI_SHOULD_TICK) cli_progress_set(bar, i);
//'   }
//'   cli_progress_done(bar);
//'   UNPROTECT(1);
//'   return Rf_ScalarInteger(i);
//' }
//' ```

static R_INLINE SEXP cli_progress_bar(double total, SEXP config);

//' ### `cli_progress_done()`
//'
//' ```c
//' void cli_progress_done(SEXP bar);
//' ```
//'
//' Terminate the progress bar.
//'
//' * `bar`: progress bar object.

static R_INLINE void cli_progress_done(SEXP bar);

//' ### `cli_progress_init_timer()`
//'
//' ```c
//' void cli_progress_init_timer();
//' ```
//'
//' Initialize the cli timer without creating a progress bar.

static R_INLINE void cli_progress_init_timer(void);

//' ### `cli_progress_num()`
//'
//' ```c
//' int cli_progress_num();
//' ```
//'
//' Returns the number of currently active progress bars.

static R_INLINE int cli_progress_num(void);

//' ### `cli_progress_set()`
//'
//' ```c
//' void cli_progress_set(SEXP bar, double set);
//' ```
//'
//' Set the progress bar to the specified number of progress units.
//'
//' * `bar`: progress bar object.
//' * `set`: number of current progress progress units.

static R_INLINE void cli_progress_set(SEXP bar, double set);

//' ### `cli_progress_set_clear()`
//'
//' ```c
//' void cli_progress_set_clear(SEXP bar, int clear);
//' ```
//'
//' Set whether to remove the progress bar from the screen. You can call
//' this any time before `cli_progress_done()` is called.
//'
//' * `bar`: progress bar object.
//' * `clear`: whether to remove the progress bar from the screen, zero or
//'   one.

static R_INLINE void cli_progress_set_clear(SEXP bar, int clear);

//' ### `cli_progress_set_format()`
//'
//' ```c
//' void cli_progress_set_format(SEXP bar, const char *format, ...);
//' ```
//'
//' Set a custom format string for the progress bar. This call does not
//' try to update the progress bar. If you want to request an update,
//' call `cli_progress_add()`, `cli_progress_set()` or
//' `cli_progress_update()`.
//'
//' * `bar`: progress bar object.
//' * `format`: format string.
//' * `...`: values to substitute into `format`.
//'
//' `format` and `...` are passed to `vsnprintf()` to create a format
//' string.
//'
//' Format strings may contain glue substitutions, referring to
//' [progress variables][progress-variables], pluralization, and cli
//' styling.
//'
//' [progress-variables]: https://cli.r-lib.org/dev/reference/progress-variables.html

static R_INLINE void cli_progress_set_format(SEXP bar, const char *format, ...);

//' ### `cli_progress_set_name()`
//'
//' ```c
//' void cli_progress_set_name(SEXP bar, const char *name);
//' ```
//'
//' Set the name of the progress bar.
//'
//' * `bar`; progress bar object.
//' * `name`: progress bar name.

static R_INLINE void cli_progress_set_name(SEXP bar, const char *name);

//' ### `cli_progress_set_status()`
//'
//' ```c
//' void cli_progress_set_status(SEXP bar, const char *status);
//' ```
//'
//' Set the status of the progress bar.
//'
//' * `bar`: progress bar object.
//' * `status `: progress bar status.

static R_INLINE void cli_progress_set_status(SEXP bar, const char *status);

//' ### `cli_progress_set_type()`
//'
//' ```c
//' void cli_progress_set_type(SEXP bar, const char *type);
//' ```
//'
//' Set the progress bar type. Call this function right after creating
//' the progress bar with `cli_progress_bar()`. Otherwise the behavior is
//' undefined.
//'
//' * `bar`: progress bar object.
//' * `type`: progress bar type. Possible progress bar types:
//'   `iterator`, `tasks`, `download` and `custom`.

static R_INLINE void cli_progress_set_type(SEXP bar, const char *type);

//' ### `cli_progress_update()`
//'
//' ```c
//' void cli_progress_update(SEXP bar, double set, double inc, int force);
//' ```
//'
//' Update the progress bar. Unlike the simpler `cli_progress_add()` and
//' `cli_progress_set()` function, it can force an update if `force` is
//' set to 1.
//'
//' * `bar`: progress bar object.
//' * `set`: the number of current progress units. It is ignored if
//'   negative.
//' * `inc`: increment to add to the current number of progress units.
//'   It is ignored if `set` is not negative.
//' * `force`: whether to force an update, even if no update is due.
//'
//' To force an update without changing the current number of progress units,
//' supply `set = -1`, `inc = 0` and `force = 1`.

static R_INLINE void cli_progress_update(SEXP bar, double set, double inc, int force);

// ----------------------------------------------------------------------
// Internals
// ----------------------------------------------------------------------

typedef volatile int vint;

static vint cli__false = 0;
static vint *cli__should_tick = &cli__false;

#ifndef __has_builtin         // Optional of course.
  #define __has_builtin(x) 0  // Compatibility with non-clang compilers.
#endif

#if __has_builtin (__builtin_expect)
#   define CLI_UNLIKELY(a) __builtin_expect((a), 0)
#   define CLI_LIKELY(a)   __builtin_expect((a), 1)
# else
#   define CLI_UNLIKELY(a) a
#   define CLI_LIKELY(a)   a
#endif

#undef CLI_SHOULD_TICK
#define CLI_SHOULD_TICK (CLI_UNLIKELY(*cli__should_tick))

static R_INLINE void cli_progress_done(SEXP bar) {
  if (Rf_isNull(bar)) return;
  static void (*ptr)(SEXP) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(SEXP)) R_GetCCallable("cli", "cli_progress_done");
  }
  ptr(bar);
}

#ifdef R_CLEANCALL_SUPPORT
static void cli_progress_done2(SEXP bar) {
  if (Rf_isNull(bar)) return;
  static void (*ptr)(SEXP) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(SEXP)) R_GetCCallable("cli", "cli_progress_done");
  }
  ptr(bar);
}
#endif

static R_INLINE void cli_progress_init_timer(void) {
  static void (*ptr)(vint **) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(vint **)) R_GetCCallable("cli", "cli_progress_init_timer");
  }
  ptr(&cli__should_tick);
}

static R_INLINE SEXP cli_progress_bar(double total, SEXP config) {
  static SEXP (*ptr)(vint **, double, SEXP) = NULL;
  if (ptr == NULL) {
    ptr = (SEXP (*)(vint **, double, SEXP)) R_GetCCallable("cli", "cli_progress_bar");
  }

  SEXP bar = PROTECT(ptr(&cli__should_tick, total, config));

#ifdef R_CLEANCALL_SUPPORT
  if (r_cleancall_is_active()) {
    r_call_on_early_exit((void (*)(void *)) cli_progress_done2, (void*) bar);
  }
#endif

  UNPROTECT(1);
  return bar;
}

static R_INLINE void cli_progress_set_name(SEXP bar, const char *name) {
  if (Rf_isNull(bar)) return;
  static void (*ptr)(SEXP, const char*) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(SEXP, const char*))
      R_GetCCallable("cli", "cli_progress_set_name");
  }
  ptr(bar, name);
}

static R_INLINE void cli_progress_set_status(SEXP bar, const char *status) {
  if (Rf_isNull(bar)) return;
  static void (*ptr)(SEXP, const char*) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(SEXP, const char*))
      R_GetCCallable("cli", "cli_progress_set_status");
  }
  ptr(bar, status);
}

static R_INLINE void cli_progress_set_type(SEXP bar, const char *type) {
  if (Rf_isNull(bar)) return;
  static void (*ptr)(SEXP, const char*) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(SEXP, const char*))
      R_GetCCallable("cli", "cli_progress_set_type");
  }
  ptr(bar, type);
}

static R_INLINE void cli_progress_set_clear(SEXP bar, int clear) {
  if (Rf_isNull(bar)) return;
  static void (*ptr)(SEXP, int) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(SEXP, int))
      R_GetCCallable("cli", "cli_progress_set_clear");
  }
  ptr(bar, clear);
}

static R_INLINE void cli_progress_set(SEXP bar, double set) {
  if (Rf_isNull(bar)) return;
  static void (*ptr)(SEXP, double) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(SEXP, double)) R_GetCCallable("cli", "cli_progress_set");
  }
  ptr(bar, set);
}

static R_INLINE void cli_progress_set_format(SEXP bar, const char *format, ...) {
  if (Rf_isNull(bar)) return;
  static void (*ptr)(SEXP, const char*) = NULL;
  static char str[1024];
  if (ptr == NULL) {
    ptr = (void (*)(SEXP, const char*))
      R_GetCCallable("cli", "cli_progress_set_format");
  }

  va_list ap;
  va_start(ap, format);
  vsnprintf(str, sizeof(str) / sizeof(char), format, ap);

  ptr(bar, str);
}

static R_INLINE void cli_progress_add(SEXP bar, double inc) {
  if (Rf_isNull(bar)) return;
  static void (*ptr)(SEXP, double) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(SEXP, double)) R_GetCCallable("cli", "cli_progress_add");
  }
  ptr(bar, inc);
}

static R_INLINE int cli_progress_num(void) {
  static int (*ptr)(void) = NULL;
  if (ptr == NULL) {
    ptr = (int (*)(void)) R_GetCCallable("cli", "cli_progress_num");
  }
  return ptr();
}

static R_INLINE void cli_progress_sleep(int s, long ns) {
  static void (*ptr)(int, long) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(int, long)) R_GetCCallable("cli", "cli_progress_sleep");
  }
  ptr(s, ns);
}

static R_INLINE void cli_progress_update(SEXP bar,
                                         double set,
                                         double inc,
                                         int force) {
  static void (*ptr)(SEXP, double, double, int) = NULL;
  if (ptr == NULL) {
    ptr = (void (*)(SEXP, double, double, int)) R_GetCCallable("cli", "cli_progress_update");
  }
  ptr(bar, set, inc, force);
}

#ifdef __cplusplus
}
#endif

#endif