123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- /*!
- \file lib/ogsf/gsds.c
- \brief OGSF library - dataset loading and management (lower level functions)
- GRASS OpenGL gsurf OGSF Library
- The idea here is to treat datasets as seperate objects, which SHOULD:
- - allow easier reuse of data for different attributes.
- - allow a mechanism for changing data and have changes reflected
- in each attribute using that data.
- - allow a mechanism to automatically update data when the data source
- is changed.
- - allow easier weaning from GRASS.
- - allow easier use of shared memory between processes.
- These structures are defined in gstypes.h:
- <code>
- typedef struct{
- float *fb;
- int *ib;
- short *sb;
- char *cb;
- struct BM *bm;
- } typbuff;
- </code>
- How about adding a transform func here, so GET_MAPATT would do an
- on-the-fly transformation? Or even a transform func LIST!
- <code>
- typedef struct{
- int data_id;
- int dims[MAXDIMS];
- int ndims;
- int numbytes;
- char unique_name[80];
- typbuff databuff;
- int changed;
- int need_reload;
- } dataset;
- </code>
- (C) 1999-2008 by the GRASS Development Team
- This program is free software under the
- GNU General Public License (>=v2).
- Read the file COPYING that comes with GRASS
- for details.
- \author Bill Brown UI GMS Lab
- \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
- */
- #include <stdlib.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/glocale.h>
- #include <grass/ogsf.h>
- #define LUCKY 33
- #define BLOC 20
- #define MAX_DS 100
- static int init_gsds(void);
- static int check_numsets(void);
- static dataset *get_dataset(int);
- static int get_type(dataset *);
- static dataset *Data[MAX_DS];
- static dataset Ds[MAX_DS]; /* trying to avoid allocation */
- static int Numsets = 0;
- static int Cur_id = LUCKY;
- static int Cur_max;
- static size_t Tot_mem = 0;
- /*!
- \brief Initialize gsds
- */
- static int init_gsds(void)
- {
- int i;
- for (i = 0; i < MAX_DS; i++) {
- /* avoiding dynamic allocation */
- Data[i] = &(Ds[i]);
- }
- Cur_max = MAX_DS;
- return (1);
- }
- /*!
- \brief Check numsets
- \return 0 numset < cur_max
- */
- static int check_numsets(void)
- {
- if (Numsets < Cur_max) {
- return (0);
- }
- G_fatal_error(_("Maximum number of datasets exceeded"));
- /* This return statement keeps compilers happy, it is never executed */
- return (0);
- }
- /*!
- \brief Get dataset
- \param id data id
- \return pointer to dataset struct
- \return NULL dataset not found
- */
- static dataset *get_dataset(int id)
- {
- int i;
- for (i = 0; i < Numsets; i++) {
- if (Data[i]->data_id == id) {
- return (Data[i]);
- }
- }
- return (NULL);
- }
- /*!
- \brief Get type
- \param ds pointer to dataset struct
- \return type code
- \return -1 unsupported type
- */
- static int get_type(dataset * ds)
- {
- if (ds) {
- if (ds->databuff.bm) {
- return (ATTY_MASK);
- }
- if (ds->databuff.cb) {
- return (ATTY_CHAR);
- }
- if (ds->databuff.sb) {
- return (ATTY_SHORT);
- }
- if (ds->databuff.ib) {
- return (ATTY_INT);
- }
- if (ds->databuff.fb) {
- return (ATTY_FLOAT);
- }
- }
- return (-1);
- }
- /*!
- \brief Get handle to gsds.
- Successive calls will continue search until "begin" is set
- (problem here is, unique_name no longer uniquely identifies
- dataset, since changes may be made; but unique_name should still
- be useful for reloading dataset)
- changes & types are set to actual for dataset if found.
- \param name
- \param changes,types acceptable changes & types, flags may be or'd
- not changed is assumed to always be acceptable
- \param begin flag to indicate search from beginning
- \return data id
- \return -1 not found
- */
- int gsds_findh(const char *name, IFLAG * changes, IFLAG * types, int begin)
- {
- static int i;
- int start;
- start = begin ? 0 : i + 1;
- for (i = start; i < Numsets; i++) {
- if (!strcmp(Data[i]->unique_name, name)) {
- if ((Data[i]->changed & *changes) || !(Data[i]->changed)) {
- if (get_type(Data[i]) & *types) {
- *changes = Data[i]->changed;
- *types = get_type(Data[i]);
- return (Data[i]->data_id);
- }
- }
- }
- }
- return (-1);
- }
- /*!
- \brief Get handle to gsds
- \param name raster map name
- \return -1 on failure
- \return data id
- */
- int gsds_newh(const char *name)
- {
- dataset *new;
- static int first = 1;
- int i;
- if (first) {
- if (0 > init_gsds()) {
- return (-1);
- }
- first = 0;
- }
- else if (0 > check_numsets()) {
- return (-1);
- }
- if (!name) {
- return (-1);
- }
- new = Data[Numsets];
- if (new) {
- Numsets++;
- new->data_id = Cur_id++;
- for (i = 0; i < MAXDIMS; i++) {
- new->dims[i] = 0;
- }
- new->unique_name = G_store(name);
- new->databuff.fb = NULL;
- new->databuff.ib = NULL;
- new->databuff.sb = NULL;
- new->databuff.cb = NULL;
- new->databuff.bm = NULL;
- new->databuff.nm = NULL;
- new->databuff.k = 0.0;
- new->changed = 0;
- new->ndims = 0;
- new->need_reload = 1;
- return (new->data_id);
- }
- return (-1);
- }
- /*!
- \brief Get data buffer
- Doesn't prevent writing a buff thats's been gotten with change_flag
- == 0 (could return a copy, but willing to trust calling func for
- now)
- \param id dataset id
- \param change_flag set changed flag
- \return pointer to typbuff struct
- \return NULL on failure
- */
- typbuff *gsds_get_typbuff(int id, IFLAG change_flag)
- {
- dataset *ds;
- if ((ds = get_dataset(id))) {
- ds->changed = ds->changed | change_flag;
- ds->need_reload = 0;
- return (&(ds->databuff));
- }
- return (NULL);
- }
- /*!
- \brief Get name
- \param id
- \return name
- \return NULL on failure
- */
- char *gsds_get_name(int id)
- {
- int i;
- dataset *fds;
- static char retstr[GPATH_MAX];
- for (i = 0; i < Numsets; i++) {
- if (Data[i]->data_id == id) {
- fds = Data[i];
- strcpy(retstr, fds->unique_name);
- return (retstr);
- }
- }
- return (NULL);
- }
- /*!
- \brief Free allocated dataset
- \param id
- \return 0 not found
- \return 1 found
- */
- int gsds_free_datah(int id)
- {
- int i, j, found = 0;
- dataset *fds;
- G_debug(3, "gsds_free_datah");
- for (i = 0; i < Numsets; i++) {
- if (Data[i]->data_id == id) {
- found = 1;
- fds = Data[i];
- free_data_buffs(fds, ATTY_ANY);
- G_free((void *)fds->unique_name);
- fds->unique_name = NULL;
- fds->data_id = 0;
- for (j = i; j < (Numsets - 1); j++) {
- Data[j] = Data[j + 1];
- }
- Data[j] = fds;
- }
- }
- if (found) {
- --Numsets;
- }
- return (found);
- }
- /*!
- \brief Free allocated buffer
- \param id dataset id
- \param typ data type
- \return 0 not found
- \return 1 found
- */
- int gsds_free_data_buff(int id, int typ)
- {
- int i, found = 0;
- dataset *fds;
- for (i = 0; i < Numsets; i++) {
- if (Data[i]->data_id == id) {
- found = 1;
- fds = Data[i];
- free_data_buffs(fds, typ);
- }
- }
- return (found);
- }
- /*!
- \brief Free data buffer
- \param ds pointer to dataset struct
- \param typ data type
- \return freed size
- */
- size_t free_data_buffs(dataset * ds, int typ)
- {
- int i;
- size_t siz, nsiz = 1, freed = 0;
- for (i = 0; i < ds->ndims; i++) {
- nsiz *= ds->dims[i];
- }
- if (typ & ATTY_NULL) {
- if (ds->databuff.nm) {
- siz = BM_get_map_size(ds->databuff.nm);
- BM_destroy(ds->databuff.nm);
- ds->databuff.nm = NULL;
- freed += siz;
- }
- }
- if (typ & ATTY_MASK) {
- if (ds->databuff.bm) {
- siz = BM_get_map_size(ds->databuff.bm);
- BM_destroy(ds->databuff.bm);
- ds->databuff.bm = NULL;
- freed += siz;
- }
- }
- if (typ & ATTY_CHAR) {
- if (ds->databuff.cb) {
- siz = nsiz * sizeof(char);
- free(ds->databuff.cb);
- ds->databuff.cb = NULL;
- freed += siz;
- }
- }
- if (typ & ATTY_SHORT) {
- if (ds->databuff.sb) {
- siz = nsiz * sizeof(short);
- free(ds->databuff.sb);
- ds->databuff.sb = NULL;
- freed += siz;
- }
- }
- if (typ & ATTY_INT) {
- if (ds->databuff.ib) {
- siz = nsiz * sizeof(int);
- free(ds->databuff.ib);
- ds->databuff.ib = NULL;
- freed += siz;
- }
- }
- if (typ & ATTY_FLOAT) {
- if (ds->databuff.fb) {
- siz = nsiz * sizeof(float);
- free(ds->databuff.fb);
- ds->databuff.fb = NULL;
- freed += siz;
- }
- }
- Tot_mem -= freed;
- ds->numbytes -= freed;
- if (freed) {
- G_debug(5, "free_data_buffs(): freed data from id no. %d",
- ds->data_id);
- G_debug(5,
- "free_data_buffs(): %.3f Kbytes freed, current total = %.3f",
- freed / 1000., Tot_mem / 1000.);
- }
- return (freed);
- }
- /*!
- \brief Allocates correct buffer according to type, keeps track of total mem
- \todo add ATTY_CONST
- \param id dataset id
- \param dims array of dimensions
- \param ndims number of dimensions
- \param type data type
- \return amount of allocated memory
- */
- size_t gsds_alloc_typbuff(int id, int *dims, int ndims, int type)
- {
- dataset *ds;
- int i;
- size_t siz = 1;
- if ((ds = get_dataset(id))) {
- /*
- free_data_buffs(ds);
- careful here - allowing > 1 type to coexist (for float -> color conv.)
- now also use this to allocate a null mask
- (then if not used, use gsds_free_data_buff(id, ATTY_NULL))
- */
- for (i = 0; i < ndims; i++) {
- ds->dims[i] = dims[i];
- siz *= dims[i];
- }
- switch (type) {
- case ATTY_NULL:
- if (ndims != 2) {
- /* higher dimension bitmaps not supported */
- return 0;
- }
- if (NULL == (ds->databuff.nm = BM_create(dims[1], dims[0]))) {
- return 0;
- }
- siz = BM_get_map_size(ds->databuff.nm);
- break;
- case ATTY_MASK:
- if (ndims != 2) {
- /* higher dimension bitmaps not supported */
- return (-1);
- }
- if (NULL == (ds->databuff.bm = BM_create(dims[1], dims[0]))) {
- return 0;
- }
- siz = BM_get_map_size(ds->databuff.bm);
- break;
- case ATTY_CHAR:
- siz *= sizeof(char);
- if (siz) {
- if (NULL ==
- (ds->databuff.cb = (unsigned char *)G_malloc(siz))) {
- return 0;
- }
- }
- else {
- return 0;
- }
- break;
- case ATTY_SHORT:
- siz *= sizeof(short);
- if (siz) {
- if (NULL == (ds->databuff.sb = (short *)G_malloc(siz))) {
- return 0;
- }
- }
- else {
- return 0;
- }
- break;
- case ATTY_INT:
- siz *= sizeof(int);
- if (siz) {
- if (NULL == (ds->databuff.ib = (int *)G_malloc(siz))) {
- return 0;
- }
- }
- else {
- return 0;
- }
- break;
- case ATTY_FLOAT:
- siz *= sizeof(float);
- if (siz) {
- if (NULL == (ds->databuff.fb = (float *)G_malloc(siz))) {
- return 0;
- }
- }
- else {
- return 0;
- }
- break;
- default:
- return 0;
- }
- ds->changed = 0; /* starting with clean slate */
- ds->need_reload = 1;
- ds->numbytes += siz;
- ds->ndims = ndims;
- Tot_mem += siz;
- G_debug(5,
- "gsds_alloc_typbuff(): %f Kbytes allocated, current total = %f",
- siz / 1000., Tot_mem / 1000.);
- return (siz);
- }
- return 0;
- }
- /*!
- \brief ADD
- \param id
- \return -1 on error
- \return
- */
- int gsds_get_changed(int id)
- {
- dataset *ds;
- if ((ds = get_dataset(id))) {
- return ((int)ds->changed);
- }
- return (-1);
- }
- /*!
- \brief ADD
- \param id
- \param reason
- \return -1 on error
- \return
- */
- int gsds_set_changed(int id, IFLAG reason)
- {
- dataset *ds;
- if ((ds = get_dataset(id))) {
- ds->changed = reason;
- }
- return (-1);
- }
- /*!
- \brief ADD
- \param id
- \return
- */
- int gsds_get_type(int id)
- {
- dataset *ds;
- ds = get_dataset(id);
- return (get_type(ds));
- }
|