gsds.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. /*!
  2. \file lib/ogsf/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 size_t 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. size_t free_data_buffs(dataset * ds, int typ)
  306. {
  307. int i;
  308. size_t siz, nsiz = 1, freed = 0;
  309. for (i = 0; i < ds->ndims; i++) {
  310. nsiz *= ds->dims[i];
  311. }
  312. if (typ & ATTY_NULL) {
  313. if (ds->databuff.nm) {
  314. siz = BM_get_map_size(ds->databuff.nm);
  315. BM_destroy(ds->databuff.nm);
  316. ds->databuff.nm = NULL;
  317. freed += siz;
  318. }
  319. }
  320. if (typ & ATTY_MASK) {
  321. if (ds->databuff.bm) {
  322. siz = BM_get_map_size(ds->databuff.bm);
  323. BM_destroy(ds->databuff.bm);
  324. ds->databuff.bm = NULL;
  325. freed += siz;
  326. }
  327. }
  328. if (typ & ATTY_CHAR) {
  329. if (ds->databuff.cb) {
  330. siz = nsiz * sizeof(char);
  331. free(ds->databuff.cb);
  332. ds->databuff.cb = NULL;
  333. freed += siz;
  334. }
  335. }
  336. if (typ & ATTY_SHORT) {
  337. if (ds->databuff.sb) {
  338. siz = nsiz * sizeof(short);
  339. free(ds->databuff.sb);
  340. ds->databuff.sb = NULL;
  341. freed += siz;
  342. }
  343. }
  344. if (typ & ATTY_INT) {
  345. if (ds->databuff.ib) {
  346. siz = nsiz * sizeof(int);
  347. free(ds->databuff.ib);
  348. ds->databuff.ib = NULL;
  349. freed += siz;
  350. }
  351. }
  352. if (typ & ATTY_FLOAT) {
  353. if (ds->databuff.fb) {
  354. siz = nsiz * sizeof(float);
  355. free(ds->databuff.fb);
  356. ds->databuff.fb = NULL;
  357. freed += siz;
  358. }
  359. }
  360. Tot_mem -= freed;
  361. ds->numbytes -= freed;
  362. if (freed) {
  363. G_debug(5, "free_data_buffs(): freed data from id no. %d",
  364. ds->data_id);
  365. G_debug(5,
  366. "free_data_buffs(): %.3f Kbytes freed, current total = %.3f",
  367. freed / 1000., Tot_mem / 1000.);
  368. }
  369. return (freed);
  370. }
  371. /*!
  372. \brief Allocates correct buffer according to type, keeps track of total mem
  373. \todo add ATTY_CONST
  374. \param id dataset id
  375. \param dims array of dimensions
  376. \param ndims number of dimensions
  377. \param type data type
  378. \return amount of allocated memory
  379. */
  380. size_t gsds_alloc_typbuff(int id, int *dims, int ndims, int type)
  381. {
  382. dataset *ds;
  383. int i;
  384. size_t siz = 1;
  385. if ((ds = get_dataset(id))) {
  386. /*
  387. free_data_buffs(ds);
  388. careful here - allowing > 1 type to coexist (for float -> color conv.)
  389. now also use this to allocate a null mask
  390. (then if not used, use gsds_free_data_buff(id, ATTY_NULL))
  391. */
  392. for (i = 0; i < ndims; i++) {
  393. ds->dims[i] = dims[i];
  394. siz *= dims[i];
  395. }
  396. switch (type) {
  397. case ATTY_NULL:
  398. if (ndims != 2) {
  399. /* higher dimension bitmaps not supported */
  400. return 0;
  401. }
  402. if (NULL == (ds->databuff.nm = BM_create(dims[1], dims[0]))) {
  403. return 0;
  404. }
  405. siz = BM_get_map_size(ds->databuff.nm);
  406. break;
  407. case ATTY_MASK:
  408. if (ndims != 2) {
  409. /* higher dimension bitmaps not supported */
  410. return (-1);
  411. }
  412. if (NULL == (ds->databuff.bm = BM_create(dims[1], dims[0]))) {
  413. return 0;
  414. }
  415. siz = BM_get_map_size(ds->databuff.bm);
  416. break;
  417. case ATTY_CHAR:
  418. siz *= sizeof(char);
  419. if (siz) {
  420. if (NULL ==
  421. (ds->databuff.cb = (unsigned char *)G_malloc(siz))) {
  422. return 0;
  423. }
  424. }
  425. else {
  426. return 0;
  427. }
  428. break;
  429. case ATTY_SHORT:
  430. siz *= sizeof(short);
  431. if (siz) {
  432. if (NULL == (ds->databuff.sb = (short *)G_malloc(siz))) {
  433. return 0;
  434. }
  435. }
  436. else {
  437. return 0;
  438. }
  439. break;
  440. case ATTY_INT:
  441. siz *= sizeof(int);
  442. if (siz) {
  443. if (NULL == (ds->databuff.ib = (int *)G_malloc(siz))) {
  444. return 0;
  445. }
  446. }
  447. else {
  448. return 0;
  449. }
  450. break;
  451. case ATTY_FLOAT:
  452. siz *= sizeof(float);
  453. if (siz) {
  454. if (NULL == (ds->databuff.fb = (float *)G_malloc(siz))) {
  455. return 0;
  456. }
  457. }
  458. else {
  459. return 0;
  460. }
  461. break;
  462. default:
  463. return 0;
  464. }
  465. ds->changed = 0; /* starting with clean slate */
  466. ds->need_reload = 1;
  467. ds->numbytes += siz;
  468. ds->ndims = ndims;
  469. Tot_mem += siz;
  470. G_debug(5,
  471. "gsds_alloc_typbuff(): %f Kbytes allocated, current total = %f",
  472. siz / 1000., Tot_mem / 1000.);
  473. return (siz);
  474. }
  475. return 0;
  476. }
  477. /*!
  478. \brief ADD
  479. \param id
  480. \return -1 on error
  481. \return
  482. */
  483. int gsds_get_changed(int id)
  484. {
  485. dataset *ds;
  486. if ((ds = get_dataset(id))) {
  487. return ((int)ds->changed);
  488. }
  489. return (-1);
  490. }
  491. /*!
  492. \brief ADD
  493. \param id
  494. \param reason
  495. \return -1 on error
  496. \return
  497. */
  498. int gsds_set_changed(int id, IFLAG reason)
  499. {
  500. dataset *ds;
  501. if ((ds = get_dataset(id))) {
  502. ds->changed = reason;
  503. }
  504. return (-1);
  505. }
  506. /*!
  507. \brief ADD
  508. \param id
  509. \return
  510. */
  511. int gsds_get_type(int id)
  512. {
  513. dataset *ds;
  514. ds = get_dataset(id);
  515. return (get_type(ds));
  516. }