GRASS 8 Programmer's Manual 8.6.0dev(2026)-f6f2c534ea
Loading...
Searching...
No Matches
raster_metadata.c
Go to the documentation of this file.
1/*!
2 \file lib/raster/raster_metadata.c
3
4 \brief Raster library - Functions to read and write raster "units",
5 "semantic label" and "vertical datum" meta-data info
6
7 (C) 2007-2009, 2021 by Hamish Bowman, Maris Nartiss,
8 and the GRASS Development Team
9
10 This program is free software under the GNU General Public License
11 (>=v2). Read the file COPYING that comes with GRASS for details.
12
13 \author Hamish Bowman
14 */
15
16#include <stdbool.h>
17#include <stdio.h>
18#include <string.h>
19
20#include <grass/gis.h>
21#include <grass/raster.h>
22#include <grass/glocale.h>
23
24static char *misc_read_line(const char *, const char *, const char *);
25static void misc_write_line(const char *, const char *, const char *);
26
27/*!
28 * \brief Get a raster map's units metadata string
29 *
30 * Read the raster's units metadata file and put string in str
31 *
32 * \param name raster map name
33 * \param mapset mapset name
34 *
35 * \return string representing units on success
36 * \return NULL on error
37 */
38char *Rast_read_units(const char *name, const char *mapset)
39{
40 return misc_read_line("units", name, mapset);
41}
42
43/*!
44 * \brief Write a string to a raster map's units metadata file
45 *
46 * Raster map must exist in the current mapset.
47 *
48 * \param name raster map name
49 * \param str string containing data to be written
50 */
51void Rast_write_units(const char *name, const char *str)
52{
53 misc_write_line("units", name, str);
54}
55
56/*!
57 * \brief Get a raster map's vertical datum metadata string
58 *
59 * Read the raster's vertical datum metadata file and put string in str
60 *
61 * \param name raster map name
62 * \param mapset mapset name
63 *
64 * \return string representing vertical datum on success
65 * \return NULL on error
66 */
67char *Rast_read_vdatum(const char *name, const char *mapset)
68{
69 return misc_read_line("vertical_datum", name, mapset);
70}
71
72/*!
73 * \brief Write a string into a raster's vertical datum metadata file
74 *
75 * Raster map must exist in the current mapset.
76 *
77 * \param name raster map name
78 * \param str string containing data to be written
79 */
80void Rast_write_vdatum(const char *name, const char *str)
81{
82 misc_write_line("vertical_datum", name, str);
83}
84
85/*!
86 * \brief Get a raster map semantic label metadata string
87 *
88 * Read raster semantic label metadata file and put string in to str
89 *
90 * \param name raster map name
91 * \param mapset mapset name
92 *
93 * \return string representing semantic label on success
94 * \return NULL on error
95 */
96char *Rast_read_semantic_label(const char *name, const char *mapset)
97{
98 return misc_read_line("semantic_label", name, mapset);
99}
100
101/*!
102 * \brief Get a raster map semantic label or fall back to its name
103 *
104 * Use this function if a semantic label is needed but not mandated.
105 *
106 * \param name raster map name
107 * \param mapset mapset name
108 *
109 * \return string representing semantic label or map name
110 */
111char *Rast_get_semantic_label_or_name(const char *name, const char *mapset)
112{
113 char *buff;
114
115 buff = Rast_read_semantic_label(name, mapset);
116 return buff ? buff : G_store(name);
117}
118
119/*!
120 * \brief Write a string into a rasters semantic label metadata file
121 *
122 * Raster map must exist in the current mapset.
123 *
124 * It is up to the caller to validate semantic label string in advance
125 * with Rast_legal_semantic_label().
126 *
127 * \param name raster map name
128 * \param str string containing data to be written
129 */
130void Rast_write_semantic_label(const char *name, const char *str)
131{
132 misc_write_line("semantic_label", name, str);
133}
134
135/*!
136 * \brief Check for legal semantic label
137 *
138 * Legal semantic label must be a legal GRASS file name.
139 * Semantic labels are capped in length to GNAME_MAX.
140 *
141 * This function will return false if provided semantic label is not
142 * considered to be valid.
143 * This function does not check if semantic label maps to any entry in
144 * metadata files of semantic labels as not all semantic labels have
145 * files with extra metadata.
146 *
147 * The function prints a warning on error.
148 *
149 * \param semantic label reference to check
150 *
151 * \return true success
152 * \return false failure
153 */
155{
156 const char *s;
157
159 G_warning(_("Semantic label is too long"));
160 return false;
161 }
162
164 return false;
165
166 s = semantic_label;
167 while (*s) {
168 if (!((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') ||
169 (*s >= '0' && *s <= '9') || *s == '_' || *s == '-')) {
170 G_warning(_("Character '%c' not allowed in a semantic label."), *s);
171 return false;
172 }
173 s++;
174 }
175
176 return true;
177}
178
179/*!
180 * \brief Read the first line of a file in cell_misc/
181 *
182 * Read the first line of data from a cell_misc/ meta-data file.
183 *
184 * \param element metadata component filename
185 * \param name
186 * \param mapset
187 * \return dynamically-allocated string on success
188 * \return NULL on error
189 */
190static char *misc_read_line(const char *elem, const char *name,
191 const char *mapset)
192{
193 char buff[GNAME_MAX];
194 FILE *fp;
195
196 buff[0] = '\0';
197
198 if (G_find_file2_misc("cell_misc", elem, name, mapset) == NULL)
199 return NULL;
200
201 fp = G_fopen_old_misc("cell_misc", elem, name, mapset);
202 if (!fp) {
203 G_warning(_("Unable to read <%s> for raster map <%s@%s>"), elem, name,
204 mapset);
205 return NULL;
206 }
207 if (G_getl2(buff, sizeof(buff) - 1, fp) == 0) {
208 /* file is empty */
209 *buff = '\0';
210 }
211
212 if (fclose(fp) != 0)
214 _("Error closing <%s> metadata file for raster map <%s@%s>"), elem,
215 name, mapset);
216
217 return *buff ? G_store(buff) : NULL;
218}
219
220/*!
221 * \brief Write a line to a raster map metadata file
222 *
223 * Write (including overwrite) a string into a raster map's metadata file
224 * found in in cell_misc/ in the current mapset.
225 *
226 * \param element metadata component filename
227 * \param name
228 * \param *str string containing data to be written
229 */
230static void misc_write_line(const char *elem, const char *name, const char *str)
231{
232 FILE *fp;
233
234 fp = G_fopen_new_misc("cell_misc", elem, name);
235 if (!fp) {
237 _("Unable to create <%s> metadata file for raster map <%s@%s>"),
238 elem, name, G_mapset());
239 } /* This else block is unnecessary but helps to silence static code
240 analysis tools */
241 else {
242 fprintf(fp, "%s\n", str);
243
244 if (fclose(fp) != 0)
246 _("Error closing <%s> metadata file for raster map <%s@%s>"),
247 elem, name, G_mapset());
248 }
249}
#define NULL
Definition ccmath.h:32
int G_getl2(char *, int, FILE *)
Gets a line of text from a file of any pedigree.
Definition getl.c:60
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int G_legal_filename(const char *)
Check for legal database file name.
Definition legal_name.c:34
const char * G_find_file2_misc(const char *, const char *, const char *, const char *)
Searches for a misc file from the mapset search list or in a specified mapset. (look but don't touch)
Definition find_file.c:257
FILE * G_fopen_old_misc(const char *, const char *, const char *, const char *)
open a database misc file for reading
Definition open_misc.c:210
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:87
FILE * G_fopen_new_misc(const char *, const char *, const char *)
open a new database misc file
Definition open_misc.c:183
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:33
#define GNAME_MAX
Definition gis.h:196
#define _(str)
Definition glocale.h:10
const char * name
Definition named_colr.c:6
bool Rast_legal_semantic_label(const char *semantic_label)
Check for legal semantic label.
void Rast_write_semantic_label(const char *name, const char *str)
Write a string into a rasters semantic label metadata file.
char * Rast_get_semantic_label_or_name(const char *name, const char *mapset)
Get a raster map semantic label or fall back to its name.
char * Rast_read_semantic_label(const char *name, const char *mapset)
Get a raster map semantic label metadata string.
char * Rast_read_vdatum(const char *name, const char *mapset)
Get a raster map's vertical datum metadata string.
void Rast_write_units(const char *name, const char *str)
Write a string to a raster map's units metadata file.
char * Rast_read_units(const char *name, const char *mapset)
Get a raster map's units metadata string.
void Rast_write_vdatum(const char *name, const char *str)
Write a string into a raster's vertical datum metadata file.