GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
vector/Vlib/cats.c
Go to the documentation of this file.
1 
21 #include <stdlib.h>
22 #include <string.h>
23 #include <grass/gis.h>
24 #include <grass/Vect.h>
25 #include <grass/glocale.h>
26 
27 static int cmp(const void *pa, const void *pb);
28 struct line_cats *Vect__new_cats_struct(void);
29 
30 
40 struct line_cats *Vect_new_cats_struct()
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 
58 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 
81 int Vect_destroy_cats_struct(struct line_cats *p)
82 {
83  if (p) { /* probably a moot test */
84  if (p->n_cats) {
85  G_free((void *)p->field);
86  G_free((void *)p->cat);
87  }
88  G_free((void *)p);
89  }
90 
91  return 0;
92 }
93 
106 int Vect_cat_set(struct line_cats *Cats, int field, int cat)
107 {
108  register int n;
109 
110  /* check input values */
111  /* compiler may warn:
112  * comparison is always 0 due to limited range of data type
113  * but remember that limit is set to portable data type length
114  * and machine native size may be longer */
115  /*
116  if (field < 1 || field > GV_FIELD_MAX || cat < 0 || cat > GV_CAT_MAX)
117  return (-2);
118  */
119 
120  /* go through old cats and find if field/category exists */
121  for (n = 0; n < Cats->n_cats; n++) {
122  if (Cats->field[n] == field && Cats->cat[n] == cat)
123  return (1);
124  }
125 
126  /* field was not found so we shall append new cat */
127  /* test if space exist */
128  if (n >= GV_NCATS_MAX) {
129  G_fatal_error(_("Too many categories (%d), unable to set cat %d (layer %d)"),
130  Cats->n_cats, cat, field);
131  }
132 
133  if (Cats->n_cats == Cats->alloc_cats) {
134  if (0 > dig_alloc_cats(Cats, Cats->n_cats + 100))
135  return (-1);
136  }
137 
138  n = Cats->n_cats;
139  Cats->field[n] = field;
140  Cats->cat[n] = cat;
141  Cats->n_cats++;
142  return (1);
143 }
144 
157 int Vect_cat_get(struct line_cats *Cats, int field, int *cat)
158 {
159  register int n;
160 
161  /* check input value */
162  /*
163  if (field < 1 || field > GV_FIELD_MAX)
164  return (0);
165  */
166 
167  *cat = -1;
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  *cat = Cats->cat[n];
173  return (1);
174  }
175  }
176 
177  /* field was not found */
178  return (0);
179 }
180 
191 int Vect_field_cat_get(struct line_cats *Cats, int field, struct ilist *cats)
192 {
193  int n;
194 
195  /* reset list of categories */
196  Vect_reset_list(cats);
197 
198  /* check input value */
199  if (field < 1 || field > GV_FIELD_MAX)
200  return -1;
201 
202  /* go through cats and find if field exist */
203  for (n = 0; n < Cats->n_cats; n++) {
204  if (Cats->field[n] != field)
205  continue;
206  Vect_list_append(cats, Cats->cat[n]);
207  }
208 
209  return cats->n_values;
210 }
211 
221 int Vect_cat_del(struct line_cats *Cats, int field)
222 {
223  int n, m, found = 0;
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  for (n = 0; n < Cats->n_cats; n++) {
233  if (Cats->field[n] == field) {
234  for (m = n; m < Cats->n_cats - 1; m++) {
235  Cats->field[m] = Cats->field[m + 1];
236  Cats->cat[m] = Cats->cat[m + 1];
237  }
238  Cats->n_cats--;
239  found = 1;
240  n--; /* check again this position */
241  }
242  }
243 
244  return (found);
245 }
246 
257 int Vect_field_cat_del(struct line_cats *Cats, int field, int cat)
258 {
259  register int n, m, found = 0;
260 
261  /* check input value */
262  /*
263  if (field < 1 || field > GV_FIELD_MAX)
264  return (0);
265  */
266 
267  /* go through cats and find if field exist */
268  for (n = 0; n < Cats->n_cats; n++) {
269  if (Cats->field[n] == field && (Cats->cat[n] == cat || cat == -1)) {
270  for (m = n; m < Cats->n_cats - 1; m++) {
271  Cats->field[m] = Cats->field[m + 1];
272  Cats->cat[m] = Cats->cat[m + 1];
273  }
274  Cats->n_cats--;
275  found = 1;
276  }
277  }
278 
279  return (found);
280 }
281 
292 int Vect_reset_cats(struct line_cats *Cats)
293 {
294  Cats->n_cats = 0;
295 
296  return 0;
297 }
298 
305 struct cat_list *Vect_new_cat_list()
306 {
307  struct cat_list *p;
308 
309  p = (struct cat_list *)G_malloc(sizeof(struct cat_list));
310 
311  /* n_ranges MUST be initialized to zero */
312  if (p) {
313  p->n_ranges = 0;
314  p->alloc_ranges = 0;
315  p->field = 0;
316  p->min = NULL;
317  p->max = NULL;
318  }
319 
320  return p;
321 }
322 
323 
331 int Vect_destroy_cat_list(struct cat_list *p)
332 {
333  if (p) { /* probably a moot test */
334  if (p->n_ranges) {
335  G_free((void *)p->min);
336  G_free((void *)p->max);
337  }
338  G_free((void *)p);
339  }
340 
341  return 0;
342 }
343 
344 
355 int Vect_str_to_cat_list(const char *str, struct cat_list *list)
356 {
357  int i, nr, l, err = 0;
358  const char *s, *e;
359  char buf[100];
360  int min, max;
361 
362  G_debug(3, "Vect_str_to_cat_list(): str = %s", str);
363 
364  list->n_ranges = 0;
365  l = strlen(str);
366 
367  /* find number of ranges */
368  nr = 1; /* one range */
369  for (i = 0; i < l; i++)
370  if (str[i] == ',')
371  nr++;
372 
373  /* allocate space */
374  if (list->alloc_ranges == 0) {
375  list->min = (int *)G_malloc(nr * sizeof(int));
376  list->max = (int *)G_malloc(nr * sizeof(int));
377  }
378  else if (nr > list->alloc_ranges) {
379  list->min = (int *)G_realloc((void *)list->min, nr * sizeof(int));
380  list->max = (int *)G_realloc((void *)list->max, nr * sizeof(int));
381  }
382 
383  /* go through string and read ranges */
384  i = 0;
385  s = str;
386 
387  while (s) {
388  e = (char *)strchr(s, ','); /* first comma */
389  if (e) {
390  l = e - s;
391  strncpy(buf, s, l);
392  buf[l] = '\0';
393  s = e + 1;
394  }
395  else {
396  strcpy(buf, s);
397  s = NULL;
398  }
399 
400  G_debug(3, " buf = %s", buf);
401  if (sscanf(buf, "%d-%d", &min, &max) == 2) {
402  }
403  else if (sscanf(buf, "%d", &min) == 1)
404  max = min;
405  else { /* error */
406 
407  G_warning(_("Unable to convert category string '%s' (from '%s') to category range"),
408  buf, str);
409  err++;
410  continue;
411  }
412 
413  list->min[i] = min;
414  list->max[i] = max;
415  i++;
416  }
417 
418  list->n_ranges = i;
419 
420  return (err);
421 }
422 
432 int Vect_array_to_cat_list(int *vals, int nvals, struct cat_list *list)
433 {
434  int i, range;
435 
436  G_debug(1, "Vect_array_to_cat_list()");
437  range = -1;
438  for (i = 0; i < nvals; i++) {
439  if (i == 0 || (vals[i] - list->max[range]) > 1) {
440  range++;
441  if (range == list->alloc_ranges) {
442  list->alloc_ranges += 1000;
443  list->min = (int *)G_realloc((void *)list->min,
444  list->alloc_ranges *
445  sizeof(int));
446  list->max =
447  (int *)G_realloc((void *)list->max,
448  list->alloc_ranges * sizeof(int));
449  }
450  list->min[range] = vals[i];
451  list->max[range] = vals[i];
452  }
453  else {
454  list->max[range] = vals[i];
455  }
456  }
457 
458  list->n_ranges = range + 1;
459 
460  return (list->n_ranges);
461 }
462 
472 int Vect_cat_in_cat_list(int cat, struct cat_list *list)
473 {
474  int i;
475 
476  for (i = 0; i < list->n_ranges; i++)
477  if (cat >= list->min[i] && cat <= list->max[i])
478  return (TRUE);
479 
480  return (FALSE);
481 }
482 
493 int Vect_cat_in_array(int cat, int *array, int ncats)
494 {
495  int *i;
496 
497  i = bsearch((void *)&cat, (void *)array, (size_t) ncats,
498  sizeof(int), cmp);
499 
500  if (i != NULL)
501  return (TRUE);
502 
503  return (FALSE);
504 }
505 
506 static int cmp(const void *pa, const void *pb)
507 {
508  int *p1 = (int *)pa;
509  int *p2 = (int *)pb;
510 
511  if (*p1 < *p2)
512  return -1;
513  if (*p1 > *p2)
514  return 1;
515  return 0;
516 }