gsds.c 11 KB

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