#include #include #include #include #include #include #include #include #include "local_proto.h" /* Determine if the string is integer, e.g. 123, +123, -123, * return 1 if integer, 0 otherwise */ static int is_int(char *str) { char *tail; if (strtol(str, &tail, 10), tail == str || *tail != '\0') { /* doesn't look like a number, or has extra characters after what looks to be a number */ return 0; } return 1; } /* Determine if the string is double, e.g. 123.456, +123.456, -123.456, 1.23456e2 * return 1 if double, 0 otherwise */ static int is_double(char *str) { char *tail; if (strtod(str, &tail), tail == str || *tail != '\0') { /* doesn't look like a number, or has extra characters after what looks to be a number */ return 0; } return 1; } /* Analyse points ascii file. Determine number of columns and column types. * ascii_tmp: write copy of tempfile to ascii_tmp: * rowlength: maximum row length * ncolumns: number of columns * minncolumns: minimum number of columns * nrows: number of rows * column_type: column types * column_length: column lengths (string only) */ int points_analyse(FILE * ascii_in, FILE * ascii, char *fs, int *rowlength, int *ncolumns, int *minncolumns, int *nrows, int **column_type, int **column_length, int skip_lines, int xcol, int ycol, int region_flag) { int i; int buflen; /* buffer length */ char *buf, *buf_raw; /* buffer */ int row = 1; /* line number, first is 1 */ int ncols = 0; /* number of columns */ int minncols = -1; int *coltype = NULL; /* column types */ int *collen = NULL; /* column lengths */ char **tokens; int ntokens; /* number of tokens */ int len, rowlen = 0; /* maximum row length */ struct Cell_head window; double northing = .0; double easting = .0; char *coorbuf, *tmp_token, *sav_buf; int skip = FALSE, skipped = 0; buflen = 4000; buf = (char *)G_malloc(buflen); buf_raw = (char *)G_malloc(buflen); coorbuf = (char *)G_malloc(256); tmp_token = (char *)G_malloc(256); sav_buf = NULL; G_message(_("Scanning input for column types...")); /* fetch projection for LatLong test */ G_get_window(&window); while (1) { len = 0; /* not really needed, but what the heck */ skip = FALSE; /* reset out-of-region check */ if (G_getl2(buf, buflen - 1, ascii_in) == 0) break; /* EOF */ if (row <= skip_lines) { G_debug(3, "skipping header row %d : %d chars", row, (int)strlen(buf)); /* this fn is read-only, write to hist with points_to_bin() */ fprintf(ascii, "%s\n", buf); len = strlen(buf) + 1; if (len > rowlen) rowlen = len; row++; continue; } if ((buf[0] == '#') || (buf[0] == '\0')) { G_debug(3, "skipping comment row %d : %d chars", row, (int)strlen(buf)); continue; } /* no G_chop() as first/last column may be empty fs=tab value */ G_debug(3, "row %d : %d chars", row, (int)strlen(buf)); /* G_tokenize() will modify the buffer, so we make a copy */ strcpy(buf_raw, buf); len = strlen(buf) + 1; if (len > rowlen) rowlen = len; tokens = G_tokenize(buf, fs); ntokens = G_number_of_tokens(tokens); if (ntokens > ncols) { int c; coltype = (int *)G_realloc(coltype, ntokens * sizeof(int)); collen = (int *)G_realloc(collen, ntokens * sizeof(int)); for (c = ncols; c < ntokens; c++) { coltype[c] = DB_C_TYPE_INT; /* default type */ collen[c] = 0; } ncols = ntokens; } if (minncols == -1 || minncols > ntokens) minncols = ntokens; /* Determine column types */ for (i = 0; i < ntokens; i++) { if ((G_projection() == PROJECTION_LL)) { if (i == xcol || i == ycol) { if (i == 0) { /* Save position of original internal token buffer */ /* Prevent memory leaks */ sav_buf = tokens[0]; } /* check if coordinates are DMS or decimal or not latlong at all */ sprintf(coorbuf, "%s", tokens[i]); G_debug(4, "token: %s", coorbuf); if (i == xcol) { if (G_scan_easting(coorbuf, &easting, window.proj)) { G_debug(4, "is_latlong east: %f", easting); sprintf(tmp_token, "%.12f", easting); /* replace current DMS token by decimal degree */ tokens[i] = tmp_token; if (region_flag) { if ((window.east < easting) || (window.west > easting)) skip = TRUE; } } else { fprintf(stderr, "Current row: '%s'\n", buf_raw); G_fatal_error(_("Unparsable longitude value in column <%d>: %s"), i, tokens[i]); } } if (i == ycol) { if (G_scan_northing(coorbuf, &northing, window.proj)) { G_debug(4, "is_latlong north: %f", northing); sprintf(tmp_token, "%.12f", northing); /* replace current DMS token by decimal degree */ tokens[i] = tmp_token; if (region_flag) { if ((window.north < northing) || (window.south > northing)) skip = TRUE; } } else { fprintf(stderr, "Current row: '%s'\n", buf_raw); G_fatal_error(_("Unparsable latitude value in column <%d>: %s"), i, tokens[i]); } } } /* if (x or y) */ if (i == ntokens - 1 && sav_buf != NULL) { /* Restore original token buffer so free_tokens works */ /* Only do this if tokens[0] was re-assigned */ tokens[0] = sav_buf; sav_buf = NULL; } } /* PROJECTION_LL */ else { if (region_flag) { /* consider z range if -z flag is used? */ /* change to if(>= east,north){skip=1;} to allow correct tiling */ /* don't "continue;" so multiple passes will have the same column types and length for patching */ if (i == xcol) { easting = atof(tokens[i]); if ((window.east < easting) || (window.west > easting)) skip = TRUE; } if (i == ycol) { northing = atof(tokens[i]); if ((window.north < northing) || (window.south > northing)) skip = TRUE; } } } G_debug(4, "row %d col %d: '%s' is_int = %d is_double = %d", row, i, tokens[i], is_int(tokens[i]), is_double(tokens[i])); if (is_int(tokens[i])) { continue; /* integer */ } if (is_double(tokens[i])) { /* double */ if (coltype[i] == DB_C_TYPE_INT) { coltype[i] = DB_C_TYPE_DOUBLE; } continue; } /* string */ coltype[i] = DB_C_TYPE_STRING; len = strlen(tokens[i]); if (len > collen[i]) collen[i] = len; } /* write dataline to tmp file */ if (!skip) fprintf(ascii, "%s\n", buf_raw); else skipped++; G_free_tokens(tokens); row++; } *rowlength = rowlen; *ncolumns = ncols; *minncolumns = minncols; *column_type = coltype; *column_length = collen; *nrows = row - 1; /* including skipped lines */ G_free(buf); G_free(buf_raw); G_free(coorbuf); G_free(tmp_token); if (region_flag) G_message(_("Skipping %d of %d rows falling outside of current region"), skipped, row - 1); return 0; } /* Import points from ascii file. * * fs: field separator * xcol, ycol, zcol, catcol: x,y,z,cat column in input file, first column is 1, * zcol and catcol may be 0 (do not use) * rowlen: maximum row length * Note: column types (both in header or coldef) must be supported by driver */ int points_to_bin(FILE * ascii, int rowlen, struct Map_info *Map, dbDriver * driver, char *table, char *fs, int nrows, int ncols, int *coltype, int xcol, int ycol, int zcol, int catcol, int skip_lines) { char *buf, buf2[4000]; int cat = 0; int row = 1; struct line_pnts *Points; struct line_cats *Cats; dbString sql, val; struct Cell_head window; G_message(_("Importing points...")); /* fetch projection for LatLong test */ G_get_window(&window); rewind(ascii); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); buf = (char *)G_malloc(rowlen + 1); db_init_string(&sql); db_init_string(&val); if (skip_lines > 0) { sprintf(buf2, "HEADER: (%d lines)\n", skip_lines); Vect_hist_write(Map, buf2); } while (G_getl2(buf, rowlen, ascii) != 0) { int i, len; double x, y, z; char **tokens; int ntokens; /* number of tokens */ if (row <= skip_lines) { G_debug(4, "writing skip line %d to hist : %d chars", row, (int)strlen(buf)); Vect_hist_write(Map, buf); Vect_hist_write(Map, "\n"); row++; continue; } len = strlen(buf); if (len == 0) continue; /* should not happen */ G_debug(4, "row: %s", buf); tokens = G_tokenize(buf, fs); ntokens = G_number_of_tokens(tokens); if ((G_projection() == PROJECTION_LL)) { G_scan_easting(tokens[xcol], &x, window.proj); G_scan_northing(tokens[ycol], &y, window.proj); } else { x = atof(tokens[xcol]); y = atof(tokens[ycol]); } G_debug(4, "x: %f, y: %f", x, y); if (zcol >= 0) z = atof(tokens[zcol]); else z = 0.0; if (catcol >= 0) cat = atof(tokens[catcol]); else cat++; Vect_reset_line(Points); Vect_reset_cats(Cats); Vect_append_point(Points, x, y, z); Vect_cat_set(Cats, 1, cat); Vect_write_line(Map, GV_POINT, Points, Cats); /* Attributes */ if (driver) { sprintf(buf2, "insert into %s values ( ", table); db_set_string(&sql, buf2); if (catcol < 0) { sprintf(buf2, "%d, ", cat); db_append_string(&sql, buf2); } for (i = 0; i < ntokens; i++) { if (i > 0) db_append_string(&sql, ", "); if (strlen(tokens[i]) > 0) { if (coltype[i] == DB_C_TYPE_INT || coltype[i] == DB_C_TYPE_DOUBLE) { if (G_projection() == PROJECTION_LL && (i == xcol || i == ycol)) { if (i == xcol) sprintf(buf2, "%.15g", x); else sprintf(buf2, "%.15g", y); } else sprintf(buf2, "%s", tokens[i]); } else { db_set_string(&val, tokens[i]); /* TODO: strip leading and trailing "quotes" from input string */ db_double_quote_string(&val); sprintf(buf2, "'%s'", db_get_string(&val)); } } else { sprintf(buf2, "null"); } db_append_string(&sql, buf2); } db_append_string(&sql, ")"); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Unable to insert new record: %s"), db_get_string(&sql)); } } G_percent(row, nrows, 2); G_free_tokens(tokens); row++; } return 0; }