GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
vector/Vlib/cats.c
Go to the documentation of this file.
1 /*!
2  * \file lib/vector/Vlib/cats.c
3  *
4  * \brief Vector library - Category management
5  *
6  * Higher level functions for reading/writing/manipulating vectors.
7  *
8  * (C) 2001-2012 by the GRASS Development Team
9  *
10  * This program is free software under the GNU General Public License
11  * (>=v2). Read the file COPYING that comes with GRASS for details.
12  *
13  * \author Original author CERL, probably Dave Gerdes or Mike Higgins
14  * \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
15  * \author Various updates by Martin Landa <landa.martin gmail.com>
16  * \author Various updates by Markus Metz
17  */
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include <grass/vector.h>
22 #include <grass/dbmi.h>
23 #include <grass/glocale.h>
24 
25 static int cmp(const void *pa, const void *pb);
26 static struct line_cats *Vect__new_cats_struct(void);
27 
28 
29 /*!
30  \brief Creates and initializes line_cats structure.
31 
32  This structure is used for reading and writing vector cats. The
33  library routines handle all memory allocation.
34 
35  To free allocated memory call Vect_destroy_cats_struct().
36 
37  \return struct line_cats *
38  \return NULL on error
39  */
41 {
42  struct line_cats *p;
43 
44  if (NULL == (p = Vect__new_cats_struct()))
45  G_fatal_error(_("Vect_new_cats_struct(): Out of memory"));
46 
47  return p;
48 }
49 
50 /*!
51  \brief Creates and initializes line_cats structure (lower level fn)
52 
53  This structure is used for reading and writing vector cats. The
54  library routines handle all memory allocation.
55 
56  \return struct line_cats *
57  */
58 static struct line_cats *Vect__new_cats_struct()
59 {
60  struct line_cats *p;
61 
62  p = (struct line_cats *)G_malloc(sizeof(struct line_cats));
63 
64  /* n_cats MUST be initialized to zero */
65  if (p)
66  p->n_cats = 0;
67 
68  if (p)
69  p->alloc_cats = 0;
70 
71  return p;
72 }
73 
74 /*!
75  \brief Frees all memory associated with line_cats structure,
76  including the struct itself.
77 
78  \param p line_cats structure
79  */
81 {
82  if (p) { /* probably a moot test */
83  if (p->n_cats) {
84  G_free((void *)p->field);
85  G_free((void *)p->cat);
86  }
87  G_free((void *)p);
88  }
89 }
90 
91 /*!
92  \brief Add new field/cat to category structure if doesn't exist
93  yet.
94 
95  \param[in,out] Cats line_cats structure
96  \param[in] field layer number
97  \param[in] cat category number
98 
99  \return number of categories
100  \return 0 if no space for new category in structure, n_cats would be > GV_NCATS_MAX
101  \return -1 on out of memory
102  \return -2 if field out of range: 1 - GV_FIELD_MAX or cat out of range: 1 - GV_CAT_MAX
103  */
104 int Vect_cat_set(struct line_cats *Cats, int field, int cat)
105 {
106  register int n;
107 
108  /* check input values */
109  /* compiler may warn:
110  * comparison is always 0 due to limited range of data type
111  * but remember that limit is set to portable data type length
112  * and machine native size may be longer */
113  /*
114  if (field < 1 || field > GV_FIELD_MAX || cat < 0 || cat > GV_CAT_MAX)
115  return (-2);
116  */
117 
118  /* go through old cats and find if field/category exists */
119  for (n = 0; n < Cats->n_cats; n++) {
120  if (Cats->field[n] == field && Cats->cat[n] == cat)
121  return (1);
122  }
123 
124  /* field was not found so we shall append new cat */
125  /* test if space exist */
126  if (n >= GV_NCATS_MAX) {
127  G_fatal_error(_("Too many categories (%d), unable to set cat %d (layer %d)"),
128  Cats->n_cats, cat, field);
129  }
130 
131  if (Cats->n_cats == Cats->alloc_cats) {
132  if (0 > dig_alloc_cats(Cats, Cats->n_cats + 100))
133  return (-1);
134  }
135 
136  n = Cats->n_cats;
137  Cats->field[n] = field;
138  Cats->cat[n] = cat;
139  Cats->n_cats++;
140  return (1);
141 }
142 
143 /*!
144  \brief Get first found category of given field.
145 
146  <em>cat</em> is set to first category found or -1 if field was not
147  found
148 
149  \param Cats pointer line_cats structure
150  \param field layer number
151  \param[out] cat pointer to variable where cat will be written (can be NULL)
152 
153  \return number of found cats for given field (first reported)
154  \return 0 layer does not exist
155  */
156 int Vect_cat_get(const struct line_cats *Cats, int field, int *cat)
157 {
158  int n, ret;
159 
160  /* field was not found */
161  ret = 0;
162  if (cat)
163  *cat = -1;
164 
165  /* check input value */
166  if (field < 1 || field > GV_FIELD_MAX)
167  return (0);
168 
169  /* go through cats and find if field exist */
170  for (n = 0; n < Cats->n_cats; n++) {
171  if (Cats->field[n] == field) {
172  if (cat && ret == 0) {
173  *cat = Cats->cat[n];
174  }
175  ret++;
176  }
177  }
178 
179  return ret;
180 }
181 
182 /*!
183  \brief Get list of categories of given field.
184 
185  \param Cats line_cats structure
186  \param field layer number
187  \param[out] cats pointer to list where cats will be written
188 
189  \return number of found categories
190  \return -1 on invalid field
191  */
192 int Vect_field_cat_get(const struct line_cats *Cats, int field, struct ilist *cats)
193 {
194  int n;
195 
196  /* reset list of categories */
197  Vect_reset_list(cats);
198 
199  /* check input value */
200  if (field < 1 || field > GV_FIELD_MAX)
201  return -1;
202 
203  /* go through cats and find if field exist */
204  for (n = 0; n < Cats->n_cats; n++) {
205  if (Cats->field[n] == field)
206  Vect_list_append(cats, Cats->cat[n]);
207  }
208 
209  return cats->n_values;
210 }
211 
212 /*!
213  \brief Delete all categories of given layer
214 
215  \param[in,out] Cats line_cats structure
216  \param field layer number
217 
218  \return number of categories deleted
219  \return 0 layer does not exist
220  */
221 int Vect_cat_del(struct line_cats *Cats, int field)
222 {
223  int n, m, found;
224 
225  /* check input value */
226  /*
227  if (field < 1 || field > GV_FIELD_MAX)
228  return (0);
229  */
230 
231  /* go through cats and find if field exist */
232  m = 0;
233  for (n = 0; n < Cats->n_cats; n++) {
234  if (Cats->field[n] != field) {
235  Cats->field[m] = Cats->field[n];
236  Cats->cat[m] = Cats->cat[n];
237  m++;
238  }
239  }
240  found = Cats->n_cats - m;
241  Cats->n_cats = m;
242 
243  return (found);
244 }
245 
246 /*!
247  \brief Delete field/cat from line_cats structure
248 
249  \param[in,out] Cats line_cats structure
250  \param field layer number
251  \param cat category to be deleted or -1 to delete all cats of given field
252 
253  \return number of categories deleted
254  \return 0 field/category number does not exist
255  */
256 int Vect_field_cat_del(struct line_cats *Cats, int field, int cat)
257 {
258  register int n, m, found;
259 
260  /* check input value */
261  /*
262  if (field < 1 || field > GV_FIELD_MAX)
263  return (0);
264  */
265 
266  if (cat == -1)
267  return Vect_cat_del(Cats, field);
268 
269  /* go through cats and find if field exist */
270  m = 0;
271  for (n = 0; n < Cats->n_cats; n++) {
272  if (Cats->field[n] != field || Cats->cat[n] != cat) {
273  Cats->field[m] = Cats->field[n];
274  Cats->cat[m] = Cats->cat[n];
275  m++;
276  }
277  }
278  found = Cats->n_cats - m;
279  Cats->n_cats = m;
280 
281  return (found);
282 }
283 
284 /*!
285  \brief Reset category structure to make sure cats structure is clean to be re-used.
286 
287  I.e. it has no cats associated with it. Cats must have
288  previously been created with Vect_new_cats_struct()
289 
290  \param[out] Cats line_cats structure
291 
292  \return 0
293  */
294 int Vect_reset_cats(struct line_cats *Cats)
295 {
296  Cats->n_cats = 0;
297 
298  return 0;
299 }
300 
301 /*!
302  \brief Allocate memory for cat_list structure.
303 
304  \return pointer to allocated structure
305  \return NULL if out of memory
306  */
308 {
309  struct cat_list *p;
310 
311  p = (struct cat_list *)G_malloc(sizeof(struct cat_list));
312 
313  /* n_ranges MUST be initialized to zero */
314  if (p)
315  G_zero(p, sizeof(struct cat_list));
316 
317  return p;
318 }
319 
320 
321 /*!
322  \brief Frees allocated cat_list memory.
323 
324  \param p pointer to line_cats structure
325  */
327 {
328  if (p) { /* probably a moot test */
329  if (p->n_ranges) {
330  G_free((void *)p->min);
331  G_free((void *)p->max);
332  }
333  G_free((void *)p);
334  }
335 }
336 
337 
338 /*!
339  \brief Converts string of categories and cat ranges separated by commas to cat_list.
340 
341  \par Examples of string:
342  \verbatim
343  5,6,7
344  3-9
345  2,3,5-9,20\endverbatim
346 
347  \par Example:
348  \code
349  ...
350  str = "2,3,5-9,20"
351  cat_list = Vect_new_cat_list()
352 
353  Vect_str_to_cat_list(str, cat_list)
354  \endcode
355  \verbatim
356  cat_list->field = 0
357  cat_list->n_ranges = 4
358  cat_list->min = {2, 3, 5, 20}
359  cat_list->max = {2, 3, 9, 20}
360  \endverbatim
361 
362  \param str category list as a string
363  \param[in,out] list pointer to cat_list structure
364 
365  \return number of errors in ranges
366  */
367 int Vect_str_to_cat_list(const char *str, struct cat_list *list)
368 {
369  int i, nr, l, err = 0;
370  const char *s, *e;
371  char buf[100];
372  int min, max;
373 
374  G_debug(3, "Vect_str_to_cat_list(): str = %s", str);
375 
376  list->n_ranges = 0;
377  l = strlen(str);
378 
379  /* find number of ranges */
380  nr = 1; /* one range */
381  for (i = 0; i < l; i++)
382  if (str[i] == ',')
383  nr++;
384 
385  /* allocate space */
386  if (list->alloc_ranges == 0) {
387  list->min = (int *)G_malloc(nr * sizeof(int));
388  list->max = (int *)G_malloc(nr * sizeof(int));
389  }
390  else if (nr > list->alloc_ranges) {
391  list->min = (int *)G_realloc((void *)list->min, nr * sizeof(int));
392  list->max = (int *)G_realloc((void *)list->max, nr * sizeof(int));
393  }
394 
395  /* go through string and read ranges */
396  i = 0;
397  s = str;
398 
399  while (s) {
400  e = (char *)strchr(s, ','); /* first comma */
401  if (e) {
402  l = e - s;
403  strncpy(buf, s, l);
404  buf[l] = '\0';
405  s = e + 1;
406  }
407  else {
408  strcpy(buf, s);
409  s = NULL;
410  }
411 
412  G_debug(3, " buf = %s", buf);
413  if (sscanf(buf, "%d-%d", &min, &max) == 2) {
414  }
415  else if (sscanf(buf, "%d", &min) == 1)
416  max = min;
417  else { /* error */
418 
419  G_warning(_("Unable to convert category string '%s' (from '%s') to category range"),
420  buf, str);
421  err++;
422  continue;
423  }
424 
425  list->min[i] = min;
426  list->max[i] = max;
427  i++;
428  }
429 
430  list->n_ranges = i;
431 
432  return (err);
433 }
434 
435 /*!
436  \brief Convert ordered array of integers to cat_list structure.
437 
438  \param vals array of integers
439  \param nvals number of values
440  \param[in,out] list pointer to cat_list structure
441 
442  \return number of ranges
443  */
444 int Vect_array_to_cat_list(const int *vals, int nvals, struct cat_list *list)
445 {
446  int i, range;
447 
448  G_debug(1, "Vect_array_to_cat_list()");
449  range = -1;
450  for (i = 0; i < nvals; i++) {
451  if (i == 0 || (vals[i] - list->max[range]) > 1) {
452  range++;
453  if (range == list->alloc_ranges) {
454  list->alloc_ranges += 1000;
455  list->min = (int *)G_realloc((void *)list->min,
456  list->alloc_ranges *
457  sizeof(int));
458  list->max =
459  (int *)G_realloc((void *)list->max,
460  list->alloc_ranges * sizeof(int));
461  }
462  list->min[range] = vals[i];
463  list->max[range] = vals[i];
464  }
465  else {
466  list->max[range] = vals[i];
467  }
468  }
469 
470  list->n_ranges = range + 1;
471 
472  return (list->n_ranges);
473 }
474 
475 /*!
476  \brief Convert cat_list struct to ordered array of unique integers.
477 
478  Output array do not contain duplicate items.
479 
480  Allocated array should be freed by G_free().
481 
482  \param cat_list pointer to cat_list struct
483  \param[out] vals array of integers
484  \param[out] nvals number of values
485 
486  \return 0 on success
487  \return -1 on failure
488  */
489 int Vect_cat_list_to_array(const struct cat_list *list, int **vals, int *nvals)
490 {
491  int i, j, k, n, n_cats, n_ucats, last_cat;
492  int *cats, *ucats;
493 
494  G_debug(1, "Vect_cat_list_to_array()");
495 
496  *nvals = n_cats = 0;
497  cats = NULL;
498  for (i = 0; i < list->n_ranges; i++) {
499  n = list->max[i] - list->min[i] + 1;
500  if (n < 1)
501  return -1;
502 
503  /* realloc array */
504  cats = (int *) G_realloc(cats, sizeof(int) * (n_cats + n));
505 
506  for (j = n_cats, k = 0; j < n_cats + n; j++, k++) {
507  cats[j] = list->min[i] + k;
508  }
509  n_cats += n;
510  }
511 
512  /* sort array */
513  qsort(cats, n_cats, sizeof(int), cmp);
514 
515  /* skip duplicated values */
516  ucats = G_malloc(sizeof(int) * n_cats);
517  last_cat = ucats[0] = cats[0];
518  n_ucats = 1;
519  for (i = 1; i < n_cats; i++) {
520  if (last_cat == cats[i])
521  continue;
522  last_cat = ucats[n_ucats++] = cats[i];
523  }
524  G_free(cats);
525 
526  /* reallocate array for unique values */
527  ucats = (int *) G_realloc(ucats, sizeof(int) * n_ucats);
528 
529  *nvals = n_ucats;
530  *vals = ucats;
531 
532  return 0;
533 }
534 
535 /*!
536  \brief Check if category number is in list.
537 
538  \param cat category number
539  \param list cat_list structure
540 
541  \return TRUE if cat is in list
542  \return FALSE if not
543  */
544 int Vect_cat_in_cat_list(int cat, const struct cat_list *list)
545 {
546  int i;
547 
548  for (i = 0; i < list->n_ranges; i++)
549  if (cat >= list->min[i] && cat <= list->max[i])
550  return (TRUE);
551 
552  return (FALSE);
553 }
554 
555 /*!
556  \brief Set category constraints using 'where' or 'cats' option and layer number.
557 
558  \param Map pointer to Map_info structure
559  \param layer layer number
560  \param where where statement
561  \param catstr category list as string
562 
563  \return pointer to cat_list structure or NULL
564  */
565 struct cat_list *Vect_cats_set_constraint(struct Map_info *Map, int layer,
566  char *where, char *catstr)
567 {
568  struct cat_list *list = NULL;
569  int ret;
570 
571  if (layer < 1) {
572  G_warning(_("Layer number must be > 0 for category constraints"));
573  /* no valid constraints, all categories qualify */
574  return list;
575  }
576 
577  /* where has precedence over cats */
578  if (where) {
579  struct field_info *Fi = NULL;
580  dbDriver *driver = NULL;
581  int ncats, *cats = NULL;
582  int i, j;
583 
584  if (catstr)
585  G_warning(_("'%s' and '%s' parameters were supplied, cats will be ignored"), "where", "cats");
586 
587  Fi = Vect_get_field(Map, layer);
588  if (!Fi) {
589  G_fatal_error(_("Database connection not defined for layer %d"),
590  layer);
591  }
592 
593  G_verbose_message(_("Loading categories from table <%s>..."), Fi->table);
594 
595  driver = db_start_driver_open_database(Fi->driver, Fi->database);
596  if (driver == NULL)
597  G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
598  Fi->database, Fi->driver);
599 
600  ncats = db_select_int(driver, Fi->table, Fi->key, where,
601  &cats);
602  if (ncats == -1)
603  G_fatal_error(_("Unable select records from table <%s>"),
604  Fi->table);
605  G_verbose_message(n_("One category loaded", "%d categories loaded", ncats), ncats);
606 
608 
609  /* sort */
610  qsort(cats, ncats, sizeof(int), cmp);
611 
612  /* remove duplicates */
613  j = 1;
614  for (i = 1; i < ncats; i++) {
615  if (cats[i] != cats[j - 1]) {
616  cats[j] = cats[i];
617  j++;
618  }
619  }
620  ncats = j;
621 
622  /* convert to cat list */
623  list = Vect_new_cat_list();
624 
625  ret = Vect_array_to_cat_list(cats, ncats, list);
626  if (ret == 0)
627  G_warning(_("No categories selected with '%s' option"), "where");
628 
629  if (cats)
630  G_free(cats);
631  }
632  else if (catstr) {
633  list = Vect_new_cat_list();
634 
635  ret = Vect_str_to_cat_list(catstr, list);
636  if (ret > 0)
637  G_warning(_("%d errors in '%s' option"), ret, "cats");
638  }
639 
640  if (list) {
641  if (list->n_ranges < 1) {
642  Vect_destroy_cat_list(list);
643  list = NULL;
644  }
645  else
646  list->field = layer;
647  }
648 
649  return list;
650 }
651 
652 /*!
653  \brief Check if categories match with category constraints.
654 
655  \param Cats line_cats structure
656  \param layer layer number
657  \param list cat_list structure
658 
659  \return 0 no match, categories are outside constraints
660  \return 1 match, categories are inside constraints
661  */
662 /* TODO:
663  * for GRASS 8, change return type:
664  * return a list of all category numbers that match the constraints
665  * return NULL if no category number matches the constraints
666  */
667 int Vect_cats_in_constraint(struct line_cats *Cats, int layer,
668  struct cat_list *list)
669 {
670  int i;
671 
672  if (layer < 1) {
673  G_warning(_("Layer number must be > 0 for category constraints"));
674  /* no valid constraint, all categories qualify */
675  return 1;
676  }
677 
678  if (list) {
679  for (i = 0; i < Cats->n_cats; i++) {
680  if (Cats->field[i] == layer &&
681  Vect_cat_in_cat_list(Cats->cat[i], list)) {
682  return 1;
683  }
684  }
685  return 0;
686  }
687 
688  for (i = 0; i < Cats->n_cats; i++) {
689  if (Cats->field[i] == layer)
690  return 1;
691  }
692 
693  return 0;
694 }
695 
696 
697 /*!
698  \brief Check if category is in ordered array of integers.
699 
700  \param cat category number
701  \param array ordered array of integers
702  \param ncats number of categories in array
703 
704  \return TRUE if cat is in list
705  \return FALSE if it is not
706  */
707 int Vect_cat_in_array(int cat, const int *array, int ncats)
708 {
709  int *i;
710 
711  i = bsearch((void *)&cat, (void *)array, (size_t) ncats,
712  sizeof(int), cmp);
713 
714  return (i != NULL);
715 }
716 
717 /* return -1 if *p1 < *p2
718  * return 1 if *p1 > *p2
719  * return 0 if *p1 == *p2 */
720 static int cmp(const void *pa, const void *pb)
721 {
722  int *p1 = (int *)pa;
723  int *p2 = (int *)pb;
724 
725  if (*p1 < *p2)
726  return -1;
727  return (*p1 > *p2);
728 }
#define TRUE
Definition: gis.h:59
#define G_malloc(n)
Definition: defs/gis.h:112
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int Vect_field_cat_get(const struct line_cats *Cats, int field, struct ilist *cats)
Get list of categories of given field.
int alloc_ranges
Allocated space for ranges.
Definition: dig_structs.h:1744
int Vect_field_cat_del(struct line_cats *Cats, int field, int cat)
Delete field/cat from line_cats structure.
int Vect_reset_list(struct ilist *)
Reset ilist structure.
void Vect_destroy_cat_list(struct cat_list *p)
Frees allocated cat_list memory.
#define min(x, y)
Definition: draw2.c:31
int Vect_cat_del(struct line_cats *Cats, int field)
Delete all categories of given layer.
#define n_(strs, strp, num)
Definition: glocale.h:11
int alloc_cats
Allocated space for categories.
Definition: dig_structs.h:1719
char * table
Name of DB table.
Definition: dig_structs.h:155
int n_values
Number of values in the list.
Definition: gis.h:698
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
int * min
Array of minimum values.
Definition: dig_structs.h:1732
dbDriver * db_start_driver_open_database(const char *, const char *)
Open driver/database connection.
Definition: db.c:28
void Vect_destroy_cats_struct(struct line_cats *p)
Frees all memory associated with line_cats structure, including the struct itself.
int Vect_reset_cats(struct line_cats *Cats)
Reset category structure to make sure cats structure is clean to be re-used.
int Vect_cat_list_to_array(const struct cat_list *list, int **vals, int *nvals)
Convert cat_list struct to ordered array of unique integers.
#define NULL
Definition: ccmath.h:32
#define max(x, y)
Definition: draw2.c:32
int db_close_database_shutdown_driver(dbDriver *)
Close driver/database connection.
Definition: db.c:62
struct field_info * Vect_get_field(const struct Map_info *, int)
Get information about link to database (by layer number)
Definition: field.c:506
char * database
Definition: dig_structs.h:151
int Vect_cat_in_cat_list(int cat, const struct cat_list *list)
Check if category number is in list.
int n_ranges
Number of ranges.
Definition: dig_structs.h:1740
Feature category info.
Definition: dig_structs.h:1702
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:220
int Vect_cat_set(struct line_cats *Cats, int field, int cat)
Add new field/cat to category structure if doesn&#39;t exist yet.
int dig_alloc_cats(struct line_cats *, int)
Allocate room for &#39;num&#39; fields and category arrays in struct line_cats.
Definition: struct_alloc.c:383
Layer (old: field) information.
Definition: dig_structs.h:134
struct cat_list * Vect_new_cat_list()
Allocate memory for cat_list structure.
double l
Definition: r_raster.c:39
int Vect_cat_in_array(int cat, const int *array, int ncats)
Check if category is in ordered array of integers.
int Vect_array_to_cat_list(const int *vals, int nvals, struct cat_list *list)
Convert ordered array of integers to cat_list structure.
#define GV_NCATS_MAX
Maximum number of categories for one element.
Definition: dig_defines.h:217
int Vect_cat_get(const struct line_cats *Cats, int field, int *cat)
Get first found category of given field.
#define FALSE
Definition: gis.h:63
struct list * list
Definition: read_list.c:24
int field
Category layer (field)
Definition: dig_structs.h:1728
int n_cats
Number of categories attached to element.
Definition: dig_structs.h:1715
int * cat
Array of categories.
Definition: dig_structs.h:1711
Category list.
Definition: dig_structs.h:1723
struct cat_list * Vect_cats_set_constraint(struct Map_info *Map, int layer, char *where, char *catstr)
Set category constraints using &#39;where&#39; or &#39;cats&#39; option and layer number.
Vector map info.
Definition: dig_structs.h:1259
char * driver
Name of DB driver (&#39;sqlite&#39;, &#39;dbf&#39;, ...)
Definition: dig_structs.h:147
struct line_cats * Vect_new_cats_struct()
Creates and initializes line_cats structure.
Definition: driver.h:22
int Vect_cats_in_constraint(struct line_cats *Cats, int layer, struct cat_list *list)
Check if categories match with category constraints.
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
Definition: manage.h:4
int Vect_list_append(struct ilist *, int)
Append new item to the end of list if not yet present.
void G_warning(const char *,...) __attribute__((format(printf
#define GV_FIELD_MAX
Maximum field.
Definition: dig_defines.h:219
#define G_realloc(p, n)
Definition: defs/gis.h:114
#define _(str)
Definition: glocale.h:10
List of integers.
Definition: gis.h:689
int Vect_str_to_cat_list(const char *str, struct cat_list *list)
Converts string of categories and cat ranges separated by commas to cat_list.
int * field
Array of layers (fields)
Definition: dig_structs.h:1707
void void G_verbose_message(const char *,...) __attribute__((format(printf
int db_select_int(dbDriver *, const char *, const char *, const char *, int **)
Select array of ordered integers from table/column.
int G_debug(int, const char *,...) __attribute__((format(printf
int * max
Array of maximum values.
Definition: dig_structs.h:1736
char * key
Name of key column (usually &#39;cat&#39;)
Definition: dig_structs.h:159