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