sites.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341
  1. /*-
  2. * These functions and definitions support the site format for 5.0
  3. * (format proposed by Dave Gerdes):
  4. *
  5. * easting|northing|[z|[d4|]...][#category_int] [ [@attr_text OR %flt] ... ]
  6. *
  7. * to allow multidimensions (everything preceding the last '|') and any
  8. * number of text or numeric attribute fields.
  9. *
  10. * Author: James Darrell McCauley <mccauley@ecn.purdue.edu>
  11. * 31 Jan 1994
  12. */
  13. #include <ctype.h>
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <errno.h>
  18. #include <grass/gis.h>
  19. #include <grass/site.h>
  20. #include <grass/dbmi.h>
  21. #include <grass/Vect.h>
  22. #define DQUOTE '"'
  23. #define SPACE ' '
  24. #define BSLASH 92
  25. #define PIPE '|'
  26. #define ispipe(c) (c==PIPE)
  27. #define isnull(c) (c==(char)NULL)
  28. #define isquote(c) (c==DQUOTE)
  29. #define isbslash(c) (c==BSLASH)
  30. static int format_double ( double , char *);
  31. static char *next_att (const char *);
  32. static int cleanse_string(char *);
  33. static int site_att_cmp ( const void *pa, const void *pb) {
  34. const SITE_ATT *a = pa, *b = pb;
  35. return a->cat - b->cat;
  36. }
  37. /*-
  38. * Reads ptr and returns 0 on success,
  39. * -1 on EOF,
  40. * -2 on other fatal error or insufficient data,
  41. * 1 on format mismatch (extra data)
  42. */
  43. int G_site_get ( FILE *fptr, Site *s)
  44. {
  45. int i, type, cat;
  46. struct Map_info *Map;
  47. static struct line_pnts *Points = NULL;
  48. static struct line_cats *Cats = NULL;
  49. SITE_ATT *sa;
  50. Map = (struct Map_info *) fptr;
  51. if ( Points == NULL ) Points = Vect_new_line_struct ();
  52. if ( Cats == NULL ) Cats = Vect_new_cats_struct ();
  53. while ( 1 ) {
  54. type = Vect_read_next_line (Map, Points, Cats);
  55. if ( type == -1 ) return -2; /* Error */
  56. if ( type == -2 ) return -1; /* EOF */
  57. if ( type != GV_POINT ) continue; /* Is not point */
  58. Vect_cat_get (Cats, 1, &cat);
  59. G_debug (4, "Site: %f|%f|%f|#%d", Points->x[0], Points->y[0], Points->z[0], cat);
  60. s->east = Points->x[0];
  61. s->north = Points->y[0];
  62. if ( Vect_is_3d(Map) ) s->dim[0] = Points->z[0];
  63. s->ccat = cat;
  64. /* find att */
  65. if ( Map->n_site_att > 0 ) {
  66. sa = (SITE_ATT *) bsearch ( (void *) &cat, (void *)Map->site_att, Map->n_site_att,
  67. sizeof(SITE_ATT), site_att_cmp );
  68. if ( sa == NULL ) {
  69. G_warning ( "Attributes for category %d not found", cat );
  70. for ( i = 0; i < Map->n_site_dbl; i++ ) s->dbl_att[i] = 0;
  71. for ( i = 0; i < Map->n_site_str; i++ ) G_strncpy (s->str_att[i], "", MAX_SITE_STRING);
  72. } else {
  73. for ( i = 0; i < Map->n_site_dbl; i++ ) s->dbl_att[i] = sa->dbl[i];
  74. for ( i = 0; i < Map->n_site_str; i++ )
  75. G_strncpy (s->str_att[i], sa->str[i], MAX_SITE_STRING);
  76. }
  77. }
  78. return 0;
  79. }
  80. }
  81. /* Writes a site to file open on fptr. */
  82. int G_site_put ( FILE *fptr, const Site *s)
  83. {
  84. struct Map_info *Map;
  85. static struct line_pnts *Points = NULL;
  86. static struct line_cats *Cats = NULL;
  87. Map = (struct Map_info *) fptr;
  88. if ( Points == NULL ) Points = Vect_new_line_struct ();
  89. if ( Cats == NULL ) Cats = Vect_new_cats_struct ();
  90. Vect_reset_line (Points);
  91. Vect_reset_cats (Cats);
  92. /* no 3D support so far: s->dim[0] */
  93. Vect_append_point (Points, s->east, s->north, 0.0);
  94. G_debug (4, "cattype = %d", s->cattype);
  95. if ( s->cattype == FCELL_TYPE || s->cattype == DCELL_TYPE )
  96. G_fatal_error ( "Category must be integer" );
  97. if ( s->cattype == CELL_TYPE )
  98. Vect_cat_set (Cats, 1, s->ccat);
  99. Vect_write_line (Map, GV_POINT, Points, Cats);
  100. return 0;
  101. }
  102. /*-
  103. * Tries to guess the format of a sites list (the dimensionality,
  104. * the presence/type of a category, and the number of string and decimal
  105. * attributes) by reading the first record in the file.
  106. * Reads ptr and returns 0 on success,
  107. * -1 on EOF,
  108. * -2 for other error.
  109. */
  110. int G_site_describe ( FILE *ptr,
  111. int *dims,int *cat,int *strs,int *dbls)
  112. {
  113. struct Map_info *Map;
  114. Map = (struct Map_info *) ptr;
  115. if ( Vect_is_3d(Map) ) {
  116. G_debug (1, "Vector is 3D -> number of site dimensions is 3");
  117. *dims = 3;
  118. } else {
  119. G_debug (1, "Vector is 2D -> number of site dimensions is 2");
  120. *dims = 2;
  121. }
  122. *cat=CELL_TYPE;
  123. /* attributes ignored for now, later read from DB */
  124. *dbls = Map->n_site_dbl;
  125. *strs = Map->n_site_str;
  126. return 0;
  127. }
  128. /*-
  129. * Writes site_head struct.
  130. */
  131. int G_site_put_head ( FILE *ptr, Site_head *head)
  132. {
  133. struct Map_info *Map;
  134. static char buf[128];
  135. Map = (struct Map_info *) ptr;
  136. if (head->name!=NULL)
  137. Vect_set_map_name (Map, head->name);
  138. /* crashes:
  139. if (head->desc!=NULL)
  140. Vect_set_comment (Map, head->desc);
  141. */
  142. /*
  143. if (head->form!=NULL)
  144. fprintf(ptr,"form|%s\n",head->form);
  145. if (head->labels!=NULL)
  146. fprintf(ptr,"labels|%s\n",head->labels);
  147. */
  148. /* time could be in (char *) stime, (struct TimeStamp *) time,
  149. both, or neither */
  150. if (head->stime!=NULL || head->time !=NULL) {
  151. if (head->time != NULL) { /* TimeStamp struct has precendence */
  152. G_format_timestamp (head->time, buf);
  153. Vect_set_date (Map, buf);
  154. } else if (head->stime != NULL) { /* next check string */
  155. if (head->time==NULL) {
  156. if ((head->time=(struct TimeStamp *) G_malloc(sizeof(struct TimeStamp)))==NULL)
  157. G_fatal_error("Memory error in writing timestamp");
  158. else
  159. if (G_scan_timestamp (head->time, head->stime) < 0) {
  160. G_warning("Illegal TimeStamp string");
  161. return -1; /* added to prevent crash 5/2000 MN*/
  162. }
  163. }
  164. G_format_timestamp (head->time, head->stime);
  165. Vect_set_date (Map, head->stime);
  166. }
  167. }
  168. return 0;
  169. }
  170. /*-
  171. * Fills in site_head struct.
  172. */
  173. int G_site_get_head (FILE *ptr, Site_head *head)
  174. {
  175. struct Map_info *Map;
  176. Map = (struct Map_info *) ptr;
  177. head->name = Vect_get_name(Map);
  178. head->desc = Vect_get_comment(Map);
  179. head->form = NULL;
  180. head->labels = NULL;
  181. /* head->stime = Vect_get_date(Map); */ /* crashes, G_scan_timestamp() needed? */
  182. head->stime = NULL;
  183. head->time=NULL;
  184. if ( head->stime && strlen(head->stime) > 0 ) {
  185. if ((head->time=(struct TimeStamp *) G_malloc(sizeof(struct TimeStamp)))==NULL)
  186. G_fatal_error("Memory error in allocating timestamp");
  187. if (G_scan_timestamp (head->time , head->stime)<0) {
  188. G_warning(datetime_error_msg());
  189. head->time=NULL;
  190. head->stime=NULL;
  191. }
  192. }
  193. return 0;
  194. }
  195. /*-************************************************************************
  196. * char *
  197. * G_ask_sites_new(prompt, name))
  198. * asks user to input name of a new site list file
  199. *
  200. * char *
  201. * G_ask_sites_old(prompt, name)
  202. * asks user to input name of an existing site list file
  203. *
  204. * char *
  205. * G_ask_sites_any(prompt, name)
  206. * asks user to input any site list name
  207. *
  208. * char *
  209. * G_ask_sites_in_mapset(prompt, name)
  210. * asks user to input name of an existing site list file in
  211. * current mapset
  212. *
  213. * parms:
  214. * char *prompt optional prompt for user
  215. * char *name buffer to hold name of map found
  216. *
  217. * returns:
  218. * char *pointer to a string with name of mapset
  219. * where file was found, or NULL if not found
  220. *
  221. * note:
  222. * rejects all names that begin with .
  223. **********************************************************************
  224. *
  225. * FILE *
  226. * G_sites_open_old (name, mapset)
  227. * opens the existing site list file 'name' in the 'mapset'
  228. *
  229. * FILE *
  230. * G_sites_open_new (name)
  231. * opens a new site list file 'name' in the current mapset
  232. *
  233. * parms
  234. * char *name map file name
  235. * char *mapset mapset containing map "name"
  236. *
  237. **********************************************************************/
  238. char * G_find_sites (char *name, const char *mapset)
  239. {
  240. return G_find_vector (name, mapset);
  241. }
  242. char * G_find_sites2 (const char *name, const char *mapset)
  243. {
  244. return G_find_vector2 (name, mapset);
  245. }
  246. char * G_ask_sites_new (const char *prompt, char *name)
  247. {
  248. return G_ask_new (prompt, name, "vector", "vector");
  249. }
  250. char * G_ask_sites_old (const char *prompt, char *name)
  251. {
  252. return G_ask_old (prompt, name, "vector", "vector");
  253. }
  254. char * G_ask_sites_any (const char *prompt, char *name)
  255. {
  256. return G_ask_any (prompt, name, "vector", "vector", 1);
  257. }
  258. char * G_ask_sites_in_mapset (const char *prompt, char *name)
  259. {
  260. return G_ask_in_mapset (prompt, name, "vector", "vector");
  261. }
  262. FILE * G_sites_open_old (char *name,char *mapset)
  263. {
  264. struct Map_info *Map;
  265. struct field_info *fi;
  266. int more, nrows, row, ncols, col, ndbl, nstr, adbl, astr, ctype;
  267. SITE_ATT *sa;
  268. dbDriver *driver;
  269. dbString stmt;
  270. dbCursor cursor;
  271. dbTable *table;
  272. dbColumn *column;
  273. dbValue *value;
  274. G_warning ( "Adapted sites library used for vector points (module should be updated to GRASS 6 vector library).");
  275. Map = (struct Map_info *) G_malloc ( sizeof(struct Map_info) );
  276. Vect_set_open_level (1);
  277. Vect_open_old (Map, name, mapset);
  278. G_debug ( 1, "Vector map opened");
  279. /* Load attributes */
  280. Map->site_att = NULL;
  281. Map->n_site_att = 0;
  282. Map->n_site_dbl = 0;
  283. Map->n_site_str = 0;
  284. fi = Vect_get_field(Map, 1);
  285. if ( fi == NULL ) { /* not attribute table */
  286. G_debug ( 1, "No attribute table" );
  287. return (FILE *) Map;
  288. }
  289. driver = db_start_driver_open_database ( fi->driver, fi->database );
  290. if ( driver == NULL )
  291. G_fatal_error ( "Cannot open database %s by driver %s", fi->database, fi->driver );
  292. db_init_string (&stmt);
  293. db_set_string ( &stmt, "select * from ");
  294. db_append_string ( &stmt, fi->table );
  295. if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK)
  296. G_fatal_error ("Cannot select attributes.");
  297. nrows = db_get_num_rows ( &cursor );
  298. G_debug ( 1, "%d rows selected from vector attribute table", nrows);
  299. Map->site_att = (SITE_ATT *) malloc ( nrows * sizeof(SITE_ATT) );
  300. Map->n_site_att = nrows;
  301. table = db_get_cursor_table (&cursor);
  302. ncols = db_get_table_number_of_columns(table);
  303. row = 0;
  304. adbl = astr = 0;
  305. while (1) {
  306. if(db_fetch (&cursor, DB_NEXT, &more) != DB_OK)
  307. G_fatal_error ("Cannot fetch row.");
  308. if (!more) break;
  309. /* Get number of each type */
  310. if ( row == 0 ) {
  311. for (col = 0; col < ncols; col++) {
  312. column = db_get_table_column ( table, col );
  313. ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) );
  314. if ( strcmp(db_get_column_name(column),fi->key) == 0 )
  315. continue;
  316. switch ( ctype ) {
  317. case DB_C_TYPE_INT:
  318. case DB_C_TYPE_DOUBLE:
  319. adbl++;
  320. break;
  321. case DB_C_TYPE_STRING:
  322. case DB_C_TYPE_DATETIME:
  323. astr++;
  324. break;
  325. }
  326. }
  327. Map->n_site_dbl = adbl;
  328. Map->n_site_str = astr;
  329. G_debug ( 1, "adbl = %d astr = %d", adbl, astr );
  330. }
  331. sa = &(Map->site_att[row]);
  332. sa->dbl = (double *) malloc ( adbl * sizeof(double) );
  333. sa->str = (char **) malloc ( astr * sizeof(char *) );
  334. ndbl = nstr = 0;
  335. for (col = 0; col < ncols; col++) {
  336. column = db_get_table_column ( table, col );
  337. ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) );
  338. value = db_get_column_value(column);
  339. if ( strcmp(db_get_column_name(column),fi->key) == 0 ) {
  340. sa->cat = db_get_value_int(value);
  341. } else {
  342. switch ( ctype ) {
  343. case DB_C_TYPE_INT:
  344. sa->dbl[ndbl] = db_get_value_int(value);
  345. ndbl++;
  346. break;
  347. case DB_C_TYPE_DOUBLE:
  348. sa->dbl[ndbl] = db_get_value_double(value);
  349. ndbl++;
  350. break;
  351. case DB_C_TYPE_STRING:
  352. sa->str[nstr] = G_store ( db_get_value_string(value) ) ;
  353. nstr++;
  354. break;
  355. case DB_C_TYPE_DATETIME:
  356. sa->str[nstr] = ""; /* TODO */
  357. nstr++;
  358. break;
  359. }
  360. }
  361. }
  362. row++;
  363. }
  364. db_close_database_shutdown_driver ( driver );
  365. /* sort attributes */
  366. qsort ( (void *)Map->site_att, Map->n_site_att, sizeof(SITE_ATT), site_att_cmp );
  367. return (FILE *) Map;
  368. }
  369. FILE * G_sites_open_new (char *name)
  370. {
  371. struct Map_info *Map;
  372. G_warning ( "Adapted sites library used for vector points (module should be updated to GRASS 6 vector library).");
  373. G_warning ( "Site/vector attributes ignored.");
  374. Map = (struct Map_info *) G_malloc ( sizeof(struct Map_info) );
  375. Vect_open_new (Map, name, 0);
  376. G_debug ( 1, "New vector map opened");
  377. return (FILE *) Map;
  378. }
  379. void G_sites_close ( FILE * ptr)
  380. {
  381. int i, j;
  382. struct Map_info *Map;
  383. Map = (struct Map_info *) ptr;
  384. if (Map->mode == GV_MODE_WRITE || Map->mode == GV_MODE_RW)
  385. Vect_build (Map, stderr);
  386. Vect_close ( Map );
  387. for ( i = 0; i < Map->n_site_att; i++ ) {
  388. free ( Map->site_att[i].dbl );
  389. for ( j = 0; j < Map->n_site_str; j++ )
  390. free ( Map->site_att[i].str[j] );
  391. free ( Map->site_att[i].str );
  392. }
  393. free (Map->site_att);
  394. G_free ( Map );
  395. }
  396. /*********************************************/
  397. /* The following functions are obsolete. */
  398. /* They are retained here only for backwards */
  399. /* compatability while porting applications */
  400. /*********************************************/
  401. FILE *G_fopen_sites_old (char *name, char *mapset)
  402. {
  403. return G_sites_open_old (name, mapset);
  404. }
  405. FILE *G_fopen_sites_new (char *name)
  406. {
  407. return G_sites_open_new (name);
  408. }
  409. int G_get_site ( FILE *fd, double *east,double *north, char **desc)
  410. {
  411. /* TODO ? */
  412. G_fatal_error ( "G_get_site() not yet updated.");
  413. return -1;
  414. }
  415. int G_put_site ( FILE *fd, double east,double north, const char *desc)
  416. {
  417. /* TODO ? */
  418. G_fatal_error ( "G_put_site() not yet updated.");
  419. return 0;
  420. }
  421. /* Functions moved here from lib/gis/sites.c */
  422. void G_site_free_struct (Site *s)
  423. /* Free memory for a Site struct */
  424. {
  425. if(s->dim_alloc)
  426. G_free(s->dim);
  427. if(s->str_alloc)
  428. G_free(s->str_att);
  429. if(s->dbl_alloc)
  430. G_free(s->dbl_att);
  431. G_free(s);
  432. return;
  433. }
  434. Site *G_site_new_struct (RASTER_MAP_TYPE cattype,
  435. int n_dim,int n_s_att,int n_d_att)
  436. /* Allocate memory for a Site struct. Returns a properly allocated
  437. site struct or NULL on error.
  438. cattype= -1 (no cat), CELL_TYPE, FCELL_TYPE, or DCELL_TYPE
  439. */
  440. {
  441. int i;
  442. Site *s;
  443. if (n_dim < 2 || n_s_att < 0 || n_d_att < 0)
  444. G_fatal_error ("G_oldsite_new_struct: invalid # dims or fields\n");
  445. if ((s = (Site *) G_malloc (sizeof (Site))) == NULL)
  446. return (Site *) NULL;
  447. s->cattype=cattype;
  448. s->ccat=s->fcat=s->dcat=0;
  449. if (n_dim > 2)
  450. {
  451. if ((s->dim =
  452. (double *) G_malloc ((n_dim - 2) * sizeof (double))) == NULL) {
  453. G_free(s);
  454. return (Site *) NULL;
  455. }
  456. }
  457. s->dim_alloc = n_dim - 2;
  458. if (n_d_att > 0)
  459. {
  460. if ((s->dbl_att =
  461. (double *) G_malloc (n_d_att * sizeof (double))) == NULL) {
  462. if (n_dim > 2) G_free(s->dim);
  463. G_free(s);
  464. return (Site *) NULL;
  465. }
  466. }
  467. s->dbl_alloc = n_d_att;
  468. if (n_s_att > 0)
  469. {
  470. if ((s->str_att =
  471. (char **) G_malloc (n_s_att * sizeof (char *))) == NULL) {
  472. if (n_d_att > 0) G_free(s->dbl_att);
  473. if (n_dim > 2) G_free(s->dim);
  474. G_free(s);
  475. return (Site *) NULL;
  476. }
  477. else
  478. for (i = 0; i < n_s_att; ++i)
  479. if ((s->str_att[i] =
  480. (char *) G_malloc (MAX_SITE_STRING * sizeof (char))) == NULL) {
  481. while (--i) G_free(s->str_att[i]);
  482. G_free(s->str_att);
  483. if (n_d_att > 0) G_free(s->dbl_att);
  484. if (n_dim > 2) G_free(s->dim);
  485. G_free(s);
  486. return (Site *) NULL;
  487. }
  488. }
  489. s->str_alloc = n_s_att;
  490. return s;
  491. }
  492. #define FOUND_ALL(s,n,dim,c,d) (((s->cattype != -1 && !n) || \
  493. (dim < s->dim_alloc) || \
  494. (c < s->str_alloc) || \
  495. (d < s->dbl_alloc))?0:1)
  496. int G_oldsite_get ( FILE *fptr, Site *s)
  497. /* Writes a site to file open on fptr. */
  498. {
  499. return G__oldsite_get (fptr, s, G_projection() );
  500. }
  501. int G__oldsite_get ( FILE *ptr, Site *s, int fmt)
  502. /*-
  503. * Reads ptr and returns 0 on success,
  504. * -1 on EOF,
  505. * -2 on other fatal error or insufficient data,
  506. * 1 on format mismatch (extra data)
  507. */
  508. {
  509. char sbuf[MAX_SITE_LEN], *buf, *last, *p1, *p2;
  510. char ebuf[128], nbuf[128];
  511. int n = 0, d = 0, c = 0, dim = 0, err = 0, tmp;
  512. buf = sbuf;
  513. if ((buf = fgets (sbuf, 1024, ptr)) == (char *) NULL)
  514. return EOF;
  515. while ((*buf == '#' || !isdigit(*buf)) && *buf != '-' && *buf != '+')
  516. if ((buf = fgets (sbuf, 1024, ptr)) == (char *) NULL)
  517. return EOF;
  518. if (buf[strlen (buf) - 1] == '\n')
  519. buf[strlen (buf) - 1] = (char) NULL;
  520. if (sscanf (buf, "%[^|]|%[^|]|%*[^\n]", ebuf, nbuf) < 2)
  521. {
  522. fprintf (stderr, "ERROR: ebuf %s nbuf %s\n", ebuf, nbuf);
  523. return -2;
  524. }
  525. if (!G_scan_northing (nbuf, &(s->north), fmt) ||
  526. !G_scan_easting (ebuf, &(s->east), fmt))
  527. {
  528. fprintf (stderr, "ERROR: ebuf %s nbuf %s\n", ebuf, nbuf);
  529. return -2;
  530. }
  531. /* move pointer past easting and northing fields */
  532. if (NULL == (buf = G_index(buf, PIPE)))
  533. return -2;
  534. if (NULL == (buf = G_index(buf+1, PIPE)))
  535. return -2;
  536. /* check for remaining dimensional fields */
  537. do {
  538. buf++;
  539. if (isnull(*buf)) return (FOUND_ALL(s,n,dim,c,d)? 0: -2);
  540. last = buf;
  541. if (dim < s->dim_alloc) /* should be more dims to read */
  542. {
  543. if (sscanf (buf, "%lf|", &(s->dim[dim++])) < 1)
  544. return -2; /* no more dims, though expected */
  545. }
  546. else if (NULL != (p1 = G_index(buf, PIPE)))
  547. {
  548. if (NULL == (p2 = G_index(buf, DQUOTE)))
  549. err = 1; /* more dims, though none expected */
  550. else if (strlen(p1) > strlen(p2))
  551. err = 1; /* more dims, though none expected */
  552. }
  553. } while ((buf = G_index (buf, PIPE)) != NULL);
  554. buf = last;
  555. /* no more dimensions-now we parse attribute fields */
  556. while (!isnull(*buf))
  557. {
  558. switch (*buf)
  559. {
  560. case '#': /* category field */
  561. if (n == 0)
  562. {
  563. switch(s->cattype)
  564. {
  565. case CELL_TYPE:
  566. if(sscanf (buf, "#%d", &s->ccat)==1)
  567. n++;
  568. break;
  569. case FCELL_TYPE:
  570. if(sscanf (buf, "#%f", &s->fcat)==1)
  571. n++;
  572. break;
  573. case DCELL_TYPE:
  574. if(sscanf (buf, "#%lf", &s->dcat)==1)
  575. n++;
  576. break;
  577. default:
  578. err = 1; /* has cat, none expected */
  579. break;
  580. }
  581. }
  582. else{
  583. err = 1; /* extra cat */
  584. }
  585. /* move to beginning of next attribute */
  586. if ((buf = next_att (buf)) == (char *) NULL)
  587. return (FOUND_ALL(s,n,dim,c,d)? err: -2);
  588. break;
  589. case '%': /* decimal attribute */
  590. if (d < s->dbl_alloc) {
  591. p1 = ++buf;
  592. errno = 0;
  593. s->dbl_att[d++] = strtod(buf, &p1);
  594. if (p1 == buf || errno == ERANGE) {
  595. /* replace with:
  596. * s->dbl_att[d - 1] = NAN
  597. * when we add NULL attribute support
  598. */
  599. return -2;
  600. }
  601. /* err = 0; Make sure this is zeroed */
  602. } else {
  603. err = 1; /* extra decimal */
  604. }
  605. if ((buf = next_att (buf)) == (char *) NULL) {
  606. return (FOUND_ALL(s,n,dim,c,d)) ? err : -2;
  607. }
  608. break;
  609. case '@': /* string attribute */
  610. if (isnull(*buf) || isnull(*(buf + 1)))
  611. return (FOUND_ALL(s,n,dim,c,d)? err: -2);
  612. else
  613. buf++;
  614. default: /* defaults to string attribute */
  615. /* allow both prefixed and unprefixed strings */
  616. if (c < s->str_alloc)
  617. {
  618. if ((tmp = cleanse_string (buf)) > 0)
  619. {
  620. G_strncpy (s->str_att[c++], buf, tmp);
  621. buf += tmp;
  622. }
  623. else
  624. return (FOUND_ALL(s,n,dim,c,d)? err: -2);
  625. }
  626. if ((buf = next_att (buf)) == (char *) NULL) {
  627. return (FOUND_ALL(s,n,dim,c,d)? err: -2);
  628. }
  629. break;
  630. }
  631. }
  632. return (FOUND_ALL(s,n,dim,c,d)? err: -2);
  633. }
  634. int G_oldsite_describe ( FILE *ptr,
  635. int *dims,int *cat,int *strs,int *dbls)
  636. /*-
  637. * Tries to guess the format of a sites list (the dimensionality,
  638. * the presence/type of a category, and the number of string and decimal
  639. * attributes) by reading the first record in the file.
  640. * Reads ptr and returns 0 on success,
  641. * -1 on EOF,
  642. * -2 for other error.
  643. */
  644. {
  645. char sbuf[MAX_SITE_LEN], *buf;
  646. char ebuf[128], nbuf[128];
  647. int err;
  648. int itmp;
  649. float ftmp;
  650. if (ftell (ptr) != 0L)
  651. {
  652. fprintf (stderr, "\nPROGRAMMER ERROR: G_oldsite_describe() must be called\n");
  653. fprintf (stderr, " immediately after G_fopen_sites_old()\n");
  654. return -2;
  655. }
  656. *dims = *strs = *dbls = 0;
  657. *cat = -1;
  658. buf = sbuf;
  659. if ((buf = fgets (sbuf, 1024, ptr)) == (char *) NULL)
  660. {
  661. rewind (ptr);
  662. return EOF;
  663. }
  664. /* skip over comment & header lines */
  665. while ((*buf == '#' || !isdigit(*buf)) && *buf != '-' && *buf != '+')
  666. if ((buf = fgets (sbuf, 1024, ptr)) == (char *) NULL)
  667. {
  668. rewind (ptr);
  669. return EOF;
  670. }
  671. if (buf[strlen (buf) - 1] == '\n')
  672. buf[strlen (buf) - 1] = '\0' ;
  673. if ((err = sscanf (buf, "%[^|]|%[^|]|%*[^\n]", ebuf, nbuf)) < 2)
  674. {
  675. fprintf (stderr, "ERROR: ebuf %s nbuf %s\n", ebuf, nbuf);
  676. rewind (ptr);
  677. return -2;
  678. }
  679. *dims = 2;
  680. /* move pointer past easting and northing fields */
  681. while (!ispipe(*buf) && !isnull(*buf))
  682. buf++;
  683. if (!isnull(*buf) && !isnull(*(buf + 1)))
  684. buf++;
  685. else
  686. {
  687. rewind (ptr);
  688. return -2;
  689. }
  690. while (!ispipe(*buf) && !isnull(*buf))
  691. buf++;
  692. if (!isnull(*buf) && !isnull(*(buf + 1)))
  693. buf++;
  694. else
  695. {
  696. rewind (ptr);
  697. return 0;
  698. }
  699. /* check for remaining dimensional fields */
  700. while (G_index (buf, PIPE) != (char *) NULL)
  701. {
  702. (*dims)++;
  703. while (!ispipe(*buf) && !isnull(*buf))
  704. buf++;
  705. if (isnull(*buf) || isnull(*(buf+1)))
  706. {
  707. rewind (ptr);
  708. return 0;
  709. }
  710. if (!isnull(*(buf + 1)))
  711. buf++;
  712. else
  713. {
  714. rewind (ptr);
  715. return -2;
  716. }
  717. }
  718. /* no more dimensions-now we parse attribute fields */
  719. while (!isnull(*buf))
  720. {
  721. switch (*buf)
  722. {
  723. case '#': /* category field */
  724. sscanf(buf,"#%s ",ebuf);
  725. if(G_strstr(ebuf,".")==NULL && sscanf(ebuf,"%d", &itmp) ==1)
  726. *cat=CELL_TYPE;
  727. else if(G_strstr(ebuf,".")!=NULL && sscanf(ebuf,"%f", &ftmp) ==1)
  728. *cat=FCELL_TYPE;
  729. else
  730. *cat=-1;
  731. /* move to beginning of next attribute */
  732. while (!isspace (*buf) && !isnull(*buf))
  733. buf++;
  734. if (isnull(*buf) || isnull(*(buf + 1)))
  735. {
  736. rewind (ptr);
  737. return 0;
  738. }
  739. else
  740. buf++;
  741. break;
  742. case '%': /* decimal attribute */
  743. (*dbls)++;
  744. /* move to beginning of next attribute */
  745. while (!isspace (*buf) && !isnull(*buf))
  746. buf++;
  747. if (isnull(*buf) || isnull(*(buf + 1)))
  748. {
  749. rewind (ptr);
  750. return 0;
  751. }
  752. else
  753. buf++;
  754. break;
  755. case '@': /* string attribute */
  756. if (isnull(*buf) || isnull(*(buf + 1)))
  757. {
  758. rewind (ptr);
  759. return 0;
  760. }
  761. else
  762. buf++;
  763. default: /* defaults to string attribute */
  764. /* allow both prefixed and unprefixed strings */
  765. if ((err = cleanse_string (buf)) > 0)
  766. {
  767. (*strs)++;
  768. buf += err;
  769. }
  770. /* move to beginning of next attribute */
  771. while (!isspace (*buf) && !isnull(*buf))
  772. buf++;
  773. if (isnull(*buf) || isnull(*(buf + 1)))
  774. {
  775. rewind (ptr);
  776. return 0;
  777. }
  778. else
  779. buf++;
  780. break;
  781. }
  782. }
  783. rewind (ptr);
  784. return 0;
  785. }
  786. int G_site_in_region ( const Site *site, const struct Cell_head *region)
  787. /* returns 1 if site is contained within region, 0 otherwise */
  788. {
  789. /* northwest corner is in region, southeast corner is not. */
  790. double e_ing;
  791. e_ing = G_adjust_easting (site->east, region);
  792. if (e_ing >= region->west &&
  793. e_ing < region->east &&
  794. site->north <= region->north &&
  795. site->north > region->south)
  796. return 1;
  797. return 0;
  798. }
  799. static int format_double ( double value, char *buf)
  800. {
  801. sprintf (buf, "%.8f", value);
  802. G_trim_decimal (buf);
  803. return 0;
  804. }
  805. int cleanse_string (char *buf)
  806. {
  807. char *stop, *p, *p2;
  808. p = buf;
  809. /*
  810. * get rid of any SPACEs at beginning while ( !isspace(*buf) && *buf !=
  811. * (char) NULL) buf++; if (*buf == (char) NULL) return -1;
  812. */
  813. /* find where this string terminates */
  814. if ( *buf != DQUOTE) /* if no DQUOTEs, */
  815. {
  816. stop = G_index (buf, SPACE);/* then SPACE separates */
  817. if (stop == (char *) NULL)
  818. return strlen (buf);
  819. else
  820. return (int) (stop - buf);
  821. }
  822. else /* otherwise string is in DQUOTEs */
  823. { /* but we must skip over escaped */
  824. /* (BSLASHed) DQUOTEs */
  825. if (*p == DQUOTE)
  826. {
  827. while (*p != (char) NULL) /* get rid of first DQUOTE */
  828. {
  829. *p = *(p + 1);
  830. p++;
  831. }
  832. p = buf;
  833. stop = G_index (p + 1, DQUOTE);
  834. while (*(stop - 1) == BSLASH)
  835. stop = G_index (++stop, DQUOTE);
  836. }
  837. }
  838. /* remove backslashes between buf and stop */
  839. p = buf;
  840. while ((p = G_index (p, BSLASH)) != (char *) NULL && p <= stop)
  841. {
  842. p2 = p + 1;
  843. if (*p2 != (char) NULL && (*p2 == DQUOTE || *p2 == BSLASH))
  844. {
  845. while (*p != (char) NULL)
  846. {
  847. *p = *(p + 1);
  848. p++;
  849. }
  850. stop--;
  851. }
  852. p = p2;
  853. }
  854. return (int) (stop - buf);
  855. }
  856. static char *next_att (const char *buf)
  857. {
  858. while (!isspace (*buf) && !isnull(*buf))
  859. buf++;
  860. if (isnull(*buf) || isnull(*(buf + 1)))
  861. return NULL;
  862. else
  863. while (isspace (*(buf + 1)) && !isnull(*(buf + 1)))
  864. buf++;
  865. buf++;
  866. return (char *) buf;
  867. }
  868. int G_site_c_cmp (const void *a, const void *b)
  869. /* qsort() comparison function for sorting an array of
  870. site structures by category. */
  871. {
  872. int result = 0; /* integer to be returned */
  873. double diff = 0;
  874. switch((*(Site **)a)->cattype)
  875. {
  876. case CELL_TYPE:
  877. diff = (double) (*(Site **) a)->ccat - (*(Site **) b)->ccat;
  878. break;
  879. case FCELL_TYPE:
  880. diff = (double) (*(Site **) a)->fcat - (*(Site **) b)->fcat;
  881. break;
  882. case DCELL_TYPE:
  883. diff = (double) (*(Site **) a)->dcat - (*(Site **) b)->dcat;
  884. break;
  885. }
  886. if (diff < 0.0 )
  887. result = -1;
  888. else if (diff > 0.0)
  889. result = 1;
  890. return result;
  891. }
  892. int G_site_d_cmp (const void *a, const void *b)
  893. /* qsort() comparison function for sorting an array of
  894. site structures by first decimal attribute. */
  895. {
  896. int result = 0; /* integer to be returned */
  897. double diff;
  898. diff = (*(Site **) a)->dbl_att[0] - (*(Site **) b)->dbl_att[0];
  899. if (diff < 0.0 )
  900. result = -1;
  901. else if (diff > 0.0)
  902. result = 1;
  903. return result;
  904. }
  905. int G_oldsite_s_cmp (const void *a, const void *b)
  906. /* qsort() comparison function for sorting an array of
  907. site structures by first decimal attribute. */
  908. {
  909. return strcmp((*(char **)((*(Site **) a)->str_att)),
  910. (*(char **)((*(Site **) b)->str_att)));
  911. }
  912. /*-************************************************************************
  913. *
  914. * FILE *
  915. * G_oldsites_open_old (name, mapset)
  916. * opens the existing site list file 'name' in the 'mapset'
  917. *
  918. * parms
  919. * char *name map file name
  920. * char *mapset mapset containing map "name"
  921. *
  922. **********************************************************************/
  923. FILE * G_oldsites_open_old (const char *name, const char *mapset)
  924. {
  925. return G_fopen_old ("site_lists", name, mapset);
  926. }
  927. FILE * G_oldsites_open_new (const char *name)
  928. {
  929. return G_fopen_new ("site_lists", name);
  930. }
  931. /*********************************************/
  932. /* The following functions are obsolete. */
  933. /* They are retained here only for backwards */
  934. /* compatability while porting applications */
  935. /*********************************************/
  936. char *G_site_format (const Site *s, const char *fs, int id)
  937. /* sprintf analog to G_site_put with the addition of a field seperator fs
  938. and option of printing site attribute identifiers
  939. */
  940. {
  941. char ebuf[MAX_SITE_STRING], nbuf[MAX_SITE_STRING];
  942. char xbuf[MAX_SITE_STRING];
  943. const char *nfs;
  944. char *buf;
  945. int fmt, i, j, k;
  946. buf=(char *)G_malloc(MAX_SITE_LEN*sizeof(char));
  947. fmt = G_projection ();
  948. G_format_northing (s->north, nbuf, fmt);
  949. G_format_easting (s->east, ebuf, fmt);
  950. nfs = (char *) ((fs == (char *) NULL) ? "|" : fs);
  951. sprintf (buf, "%s%s%s", ebuf, nfs, nbuf);
  952. for (i = 0; i < s->dim_alloc; ++i)
  953. {
  954. format_double (s->dim[i], nbuf);
  955. sprintf (xbuf, "%s%s", nfs, nbuf);
  956. G_strcat (buf, xbuf);
  957. }
  958. nfs= (fs == NULL) ? " " : fs;
  959. switch(s->cattype)
  960. {
  961. case CELL_TYPE:
  962. sprintf (xbuf, "%s%s%d ", nfs, ((id==0) ? "" : "#"), (int)s->ccat);
  963. G_strcat (buf, xbuf);
  964. break;
  965. case FCELL_TYPE:
  966. case DCELL_TYPE:
  967. sprintf (xbuf, "%s%s%g ", nfs, ((id==0) ? "" : "#"), (float)s->fcat);
  968. G_strcat (buf, xbuf);
  969. break;
  970. }
  971. for (i = 0; i < s->dbl_alloc; ++i)
  972. {
  973. format_double (s->dbl_att[i], nbuf);
  974. sprintf (xbuf, "%s%s%s", nfs, ((id==0) ? "" : "%"), nbuf);
  975. G_strcat (buf, xbuf);
  976. }
  977. for (i = 0; i < s->str_alloc; ++i)
  978. {
  979. if (strlen (s->str_att[i]) != 0)
  980. {
  981. /* escape double quotes */
  982. j = k = 0;
  983. /* do not uncomment this code because sites file was created
  984. * as we want. So it's enough to print them out as it is.
  985. *
  986. if (G_index (s->str_att[i], DQUOTE) != (char *) NULL)
  987. {
  988. while (!isnull(s->str_att[i][j]))
  989. {
  990. if (isquote(s->str_att[i][j]))
  991. {
  992. xbuf[k++] = BSLASH;
  993. xbuf[k++] = DQUOTE;
  994. }
  995. else
  996. xbuf[k++] = s->str_att[i][j];
  997. j++;
  998. }
  999. xbuf[k] = (char) NULL;
  1000. }
  1001. else
  1002. */
  1003. G_strcpy (xbuf, s->str_att[i]);
  1004. G_strcpy (s->str_att[i], xbuf);
  1005. if (G_index (s->str_att[i], SPACE) != (char *) NULL)
  1006. sprintf (xbuf, "%s%s\"%s\"", nfs, ((id==0) ? "" : "@"), s->str_att[i]);
  1007. else
  1008. sprintf (xbuf, "%s%s%s", nfs, ((id==0) ? "" : "@"), s->str_att[i]);
  1009. G_strcat (buf, xbuf);
  1010. }
  1011. }
  1012. return buf;
  1013. }
  1014. /*******************************************************************************/
  1015. /*******************************************************************************/
  1016. /*** ACS_MODIFY_BEGIN - sites_attribute management *****************************/
  1017. /*
  1018. These functions are used in visualization/nviz/src/site_attr_commands.c
  1019. Functions to obtain fields in order to draw sites with each point having a
  1020. geometric property depending from database values.
  1021. IN ALL THESE FUNCTIONS I FOLLOW THE CONVENTION TO PASS Map_info* as FILE*
  1022. FOR COHERENCE WITH OTHER ALREADY WRITTEN FUNCTION IN sites.c FILE.
  1023. */
  1024. /*
  1025. Returns a pointer to the SITE_ATT in Map_info *ptr and with category cat
  1026. */
  1027. SITE_ATT * G_sites_get_atts (FILE * ptr, int* cat)
  1028. {
  1029. struct Map_info *Map;
  1030. Map = (struct Map_info *) ptr;
  1031. return (SITE_ATT *) bsearch ( (void *) cat, (void *)Map->site_att, Map->n_site_att,
  1032. sizeof(SITE_ATT), site_att_cmp );
  1033. }
  1034. /*
  1035. Returns field names, types and indexes in double and string Map_info arrays
  1036. WARNING: user is responsible to free allocated memory, directly or calling G_sites_free_fields()
  1037. */
  1038. int G_sites_get_fields(FILE * ptr, char*** cnames, int** ctypes, int** ndx)
  1039. {
  1040. struct Map_info *Map;
  1041. struct field_info *fi;
  1042. int nrows, row, ncols, col, ndbl, nstr, ctype;
  1043. char * name;
  1044. dbDriver *driver;
  1045. dbString stmt;
  1046. dbCursor cursor;
  1047. dbTable *table;
  1048. dbColumn *column;
  1049. /*dbValue *value;*/
  1050. /* warning: we are using "1" as cat field in Vect_get_field because G_sites_open_old
  1051. (in lib/sites/sites.c), that we use here to open sites, does the same and then
  1052. queries the db in the same way we do here.
  1053. Should it be not true in the future, maybe we'll have to change this by choosing
  1054. appropriate fields and multiple categories */
  1055. Map = (struct Map_info *) ptr;
  1056. fi = (struct field_info *)Vect_get_field(Map, 1);
  1057. if ( fi == NULL ) { /* not attribute table */
  1058. G_debug ( 1, "No attribute table" );
  1059. return -1;
  1060. }
  1061. driver = db_start_driver_open_database ( fi->driver, fi->database );
  1062. if ( driver == NULL )
  1063. G_fatal_error ( "Cannot open database %s by driver %s", fi->database, fi->driver );
  1064. db_init_string (&stmt);
  1065. db_set_string ( &stmt, "select * from ");
  1066. db_append_string ( &stmt, fi->table );
  1067. if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK)
  1068. G_fatal_error ("Cannot select attributes.");
  1069. nrows = db_get_num_rows ( &cursor );
  1070. G_debug ( 1, "%d rows selected from vector attribute table", nrows);
  1071. table = db_get_cursor_table (&cursor);
  1072. ncols = db_get_table_number_of_columns(table);
  1073. if (ncols <=0) return ncols;
  1074. row = 0;
  1075. /* Get number of each type */
  1076. ndbl = nstr = 0;
  1077. *cnames=(char**)malloc(ncols*sizeof(char*));
  1078. *ctypes=(int*)malloc(ncols*sizeof(int));
  1079. *ndx=(int*)malloc(ncols*sizeof(int));
  1080. for (col = 0; col < ncols; col++) {
  1081. column = db_get_table_column ( table, col );
  1082. ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) );
  1083. name=db_get_column_name(column);
  1084. *(*cnames+col) = (char*)malloc(strlen(name) + 1);
  1085. strcpy(*(*cnames+col), db_get_column_name(column));
  1086. /* ctypes is 'c' for cat, 'd' for double, 's' for string */
  1087. if (strcmp(name, fi->key)==0) {
  1088. *(*ctypes+col)='c';
  1089. *(*ndx+col)=-1;
  1090. } else {
  1091. switch ( ctype ) {
  1092. case DB_C_TYPE_INT:
  1093. case DB_C_TYPE_DOUBLE:
  1094. *(*ctypes+col)='d';
  1095. *(*ndx+col)=ndbl;
  1096. ndbl++;
  1097. break;
  1098. case DB_C_TYPE_STRING:
  1099. case DB_C_TYPE_DATETIME:
  1100. *(*ctypes+col)='s';
  1101. *(*ndx+col)=nstr;
  1102. nstr++;
  1103. break;
  1104. }
  1105. }
  1106. }
  1107. db_close_database_shutdown_driver ( driver );
  1108. return ncols;
  1109. }
  1110. /*
  1111. Frees fields allocated with G_sites_get_fields
  1112. */
  1113. void G_sites_free_fields(int ncols, char** cnames, int* ctypes, int* ndx)
  1114. {
  1115. for (; ncols > 0; ncols--) free(*(cnames+ncols-1));
  1116. free(cnames);
  1117. free(ctypes);
  1118. free(ndx);
  1119. }
  1120. /*** ACS_MODIFY_END - sites_attribute management *******************************/
  1121. /*******************************************************************************/
  1122. /*******************************************************************************/