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