percent.c 4.5 KB

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