source: grass/branches/releasebranch_6_4/vector/v.in.ascii/points.c

Last change on this file was 66616, checked in by neteler, 9 years ago

fixes for fail to compile with -Werror=format-security (#2773) (partial backport from trunk, r66614)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id
  • Property svn:mime-type set to text/x-csrc
File size: 10.5 KB
Line 
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4#include <ctype.h>
5#include <grass/gis.h>
6#include <grass/dbmi.h>
7#include <grass/Vect.h>
8#include <grass/glocale.h>
9#include "local_proto.h"
10
11/* Determine if the string is integer, e.g. 123, +123, -123,
12 * return 1 if integer, 0 otherwise */
13static int is_int(char *str)
14{
15 char *tail;
16
17 if (strtol(str, &tail, 10), tail == str || *tail != '\0') {
18 /* doesn't look like a number,
19 or has extra characters after what looks to be a number */
20 return 0;
21 }
22
23 return 1;
24}
25
26
27/* Determine if the string is double, e.g. 123.456, +123.456, -123.456, 1.23456e2
28 * return 1 if double, 0 otherwise */
29static int is_double(char *str)
30{
31 char *tail;
32
33 if (strtod(str, &tail), tail == str || *tail != '\0') {
34 /* doesn't look like a number,
35 or has extra characters after what looks to be a number */
36 return 0;
37 }
38
39 return 1;
40}
41
42
43
44/* Analyse points ascii file. Determine number of columns and column types.
45 * ascii_tmp: write copy of tempfile to ascii_tmp:
46 * rowlength: maximum row length
47 * ncolumns: number of columns
48 * minncolumns: minimum number of columns
49 * nrows: number of rows
50 * column_type: column types
51 * column_length: column lengths (string only)
52 */
53
54int points_analyse(FILE * ascii_in, FILE * ascii, char *fs,
55 int *rowlength, int *ncolumns, int *minncolumns,
56 int *nrows, int **column_type, int **column_length,
57 int skip_lines, int xcol, int ycol, int region_flag)
58{
59 int i;
60 int buflen; /* buffer length */
61 char *buf, *buf_raw; /* buffer */
62 int row = 1; /* line number, first is 1 */
63 int ncols = 0; /* number of columns */
64 int minncols = -1;
65 int *coltype = NULL; /* column types */
66 int *collen = NULL; /* column lengths */
67 char **tokens;
68 int ntokens; /* number of tokens */
69 int len, rowlen = 0; /* maximum row length */
70 struct Cell_head window;
71 double northing = .0;
72 double easting = .0;
73 char *coorbuf, *tmp_token, *sav_buf;
74 int skip = FALSE, skipped = 0;
75
76 buflen = 4000;
77 buf = (char *)G_malloc(buflen);
78 buf_raw = (char *)G_malloc(buflen);
79 coorbuf = (char *)G_malloc(256);
80 tmp_token = (char *)G_malloc(256);
81 sav_buf = NULL;
82
83 G_message(_("Scanning input for column types..."));
84 /* fetch projection for LatLong test */
85 G_get_window(&window);
86
87 while (1) {
88 len = 0; /* not really needed, but what the heck */
89 skip = FALSE; /* reset out-of-region check */
90
91 if (G_getl2(buf, buflen - 1, ascii_in) == 0)
92 break; /* EOF */
93
94 if (row <= skip_lines) {
95 G_debug(3, "skipping header row %d : %d chars", row,
96 (int)strlen(buf));
97 /* this fn is read-only, write to hist with points_to_bin() */
98 fprintf(ascii, "%s\n", buf);
99 len = strlen(buf) + 1;
100 if (len > rowlen)
101 rowlen = len;
102
103 row++;
104 continue;
105 }
106
107 if ((buf[0] == '#') || (buf[0] == '\0')) {
108 G_debug(3, "skipping comment row %d : %d chars", row,
109 (int)strlen(buf));
110 continue;
111 }
112
113 /* no G_chop() as first/last column may be empty fs=tab value */
114 G_debug(3, "row %d : %d chars", row, (int)strlen(buf));
115
116 /* G_tokenize() will modify the buffer, so we make a copy */
117 strcpy(buf_raw, buf);
118
119 len = strlen(buf) + 1;
120 if (len > rowlen)
121 rowlen = len;
122
123 tokens = G_tokenize(buf, fs);
124 ntokens = G_number_of_tokens(tokens);
125 if (ntokens > ncols) {
126 int c;
127 coltype = (int *)G_realloc(coltype, ntokens * sizeof(int));
128 collen = (int *)G_realloc(collen, ntokens * sizeof(int));
129 for (c = ncols; c < ntokens; c++) {
130 coltype[c] = DB_C_TYPE_INT; /* default type */
131 collen[c] = 0;
132 }
133 ncols = ntokens;
134 }
135
136 if (minncols == -1 || minncols > ntokens)
137 minncols = ntokens;
138
139 /* Determine column types */
140 for (i = 0; i < ntokens; i++) {
141 if ((G_projection() == PROJECTION_LL)) {
142 if (i == xcol || i == ycol) {
143 if (i == 0) { /* Save position of original internal token buffer */
144 /* Prevent memory leaks */
145 sav_buf = tokens[0];
146 }
147 /* check if coordinates are DMS or decimal or not latlong at all */
148 sprintf(coorbuf, "%s", tokens[i]);
149 G_debug(4, "token: %s", coorbuf);
150
151 if (i == xcol) {
152 if (G_scan_easting(coorbuf, &easting, window.proj)) {
153 G_debug(4, "is_latlong east: %f", easting);
154 sprintf(tmp_token, "%.12f", easting);
155 /* replace current DMS token by decimal degree */
156 tokens[i] = tmp_token;
157 if (region_flag) {
158 if ((window.east < easting) ||
159 (window.west > easting))
160 skip = TRUE;
161 }
162 }
163 else {
164 fprintf(stderr, "Current row: '%s'\n", buf_raw);
165 G_fatal_error(_("Unparsable longitude value in column <%d>: %s"),
166 i, tokens[i]);
167 }
168 }
169
170 if (i == ycol) {
171 if (G_scan_northing(coorbuf, &northing, window.proj)) {
172 G_debug(4, "is_latlong north: %f", northing);
173 sprintf(tmp_token, "%.12f", northing);
174 /* replace current DMS token by decimal degree */
175 tokens[i] = tmp_token;
176 if (region_flag) {
177 if ((window.north < northing) ||
178 (window.south > northing))
179 skip = TRUE;
180 }
181 }
182 else {
183 fprintf(stderr, "Current row: '%s'\n", buf_raw);
184 G_fatal_error(_("Unparsable latitude value in column <%d>: %s"),
185 i, tokens[i]);
186 }
187 }
188 } /* if (x or y) */
189
190 if (i == ntokens - 1 && sav_buf != NULL) {
191 /* Restore original token buffer so free_tokens works */
192 /* Only do this if tokens[0] was re-assigned */
193 tokens[0] = sav_buf;
194 sav_buf = NULL;
195 }
196 } /* PROJECTION_LL */
197 else {
198 if (region_flag) {
199 /* consider z range if -z flag is used? */
200 /* change to if(>= east,north){skip=1;} to allow correct tiling */
201 /* don't "continue;" so multiple passes will have the
202 same column types and length for patching */
203 if (i == xcol) {
204 easting = atof(tokens[i]);
205 if ((window.east < easting) ||
206 (window.west > easting))
207 skip = TRUE;
208 }
209 if (i == ycol) {
210 northing = atof(tokens[i]);
211 if ((window.north < northing) ||
212 (window.south > northing))
213 skip = TRUE;
214 }
215 }
216 }
217
218 len = strlen(tokens[i]);
219 /* do not guess column type for missing values */
220 if (len == 0)
221 continue;
222
223 G_debug(4, "row %d col %d: '%s' is_int = %d is_double = %d",
224 row, i, tokens[i], is_int(tokens[i]),
225 is_double(tokens[i]));
226
227 if (is_int(tokens[i])) {
228 continue; /* integer */
229 }
230 if (is_double(tokens[i])) { /* double */
231 if (coltype[i] == DB_C_TYPE_INT) {
232 coltype[i] = DB_C_TYPE_DOUBLE;
233 }
234 continue;
235 }
236 /* string */
237 coltype[i] = DB_C_TYPE_STRING;
238 if (len > collen[i])
239 collen[i] = len;
240 }
241
242 /* write dataline to tmp file */
243 if (!skip)
244 fprintf(ascii, "%s\n", buf_raw);
245 else
246 skipped++;
247
248 G_free_tokens(tokens);
249 row++;
250 }
251
252 *rowlength = rowlen;
253 *ncolumns = ncols;
254 *minncolumns = minncols;
255 *column_type = coltype;
256 *column_length = collen;
257 *nrows = row - 1; /* including skipped lines */
258
259 G_free(buf);
260 G_free(buf_raw);
261 G_free(coorbuf);
262 G_free(tmp_token);
263
264 if (region_flag)
265 G_message(_("Skipping %d of %d rows falling outside of current region"),
266 skipped, row - 1);
267
268 return 0;
269}
270
271
272/* Import points from ascii file.
273 *
274 * fs: field separator
275 * xcol, ycol, zcol, catcol: x,y,z,cat column in input file, first column is 1,
276 * zcol and catcol may be 0 (do not use)
277 * rowlen: maximum row length
278 * Note: column types (both in header or coldef) must be supported by driver
279 */
280int points_to_bin(FILE * ascii, int rowlen, struct Map_info *Map,
281 dbDriver * driver, char *table, char *fs, int nrows,
282 int ncols, int *coltype, int xcol, int ycol, int zcol,
283 int catcol, int skip_lines)
284{
285 char *buf, buf2[4000];
286 int cat = 0;
287 int row = 1;
288 struct line_pnts *Points;
289 struct line_cats *Cats;
290 dbString sql, val;
291 struct Cell_head window;
292
293 G_message(_("Importing points..."));
294 /* fetch projection for LatLong test */
295 G_get_window(&window);
296
297 rewind(ascii);
298 Points = Vect_new_line_struct();
299 Cats = Vect_new_cats_struct();
300
301 buf = (char *)G_malloc(rowlen + 1);
302 db_init_string(&sql);
303 db_init_string(&val);
304
305 if (skip_lines > 0) {
306 sprintf(buf2, "HEADER: (%d lines)\n", skip_lines);
307 Vect_hist_write(Map, buf2);
308 }
309
310 while (G_getl2(buf, rowlen, ascii) != 0) {
311 int i, len;
312 double x, y, z;
313 char **tokens;
314 int ntokens; /* number of tokens */
315
316 if (row <= skip_lines) {
317 G_debug(4, "writing skip line %d to hist : %d chars", row,
318 (int)strlen(buf));
319 Vect_hist_write(Map, buf);
320 Vect_hist_write(Map, "\n");
321 row++;
322 continue;
323 }
324
325 len = strlen(buf);
326 if (len == 0)
327 continue; /* should not happen */
328
329 G_debug(4, "row: %s", buf);
330
331 tokens = G_tokenize(buf, fs);
332 ntokens = G_number_of_tokens(tokens);
333
334 if ((G_projection() == PROJECTION_LL)) {
335 G_scan_easting(tokens[xcol], &x, window.proj);
336 G_scan_northing(tokens[ycol], &y, window.proj);
337 }
338 else {
339 x = atof(tokens[xcol]);
340 y = atof(tokens[ycol]);
341 }
342 G_debug(4, "x: %f, y: %f", x, y);
343
344 if (zcol >= 0)
345 z = atof(tokens[zcol]);
346 else
347 z = 0.0;
348
349 if (catcol >= 0)
350 cat = atof(tokens[catcol]);
351 else
352 cat++;
353
354 Vect_reset_line(Points);
355 Vect_reset_cats(Cats);
356
357 Vect_append_point(Points, x, y, z);
358 Vect_cat_set(Cats, 1, cat);
359
360 Vect_write_line(Map, GV_POINT, Points, Cats);
361
362 /* Attributes */
363 if (driver) {
364 sprintf(buf2, "insert into %s values ( ", table);
365 db_set_string(&sql, buf2);
366
367 if (catcol < 0) {
368 sprintf(buf2, "%d, ", cat);
369 db_append_string(&sql, buf2);
370 }
371
372 for (i = 0; i < ntokens; i++) {
373 if (i > 0)
374 db_append_string(&sql, ", ");
375
376 if (strlen(tokens[i]) > 0) {
377 if (coltype[i] == DB_C_TYPE_INT ||
378 coltype[i] == DB_C_TYPE_DOUBLE) {
379 if (G_projection() == PROJECTION_LL &&
380 (i == xcol || i == ycol)) {
381 if (i == xcol)
382 sprintf(buf2, "%.15g", x);
383 else
384 sprintf(buf2, "%.15g", y);
385 }
386 else
387 sprintf(buf2, "%s", tokens[i]);
388 }
389 else {
390 db_set_string(&val, tokens[i]);
391 /* TODO: strip leading and trailing "quotes" from input string */
392 db_double_quote_string(&val);
393 sprintf(buf2, "'%s'", db_get_string(&val));
394 }
395 }
396 else {
397 sprintf(buf2, "null");
398 }
399 db_append_string(&sql, buf2);
400 }
401 db_append_string(&sql, ")");
402 G_debug(3, "%s", db_get_string(&sql));
403
404 if (db_execute_immediate(driver, &sql) != DB_OK) {
405 G_fatal_error(_("Unable to insert new record: %s"),
406 db_get_string(&sql));
407 }
408 }
409
410 G_percent(row, nrows, 2);
411
412 G_free_tokens(tokens);
413
414 row++;
415 }
416
417 return 0;
418}
Note: See TracBrowser for help on using the repository browser.