basename.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*!
  2. * \file lib/gis/basename.c
  3. *
  4. * \brief GIS Library - Program basename routines.
  5. *
  6. * (C) 2001-2014 by the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public License
  9. * (>=v2). Read the file COPYING that comes with GRASS for details.
  10. *
  11. * \author GRASS GIS Development Team
  12. */
  13. #include <grass/gis.h>
  14. #include <math.h>
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. /*!
  20. * \brief Truncates filename to the base part (before the last '.')
  21. * if it matches the extension, otherwise leaves it unchanged.
  22. *
  23. * Checks if a filename matches a certain file extension
  24. * (case insensitive) and if so, truncates the string to the
  25. * base file name (cf. basename Unix command)
  26. *
  27. * \param filename string containing filename
  28. * \param desired_ext string containing extension to look for (case
  29. * insensitive)
  30. *
  31. * \return pointer to filename
  32. */
  33. char *G_basename(char *filename, const char *desired_ext)
  34. {
  35. /* Find the last . in the filename */
  36. char *dot = strrchr(filename, '.');
  37. if (dot && G_strcasecmp(dot + 1, desired_ext) == 0)
  38. *dot = '\0';
  39. return filename;
  40. }
  41. /*!
  42. * \brief Get number of decimals from a string
  43. *
  44. * \param str String to analyse
  45. *
  46. * \return number of decimals
  47. */
  48. size_t G_get_num_decimals(const char *str)
  49. {
  50. int sep = '.';
  51. size_t len;
  52. char *sep_ptr = strchr(str, sep);
  53. if (sep_ptr == NULL)
  54. return 0;
  55. len = strlen(str);
  56. return len - (size_t)(sep_ptr - str) - 1;
  57. }
  58. /*!
  59. * \brief Convert a double to a string substituting the dot with underscore
  60. * 12.3456 => '12_3456'
  61. *
  62. * \param number the double number that will be convert to string
  63. * \param ndigits the number of integer digits in the output string
  64. * \param ndecimals the number of decimals in the output string
  65. *
  66. * \return a formatted string
  67. */
  68. char *G_double_to_basename_format(double number,
  69. size_t ndigits, size_t ndecimals)
  70. {
  71. double integer, decimal;
  72. integer = floor(number);
  73. char intfmt[GNAME_MAX] = "%d";
  74. char intstr[GNAME_MAX];
  75. char decfmt[GNAME_MAX] = "";
  76. char decstr[GNAME_MAX] = "";
  77. char *result;
  78. if (ndigits != 0){
  79. sprintf(intfmt, "%%0%ud", ndigits);
  80. }
  81. sprintf(intstr, intfmt, (int)integer);
  82. if (ndecimals != 0){
  83. sprintf(decfmt, "_%%0%ud", ndecimals);
  84. decimal = ((number - integer) * pow(10., (double)ndecimals));
  85. sprintf(decstr, decfmt, (int)decimal);
  86. }
  87. result = G_malloc(strlen(intstr) + strlen(decstr) + 1);
  88. sprintf(result, "%s%s", intstr, decstr);
  89. return result;
  90. }
  91. /*!
  92. * \brief Return the environmental basename variable or the default
  93. * value
  94. *
  95. * return pointer to basename separator
  96. */
  97. char *G_get_basename_separator()
  98. {
  99. char *envvar = "GRASS_BASENAME_SEPARATOR";
  100. char *envsep;
  101. envsep = getenv(envvar);
  102. return (envsep != NULL && strlen(envsep) > 0) ? envsep: GBASENAME_SEP;
  103. }
  104. /*!
  105. * \brief join an array of strings using the basename separator
  106. *
  107. * \param strings is an array of strings
  108. * \param len is the length of the array
  109. *
  110. * \return a joined string
  111. */
  112. char *G_join_basename_strings(const char**strings, size_t len)
  113. {
  114. size_t i, length, lensep;
  115. char *result;
  116. char *separator;
  117. separator = G_get_basename_separator();
  118. lensep = strlen(separator);
  119. length = lensep * (len - 1) + 1;
  120. for (i = 0; i < len; i++){
  121. length += strlen(strings[i]);
  122. }
  123. result = G_malloc(length);
  124. if (result)
  125. {
  126. strcpy(result, strings[0]);
  127. for (i = 1; i < len; i++){
  128. strcat(result, separator);
  129. strcat(result, strings[i]);
  130. }
  131. }
  132. return result;
  133. }
  134. /*!
  135. * \brief Generate the format string
  136. *
  137. * \param basename String with the basename
  138. * \param digits Number of digits number
  139. * \param decimals Number of decimal number
  140. * \param filler String used to fill, default is 0
  141. *
  142. * \return Format string
  143. */
  144. char *G_generate_basename(const char *basename, double number,
  145. size_t ndigits, size_t ndecimals)
  146. {
  147. char *separator, *numberstr, *result;
  148. separator = G_get_basename_separator();
  149. numberstr = G_double_to_basename_format(number, ndigits, ndecimals);
  150. result = G_malloc(strlen(basename) + strlen(separator) + strlen(numberstr) + 1);
  151. if (result)
  152. sprintf(result, "%s%s%s", basename, separator, numberstr);
  153. return result;
  154. }