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