grass  7.8.6
About: GRASS (Geographic Resources Analysis Support System) is a raster- and vector-based GIS, image processing system, graphics production system and spatial modeling system.
  Fossies Dox: grass-7.8.6.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

scan.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 1995. Bill Brown <brown@gis.uiuc.edu> & Michael Shapiro
3 *
4 * This program is free software under the GPL (>=v2)
5 * Read the file GPL.TXT coming with GRASS for details.
6 */
7#include <stdio.h>
8#include <string.h>
9#include <grass/datetime.h>
10
11
12static int scan_absolute(DateTime *, const char *);
13static int more(const char **);
14static int minus_sign(const char **);
15static int is_bc(const char **);
16static int is_relative(const char *);
17static int relative_term(const char **, double *, int *, int *, int *);
18static int scan_tz(const char *, int *);
19static int get_word(const char **, char *);
20static char lowercase(char);
21static int which_month(const char *, int *);
22static int scan_relative(DateTime *, const char *);
23static int is_space(char);
24static int is_digit(char);
25static void skip_space(const char **);
26static int get_int(const char **, int *, int *);
27static int get_double(const char **, double *, int *, int *);
28
29
30/*!
31 * \brief
32 *
33 * Convert the ascii string
34 * into a DateTime. This determines the mode/from/to based on the string, inits
35 * 'dt' and then sets values in 'dt' based on the [???]
36 * Returns 0 if 'string' is legal, -1 if not.
37 *
38 * \param dt
39 * \param buf
40 * \return int
41 */
42
43int datetime_scan(DateTime * dt, const char *buf)
44{
45 if (is_relative(buf)) {
46 if (scan_relative(dt, buf))
47 return 0;
48 return datetime_error(-1, "Invalid interval datetime format");
49 }
50 if (scan_absolute(dt, buf))
51 return 0;
52 return datetime_error(-2, "Invalid absolute datetime format");
53}
54
55static const char *month_names[] = {
56 "jan", "feb", "mar", "apr", "may", "jun",
57 "jul", "aug", "sep", "oct", "nov", "dec"
58};
59
60static int scan_absolute(DateTime * dt, const char *buf)
61{
62 char word[1024];
63 int n;
64 int ndigits;
65 int tz = 0;
66 int have_tz = 0;
67 int bc = 0;
68 int to, fracsec = 0;
69 int year, month, day = 0, hour, minute;
70 double second;
71 const char *p;
72
73 p = buf;
74 if (!more(&p))
75 return 0;
76
77 if (!get_int(&p, &n, &ndigits)) { /* no day, so must be month, like Jan */
78 if (!get_word(&p, word))
79 return 0;
80 if (!which_month(word, &month))
81 return 0;
82 if (!get_int(&p, &year, &ndigits)) /* year following the month */
83 return 0;
84 to = DATETIME_MONTH;
85 if (is_bc(&p))
86 bc = 1;
87 goto set;
88 }
89
90 bc = is_bc(&p);
91 if (bc || !get_word(&p, word)) { /* just a year */
92 year = n;
93 to = DATETIME_YEAR;
94 goto set;
95 }
96 to = DATETIME_DAY; /* must be at least: day Mon year [bc] */
97 day = n;
98 if (!which_month(word, &month))
99 return 0;
100 if (!get_int(&p, &year, &ndigits))
101 return 0;
102 if (is_bc(&p))
103 bc = 1;
104
105 /* now for the time */
106 if (!get_int(&p, &hour, &ndigits))
107 goto set;
108 to = DATETIME_HOUR;
109 if (*p != ':')
110 goto set;
111 p++;
112 if (!get_int(&p, &minute, &ndigits))
113 return 0;
114 if (ndigits != 2)
115 return 0;
116 to = DATETIME_MINUTE;
117 if (*p != ':')
118 goto timezone;
119 p++;
120 if (!get_double(&p, &second, &ndigits, &fracsec))
121 return 0;
122 if (ndigits != 2)
123 return 0;
124 to = DATETIME_SECOND;
125
126 timezone:
127 if (!get_word(&p, word))
128 goto set;
129 if (!scan_tz(word, &tz))
130 return 0;
131 have_tz = 1;
132
133 set:
134 if (more(&p)) /* make sure there isn't anything else */
135 return 0;
137 return 0;
138 for (n = DATETIME_YEAR; n <= to; n++) {
139 switch (n) {
140 case DATETIME_YEAR:
141 if (datetime_set_year(dt, year))
142 return 0;
143 break;
144 case DATETIME_MONTH:
145 if (datetime_set_month(dt, month))
146 return 0;
147 break;
148 case DATETIME_DAY:
149 if (datetime_set_day(dt, day))
150 return 0;
151 break;
152 case DATETIME_HOUR:
153 if (datetime_set_hour(dt, hour))
154 return 0;
155 break;
156 case DATETIME_MINUTE:
157 if (datetime_set_minute(dt, minute))
158 return 0;
159 break;
160 case DATETIME_SECOND:
162 return 0;
163 break;
164 }
165 }
166 if (bc)
168 if (have_tz && datetime_set_timezone(dt, tz))
169 return 0;
170
171 return 1;
172}
173
174
175static int scan_relative(DateTime * dt, const char *buf)
176{
177 const char *p;
178 double x;
179 int ndigits, ndecimal;
180 int pos;
181 int neg = 0;
182 int year = 0, month = 0, day = 0, hour = 0, minute = 0, fracsec = 0;
183 double second = 0.0;
184 int from = DATETIME_SECOND + 1, to = DATETIME_YEAR - 1;
185
186 p = buf;
187 neg = minus_sign(&p);
188 if (!more(&p))
189 return 0;
190
191 while (relative_term(&p, &x, &ndigits, &ndecimal, &pos)) {
192 if (from > pos)
193 from = pos;
194 if (to < pos)
195 to = pos;
196
197 if (pos != DATETIME_SECOND && ndecimal != 0)
198 return 0;
199
200 switch (pos) {
201 case DATETIME_YEAR:
202 year = (int)x;
203 break;
204 case DATETIME_MONTH:
205 month = (int)x;
206 break;
207 case DATETIME_DAY:
208 day = (int)x;;
209 break;
210 case DATETIME_HOUR:
211 hour = (int)x;
212 break;
213 case DATETIME_MINUTE:
214 minute = (int)x;
215 break;
216 case DATETIME_SECOND:
217 second = x;
218 fracsec = ndecimal;
219 break;
220 }
221
222 }
223
224 if (more(&p)) /* make sure there isn't anything else */
225 return 0;
226 if (datetime_set_type(dt, DATETIME_RELATIVE, from, to, fracsec))
227 return 0;
228 for (pos = from; pos <= to; pos++) {
229 switch (pos) {
230 case DATETIME_YEAR:
231 if (datetime_set_year(dt, year))
232 return 0;
233 break;
234 case DATETIME_MONTH:
235 if (datetime_set_month(dt, month))
236 return 0;
237 break;
238 case DATETIME_DAY:
239 if (datetime_set_day(dt, day))
240 return 0;
241 break;
242 case DATETIME_HOUR:
243 if (datetime_set_hour(dt, hour))
244 return 0;
245 break;
246 case DATETIME_MINUTE:
247 if (datetime_set_minute(dt, minute))
248 return 0;
249 break;
250 case DATETIME_SECOND:
252 return 0;
253 break;
254 }
255 }
256 if (neg)
258
259 return 1;
260}
261
262static int is_space(char c)
263{
264 return (c == ' ' || c == '\t' || c == '\n');
265}
266
267static int is_digit(char c)
268{
269 return (c >= '0' && c <= '9');
270}
271
272static void skip_space(const char **s)
273{
274 while (is_space(**s))
275 (*s)++;
276}
277
278static int get_int(const char **s, int *n, int *ndigits)
279{
280 const char *p;
281
282 *n = 0;
283 skip_space(s);
284 p = *s;
285 for (*ndigits = 0; is_digit(*p); (*ndigits)++) {
286 *n *= 10;
287 *n += *p - '0';
288 p++;
289 }
290 if (*ndigits > 0)
291 *s = p;
292 return (*ndigits > 0);
293}
294
295static int get_double(const char **s, double *x, int *ndigits, /* number of digits before decimal */
296 int *ndecimal)
297{ /* number of decimal places */
298 char buf[1024];
299 char *b;
300 const char *p;
301
302 skip_space(s);
303
304 p = *s;
305 *ndecimal = 0;
306 b = buf;
307
308 for (*ndigits = 0; is_digit(*p); (*ndigits)++)
309 *b++ = *p++;
310 if (*p == '.') {
311 *b++ = *p++;
312 while (is_digit(*p)) {
313 *b++ = *p++;
314 (*ndecimal)++;
315 }
316 }
317 *b = 0;
318 if (sscanf(buf, "%lf", x) != 1)
319 return 0;
320 *s = p;
321 return 1;
322}
323
324
325/* if pos is non-zero, *(p-1) must be legal */
326/*
327 static int
328 is_wordend (pos, p)
329 int pos;
330 char *p;
331 {
332 int d1, d0;
333
334 if ('\0'==(*p)) return (1);
335 if (is_space(*p)) return (1);
336 if (pos){
337 d0 = is_digit(*(p-1));
338 d1 = is_digit(*p);
339 return(d0 != d1);
340 }
341 return (0);
342
343 }
344 */
345
346/* get a word (between white space) and convert to lowercase */
347static int get_word(const char **s, char *word)
348{
349 const char *p;
350 int any;
351
352 skip_space(s);
353 p = *s;
354 for (any = 0; *p && !is_space(*p); any = 1)
355 *word++ = lowercase(*p++);
356 *word = 0;
357 *s = p;
358 return any;
359}
360
361static char lowercase(char c)
362{
363 if (c >= 'A' && c <= 'Z')
364 c += 'a' - 'A';
365 return c;
366}
367
368static int which_month(const char *name, int *n)
369{
370 int i;
371
372 for (i = 0; i < 12; i++)
373 if (strcmp(name, month_names[i]) == 0) {
374 *n = i + 1;
375 return 1;
376 }
377 return 0;
378}
379
380static int is_bc(const char **s)
381{
382 const char *p;
383 char word[1024];
384
385 p = *s;
386 if (!get_word(&p, word))
387 return 0;
388 if (strcmp("bc", word) != 0)
389 return 0;
390 *s = p;
391 return 1;
392}
393
394static int scan_tz(const char *word, int *tz)
395{
396 int neg = 0;
397
398 if (word[0] == '+')
399 neg = 0;
400 else if (word[0] == '-')
401 neg = 1;
402 else
403 return 0;
404
405 if (!is_digit(word[1]))
406 return 0;
407 if (!is_digit(word[2]))
408 return 0;
409 if (!is_digit(word[3]))
410 return 0;
411 if (!is_digit(word[4]))
412 return 0;
413
414 *tz = (word[1] - '0') * 600 + (word[2] - '0') * 60 +
415 (word[3] - '0') * 10 + (word[4] - '0');
416 if (neg)
417 *tz = -(*tz);
418 return 1;
419}
420
421/* returns
422 0 not a recognized term
423 1 valid term, but perhaps illegal value
424 */
425static int relative_term(const char **s,
426 double *x, int *ndigits, int *ndecimal, int *pos)
427{
428 char word[1024];
429 const char *p;
430
431 p = *s;
432 if (!get_double(&p, x, ndigits, ndecimal) || !get_word(&p, word))
433 return 0;
434
435 if (strcmp(word, "year") == 0 || strcmp(word, "years") == 0)
436 *pos = DATETIME_YEAR;
437 else if (strcmp(word, "month") == 0 || strcmp(word, "months") == 0 ||
438 strcmp(word, "mon") == 0)
439 *pos = DATETIME_MONTH;
440 else if (strcmp(word, "day") == 0 || strcmp(word, "days") == 0)
441 *pos = DATETIME_DAY;
442 else if (strcmp(word, "hour") == 0 || strcmp(word, "hours") == 0)
443 *pos = DATETIME_HOUR;
444 else if (strcmp(word, "minute") == 0 || strcmp(word, "minutes") == 0 ||
445 strcmp(word, "min") == 0)
446 *pos = DATETIME_MINUTE;
447 else if (strcmp(word, "second") == 0 || strcmp(word, "seconds") == 0 ||
448 strcmp(word, "sec") == 0)
449 *pos = DATETIME_SECOND;
450 else
451 return 0;
452 *s = p;
453 return 1;
454}
455
456static int minus_sign(const char **s)
457{
458 skip_space(s);
459 if (**s == '-') {
460 (*s)++;
461 return 1;
462 }
463 return 0;
464}
465
466static int is_relative(const char *buf)
467{
468 int n;
469 double x;
470 const char *p;
471
472 p = buf;
473 (void)minus_sign(&p);
474 return relative_term(&p, &x, &n, &n, &n) != 0;
475}
476
477static int more(const char **s)
478{
479 skip_space(s);
480 return **s != 0;
481}
int datetime_error(int code, char *msg)
record 'code' and 'msg' as error code/msg (in static variables) code==0 will clear the error (ie set ...
Definition: error.c:30
int datetime_set_type(DateTime *dt, int mode, int from, int to, int fracsec)
Definition: type.c:37
#define DATETIME_ABSOLUTE
Definition: datetime.h:4
#define DATETIME_MONTH
Definition: datetime.h:11
#define DATETIME_DAY
Definition: datetime.h:12
#define DATETIME_HOUR
Definition: datetime.h:13
#define DATETIME_SECOND
Definition: datetime.h:15
#define DATETIME_MINUTE
Definition: datetime.h:14
#define DATETIME_RELATIVE
Definition: datetime.h:5
#define DATETIME_YEAR
Definition: datetime.h:10
const char * name
Definition: named_colr.c:7
double b
Definition: r_raster.c:39
static int is_digit(char)
Definition: scan.c:267
static int relative_term(const char **, double *, int *, int *, int *)
Definition: scan.c:425
static int minus_sign(const char **)
Definition: scan.c:456
static int is_bc(const char **)
Definition: scan.c:380
static int get_int(const char **, int *, int *)
Definition: scan.c:278
int datetime_scan(DateTime *dt, const char *buf)
Convert the ascii string into a DateTime. This determines the mode/from/to based on the string,...
Definition: scan.c:43
static int scan_absolute(DateTime *, const char *)
Definition: scan.c:60
static void skip_space(const char **)
Definition: scan.c:272
static int is_relative(const char *)
Definition: scan.c:466
static char lowercase(char)
Definition: scan.c:361
static int scan_tz(const char *, int *)
Definition: scan.c:394
static int scan_relative(DateTime *, const char *)
Definition: scan.c:175
static int get_word(const char **, char *)
Definition: scan.c:347
static int which_month(const char *, int *)
Definition: scan.c:368
static const char * month_names[]
Definition: scan.c:55
static int is_space(char)
Definition: scan.c:262
static int more(const char **)
Definition: scan.c:477
static int get_double(const char **, double *, int *, int *)
Definition: scan.c:295
void datetime_set_negative(DateTime *dt)
Makes the DateTime negative. (B.C. for ABSOLUTE DateTimes)
Definition: sign.c:67
int datetime_set_timezone(DateTime *dt, int minutes)
returns 0 on success
Definition: tz1.c:71
static unsigned int s
Definition: unfl.c:9
static unsigned int c
Definition: unfl.c:8
int datetime_set_day(DateTime *dt, int day)
if dt.mode = ABSOLUTE, then the dt.year, dt.month:
Definition: values.c:354
int datetime_set_month(DateTime *dt, int month)
if dt.mode = ABSOLUTE, this also sets dt.day = 0
Definition: values.c:300
int datetime_set_hour(DateTime *dt, int hour)
returns 0 on success or negative value on error
Definition: values.c:398
int datetime_set_year(DateTime *dt, int year)
if dt.mode = ABSOLUTE, this also sets dt.day = 0
Definition: values.c:251
int datetime_set_second(DateTime *dt, double second)
returns 0 on success or negative value on error
Definition: values.c:486
int datetime_set_minute(DateTime *dt, int minute)
returns 0 on success or negative value on error
Definition: values.c:442
static int second
Definition: intersect.c:516
#define x