cindex_rw.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /****************************************************************************
  2. *
  3. * MODULE: Vector library
  4. *
  5. * AUTHOR(S): Radim Blazek.
  6. *
  7. * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
  8. *
  9. * COPYRIGHT: (C) 2001 by the GRASS Development Team
  10. *
  11. * This program is free software under the GNU General Public
  12. * License (>=v2). Read the file COPYING that comes with GRASS
  13. * for details.
  14. *
  15. *****************************************************************************/
  16. #include <stdlib.h>
  17. #include <sys/types.h>
  18. #include <string.h>
  19. #include <grass/vector.h>
  20. #include <grass/glocale.h>
  21. #include <grass/version.h>
  22. int dig_write_cidx_head(struct gvfile * fp, struct Plus_head *plus)
  23. {
  24. int i;
  25. unsigned char buf[5];
  26. long length = 9;
  27. G_debug(3, "dig_write_cidx_head()");
  28. dig_rewind(fp);
  29. dig_set_cur_port(&(plus->cidx_port));
  30. /* Head of header */
  31. /* bytes 1 - 5 */
  32. buf[0] = GV_CIDX_VER_MAJOR;
  33. buf[1] = GV_CIDX_VER_MINOR;
  34. buf[2] = GV_CIDX_EARLIEST_MAJOR;
  35. buf[3] = GV_CIDX_EARLIEST_MINOR;
  36. buf[4] = plus->cidx_port.byte_order;
  37. if (0 >= dig__fwrite_port_C((const char *)buf, 5, fp))
  38. return (-1);
  39. /* get required offset size */
  40. if (plus->off_t_size == 0) {
  41. /* should not happen, topo is written first */
  42. if (plus->coor_size > (off_t)PORT_LONG_MAX)
  43. plus->off_t_size = 8;
  44. else
  45. plus->off_t_size = 4;
  46. }
  47. /* bytes 6 - 9 : header size */
  48. if (0 >= dig__fwrite_port_L(&length, 1, fp))
  49. return (0);
  50. /* Body of header - info about all fields */
  51. /* Number of fields */
  52. if (0 >= dig__fwrite_port_I(&(plus->n_cidx), 1, fp))
  53. return (-1);
  54. for (i = 0; i < plus->n_cidx; i++) {
  55. int t;
  56. struct Cat_index *ci;
  57. ci = &(plus->cidx[i]);
  58. G_debug(3, "cidx %d head offset: %"PRI_OFF_T, i, dig_ftell(fp));
  59. /* Field number */
  60. if (0 >= dig__fwrite_port_I(&(ci->field), 1, fp))
  61. return (-1);
  62. /* Number of categories */
  63. if (0 >= dig__fwrite_port_I(&(ci->n_cats), 1, fp))
  64. return (-1);
  65. /* Number of unique categories */
  66. if (0 >= dig__fwrite_port_I(&(ci->n_ucats), 1, fp))
  67. return (-1);
  68. /* Number of types */
  69. if (0 >= dig__fwrite_port_I(&(ci->n_types), 1, fp))
  70. return (-1);
  71. /* Types */
  72. for (t = 0; t < ci->n_types; t++) {
  73. int wtype;
  74. /* type */
  75. wtype = dig_type_to_store(ci->type[t][0]);
  76. if (0 >= dig__fwrite_port_I(&wtype, 1, fp))
  77. return (-1);
  78. /* number of items */
  79. if (0 >= dig__fwrite_port_I(&(ci->type[t][1]), 1, fp))
  80. return (-1);
  81. }
  82. /* Offset */
  83. if (0 >= dig__fwrite_port_O(&(ci->offset), 1, fp, plus->off_t_size))
  84. return (0);
  85. G_debug(3, "cidx %d offset: %"PRI_OFF_T, i, ci->offset);
  86. }
  87. G_debug(3, "cidx body offset %"PRI_OFF_T, dig_ftell(fp));
  88. return (0);
  89. }
  90. /*!
  91. \brief Read header of cidx file
  92. \param fp pointer to gvfile structure
  93. \param plus pointer to Plus_head strcuture
  94. \return 0 OK
  95. \return -1 error
  96. */
  97. int dig_read_cidx_head(struct gvfile * fp, struct Plus_head *plus)
  98. {
  99. unsigned char buf[5];
  100. int i, byte_order;
  101. dig_rewind(fp);
  102. /* bytes 1 - 5 */
  103. if (0 >= dig__fread_port_C((char *)buf, 5, fp))
  104. return (-1);
  105. plus->version.cidx.major = buf[0];
  106. plus->version.cidx.minor = buf[1];
  107. plus->version.cidx.back_major = buf[2];
  108. plus->version.cidx.back_minor = buf[3];
  109. byte_order = buf[4];
  110. G_debug(3,
  111. "Cidx header: file version %d.%d , supported from GRASS version %d.%d",
  112. plus->version.cidx.major, plus->version.cidx.minor,
  113. plus->version.cidx.back_major, plus->version.cidx.back_minor);
  114. G_debug(3, " byte order %d", byte_order);
  115. /* check version numbers */
  116. if (plus->version.cidx.major > GV_CIDX_VER_MAJOR ||
  117. plus->version.cidx.minor > GV_CIDX_VER_MINOR) {
  118. /* The file was created by GRASS library with higher version than this one */
  119. if (plus->version.cidx.back_major > GV_CIDX_VER_MAJOR ||
  120. plus->version.cidx.back_minor > GV_CIDX_VER_MINOR) {
  121. /* This version of GRASS lib is lower than the oldest which can read this format */
  122. G_debug(1, "Category index format version %d.%d",
  123. plus->version.cidx.major, plus->version.cidx.minor);
  124. G_fatal_error
  125. (_("This version of GRASS (%d.%d) is too old to read this category index format."
  126. " Try to rebuild topology or upgrade GRASS to at least version %d."),
  127. GRASS_VERSION_MAJOR, GRASS_VERSION_MINOR, GRASS_VERSION_MAJOR + 1);
  128. return (-1);
  129. }
  130. G_warning
  131. ("Your GRASS version does not fully support category index format %d.%d of the vector."
  132. " Consider to rebuild topology or upgrade GRASS.",
  133. plus->version.cidx.major, plus->version.cidx.minor);
  134. }
  135. dig_init_portable(&(plus->cidx_port), byte_order);
  136. dig_set_cur_port(&(plus->cidx_port));
  137. /* bytes 6 - 9 : header size */
  138. if (0 >= dig__fread_port_L(&(plus->cidx_head_size), 1, fp))
  139. return (-1);
  140. G_debug(3, " header size %ld", plus->cidx_head_size);
  141. /* get required offset size */
  142. if (plus->off_t_size == 0) {
  143. /* should not happen, topo is opened first */
  144. if (plus->coor_size > (off_t)PORT_LONG_MAX)
  145. plus->off_t_size = 8;
  146. else
  147. plus->off_t_size = 4;
  148. }
  149. /* Body of header - info about all fields */
  150. /* Number of fields */
  151. if (0 >= dig__fread_port_I(&(plus->n_cidx), 1, fp))
  152. return (-1);
  153. /* alloc space */
  154. if (plus->a_cidx < plus->n_cidx) {
  155. plus->a_cidx = plus->n_cidx;
  156. plus->cidx =
  157. (struct Cat_index *)G_realloc(plus->cidx, plus->a_cidx * sizeof(struct Cat_index));
  158. }
  159. for (i = 0; i < plus->n_cidx; i++) {
  160. int t;
  161. struct Cat_index *ci;
  162. ci = &(plus->cidx[i]);
  163. ci->cat = NULL;
  164. ci->a_cats = 0;
  165. /* Field number */
  166. if (0 >= dig__fread_port_I(&(ci->field), 1, fp))
  167. return (-1);
  168. /* Number of categories */
  169. if (0 >= dig__fread_port_I(&(ci->n_cats), 1, fp))
  170. return (-1);
  171. /* Number of unique categories */
  172. if (0 >= dig__fread_port_I(&(ci->n_ucats), 1, fp))
  173. return (-1);
  174. /* Number of types */
  175. if (0 >= dig__fread_port_I(&(ci->n_types), 1, fp))
  176. return (-1);
  177. /* Types */
  178. for (t = 0; t < ci->n_types; t++) {
  179. int rtype;
  180. /* type */
  181. if (0 >= dig__fread_port_I(&rtype, 1, fp))
  182. return (-1);
  183. ci->type[t][0] = dig_type_from_store(rtype);
  184. /* number of items */
  185. if (0 >= dig__fread_port_I(&(ci->type[t][1]), 1, fp))
  186. return (-1);
  187. }
  188. /* Offset */
  189. if (0 >= dig__fread_port_O(&(ci->offset), 1, fp, plus->off_t_size))
  190. return (0);
  191. }
  192. if (dig_fseek(fp, plus->cidx_head_size, SEEK_SET) == -1)
  193. return (-1);
  194. return (0);
  195. }
  196. /* Write spatial index */
  197. int dig_write_cidx(struct gvfile * fp, struct Plus_head *plus)
  198. {
  199. int i;
  200. dig_set_cur_port(&(plus->cidx_port));
  201. dig_rewind(fp);
  202. dig_write_cidx_head(fp, plus);
  203. /* Write category-type-id for each field */
  204. for (i = 0; i < plus->n_cidx; i++) {
  205. int j;
  206. struct Cat_index *ci;
  207. ci = &(plus->cidx[i]);
  208. ci->offset = dig_ftell(fp);
  209. /* convert type */
  210. for (j = 0; j < ci->n_cats; j++)
  211. ci->cat[j][1] = dig_type_to_store(ci->cat[j][1]);
  212. if (0 >= dig__fwrite_port_I((int *)ci->cat, 3 * ci->n_cats, fp))
  213. return (-1);
  214. /* Return back */
  215. for (j = 0; j < ci->n_cats; j++)
  216. ci->cat[j][1] = dig_type_from_store(ci->cat[j][1]);
  217. }
  218. dig_write_cidx_head(fp, plus); /* rewrite with offsets */
  219. return 0;
  220. }
  221. /*!
  222. \brief Read spatial index file
  223. \param fp pointer to gvfile structure
  224. \param[in,out] plus pointer to Plus_head structure
  225. \param head_only non-zero to read only head
  226. \return 0 OK
  227. \return 1 error
  228. */
  229. int dig_read_cidx(struct gvfile * fp, struct Plus_head *plus, int head_only)
  230. {
  231. int i;
  232. G_debug(3, "dig_read_cidx()");
  233. dig_cidx_free(plus);
  234. dig_cidx_init(plus);
  235. dig_rewind(fp);
  236. if (dig_read_cidx_head(fp, plus) == -1) {
  237. G_debug(3, "Cannot read cidx head");
  238. return 1;
  239. }
  240. if (head_only) {
  241. plus->cidx_up_to_date = 1; /* OK ? */
  242. return 0;
  243. }
  244. dig_set_cur_port(&(plus->cidx_port));
  245. /* Read category-type-id for each field */
  246. for (i = 0; i < plus->n_cidx; i++) {
  247. int j;
  248. struct Cat_index *ci;
  249. ci = &(plus->cidx[i]);
  250. ci->a_cats = ci->n_cats;
  251. ci->cat = G_malloc(ci->a_cats * 3 * sizeof(int));
  252. if (dig_fseek(fp, ci->offset, 0) == -1)
  253. return 1;
  254. if (0 >= dig__fread_port_I((int *)ci->cat, 3 * ci->n_cats, fp))
  255. return 1;
  256. /* convert type */
  257. for (j = 0; j < ci->n_cats; j++)
  258. ci->cat[j][1] = dig_type_from_store(ci->cat[j][1]);
  259. }
  260. plus->cidx_up_to_date = 1;
  261. return 0;
  262. }