GRASS 8 Programmer's Manual 8.6.0dev(2026)-0f6a7341fc
Loading...
Searching...
No Matches
raster/history.c
Go to the documentation of this file.
1/*!
2 * \file lib/raster/history.c
3 *
4 * \brief Raster Library - History management
5 *
6 * SPDX-FileCopyrightText: 2001-2009 GRASS Development Team
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 *
9 * \author Original author CERL
10 */
11
12#include <stdarg.h>
13#include <string.h>
14#include <grass/gis.h>
15#include <grass/raster.h>
16#include <grass/glocale.h>
17
18/*!
19 * \brief Append a string to a History structure
20 *
21 *
22 * \param hist pointer to History structure which holds history info
23 * \param str string to append
24 *
25 * \return void
26 */
27void Rast_append_history(struct History *hist, const char *str)
28{
29 hist->lines = G_realloc(hist->lines, (hist->nlines + 1) * sizeof(char *));
30 hist->lines[hist->nlines++] = G_store(str);
31}
32
33/*!
34 * \brief Append a formatted string to a History structure
35 *
36 *
37 * \param hist pointer to History structure which holds history info
38 * \param fmt a string of format characters
39 * \param ... the arguments associated with the format characters
40 *
41 * \return void
42 */
43void Rast_append_format_history(struct History *hist, const char *fmt, ...)
44{
45 va_list ap;
46 char *str;
47
48 hist->lines = G_realloc(hist->lines, (hist->nlines + 1) * sizeof(char *));
49
50 va_start(ap, fmt);
51 G_vasprintf(&str, fmt, ap);
52 va_end(ap);
53
54 hist->lines[hist->nlines++] = str;
55}
56
57int Rast__read_history(struct History *hist, FILE *fp)
58{
59 int i;
60
61 for (i = 0; i < HIST_NUM_FIELDS; i++) {
62 char buf[4096];
63
64 if (!G_getl(buf, sizeof(buf), fp)) {
65 fclose(fp);
66 return -1;
67 }
68
69 G_ascii_check(buf);
70
71 hist->fields[i] = G_store(buf);
72 }
73
74 hist->nlines = 0;
75
76 for (;;) {
77 char buf[4096];
78
79 if (!G_getl(buf, sizeof(buf), fp))
80 break;
81 Rast_append_history(hist, buf);
82 }
83
84 fclose(fp);
85
86 return 0;
87}
88
89/*!
90 * \brief Read raster history file
91 *
92 * This routine reads the history file for the raster map <i>name</i>
93 * in <i>mapset</i> into the <i>hist</i> structure.
94 *
95 * A diagnostic message is printed and -1 is returned if there is an
96 * error reading the history file. Otherwise, 0 is returned.
97 *
98 * \param name map name
99 * \param mapset mapset name
100 * \param hist pointer to History structure which holds history info
101 *
102 * \return -1 on error
103 * \return 0 on success
104 */
105int Rast_read_history(const char *name, const char *mapset,
106 struct History *hist)
107{
108 FILE *fp;
109
110 G_zero(hist, sizeof(struct History));
111
112 fp = G_fopen_old("hist", name, mapset);
113 if (!fp) {
114 G_warning(_("Unable to get history information for <%s@%s>"), name,
115 mapset);
116 return -1;
117 }
118
119 if (Rast__read_history(hist, fp) == 0)
120 return 0;
121
122 G_warning(_("Unable to get history information for <%s@%s>"), name, mapset);
123 return -1;
124}
125
126void Rast__write_history(struct History *hist, FILE *fp)
127{
128 int i;
129
130 for (i = 0; i < HIST_NUM_FIELDS; i++)
131 fprintf(fp, "%s\n", hist->fields[i] ? hist->fields[i] : "");
132
133 for (i = 0; i < hist->nlines; i++)
134 fprintf(fp, "%s\n", hist->lines[i]);
135
136 fclose(fp);
137}
138
139/*!
140 * \brief Write raster history file
141 *
142 * This routine writes the history file for the raster map
143 * <i>name</i> in the current mapset from the <i>hist</i> structure.
144 *
145 * A diagnostic message is printed and -1 is returned if there is an
146 * error writing the history file. Otherwise, 0 is returned.
147 *
148 * <b>Note:</b> The <i>hist</i> structure should first be initialized
149 * using Rast_short_history().
150 *
151 * \param name map name
152 * \param[out] hist pointer to History structure which holds history info
153 *
154 * \return void
155 */
156void Rast_write_history(const char *name, struct History *hist)
157{
158 FILE *fp = G_fopen_new("hist", name);
159
160 if (!fp)
161 G_fatal_error(_("Unable to write history information for <%s>"), name);
162
163 Rast__write_history(hist, fp);
164}
165
166/*!
167 * \brief Set the string of a specific history field
168 *
169 *
170 * \param hist pointer to History structure which holds history info
171 * \param field number of a specific history field, should be accessed with
172 * macros (HIST_MAPID, ...)
173 *
174 * \return string of the history field
175 */
176const char *Rast_get_history(struct History *hist, int field)
177{
178 return hist->fields[field];
179}
180
181/*!
182 * \brief Set the string of a specific history field
183 *
184 *
185 * \param hist pointer to History structure which holds history info
186 * \param field number of a specific history field, should be accessed with
187 * macros (HIST_MAPID, ...) \param str string of the history field
188 *
189 * \return void
190 */
191void Rast_set_history(struct History *hist, int field, const char *str)
192{
193 if (hist->fields[field])
194 G_free(hist->fields[field]);
195 hist->fields[field] = str ? G_store(str) : NULL;
196}
197
198void Rast_format_history(struct History *hist, int field, const char *fmt, ...)
199{
200 va_list ap;
201
202 if (hist->fields[field])
203 G_free(hist->fields[field]);
204
205 va_start(ap, fmt);
206 G_vasprintf(&hist->fields[field], fmt, ap);
207 va_end(ap);
208}
209
210/*!
211 * \brief Initialize history structure
212 *
213 * This routine initializes the <i>hist</i> structure, recording the
214 * date, user, module name and the raster map <i>name</i>
215 * structure. The <i>type</i> can be "raster", "reclass", "GDAL-link",
216 * or "virtual".
217 *
218 * <b>Note:</b> This routine only initializes the data structure. It
219 * does not write the history file.
220 *
221 * \param name map name
222 * \param type map type
223 * \param hist pointer to History structure which holds history info
224 */
225void Rast_short_history(const char *name, const char *type,
226 struct History *hist)
227{
228 G_zero(hist, sizeof(struct History));
233 Rast_set_history(hist, HIST_MAPTYPE, type);
234 Rast_format_history(hist, HIST_KEYWRD, _("generated by %s"),
238 hist->nlines = 0;
239}
240
241/*!
242 * \brief Save command line to raster history structure
243 *
244 * This routine takes an existing (run Rast_short_history first() history
245 * structure and adds the command line to the end of the comments
246 * array, as cleaned & expanded by the parser.
247 *
248 * - First version had for loops of [i][j] character assignments and ending
249 * nulls, but using the string libraries is cleaner and less bug prone.
250 * - Second version had white space detection, intelligent wrapping, and
251 * indentation of continued lines, but this proved a pain in the neck for
252 * things like r.patch which can have long strings without any
253 * parser-acceptable breaks.
254 * - This is MK-III, simplified, but that's good: it's cut & paste-able.
255 *
256 * Note: use Rast_write_history() to write the structure.
257 *
258 * Sample Usage:
259 * \code
260 * struct History history;
261 * Rast_short_history(rasterfile, "raster", &history);
262 * Rast_command_history(&history);
263 * Rast_write_history(rasterfile, &history);
264 * \endcode
265 *
266 * \param hist pointer to History structure which holds history info
267 *
268 * \return 0 on success
269 * \return 1 on failure (history file full, no change)
270 * \return 2 on failure (history file full, added as much as we could)
271 */
273{
274 char *cmdlin;
275 int cmdlen;
276
279
280 if (hist->nlines > 0) /* add a blank line if preceding history exists */
281 Rast_append_history(hist, "");
282
283 if (cmdlen < 70) /* ie if it will fit on a single line */
285 else { /* multi-line required */
286 int j; /* j is the current position in the command line string */
287
288 for (j = 0; cmdlen - j > 70; j += 68) {
289 char buf[80];
290
291 memcpy(buf, &cmdlin[j], 68);
292 buf[68] = '\\';
293 buf[69] = '\0';
294 Rast_append_history(hist, buf);
295 }
296 if (cmdlen - j > 0) /* ie anything left */
298 }
299
300 G_free(cmdlin);
301
302 return 0;
303}
304
305void Rast_clear_history(struct History *hist)
306{
307 int i;
308
309 for (i = 0; i < hist->nlines; i++)
310 G_free(hist->lines[i]);
311
312 if (hist->lines)
313 G_free(hist->lines);
314
315 hist->lines = NULL;
316 hist->nlines = 0;
317}
318
319void Rast_free_history(struct History *hist)
320{
321 int i;
322
323 for (i = 0; i < HIST_NUM_FIELDS; i++)
324 if (hist->fields[i]) {
325 G_free(hist->fields[i]);
326 hist->fields[i] = NULL;
327 }
328
329 Rast_clear_history(hist);
330}
331
333{
334 return hist->nlines;
335}
336
337const char *Rast_history_line(struct History *hist, int line)
338{
339 if (line < 0 || line >= hist->nlines)
340 return "";
341 return hist->lines[line];
342}
#define NULL
Definition ccmath.h:32
void G_ascii_check(char *)
Removes non-ascii characters from buffer.
Definition ascii_chk.c:28
const char * G_program_name(void)
Return module name.
Definition progrm_nme.c:26
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition gis/zero.c:21
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_realloc(p, n)
Definition defs/gis.h:138
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
FILE * G_fopen_new(const char *, const char *)
Open a new database file.
Definition gis/open.c:218
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition gis/open.c:250
char * G_recreate_command(void)
Creates command to run non-interactive.
Definition parser.c:838
const char * G_whoami(void)
Gets user's name.
Definition gis/whoami.c:32
const char * G_date(void)
Current date and time.
Definition date.c:24
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:85
int G_getl(char *, int, FILE *)
Gets a line of text from a file.
Definition getl.c:31
int G_vasprintf(char **, const char *, va_list)
Safe replacement for asprintf().
Definition asprintf.c:38
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:31
#define _(str)
Definition glocale.h:10
const char * name
Definition named_colr.c:6
const char * Rast_history_line(struct History *hist, int line)
void Rast_free_history(struct History *hist)
void Rast_append_history(struct History *hist, const char *str)
Append a string to a History structure.
void Rast_clear_history(struct History *hist)
int Rast__read_history(struct History *hist, FILE *fp)
int Rast_history_length(struct History *hist)
int Rast_read_history(const char *name, const char *mapset, struct History *hist)
Read raster history file.
void Rast_write_history(const char *name, struct History *hist)
Write raster history file.
const char * Rast_get_history(struct History *hist, int field)
Set the string of a specific history field.
void Rast_append_format_history(struct History *hist, const char *fmt,...)
Append a formatted string to a History structure.
void Rast_format_history(struct History *hist, int field, const char *fmt,...)
int Rast_command_history(struct History *hist)
Save command line to raster history structure.
void Rast_set_history(struct History *hist, int field, const char *str)
Set the string of a specific history field.
void Rast__write_history(struct History *hist, FILE *fp)
void Rast_short_history(const char *name, const char *type, struct History *hist)
Initialize history structure.
@ HIST_NUM_FIELDS
Number of fields to be defined in History structure.
Definition raster.h:168
@ HIST_KEYWRD
One-line data description.
Definition raster.h:165
@ HIST_MAPID
Raster name.
Definition raster.h:152
@ HIST_MAPTYPE
Map type ("raster", "reclass", "GDAL-link", or "virtual")
Definition raster.h:160
@ HIST_TITLE
Raster title.
Definition raster.h:154
@ HIST_MAPSET
Raster mapset.
Definition raster.h:156
@ HIST_CREATOR
User who creates raster map.
Definition raster.h:158
@ HIST_DATSRC_1
Description of original data source (two lines)
Definition raster.h:162
@ HIST_DATSRC_2
Definition raster.h:163
Raster history info (metadata)
Definition raster.h:172
int nlines
Number of lines in lines array.
Definition raster.h:176
char ** lines
Lines array.
Definition raster.h:178
char * fields[HIST_NUM_FIELDS]
Array of fields (see History_field for details)
Definition raster.h:174