GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
gsds.c
Go to the documentation of this file.
1/*!
2 \file lib/ogsf/gsds.c
3
4 \brief OGSF library - dataset loading and management (lower level functions)
5
6 GRASS OpenGL gsurf OGSF Library
7
8 The idea here is to treat datasets as separate objects, which SHOULD:
9 - allow easier reuse of data for different attributes.
10 - allow a mechanism for changing data and have changes reflected
11 in each attribute using that data.
12 - allow a mechanism to automatically update data when the data source
13 is changed.
14 - allow easier weaning from GRASS.
15 - allow easier use of shared memory between processes.
16
17 These structures are defined in gstypes.h:
18
19 <code>
20 typedef struct{
21 float *fb;
22 int *ib;
23 short *sb;
24 char *cb;
25 struct BM *bm;
26 } typbuff;
27 </code>
28
29 How about adding a transform func here, so GET_MAPATT would do an
30 on-the-fly transformation? Or even a transform func LIST!
31
32 <code>
33 typedef struct{
34 int data_id;
35 int dims[MAXDIMS];
36 int ndims;
37 int numbytes;
38 char unique_name[80];
39 typbuff databuff;
40 int changed;
41 int need_reload;
42 } dataset;
43 </code>
44
45 SPDX-FileCopyrightText: 1999-2008 GRASS Development Team
46 SPDX-License-Identifier: GPL-2.0-or-later
47
48 \author Bill Brown UI GMS Lab
49 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
50 */
51
52#include <stdlib.h>
53#include <string.h>
54
55#include <grass/gis.h>
56#include <grass/glocale.h>
57#include <grass/ogsf.h>
58
59#define LUCKY 33
60#define BLOC 20
61#define MAX_DS 100
62
63static int init_gsds(void);
64static int check_numsets(void);
65static dataset *get_dataset(int);
66static int get_type(dataset *);
67
68static dataset *Data[MAX_DS];
69static dataset Ds[MAX_DS]; /* trying to avoid allocation */
70
71static int Numsets = 0;
72
73static int Cur_id = LUCKY;
74static int Cur_max;
75static size_t Tot_mem = 0;
76
77/*!
78 \brief Initialize gsds
79 */
80static int init_gsds(void)
81{
82 int i;
83
84 for (i = 0; i < MAX_DS; i++) {
85 /* avoiding dynamic allocation */
86 Data[i] = &(Ds[i]);
87 }
88
89 Cur_max = MAX_DS;
90
91 return (1);
92}
93
94/*!
95 \brief Check numsets
96
97 \return 0 numset < cur_max
98 */
99static int check_numsets(void)
100{
101 if (Numsets < Cur_max) {
102 return (0);
103 }
104
105 G_fatal_error(_("Maximum number of datasets exceeded"));
106
107 /* This return statement keeps compilers happy, it is never executed */
108 return (0);
109}
110
111/*!
112 \brief Get dataset
113
114 \param id data id
115
116 \return pointer to dataset struct
117 \return NULL dataset not found
118 */
119static dataset *get_dataset(int id)
120{
121 int i;
122
123 for (i = 0; i < Numsets; i++) {
124 if (Data[i]->data_id == id) {
125 return (Data[i]);
126 }
127 }
128
129 return (NULL);
130}
131
132/*!
133 \brief Get type
134
135 \param ds pointer to dataset struct
136
137 \return type code
138 \return -1 unsupported type
139 */
140static int get_type(dataset *ds)
141{
142 if (ds) {
143 if (ds->databuff.bm) {
144 return (ATTY_MASK);
145 }
146
147 if (ds->databuff.cb) {
148 return (ATTY_CHAR);
149 }
150
151 if (ds->databuff.sb) {
152 return (ATTY_SHORT);
153 }
154
155 if (ds->databuff.ib) {
156 return (ATTY_INT);
157 }
158
159 if (ds->databuff.fb) {
160 return (ATTY_FLOAT);
161 }
162 }
163
164 return (-1);
165}
166
167/*!
168 \brief Get handle to gsds.
169
170 Successive calls will continue search until "begin" is set
171 (problem here is, unique_name no longer uniquely identifies
172 dataset, since changes may be made; but unique_name should still
173 be useful for reloading dataset)
174 changes & types are set to actual for dataset if found.
175
176 \param name
177 \param changes,types acceptable changes & types, flags may be or'd
178 not changed is assumed to always be acceptable
179 \param begin flag to indicate search from beginning
180
181 \return data id
182 \return -1 not found
183 */
184int gsds_findh(const char *name, IFLAG *changes, IFLAG *types, int begin)
185{
186 static int i;
187 int start;
188
189 start = begin ? 0 : i + 1;
190
191 for (i = start; i < Numsets; i++) {
192 if (!strcmp(Data[i]->unique_name, name)) {
193 if ((Data[i]->changed & *changes) || !(Data[i]->changed)) {
194 if (get_type(Data[i]) & *types) {
195 *changes = Data[i]->changed;
196 *types = get_type(Data[i]);
197
198 return (Data[i]->data_id);
199 }
200 }
201 }
202 }
203
204 return (-1);
205}
206
207/*!
208 \brief Get handle to gsds
209
210 \param name raster map name
211
212 \return -1 on failure
213 \return data id
214 */
215int gsds_newh(const char *name)
216{
217 dataset *new;
218 static int first = 1;
219 int i;
220
221 if (first) {
222 if (0 > init_gsds()) {
223 return (-1);
224 }
225
226 first = 0;
227 }
228 else if (0 > check_numsets()) {
229 return (-1);
230 }
231
232 if (!name) {
233 return (-1);
234 }
235
236 new = Data[Numsets];
237
238 if (new) {
239 Numsets++;
240 new->data_id = Cur_id++;
241
242 for (i = 0; i < MAXDIMS; i++) {
243 new->dims[i] = 0;
244 }
245
246 new->unique_name = G_store(name);
247 new->databuff.fb = NULL;
248 new->databuff.ib = NULL;
249 new->databuff.sb = NULL;
250 new->databuff.cb = NULL;
251 new->databuff.bm = NULL;
252 new->databuff.nm = NULL;
253 new->databuff.k = 0.0;
254 new->changed = 0;
255 new->ndims = 0;
256 new->need_reload = 1;
257
258 return (new->data_id);
259 }
260
261 return (-1);
262}
263
264/*!
265 \brief Get data buffer
266
267 Doesn't prevent writing a buff thats's been gotten with change_flag
268 == 0 (could return a copy, but willing to trust calling func for
269 now)
270
271 \param id dataset id
272 \param change_flag set changed flag
273
274 \return pointer to typbuff struct
275 \return NULL on failure
276 */
278{
279 dataset *ds;
280
281 if ((ds = get_dataset(id))) {
282 ds->changed = ds->changed | change_flag;
283 ds->need_reload = 0;
284
285 return (&(ds->databuff));
286 }
287
288 return (NULL);
289}
290
291/*!
292 \brief Get name
293
294 \param id
295
296 \return name
297 \return NULL on failure
298 */
299char *gsds_get_name(int id)
300{
301 int i;
302 dataset *fds;
303 static char retstr[GPATH_MAX];
304
305 for (i = 0; i < Numsets; i++) {
306 if (Data[i]->data_id == id) {
307 fds = Data[i];
308 strcpy(retstr, fds->unique_name);
309
310 return (retstr);
311 }
312 }
313
314 return (NULL);
315}
316
317/*!
318 \brief Free allocated dataset
319
320 \param id
321
322 \return 0 not found
323 \return 1 found
324 */
326{
327 int i, j, found = 0;
328 dataset *fds;
329
330 G_debug(3, "gsds_free_datah");
331
332 for (i = 0; i < Numsets; i++) {
333 if (Data[i]->data_id == id) {
334 found = 1;
335 fds = Data[i];
337 G_free((void *)fds->unique_name);
338 fds->unique_name = NULL;
339 fds->data_id = 0;
340
341 for (j = i; j < (Numsets - 1); j++) {
342 Data[j] = Data[j + 1];
343 }
344
345 Data[j] = fds;
346 }
347 }
348
349 if (found) {
350 --Numsets;
351 }
352
353 return (found);
354}
355
356/*!
357 \brief Free allocated buffer
358
359 \param id dataset id
360 \param typ data type
361
362 \return 0 not found
363 \return 1 found
364 */
365int gsds_free_data_buff(int id, int typ)
366{
367 int i, found = 0;
368 dataset *fds;
369
370 for (i = 0; i < Numsets; i++) {
371 if (Data[i]->data_id == id) {
372 found = 1;
373 fds = Data[i];
375 }
376 }
377
378 return (found);
379}
380
381/*!
382 \brief Free data buffer
383
384 \param ds pointer to dataset struct
385 \param typ data type
386
387 \return freed size
388 */
390{
391 int i;
392 size_t siz, nsiz = 1, freed = 0;
393
394 for (i = 0; i < ds->ndims; i++) {
395 nsiz *= ds->dims[i];
396 }
397
398 if (typ & ATTY_NULL) {
399 if (ds->databuff.nm) {
402 ds->databuff.nm = NULL;
403 freed += siz;
404 }
405 }
406
407 if (typ & ATTY_MASK) {
408 if (ds->databuff.bm) {
411 ds->databuff.bm = NULL;
412 freed += siz;
413 }
414 }
415
416 if (typ & ATTY_CHAR) {
417 if (ds->databuff.cb) {
418 siz = nsiz * sizeof(char);
419 free(ds->databuff.cb);
420 ds->databuff.cb = NULL;
421 freed += siz;
422 }
423 }
424
425 if (typ & ATTY_SHORT) {
426 if (ds->databuff.sb) {
427 siz = nsiz * sizeof(short);
428 free(ds->databuff.sb);
429 ds->databuff.sb = NULL;
430 freed += siz;
431 }
432 }
433
434 if (typ & ATTY_INT) {
435 if (ds->databuff.ib) {
436 siz = nsiz * sizeof(int);
437 free(ds->databuff.ib);
438 ds->databuff.ib = NULL;
439 freed += siz;
440 }
441 }
442
443 if (typ & ATTY_FLOAT) {
444 if (ds->databuff.fb) {
445 siz = nsiz * sizeof(float);
446 free(ds->databuff.fb);
447 ds->databuff.fb = NULL;
448 freed += siz;
449 }
450 }
451
452 Tot_mem -= freed;
453 ds->numbytes -= freed;
454
455 if (freed) {
456 G_debug(5, "free_data_buffs(): freed data from id no. %d", ds->data_id);
457 G_debug(5, "free_data_buffs(): %.3f Kbytes freed, current total = %.3f",
458 freed / 1000., Tot_mem / 1000.);
459 }
460
461 return (freed);
462}
463
464/*!
465 \brief Allocates correct buffer according to type, keeps track of total mem
466
467 \todo add ATTY_CONST
468
469 \param id dataset id
470 \param dims array of dimensions
471 \param ndims number of dimensions
472 \param type data type
473
474 \return amount of allocated memory
475 */
476size_t gsds_alloc_typbuff(int id, int *dims, int ndims, int type)
477{
478 dataset *ds;
479 int i;
480 size_t siz = 1;
481
482 if ((ds = get_dataset(id))) {
483 /*
484 free_data_buffs(ds);
485 careful here - allowing > 1 type to coexist (for float -> color
486 conv.) now also use this to allocate a null mask (then if not used,
487 use gsds_free_data_buff(id, ATTY_NULL))
488 */
489
490 for (i = 0; i < ndims; i++) {
491 ds->dims[i] = dims[i];
492 siz *= dims[i];
493 }
494
495 switch (type) {
496 case ATTY_NULL:
497 if (ndims != 2) {
498 /* higher dimension bitmaps not supported */
499 return 0;
500 }
501
502 if (NULL == (ds->databuff.nm = BM_create(dims[1], dims[0]))) {
503 return 0;
504 }
505
507
508 break;
509
510 case ATTY_MASK:
511 if (ndims != 2) {
512 /* higher dimension bitmaps not supported */
513 return (-1);
514 }
515
516 if (NULL == (ds->databuff.bm = BM_create(dims[1], dims[0]))) {
517 return 0;
518 }
519
521
522 break;
523
524 case ATTY_CHAR:
525 siz *= sizeof(char);
526
527 if (siz) {
528 if (NULL ==
529 (ds->databuff.cb = (unsigned char *)G_malloc(siz))) {
530 return 0;
531 }
532 }
533 else {
534 return 0;
535 }
536
537 break;
538
539 case ATTY_SHORT:
540 siz *= sizeof(short);
541
542 if (siz) {
543 if (NULL == (ds->databuff.sb = (short *)G_malloc(siz))) {
544 return 0;
545 }
546 }
547 else {
548 return 0;
549 }
550
551 break;
552
553 case ATTY_INT:
554 siz *= sizeof(int);
555
556 if (siz) {
557 if (NULL == (ds->databuff.ib = (int *)G_malloc(siz))) {
558 return 0;
559 }
560 }
561 else {
562 return 0;
563 }
564
565 break;
566
567 case ATTY_FLOAT:
568 siz *= sizeof(float);
569
570 if (siz) {
571 if (NULL == (ds->databuff.fb = (float *)G_malloc(siz))) {
572 return 0;
573 }
574 }
575 else {
576 return 0;
577 }
578
579 break;
580
581 default:
582 return 0;
583 }
584
585 ds->changed = 0; /* starting with clean slate */
586 ds->need_reload = 1;
587 ds->numbytes += siz;
588 ds->ndims = ndims;
589 Tot_mem += siz;
590
591 G_debug(5,
592 "gsds_alloc_typbuff(): %f Kbytes allocated, current total = %f",
593 siz / 1000., Tot_mem / 1000.);
594
595 return (siz);
596 }
597
598 return 0;
599}
600
601/*!
602 \brief ADD
603
604 \param id
605
606 \return -1 on error
607 \return
608 */
610{
611 dataset *ds;
612
613 if ((ds = get_dataset(id))) {
614 return ((int)ds->changed);
615 }
616
617 return (-1);
618}
619
620/*!
621 \brief ADD
622
623 \param id
624 \param reason
625
626 \return -1 on error
627 \return
628 */
630{
631 dataset *ds;
632
633 if ((ds = get_dataset(id))) {
634 ds->changed = reason;
635 }
636
637 return (-1);
638}
639
640/*!
641 \brief ADD
642
643 \param id
644
645 \return
646 */
647int gsds_get_type(int id)
648{
649 dataset *ds;
650
651 ds = get_dataset(id);
652
653 return (get_type(ds));
654}
#define NULL
Definition ccmath.h:32
int BM_destroy(struct BM *)
Destroy bitmap and free all associated memory.
Definition bitmap.c:88
size_t BM_get_map_size(struct BM *)
Returns size in bytes that bitmap is taking up.
Definition bitmap.c:236
struct BM * BM_create(int, int)
Create bitmap of dimension x/y and return structure token.
Definition bitmap.c:57
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition defs/gis.h:136
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:85
int G_debug(int, const char *,...) __attribute__((format(printf
#define GPATH_MAX
Definition gis.h:196
#define _(str)
Definition glocale.h:10
#define MAX_DS
Definition gsds.c:61
char * gsds_get_name(int id)
Get name.
Definition gsds.c:299
int gsds_findh(const char *name, unsigned int *changes, unsigned int *types, int begin)
Get handle to gsds.
Definition gsds.c:184
int gsds_get_type(int id)
ADD.
Definition gsds.c:647
int gsds_newh(const char *name)
Get handle to gsds.
Definition gsds.c:215
typbuff * gsds_get_typbuff(int id, unsigned int change_flag)
Get data buffer.
Definition gsds.c:277
#define LUCKY
Definition gsds.c:59
int gsds_set_changed(int id, unsigned int reason)
ADD.
Definition gsds.c:629
size_t free_data_buffs(dataset *ds, int typ)
Free data buffer.
Definition gsds.c:389
int gsds_free_datah(int id)
Free allocated dataset.
Definition gsds.c:325
size_t gsds_alloc_typbuff(int id, int *dims, int ndims, int type)
Allocates correct buffer according to type, keeps track of total mem.
Definition gsds.c:476
int gsds_free_data_buff(int id, int typ)
Free allocated buffer.
Definition gsds.c:365
int gsds_get_changed(int id)
ADD.
Definition gsds.c:609
const char * name
Definition named_colr.c:6
OGSF header file (structures)
#define ATTY_SHORT
Definition ogsf.h:171
#define ATTY_NULL
Definition ogsf.h:167
#define MAXDIMS
Definition ogsf.h:178
#define ATTY_ANY
Definition ogsf.h:173
#define IFLAG
Definition ogsf.h:72
#define ATTY_FLOAT
Definition ogsf.h:169
#define ATTY_MASK
Definition ogsf.h:168
#define ATTY_INT
Definition ogsf.h:170
#define ATTY_CHAR
Definition ogsf.h:172
#define strcpy
Definition parson.c:66
void free(void *)
int dims[4]
Definition ogsf.h:237
typbuff databuff
Definition ogsf.h:241
int need_reload
Definition ogsf.h:243
int data_id
Definition ogsf.h:236
size_t numbytes
Definition ogsf.h:239
int ndims
Definition ogsf.h:238
unsigned int changed
Definition ogsf.h:242
float * fb
Definition ogsf.h:210
struct BM * nm
Definition ogsf.h:215
unsigned char * cb
Definition ogsf.h:213
short * sb
Definition ogsf.h:212
int * ib
Definition ogsf.h:211
struct BM * bm
Definition ogsf.h:214