1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273 |
- /*-
- * These functions and definitions support the site format for 5.0
- * (format proposed by Dave Gerdes):
- *
- * easting|northing|[z|[d4|]...][#category_int] [ [@attr_text OR %flt] ... ]
- *
- * to allow multidimensions (everything preceding the last '|') and any
- * number of text or numeric attribute fields.
- *
- * Author: James Darrell McCauley <mccauley@ecn.purdue.edu>
- * 31 Jan 1994
- */
- #include <ctype.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <grass/gis.h>
- #include <grass/site.h>
- #include <grass/dbmi.h>
- #include <grass/vector.h>
- #include <grass/glocale.h>
- #define DQUOTE '"'
- #define SPACE ' '
- #define BSLASH 92
- #define PIPE '|'
- #define ispipe(c) (c==PIPE)
- #define isnull(c) (c=='\0')
- #define isquote(c) (c==DQUOTE)
- #define isbslash(c) (c==BSLASH)
- static int format_double(double, char *);
- static char *next_att(const char *);
- static int cleanse_string(char *);
- static int site_att_cmp(const void *pa, const void *pb)
- {
- const struct site_att *a = pa, *b = pb;
- return a->cat - b->cat;
- }
- /*-
- * Reads ptr and returns 0 on success,
- * -1 on EOF,
- * -2 on other fatal error or insufficient data,
- * 1 on format mismatch (extra data)
- */
- int G_site_get(struct Map_info *Map, Site * s)
- {
- int i, type, cat;
- static struct line_pnts *Points = NULL;
- static struct line_cats *Cats = NULL;
- struct site_att *sa;
- if (Points == NULL)
- Points = Vect_new_line_struct();
- if (Cats == NULL)
- Cats = Vect_new_cats_struct();
- while (1) {
- type = Vect_read_next_line(Map, Points, Cats);
- if (type == -1)
- return -2; /* Error */
- if (type == -2)
- return -1; /* EOF */
- if (type != GV_POINT)
- continue; /* Is not point */
- Vect_cat_get(Cats, 1, &cat);
- G_debug(4, "Site: %f|%f|%f|#%d", Points->x[0], Points->y[0],
- Points->z[0], cat);
- s->east = Points->x[0];
- s->north = Points->y[0];
- if (Vect_is_3d(Map))
- s->dim[0] = Points->z[0];
- s->ccat = cat;
- /* find att */
- if (Map->n_site_att > 0) {
- sa = (struct site_att *) bsearch((void *)&cat, (void *)Map->site_att,
- Map->n_site_att, sizeof(struct site_att),
- site_att_cmp);
- if (sa == NULL) {
- G_warning(_("Attributes for category %d not found"), cat);
- for (i = 0; i < Map->n_site_dbl; i++)
- s->dbl_att[i] = 0;
- for (i = 0; i < Map->n_site_str; i++)
- strncpy(s->str_att[i], "", MAX_SITE_STRING);
- }
- else {
- for (i = 0; i < Map->n_site_dbl; i++)
- s->dbl_att[i] = sa->dbl[i];
- for (i = 0; i < Map->n_site_str; i++)
- strncpy(s->str_att[i], sa->str[i], MAX_SITE_STRING);
- }
- }
- return 0;
- }
- }
- /* Writes a site to file open on fptr. */
- int G_site_put(struct Map_info *Map, const Site * s)
- {
- static struct line_pnts *Points = NULL;
- static struct line_cats *Cats = NULL;
- if (Points == NULL)
- Points = Vect_new_line_struct();
- if (Cats == NULL)
- Cats = Vect_new_cats_struct();
- Vect_reset_line(Points);
- Vect_reset_cats(Cats);
- /* no 3D support so far: s->dim[0] */
- Vect_append_point(Points, s->east, s->north, 0.0);
- G_debug(4, "cattype = %d", s->cattype);
- if (s->cattype == FCELL_TYPE || s->cattype == DCELL_TYPE)
- G_fatal_error(_("Category must be integer"));
- if (s->cattype == CELL_TYPE)
- Vect_cat_set(Cats, 1, s->ccat);
- Vect_write_line(Map, GV_POINT, Points, Cats);
- return 0;
- }
- /*-
- * Tries to guess the format of a sites list (the dimensionality,
- * the presence/type of a category, and the number of string and decimal
- * attributes) by reading the first record in the file.
- * Reads ptr and returns 0 on success,
- * -1 on EOF,
- * -2 for other error.
- */
- int G_site_describe(struct Map_info *Map, int *dims, int *cat, int *strs,
- int *dbls)
- {
- if (Vect_is_3d(Map)) {
- G_debug(1, "Vector is 3D -> number of site dimensions is 3");
- *dims = 3;
- }
- else {
- G_debug(1, "Vector is 2D -> number of site dimensions is 2");
- *dims = 2;
- }
- *cat = CELL_TYPE;
- /* attributes ignored for now, later read from DB */
- *dbls = Map->n_site_dbl;
- *strs = Map->n_site_str;
- return 0;
- }
- /*-
- * Writes site_head struct.
- */
- int G_site_put_head(struct Map_info *Map, Site_head * head)
- {
- static char buf[128];
- if (head->name != NULL)
- Vect_set_map_name(Map, head->name);
- /* crashes:
- if (head->desc!=NULL)
- Vect_set_comment (Map, head->desc);
- */
- /*
- if (head->form!=NULL)
- fprintf(ptr,"form|%s\n",head->form);
- if (head->labels!=NULL)
- fprintf(ptr,"labels|%s\n",head->labels);
- */
- /* time could be in (char *) stime, (struct TimeStamp *) time,
- both, or neither */
- if (head->stime != NULL || head->time != NULL) {
- if (head->time != NULL) { /* TimeStamp struct has precendence */
- G_format_timestamp(head->time, buf);
- Vect_set_date(Map, buf);
- }
- else if (head->stime != NULL) { /* next check string */
- if (head->time == NULL) {
- if ((head->time =
- (struct TimeStamp *)G_malloc(sizeof(struct TimeStamp)))
- == NULL)
- G_fatal_error(_("Memory error in writing timestamp"));
- else if (G_scan_timestamp(head->time, head->stime) < 0) {
- G_warning(_("Illegal TimeStamp string"));
- return -1; /* added to prevent crash 5/2000 MN */
- }
- }
- G_format_timestamp(head->time, buf);
- head->stime = G_store(buf);
- Vect_set_date(Map, head->stime);
- }
- }
- return 0;
- }
- /*-
- * Fills in site_head struct.
- */
- int G_site_get_head(struct Map_info *Map, Site_head * head)
- {
- head->name = Vect_get_name(Map);
- head->desc = Vect_get_comment(Map);
- head->form = NULL;
- head->labels = NULL;
- /* head->stime = Vect_get_date(Map); *//* crashes, G_scan_timestamp() needed? */
- head->stime = NULL;
- head->time = NULL;
- if (head->stime && strlen(head->stime) > 0) {
- if ((head->time =
- (struct TimeStamp *)G_malloc(sizeof(struct TimeStamp))) == NULL)
- G_fatal_error(_("Memory error in allocating timestamp"));
- if (G_scan_timestamp(head->time, head->stime) < 0) {
- G_warning(datetime_error_msg());
- head->time = NULL;
- head->stime = NULL;
- }
- }
- return 0;
- }
- /*-************************************************************************
- *
- * struct Map_info *
- * G_sites_open_old (name, mapset)
- * opens the existing site list file 'name' in the 'mapset'
- *
- * struct Map_info *
- * G_sites_open_new (name)
- * opens a new site list file 'name' in the current mapset
- *
- * parms
- * char *name map file name
- * char *mapset mapset containing map "name"
- *
- **********************************************************************/
- const char *G_find_sites(char *name, const char *mapset)
- {
- return G_find_vector(name, mapset);
- }
- const char *G_find_sites2(const char *name, const char *mapset)
- {
- return G_find_vector2(name, mapset);
- }
- struct Map_info *G_sites_open_old(const char *name, const char *mapset)
- {
- struct Map_info *Map;
- struct field_info *fi;
- int more, nrows, row, ncols, col, ndbl, nstr, adbl, astr, ctype;
- struct site_att *sa;
- dbDriver *driver;
- dbString stmt;
- dbCursor cursor;
- dbTable *table;
- dbColumn *column;
- dbValue *value;
- G_message(
- _("Dev note: Adapted sites library used for vector points. "
- "(module should be updated to GRASS 6 vector library)"));
- Map = (struct Map_info *)G_malloc(sizeof(struct Map_info));
- Vect_set_open_level(1);
- Vect_open_old(Map, name, mapset);
- G_debug(1, "Vector map opened");
- /* Load attributes */
- Map->site_att = NULL;
- Map->n_site_att = 0;
- Map->n_site_dbl = 0;
- Map->n_site_str = 0;
- fi = Vect_get_field(Map, 1);
- if (fi == NULL) { /* not attribute table */
- G_debug(1, "No attribute table");
- return Map;
- }
- driver = db_start_driver_open_database(fi->driver, fi->database);
- if (driver == NULL)
- G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
- fi->database,
- fi->driver);
- db_init_string(&stmt);
- db_set_string(&stmt, "select * from ");
- db_append_string(&stmt, fi->table);
- if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK)
- G_fatal_error(_("Unable to open select cursor: '%s'"),
- db_get_string(&stmt));
- nrows = db_get_num_rows(&cursor);
- G_debug(1, "%d rows selected from vector attribute table", nrows);
- Map->site_att = (struct site_att *) malloc(nrows * sizeof(struct site_att));
- Map->n_site_att = nrows;
- table = db_get_cursor_table(&cursor);
- ncols = db_get_table_number_of_columns(table);
- row = 0;
- adbl = astr = 0;
- while (1) {
- if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
- G_fatal_error(_("Cannot fetch row"));
- if (!more)
- break;
- /* Get number of each type */
- if (row == 0) {
- for (col = 0; col < ncols; col++) {
- column = db_get_table_column(table, col);
- ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
- if (strcmp(db_get_column_name(column), fi->key) == 0)
- continue;
- switch (ctype) {
- case DB_C_TYPE_INT:
- case DB_C_TYPE_DOUBLE:
- adbl++;
- break;
- case DB_C_TYPE_STRING:
- case DB_C_TYPE_DATETIME:
- astr++;
- break;
- }
- }
- Map->n_site_dbl = adbl;
- Map->n_site_str = astr;
- G_debug(1, "adbl = %d astr = %d", adbl, astr);
- }
- sa = &(Map->site_att[row]);
- sa->dbl = (double *)malloc(adbl * sizeof(double));
- sa->str = (char **)malloc(astr * sizeof(char *));
- ndbl = nstr = 0;
- for (col = 0; col < ncols; col++) {
- column = db_get_table_column(table, col);
- ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
- value = db_get_column_value(column);
- if (strcmp(db_get_column_name(column), fi->key) == 0) {
- sa->cat = db_get_value_int(value);
- }
- else {
- switch (ctype) {
- case DB_C_TYPE_INT:
- sa->dbl[ndbl] = db_get_value_int(value);
- ndbl++;
- break;
- case DB_C_TYPE_DOUBLE:
- sa->dbl[ndbl] = db_get_value_double(value);
- ndbl++;
- break;
- case DB_C_TYPE_STRING:
- sa->str[nstr] = G_store(db_get_value_string(value));
- nstr++;
- break;
- case DB_C_TYPE_DATETIME:
- sa->str[nstr] = ""; /* TODO */
- nstr++;
- break;
- }
- }
- }
- row++;
- }
- db_close_database_shutdown_driver(driver);
- /* sort attributes */
- qsort((void *)Map->site_att, Map->n_site_att, sizeof(struct site_att),
- site_att_cmp);
- return Map;
- }
- struct Map_info *G_sites_open_new(const char *name)
- {
- struct Map_info *Map;
- G_message(
- _("Dev note: Adapted sites library used for vector points. "
- "(module should be updated to GRASS 6 vector library)"));
- G_warning("Site/vector attributes ignored.");
- Map = (struct Map_info *)G_malloc(sizeof(struct Map_info));
- Vect_open_new(Map, name, 0);
- G_debug(1, "New vector map opened");
- return Map;
- }
- void G_sites_close(struct Map_info *Map)
- {
- int i, j;
- if (Map->mode == GV_MODE_WRITE || Map->mode == GV_MODE_RW)
- Vect_build(Map);
- Vect_close(Map);
- for (i = 0; i < Map->n_site_att; i++) {
- free(Map->site_att[i].dbl);
- for (j = 0; j < Map->n_site_str; j++)
- free(Map->site_att[i].str[j]);
- free(Map->site_att[i].str);
- }
- free(Map->site_att);
- G_free(Map);
- }
- /*********************************************/
- /* The following functions are obsolete. */
- /* They are retained here only for backwards */
- /* compatability while porting applications */
- /*********************************************/
- struct Map_info *G_fopen_sites_old(const char *name, const char *mapset)
- {
- return G_sites_open_old(name, mapset);
- }
- struct Map_info *G_fopen_sites_new(const char *name)
- {
- return G_sites_open_new(name);
- }
- int G_get_site(struct Map_info *fd, double *east, double *north, char **desc)
- {
- /* TODO ? */
- G_fatal_error("G_get_site() not yet updated.");
- return -1;
- }
- int G_put_site(struct Map_info *fd, double east, double north,
- const char *desc)
- {
- /* TODO ? */
- G_fatal_error("G_put_site() not yet updated.");
- return 0;
- }
- /* Functions moved here from lib/gis/sites.c */
- void G_site_free_struct(Site * s)
- /* Free memory for a Site struct */
- {
- if (s->dim_alloc)
- G_free(s->dim);
- if (s->str_alloc)
- G_free(s->str_att);
- if (s->dbl_alloc)
- G_free(s->dbl_att);
- G_free(s);
- return;
- }
- Site *G_site_new_struct(RASTER_MAP_TYPE cattype,
- int n_dim, int n_s_att, int n_d_att)
- /* Allocate memory for a Site struct. Returns a properly allocated
- site struct or NULL on error.
- cattype= -1 (no cat), CELL_TYPE, FCELL_TYPE, or DCELL_TYPE
- */
- {
- int i;
- Site *s;
- if (n_dim < 2 || n_s_att < 0 || n_d_att < 0)
- G_fatal_error(_("G_oldsite_new_struct: invalid # dims or fields"));
- if ((s = (Site *) G_malloc(sizeof(Site))) == NULL)
- return (Site *) NULL;
- s->cattype = cattype;
- s->ccat = s->fcat = s->dcat = 0;
- if (n_dim > 2) {
- if ((s->dim =
- (double *)G_malloc((n_dim - 2) * sizeof(double))) == NULL) {
- G_free(s);
- return (Site *) NULL;
- }
- }
- s->dim_alloc = n_dim - 2;
- if (n_d_att > 0) {
- if ((s->dbl_att =
- (double *)G_malloc(n_d_att * sizeof(double))) == NULL) {
- if (n_dim > 2)
- G_free(s->dim);
- G_free(s);
- return (Site *) NULL;
- }
- }
- s->dbl_alloc = n_d_att;
- if (n_s_att > 0) {
- if ((s->str_att =
- (char **)G_malloc(n_s_att * sizeof(char *))) == NULL) {
- if (n_d_att > 0)
- G_free(s->dbl_att);
- if (n_dim > 2)
- G_free(s->dim);
- G_free(s);
- return (Site *) NULL;
- }
- else
- for (i = 0; i < n_s_att; ++i)
- if ((s->str_att[i] =
- (char *)G_malloc(MAX_SITE_STRING * sizeof(char))) ==
- NULL) {
- while (--i)
- G_free(s->str_att[i]);
- G_free(s->str_att);
- if (n_d_att > 0)
- G_free(s->dbl_att);
- if (n_dim > 2)
- G_free(s->dim);
- G_free(s);
- return (Site *) NULL;
- }
- }
- s->str_alloc = n_s_att;
- return s;
- }
- #define FOUND_ALL(s,n,dim,c,d) (((s->cattype != -1 && !n) || \
- (dim < s->dim_alloc) || \
- (c < s->str_alloc) || \
- (d < s->dbl_alloc))?0:1)
- int G_oldsite_get(FILE * fptr, Site * s)
- /* Writes a site to file open on fptr. */
- {
- return G__oldsite_get(fptr, s, G_projection());
- }
- int G__oldsite_get(FILE * ptr, Site * s, int fmt)
- /*-
- * Reads ptr and returns 0 on success,
- * -1 on EOF,
- * -2 on other fatal error or insufficient data,
- * 1 on format mismatch (extra data)
- */
- {
- char sbuf[MAX_SITE_LEN], *buf, *last, *p1, *p2;
- char ebuf[128], nbuf[128];
- int n = 0, d = 0, c = 0, dim = 0, err = 0, tmp;
- buf = sbuf;
- if ((buf = fgets(sbuf, 1024, ptr)) == (char *)NULL)
- return EOF;
- while ((*buf == '#' || !isdigit(*buf)) && *buf != '-' && *buf != '+')
- if ((buf = fgets(sbuf, 1024, ptr)) == (char *)NULL)
- return EOF;
- if (buf[strlen(buf) - 1] == '\n')
- buf[strlen(buf) - 1] = '\0';
- if (sscanf(buf, "%[^|]|%[^|]|%*[^\n]", ebuf, nbuf) < 2) {
- fprintf(stderr, "ERROR: ebuf %s nbuf %s\n", ebuf, nbuf);
- return -2;
- }
- if (!G_scan_northing(nbuf, &(s->north), fmt) ||
- !G_scan_easting(ebuf, &(s->east), fmt)) {
- fprintf(stderr, "ERROR: ebuf %s nbuf %s\n", ebuf, nbuf);
- return -2;
- }
- /* move pointer past easting and northing fields */
- if (NULL == (buf = strchr(buf, PIPE)))
- return -2;
- if (NULL == (buf = strchr(buf + 1, PIPE)))
- return -2;
- /* check for remaining dimensional fields */
- do {
- buf++;
- if (isnull(*buf))
- return (FOUND_ALL(s, n, dim, c, d) ? 0 : -2);
- last = buf;
- if (dim < s->dim_alloc) { /* should be more dims to read */
- if (sscanf(buf, "%lf|", &(s->dim[dim++])) < 1)
- return -2; /* no more dims, though expected */
- }
- else if (NULL != (p1 = strchr(buf, PIPE))) {
- if (NULL == (p2 = strchr(buf, DQUOTE)))
- err = 1; /* more dims, though none expected */
- else if (strlen(p1) > strlen(p2))
- err = 1; /* more dims, though none expected */
- }
- } while ((buf = strchr(buf, PIPE)) != NULL);
- buf = last;
- /* no more dimensions-now we parse attribute fields */
- while (!isnull(*buf)) {
- switch (*buf) {
- case '#': /* category field */
- if (n == 0) {
- switch (s->cattype) {
- case CELL_TYPE:
- if (sscanf(buf, "#%d", &s->ccat) == 1)
- n++;
- break;
- case FCELL_TYPE:
- if (sscanf(buf, "#%f", &s->fcat) == 1)
- n++;
- break;
- case DCELL_TYPE:
- if (sscanf(buf, "#%lf", &s->dcat) == 1)
- n++;
- break;
- default:
- err = 1; /* has cat, none expected */
- break;
- }
- }
- else {
- err = 1; /* extra cat */
- }
- /* move to beginning of next attribute */
- if ((buf = next_att(buf)) == (char *)NULL)
- return (FOUND_ALL(s, n, dim, c, d) ? err : -2);
- break;
- case '%': /* decimal attribute */
- if (d < s->dbl_alloc) {
- p1 = ++buf;
- errno = 0;
- s->dbl_att[d++] = strtod(buf, &p1);
- if (p1 == buf || errno == ERANGE) {
- /* replace with:
- * s->dbl_att[d - 1] = NAN
- * when we add NULL attribute support
- */
- return -2;
- }
- /* err = 0; Make sure this is zeroed */
- }
- else {
- err = 1; /* extra decimal */
- }
- if ((buf = next_att(buf)) == (char *)NULL) {
- return (FOUND_ALL(s, n, dim, c, d)) ? err : -2;
- }
- break;
- case '@': /* string attribute */
- if (isnull(*buf) || isnull(*(buf + 1)))
- return (FOUND_ALL(s, n, dim, c, d) ? err : -2);
- else
- buf++;
- default: /* defaults to string attribute */
- /* allow both prefixed and unprefixed strings */
- if (c < s->str_alloc) {
- if ((tmp = cleanse_string(buf)) > 0) {
- strncpy(s->str_att[c++], buf, tmp);
- buf += tmp;
- }
- else
- return (FOUND_ALL(s, n, dim, c, d) ? err : -2);
- }
- if ((buf = next_att(buf)) == (char *)NULL) {
- return (FOUND_ALL(s, n, dim, c, d) ? err : -2);
- }
- break;
- }
- }
- return (FOUND_ALL(s, n, dim, c, d) ? err : -2);
- }
- int G_oldsite_describe(FILE * ptr, int *dims, int *cat, int *strs, int *dbls)
- /*-
- * Tries to guess the format of a sites list (the dimensionality,
- * the presence/type of a category, and the number of string and decimal
- * attributes) by reading the first record in the file.
- * Reads ptr and returns 0 on success,
- * -1 on EOF,
- * -2 for other error.
- */
- {
- char sbuf[MAX_SITE_LEN], *buf;
- char ebuf[128], nbuf[128];
- int err;
- int itmp;
- float ftmp;
- if (G_ftell(ptr) != 0L) {
- fprintf(stderr,
- "\nPROGRAMMER ERROR: G_oldsite_describe() must be called\n");
- fprintf(stderr, " immediately after G_fopen_sites_old()\n");
- return -2;
- }
- *dims = *strs = *dbls = 0;
- *cat = -1;
- buf = sbuf;
- if ((buf = fgets(sbuf, 1024, ptr)) == (char *)NULL) {
- rewind(ptr);
- return EOF;
- }
- /* skip over comment & header lines */
- while ((*buf == '#' || !isdigit(*buf)) && *buf != '-' && *buf != '+')
- if ((buf = fgets(sbuf, 1024, ptr)) == (char *)NULL) {
- rewind(ptr);
- return EOF;
- }
- if (buf[strlen(buf) - 1] == '\n')
- buf[strlen(buf) - 1] = '\0';
- if ((err = sscanf(buf, "%[^|]|%[^|]|%*[^\n]", ebuf, nbuf)) < 2) {
- fprintf(stderr, "ERROR: ebuf %s nbuf %s\n", ebuf, nbuf);
- rewind(ptr);
- return -2;
- }
- *dims = 2;
- /* move pointer past easting and northing fields */
- while (!ispipe(*buf) && !isnull(*buf))
- buf++;
- if (!isnull(*buf) && !isnull(*(buf + 1)))
- buf++;
- else {
- rewind(ptr);
- return -2;
- }
- while (!ispipe(*buf) && !isnull(*buf))
- buf++;
- if (!isnull(*buf) && !isnull(*(buf + 1)))
- buf++;
- else {
- rewind(ptr);
- return 0;
- }
- /* check for remaining dimensional fields */
- while (strchr(buf, PIPE) != (char *)NULL) {
- (*dims)++;
- while (!ispipe(*buf) && !isnull(*buf))
- buf++;
- if (isnull(*buf) || isnull(*(buf + 1))) {
- rewind(ptr);
- return 0;
- }
- if (!isnull(*(buf + 1)))
- buf++;
- else {
- rewind(ptr);
- return -2;
- }
- }
- /* no more dimensions-now we parse attribute fields */
- while (!isnull(*buf)) {
- switch (*buf) {
- case '#': /* category field */
- sscanf(buf, "#%s ", ebuf);
- if (strstr(ebuf, ".") == NULL && sscanf(ebuf, "%d", &itmp) == 1)
- *cat = CELL_TYPE;
- else if (strstr(ebuf, ".") != NULL &&
- sscanf(ebuf, "%f", &ftmp) == 1)
- *cat = FCELL_TYPE;
- else
- *cat = -1;
- /* move to beginning of next attribute */
- while (!isspace(*buf) && !isnull(*buf))
- buf++;
- if (isnull(*buf) || isnull(*(buf + 1))) {
- rewind(ptr);
- return 0;
- }
- else
- buf++;
- break;
- case '%': /* decimal attribute */
- (*dbls)++;
- /* move to beginning of next attribute */
- while (!isspace(*buf) && !isnull(*buf))
- buf++;
- if (isnull(*buf) || isnull(*(buf + 1))) {
- rewind(ptr);
- return 0;
- }
- else
- buf++;
- break;
- case '@': /* string attribute */
- if (isnull(*buf) || isnull(*(buf + 1))) {
- rewind(ptr);
- return 0;
- }
- else
- buf++;
- default: /* defaults to string attribute */
- /* allow both prefixed and unprefixed strings */
- if ((err = cleanse_string(buf)) > 0) {
- (*strs)++;
- buf += err;
- }
- /* move to beginning of next attribute */
- while (!isspace(*buf) && !isnull(*buf))
- buf++;
- if (isnull(*buf) || isnull(*(buf + 1))) {
- rewind(ptr);
- return 0;
- }
- else
- buf++;
- break;
- }
- }
- rewind(ptr);
- return 0;
- }
- int G_site_in_region(const Site * site, const struct Cell_head *region)
- /* returns 1 if site is contained within region, 0 otherwise */
- {
- /* northwest corner is in region, southeast corner is not. */
- double e_ing;
- e_ing = G_adjust_easting(site->east, region);
- if (e_ing >= region->west &&
- e_ing < region->east &&
- site->north <= region->north && site->north > region->south)
- return 1;
- return 0;
- }
- static int format_double(double value, char *buf)
- {
- sprintf(buf, "%.8f", value);
- G_trim_decimal(buf);
- return 0;
- }
- int cleanse_string(char *buf)
- {
- char *stop, *p, *p2;
- p = buf;
- /*
- * get rid of any SPACEs at beginning while ( !isspace(*buf) && *buf !=
- * (char) NULL) buf++; if (*buf == (char) NULL) return -1;
- */
- /* find where this string terminates */
- if (*buf != DQUOTE) { /* if no DQUOTEs, */
- stop = strchr(buf, SPACE); /* then SPACE separates */
- if (stop == (char *)NULL)
- return strlen(buf);
- else
- return (int)(stop - buf);
- }
- else { /* otherwise string is in DQUOTEs */
- /* but we must skip over escaped */
- /* (BSLASHed) DQUOTEs */
- if (*p == DQUOTE) {
- while (*p != '\0') { /* get rid of first DQUOTE */
- *p = *(p + 1);
- p++;
- }
- p = buf;
- stop = strchr(p + 1, DQUOTE);
- while (*(stop - 1) == BSLASH)
- stop = strchr(++stop, DQUOTE);
- }
- }
- /* remove backslashes between buf and stop */
- p = buf;
- while ((p = strchr(p, BSLASH)) != (char *)NULL && p <= stop) {
- p2 = p + 1;
- if (*p2 != '\0' && (*p2 == DQUOTE || *p2 == BSLASH)) {
- while (*p != '\0') {
- *p = *(p + 1);
- p++;
- }
- stop--;
- }
- p = p2;
- }
- return (int)(stop - buf);
- }
- static char *next_att(const char *buf)
- {
- while (!isspace(*buf) && !isnull(*buf))
- buf++;
- if (isnull(*buf) || isnull(*(buf + 1)))
- return NULL;
- else
- while (isspace(*(buf + 1)) && !isnull(*(buf + 1)))
- buf++;
- buf++;
- return (char *)buf;
- }
- int G_site_c_cmp(const void *a, const void *b)
- /* qsort() comparison function for sorting an array of
- site structures by category. */
- {
- int result = 0; /* integer to be returned */
- double diff = 0;
- switch ((*(Site **) a)->cattype) {
- case CELL_TYPE:
- diff = (double)(*(Site **) a)->ccat - (*(Site **) b)->ccat;
- break;
- case FCELL_TYPE:
- diff = (double)(*(Site **) a)->fcat - (*(Site **) b)->fcat;
- break;
- case DCELL_TYPE:
- diff = (double)(*(Site **) a)->dcat - (*(Site **) b)->dcat;
- break;
- }
- if (diff < 0.0)
- result = -1;
- else if (diff > 0.0)
- result = 1;
- return result;
- }
- int G_site_d_cmp(const void *a, const void *b)
- /* qsort() comparison function for sorting an array of
- site structures by first decimal attribute. */
- {
- int result = 0; /* integer to be returned */
- double diff;
- diff = (*(Site **) a)->dbl_att[0] - (*(Site **) b)->dbl_att[0];
- if (diff < 0.0)
- result = -1;
- else if (diff > 0.0)
- result = 1;
- return result;
- }
- int G_oldsite_s_cmp(const void *a, const void *b)
- /* qsort() comparison function for sorting an array of
- site structures by first decimal attribute. */
- {
- return strcmp((*(char **)((*(Site **) a)->str_att)),
- (*(char **)((*(Site **) b)->str_att)));
- }
- /*-************************************************************************
- *
- * FILE *
- * G_oldsites_open_old (name, mapset)
- * opens the existing site list file 'name' in the 'mapset'
- *
- * parms
- * char *name map file name
- * char *mapset mapset containing map "name"
- *
- **********************************************************************/
- FILE *G_oldsites_open_old(const char *name, const char *mapset)
- {
- return G_fopen_old("site_lists", name, mapset);
- }
- FILE *G_oldsites_open_new(const char *name)
- {
- return G_fopen_new("site_lists", name);
- }
- /*********************************************/
- /* The following functions are obsolete. */
- /* They are retained here only for backwards */
- /* compatability while porting applications */
- /*********************************************/
- char *G_site_format(const Site * s, const char *fs, int id)
- /* sprintf analog to G_site_put with the addition of a field separator fs
- and option of printing site attribute identifiers
- */
- {
- char ebuf[MAX_SITE_STRING], nbuf[MAX_SITE_STRING];
- char xbuf[MAX_SITE_STRING];
- const char *nfs;
- char *buf;
- int fmt, i, j, k;
- buf = (char *)G_malloc(MAX_SITE_LEN * sizeof(char));
- fmt = G_projection();
- G_format_northing(s->north, nbuf, fmt);
- G_format_easting(s->east, ebuf, fmt);
- nfs = (char *)((fs == (char *)NULL) ? "|" : fs);
- sprintf(buf, "%s%s%s", ebuf, nfs, nbuf);
- for (i = 0; i < s->dim_alloc; ++i) {
- format_double(s->dim[i], nbuf);
- sprintf(xbuf, "%s%s", nfs, nbuf);
- strcat(buf, xbuf);
- }
- nfs = (fs == NULL) ? " " : fs;
- switch (s->cattype) {
- case CELL_TYPE:
- sprintf(xbuf, "%s%s%d ", nfs, ((id == 0) ? "" : "#"), (int)s->ccat);
- strcat(buf, xbuf);
- break;
- case FCELL_TYPE:
- case DCELL_TYPE:
- sprintf(xbuf, "%s%s%g ", nfs, ((id == 0) ? "" : "#"), (float)s->fcat);
- strcat(buf, xbuf);
- break;
- }
- for (i = 0; i < s->dbl_alloc; ++i) {
- format_double(s->dbl_att[i], nbuf);
- sprintf(xbuf, "%s%s%s", nfs, ((id == 0) ? "" : "%"), nbuf);
- strcat(buf, xbuf);
- }
- for (i = 0; i < s->str_alloc; ++i) {
- if (strlen(s->str_att[i]) != 0) {
- /* escape double quotes */
- j = k = 0;
- /* do not uncomment this code because sites file was created
- * as we want. So it's enough to print them out as it is.
- *
- if (strchr (s->str_att[i], DQUOTE) != (char *) NULL)
- {
- while (!isnull(s->str_att[i][j]))
- {
- if (isquote(s->str_att[i][j]))
- {
- xbuf[k++] = BSLASH;
- xbuf[k++] = DQUOTE;
- }
- else
- xbuf[k++] = s->str_att[i][j];
- j++;
- }
- xbuf[k] = (char) NULL;
- }
- else
- */
- strcpy(xbuf, s->str_att[i]);
- strcpy(s->str_att[i], xbuf);
- if (strchr(s->str_att[i], SPACE) != (char *)NULL)
- sprintf(xbuf, "%s%s\"%s\"", nfs, ((id == 0) ? "" : "@"),
- s->str_att[i]);
- else
- sprintf(xbuf, "%s%s%s", nfs, ((id == 0) ? "" : "@"),
- s->str_att[i]);
- strcat(buf, xbuf);
- }
- }
- return buf;
- }
- /*******************************************************************************/
- /*******************************************************************************/
- /*** ACS_MODIFY_BEGIN - sites_attribute management *****************************/
- /*
- These functions are used in visualization/nviz/src/site_attr_commands.c
- Functions to obtain fields in order to draw sites with each point having a
- geometric property depending from database values.
- */
- /*
- Returns a pointer to the struct site_att in Map_info *ptr and with category cat
- */
- struct site_att *G_sites_get_atts(struct Map_info * Map, int *cat)
- {
- return (struct site_att *) bsearch((void *)cat, (void *)Map->site_att,
- Map->n_site_att, sizeof(struct site_att),
- site_att_cmp);
- }
- /*
- Returns field names, types and indexes in double and string Map_info arrays
- WARNING: user is responsible to free allocated memory, directly or calling G_sites_free_fields()
- */
- int G_sites_get_fields(struct Map_info *Map, char ***cnames, int **ctypes,
- int **ndx)
- {
- struct field_info *fi;
- int nrows, row, ncols, col, ndbl, nstr, ctype;
- const char *name;
- dbDriver *driver;
- dbString stmt;
- dbCursor cursor;
- dbTable *table;
- dbColumn *column;
- /*dbValue *value; */
- /* warning: we are using "1" as cat field in Vect_get_field because G_sites_open_old
- (in lib/sites/sites.c), that we use here to open sites, does the same and then
- queries the db in the same way we do here.
- Should it be not true in the future, maybe we'll have to change this by choosing
- appropriate fields and multiple categories */
- fi = (struct field_info *)Vect_get_field(Map, 1);
- if (fi == NULL) { /* not attribute table */
- G_debug(1, "No attribute table");
- return -1;
- }
- driver = db_start_driver_open_database(fi->driver, fi->database);
- if (driver == NULL)
- G_fatal_error(_("Cannot open database %s by driver %s"), fi->database,
- fi->driver);
- db_init_string(&stmt);
- db_set_string(&stmt, "select * from ");
- db_append_string(&stmt, fi->table);
- if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK)
- G_fatal_error(_("Cannot select attributes"));
- nrows = db_get_num_rows(&cursor);
- G_debug(1, "%d rows selected from vector attribute table", nrows);
- table = db_get_cursor_table(&cursor);
- ncols = db_get_table_number_of_columns(table);
- if (ncols <= 0)
- return ncols;
- row = 0;
- /* Get number of each type */
- ndbl = nstr = 0;
- *cnames = (char **)malloc(ncols * sizeof(char *));
- *ctypes = (int *)malloc(ncols * sizeof(int));
- *ndx = (int *)malloc(ncols * sizeof(int));
- for (col = 0; col < ncols; col++) {
- column = db_get_table_column(table, col);
- ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
- name = db_get_column_name(column);
- *(*cnames + col) = (char *)malloc(strlen(name) + 1);
- strcpy(*(*cnames + col), db_get_column_name(column));
- /* ctypes is 'c' for cat, 'd' for double, 's' for string */
- if (strcmp(name, fi->key) == 0) {
- *(*ctypes + col) = 'c';
- *(*ndx + col) = -1;
- }
- else {
- switch (ctype) {
- case DB_C_TYPE_INT:
- case DB_C_TYPE_DOUBLE:
- *(*ctypes + col) = 'd';
- *(*ndx + col) = ndbl;
- ndbl++;
- break;
- case DB_C_TYPE_STRING:
- case DB_C_TYPE_DATETIME:
- *(*ctypes + col) = 's';
- *(*ndx + col) = nstr;
- nstr++;
- break;
- }
- }
- }
- db_close_database_shutdown_driver(driver);
- return ncols;
- }
- /* Frees fields allocated with G_sites_get_fields */
- void G_sites_free_fields(int ncols, char **cnames, int *ctypes, int *ndx)
- {
- for (; ncols > 0; ncols--)
- free(*(cnames + ncols - 1));
- free(cnames);
- free(ctypes);
- free(ndx);
- }
- /*** ACS_MODIFY_END - sites_attribute management *******************************/
|