GRASS GIS 8 Programmer's Manual 8.2.1(2023)-exported
percent.c
Go to the documentation of this file.
1
2/*!
3 \file lib/gis/percent.c
4
5 \brief GIS Library - percentage progress functions.
6
7 (C) 2001-2009, 2011 by the GRASS Development Team
8
9 This program is free software under the GNU General Public License
10 (>=v2). Read the file COPYING that comes with GRASS for details.
11
12 \author GRASS GIS Development Team
13*/
14
15#include <stdio.h>
16#include <grass/gis.h>
17
18static struct state {
19 int prev;
20 int first;
21} state = {-1, 1};
22
23static struct state *st = &state;
24static int (*ext_percent) (int);
25
26/*!
27 \brief Print percent complete messages.
28
29 This routine prints a percentage complete message to stderr. The
30 percentage complete is <i>(<b>n</b>/<b>d</b>)*100</i>, and these are
31 printed only for each <b>s</b> percentage. This is perhaps best
32 explained by example:
33 \code
34 #include <stdio.h>
35 #include <grass/gis.h>
36 int row;
37 int nrows;
38 nrows = 1352; // 1352 is not a special value - example only
39
40 G_message(_("Percent complete..."));
41 for (row = 0; row < nrows; row++)
42 {
43 G_percent(row, nrows, 10);
44 do_calculation(row);
45 }
46 G_percent(1, 1, 1);
47 \endcode
48
49 This example code will print completion messages at 10% increments;
50 i.e., 0%, 10%, 20%, 30%, etc., up to 100%. Each message does not appear
51 on a new line, but rather erases the previous message.
52
53 Note that to prevent the illusion of the module stalling, the G_percent()
54 call is placed before the time consuming part of the for loop, and an
55 additional call is generally needed after the loop to "finish it off"
56 at 100%.
57
58 \param n current element
59 \param d total number of elements
60 \param s increment size
61*/
62void G_percent(long n, long d, int s)
63{
64 int x, format;
65
66 format = G_info_format();
67
68 x = (d <= 0 || s <= 0)
69 ? 100 : (int)(100 * n / d);
70
71 /* be verbose only 1> */
72 if (format == G_INFO_FORMAT_SILENT || G_verbose() < 1)
73 return;
74
75 if (n <= 0 || n >= d || x > st->prev + s) {
76 st->prev = x;
77
78 if (ext_percent) {
79 ext_percent(x);
80 }
81 else {
82 if (format == G_INFO_FORMAT_STANDARD) {
83 fprintf(stderr, "%4d%%\b\b\b\b\b", x);
84 }
85 else {
86 if (format == G_INFO_FORMAT_PLAIN) {
87 if (x == 100)
88 fprintf(stderr, "%d\n", x);
89 else
90 fprintf(stderr, "%d..", x);
91 }
92 else { /* GUI */
93 if (st->first) {
94 fprintf(stderr, "\n");
95 }
96 fprintf(stderr, "GRASS_INFO_PERCENT: %d\n", x);
97 fflush(stderr);
98 st->first = 0;
99 }
100 }
101 }
102 }
103
104 if (x >= 100) {
105 if (ext_percent) {
106 ext_percent(100);
107 }
108 else if (format == G_INFO_FORMAT_STANDARD) {
109 fprintf(stderr, "\n");
110 }
111 st->prev = -1;
112 st->first = 1;
113 }
114}
115
116/*!
117 \brief Reset G_percent() to 0%; do not add newline.
118*/
120{
121 st->prev = -1;
122 st->first = 1;
123}
124
125/*!
126 \brief Print progress info messages
127
128 Use G_percent() when number of elements is defined.
129
130 This routine prints a progress info message to stderr. The value
131 <b>n</b> is printed only for each <b>s</b>. This is perhaps best
132 explained by example:
133 \code
134 #include <grass/vector.h>
135
136 int line;
137
138 G_message(_("Reading features..."));
139 line = 0;
140 while(TRUE)
141 {
142 if (Vect_read_next_line(Map, Points, Cats) < 0)
143 break;
144 line++;
145 G_progress(line, 1e3);
146 }
147 G_progress(1, 1);
148 \endcode
149
150 This example code will print progress in messages at 1000
151 increments; i.e., 1000, 2000, 3000, 4000, etc., up to number of
152 features for given vector map. Each message does not appear on a new
153 line, but rather erases the previous message.
154
155 \param n current element
156 \param s increment size
157
158 \return always returns 0
159*/
160void G_progress(long n, int s)
161{
162 int format;
163
164 format = G_info_format();
165
166 /* be verbose only 1> */
167 if (format == G_INFO_FORMAT_SILENT || G_verbose() < 1)
168 return;
169
170 if (n == s && n == 1) {
171 if (format == G_INFO_FORMAT_PLAIN)
172 fprintf(stderr, "\n");
173 else if (format != G_INFO_FORMAT_GUI)
174 fprintf(stderr, "\r");
175 return;
176 }
177
178 if (n % s == 0) {
179 if (format == G_INFO_FORMAT_PLAIN)
180 fprintf(stderr, "%ld..", n);
181 else if (format == G_INFO_FORMAT_GUI)
182 fprintf(stderr, "GRASS_INFO_PROGRESS: %ld\n", n);
183 else
184 fprintf(stderr, "%10ld\b\b\b\b\b\b\b\b\b\b", n);
185 }
186}
187
188/*!
189 \brief Establishes percent_routine as the routine that will handle
190 the printing of percentage progress messages.
191
192 \param percent_routine routine will be called like this: percent_routine(x)
193*/
194void G_set_percent_routine(int (*percent_routine) (int))
195{
196 ext_percent = percent_routine;
197}
198
199/*!
200 \brief After this call subsequent percentage progress messages will
201 be handled in the default method.
202
203 Percentage progress messages are printed directly to stderr.
204*/
206{
207 ext_percent = NULL;
208}
#define NULL
Definition: ccmath.h:32
int G_info_format(void)
Get current message format.
Definition: gis/error.c:532
struct state state
Definition: parser.c:103
struct state * st
Definition: parser.c:104
void G_percent_reset(void)
Reset G_percent() to 0%; do not add newline.
Definition: percent.c:119
void G_unset_percent_routine(void)
After this call subsequent percentage progress messages will be handled in the default method.
Definition: percent.c:205
void G_percent(long n, long d, int s)
Print percent complete messages.
Definition: percent.c:62
void G_set_percent_routine(int(*percent_routine)(int))
Establishes percent_routine as the routine that will handle the printing of percentage progress messa...
Definition: percent.c:194
void G_progress(long n, int s)
Print progress info messages.
Definition: percent.c:160
int G_verbose(void)
Get current verbosity level.
Definition: verbose.c:55
#define x