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