GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
portable.c
Go to the documentation of this file.
1 /*
2  ****************************************************************************
3  *
4  * MODULE: Vector library
5  *
6  * AUTHOR(S): Original author CERL, probably Dave Gerdes.
7  * Update to GRASS 5.7 Radim Blazek.
8  *
9  * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
10  *
11  * COPYRIGHT: (C) 2001 by the GRASS Development Team
12  *
13  * This program is free software under the GNU General Public
14  * License (>=v2). Read the file COPYING that comes with GRASS
15  * for details.
16  *
17  *****************************************************************************/
18 #include <string.h>
19 #include <grass/gis.h>
20 #include <grass/Vect.h>
21 
22 extern void port_init(void);
23 
24 extern int nat_dbl;
25 extern int nat_flt;
26 extern int nat_lng;
27 extern int nat_int;
28 extern int nat_shrt;
29 
30 extern int dbl_order;
31 extern int flt_order;
32 extern int lng_order;
33 extern int int_order;
34 extern int shrt_order;
35 
36 extern unsigned char dbl_cnvrt[sizeof(double)];
37 extern unsigned char flt_cnvrt[sizeof(float)];
38 extern unsigned char lng_cnvrt[sizeof(long)];
39 extern unsigned char int_cnvrt[sizeof(int)];
40 extern unsigned char shrt_cnvrt[sizeof(short)];
41 
42 struct Port_info *Cur_Head;
43 
44 static char *buffer = NULL;
45 static int buf_alloced = 0;
46 
47 static int buf_alloc(int needed)
48 {
49  char *p;
50  int cnt;
51 
52  if (needed <= buf_alloced)
53  return (0);
54  cnt = buf_alloced;
55  p = dig__alloc_space(needed, &cnt, 100, buffer, 1);
56  if (p == NULL)
57  return (dig_out_of_memory());
58  buffer = p;
59  buf_alloced = cnt;
60  return (0);
61 }
62 
63 /***************************** READ ************************************/
64 /* These are the routines to read from the Portable Vector Format.
65  These routines must handle any type size conversions between the
66  portable format and the native machine.
67 
68  Return: 0 error
69  1 OK
70 
71  */
72 
73 
74 /* read doubles from the PVF file */
75 int dig__fread_port_D(double *buf, int cnt, GVFILE * fp)
76 {
77  int i, j, ret;
78  unsigned char *c1, *c2;
79 
80  if (Cur_Head->dbl_quick) {
81  ret = dig_fread(buf, PORT_DOUBLE, cnt, fp);
82  if (ret != cnt)
83  return 0;
84  }
85  else {
86  /* read into buffer */
87  buf_alloc(cnt * PORT_DOUBLE);
88  ret = dig_fread(buffer, PORT_DOUBLE, cnt, fp);
89  if (ret != cnt)
90  return 0;
91  /* read from buffer in changed order */
92  c1 = (unsigned char *)buffer;
93  c2 = (unsigned char *)buf;
94  for (i = 0; i < cnt; i++) {
95  for (j = 0; j < PORT_DOUBLE; j++) {
96  c2[Cur_Head->dbl_cnvrt[j]] = c1[j];
97  }
98  c1 += PORT_DOUBLE;
99  c2 += sizeof(double);
100  }
101  }
102  return 1;
103 }
104 
105 /* read floats from the PVF file */
106 int dig__fread_port_F(float *buf, int cnt, GVFILE * fp)
107 {
108  int i, j, ret;
109  unsigned char *c1, *c2;
110 
111  if (Cur_Head->flt_quick) {
112  ret = dig_fread(buf, PORT_FLOAT, cnt, fp);
113  if (ret != cnt)
114  return 0;
115  }
116  else {
117  /* read into buffer */
118  buf_alloc(cnt * PORT_FLOAT);
119  ret = dig_fread(buffer, PORT_FLOAT, cnt, fp);
120  if (ret != cnt)
121  return 0;
122  /* read from buffer in changed order */
123  c1 = (unsigned char *)buffer;
124  c2 = (unsigned char *)buf;
125  for (i = 0; i < cnt; i++) {
126  for (j = 0; j < PORT_FLOAT; j++) {
127  c2[Cur_Head->flt_cnvrt[j]] = c1[j];
128  }
129  c1 += PORT_FLOAT;
130  c2 += sizeof(float);
131  }
132  }
133  return 1;
134 }
135 
136 /* read longs from the PVF file */
137 int dig__fread_port_L(long *buf, int cnt, GVFILE * fp)
138 {
139  int i, j, ret;
140  unsigned char *c1, *c2;
141 
142  if (Cur_Head->lng_quick) {
143  if (nat_lng == PORT_LONG) {
144  ret = dig_fread(buf, PORT_LONG, cnt, fp);
145  if (ret != cnt)
146  return 0;
147  }
148  else {
149  /* read into buffer */
150  buf_alloc(cnt * PORT_LONG);
151  ret = dig_fread(buffer, PORT_LONG, cnt, fp);
152  if (ret != cnt)
153  return 0;
154  /* set buffer to zero (positive numbers) */
155  memset(buf, 0, cnt * sizeof(long));
156  /* read from buffer in changed order */
157  c1 = (unsigned char *)buffer;
158  if (lng_order == ENDIAN_LITTLE)
159  c2 = (unsigned char *)buf;
160  else
161  c2 = (unsigned char *)buf + nat_lng - PORT_LONG;
162  for (i = 0; i < cnt; i++) {
163  /* set to FF if the value is negative */
164  if (lng_order == ENDIAN_LITTLE) {
165  if (c1[PORT_LONG - 1] & 0x80)
166  memset(c2, 0xff, sizeof(long));
167  }
168  else {
169  if (c1[0] & 0x80)
170  memset(c2, 0xff, sizeof(long));
171  }
172  memcpy(c2, c1, PORT_LONG);
173  c1 += PORT_LONG;
174  c2 += sizeof(long);
175  }
176  }
177  }
178  else {
179  /* read into buffer */
180  buf_alloc(cnt * PORT_LONG);
181  ret = dig_fread(buffer, PORT_LONG, cnt, fp);
182  if (ret != cnt)
183  return 0;
184  /* set buffer to zero (positive numbers) */
185  memset(buf, 0, cnt * sizeof(long));
186  /* read from buffer in changed order */
187  c1 = (unsigned char *)buffer;
188  c2 = (unsigned char *)buf;
189  for (i = 0; i < cnt; i++) {
190  /* set to FF if the value is negative */
191  if (Cur_Head->byte_order == ENDIAN_LITTLE) {
192  if (c1[PORT_LONG - 1] & 0x80)
193  memset(c2, 0xff, sizeof(long));
194  }
195  else {
196  if (c1[0] & 0x80)
197  memset(c2, 0xff, sizeof(long));
198  }
199  for (j = 0; j < PORT_LONG; j++)
200  c2[Cur_Head->lng_cnvrt[j]] = c1[j];
201  c1 += PORT_LONG;
202  c2 += sizeof(long);
203  }
204  }
205  return 1;
206 }
207 
208 /* read ints from the PVF file */
209 int dig__fread_port_I(int *buf, int cnt, GVFILE * fp)
210 {
211  int i, j, ret;
212  unsigned char *c1, *c2;
213 
214  if (Cur_Head->int_quick) {
215  if (nat_int == PORT_INT) {
216  ret = dig_fread(buf, PORT_INT, cnt, fp);
217  if (ret != cnt)
218  return 0;
219  }
220  else {
221  /* read into buffer */
222  buf_alloc(cnt * PORT_INT);
223  ret = dig_fread(buffer, PORT_INT, cnt, fp);
224  if (ret != cnt)
225  return 0;
226  /* set buffer to zero (positive numbers) */
227  memset(buf, 0, cnt * sizeof(int));
228  /* read from buffer in changed order */
229  c1 = (unsigned char *)buffer;
230  if (int_order == ENDIAN_LITTLE)
231  c2 = (unsigned char *)buf;
232  else
233  c2 = (unsigned char *)buf + nat_int - PORT_INT;
234  for (i = 0; i < cnt; i++) {
235  /* set to FF if the value is negative */
236  if (int_order == ENDIAN_LITTLE) {
237  if (c1[PORT_INT - 1] & 0x80)
238  memset(c2, 0xff, sizeof(int));
239  }
240  else {
241  if (c1[0] & 0x80)
242  memset(c2, 0xff, sizeof(int));
243  }
244  memcpy(c2, c1, PORT_INT);
245  c1 += PORT_INT;
246  c2 += sizeof(int);
247  }
248  }
249  }
250  else {
251  /* read into buffer */
252  buf_alloc(cnt * PORT_INT);
253  ret = dig_fread(buffer, PORT_INT, cnt, fp);
254  if (ret != cnt)
255  return 0;
256  /* set buffer to zero (positive numbers) */
257  memset(buf, 0, cnt * sizeof(int));
258  /* read from buffer in changed order */
259  c1 = (unsigned char *)buffer;
260  c2 = (unsigned char *)buf;
261  for (i = 0; i < cnt; i++) {
262  /* set to FF if the value is negative */
263  if (Cur_Head->byte_order == ENDIAN_LITTLE) {
264  if (c1[PORT_INT - 1] & 0x80)
265  memset(c2, 0xff, sizeof(int));
266  }
267  else {
268  if (c1[0] & 0x80)
269  memset(c2, 0xff, sizeof(int));
270  }
271  for (j = 0; j < PORT_INT; j++)
272  c2[Cur_Head->int_cnvrt[j]] = c1[j];
273  c1 += PORT_INT;
274  c2 += sizeof(int);
275  }
276  }
277  return 1;
278 }
279 
280 /* read shorts from the PVF file */
281 int dig__fread_port_S(short *buf, int cnt, GVFILE * fp)
282 {
283  int i, j, ret;
284  unsigned char *c1, *c2;
285 
286  if (Cur_Head->shrt_quick) {
287  if (nat_shrt == PORT_SHORT) {
288  ret = dig_fread(buf, PORT_SHORT, cnt, fp);
289  if (ret != cnt)
290  return 0;
291  }
292  else {
293  /* read into buffer */
294  buf_alloc(cnt * PORT_SHORT);
295  if (0 >= (ret = dig_fread(buffer, PORT_SHORT, cnt, fp)))
296  if (ret != cnt)
297  return 0;
298  /* set buffer to zero (positive numbers) */
299  memset(buf, 0, cnt * sizeof(short));
300  /* read from buffer in changed order */
301  c1 = (unsigned char *)buffer;
302  if (shrt_order == ENDIAN_LITTLE)
303  c2 = (unsigned char *)buf;
304  else
305  c2 = (unsigned char *)buf + nat_shrt - PORT_SHORT;
306  for (i = 0; i < cnt; i++) {
307  /* set to FF if the value is negative */
308  if (shrt_order == ENDIAN_LITTLE) {
309  if (c1[PORT_SHORT - 1] & 0x80)
310  memset(c2, 0xff, sizeof(short));
311  }
312  else {
313  if (c1[0] & 0x80)
314  memset(c2, 0xff, sizeof(short));
315  }
316  memcpy(c2, c1, PORT_SHORT);
317  c1 += PORT_SHORT;
318  c2 += sizeof(short);
319  }
320  }
321  }
322  else {
323  /* read into buffer */
324  buf_alloc(cnt * PORT_SHORT);
325  ret = dig_fread(buffer, PORT_SHORT, cnt, fp);
326  if (ret != cnt)
327  return 0;
328  /* set buffer to zero (positive numbers) */
329  memset(buf, 0, cnt * sizeof(short));
330  /* read from buffer in changed order */
331  c1 = (unsigned char *)buffer;
332  c2 = (unsigned char *)buf;
333  for (i = 0; i < cnt; i++) {
334  /* set to FF if the value is negative */
335  if (Cur_Head->byte_order == ENDIAN_LITTLE) {
336  if (c1[PORT_SHORT - 1] & 0x80)
337  memset(c2, 0xff, sizeof(short));
338  }
339  else {
340  if (c1[0] & 0x80)
341  memset(c2, 0xff, sizeof(short));
342  }
343  for (j = 0; j < PORT_SHORT; j++)
344  c2[Cur_Head->shrt_cnvrt[j]] = c1[j];
345  c1 += PORT_SHORT;
346  c2 += sizeof(short);
347  }
348  }
349  return 1;
350 }
351 
352 /* read chars from the PVF file */
353 int dig__fread_port_C(char *buf, int cnt, GVFILE * fp)
354 {
355  int ret;
356 
357  ret = dig_fread(buf, PORT_CHAR, cnt, fp);
358  if (ret != cnt)
359  return 0;
360  return 1;
361 }
362 
363 /* read plus_t from the PVF file */
364 /* plus_t is defined as int so we only retype pointer and use int function */
365 int dig__fread_port_P(plus_t * buf, int cnt, GVFILE * fp)
366 {
367  int *ibuf;
368 
369  ibuf = (int *)buf;
370 
371  return (dig__fread_port_I(ibuf, cnt, fp));
372 }
373 
374 /***************************** WRITE ************************************/
375 
376 int dig__fwrite_port_D(double *buf, /* DOUBLE */
377  int cnt, GVFILE * fp)
378 {
379  int i, j;
380  unsigned char *c1, *c2;
381 
382  if (Cur_Head->dbl_quick) {
383  if (dig_fwrite(buf, PORT_DOUBLE, cnt, fp) == cnt)
384  return 1;
385  }
386  else {
387  buf_alloc(cnt * PORT_DOUBLE);
388  c1 = (unsigned char *)buf;
389  c2 = (unsigned char *)buffer;
390  for (i = 0; i < cnt; i++) {
391  for (j = 0; j < PORT_DOUBLE; j++)
392  c2[j] = c1[Cur_Head->dbl_cnvrt[j]];
393  c1 += sizeof(double);
394  c2 += PORT_DOUBLE;
395  }
396  if (dig_fwrite(buffer, PORT_DOUBLE, cnt, fp) == cnt)
397  return 1;
398  }
399  return 0;
400 }
401 
402 int dig__fwrite_port_F(float *buf, /* FLOAT */
403  int cnt, GVFILE * fp)
404 {
405  int i, j;
406  unsigned char *c1, *c2;
407 
408  if (Cur_Head->flt_quick) {
409  if (dig_fwrite(buf, PORT_FLOAT, cnt, fp) == cnt)
410  return 1;
411  }
412  else {
413  buf_alloc(cnt * PORT_FLOAT);
414  c1 = (unsigned char *)buf;
415  c2 = (unsigned char *)buffer;
416  for (i = 0; i < cnt; i++) {
417  for (j = 0; j < PORT_FLOAT; j++)
418  c2[j] = c1[Cur_Head->flt_cnvrt[j]];
419  c1 += sizeof(float);
420  c2 += PORT_FLOAT;
421  }
422  if (dig_fwrite(buffer, PORT_FLOAT, cnt, fp) == cnt)
423  return 1;
424  }
425  return 0;
426 }
427 
428 int dig__fwrite_port_L(long *buf, /* LONG */
429  int cnt, GVFILE * fp)
430 {
431  int i, j;
432  unsigned char *c1, *c2;
433 
434  if (Cur_Head->lng_quick) {
435  if (nat_lng == PORT_LONG) {
436  if (dig_fwrite(buf, PORT_LONG, cnt, fp) == cnt)
437  return 1;
438  }
439  else {
440  buf_alloc(cnt * PORT_LONG);
441  if (lng_order == ENDIAN_LITTLE)
442  c1 = (unsigned char *)buf;
443  else
444  c1 = (unsigned char *)buf + nat_lng - PORT_LONG;
445  c2 = (unsigned char *)buffer;
446  for (i = 0; i < cnt; i++) {
447  memcpy(c2, c1, PORT_LONG);
448  c1 += PORT_LONG;
449  c2 += sizeof(long);
450  }
451  if (dig_fwrite(buffer, PORT_LONG, cnt, fp) == cnt)
452  return 1;
453  }
454  }
455  else {
456  buf_alloc(cnt * PORT_LONG);
457  c1 = (unsigned char *)buf;
458  c2 = (unsigned char *)buffer;
459  for (i = 0; i < cnt; i++) {
460  for (j = 0; j < PORT_LONG; j++)
461  c2[j] = c1[Cur_Head->lng_cnvrt[j]];
462  c1 += sizeof(long);
463  c2 += PORT_LONG;
464  }
465  if (dig_fwrite(buffer, PORT_LONG, cnt, fp) == cnt)
466  return 1;
467  }
468  return 0;
469 }
470 
471 int dig__fwrite_port_I(int *buf, /* INT */
472  int cnt, GVFILE * fp)
473 {
474  int i, j;
475  unsigned char *c1, *c2;
476 
477  if (Cur_Head->int_quick) {
478  if (nat_int == PORT_INT) {
479  if (dig_fwrite(buf, PORT_INT, cnt, fp) == cnt)
480  return 1;
481  }
482  else {
483  buf_alloc(cnt * PORT_INT);
484  if (int_order == ENDIAN_LITTLE)
485  c1 = (unsigned char *)buf;
486  else
487  c1 = (unsigned char *)buf + nat_int - PORT_INT;
488  c2 = (unsigned char *)buffer;
489  for (i = 0; i < cnt; i++) {
490  memcpy(c2, c1, PORT_INT);
491  c1 += PORT_INT;
492  c2 += sizeof(int);
493  }
494  if (dig_fwrite(buffer, PORT_INT, cnt, fp) == cnt)
495  return 1;
496  }
497  }
498  else {
499  buf_alloc(cnt * PORT_INT);
500  c1 = (unsigned char *)buf;
501  c2 = (unsigned char *)buffer;
502  for (i = 0; i < cnt; i++) {
503  for (j = 0; j < PORT_INT; j++)
504  c2[j] = c1[Cur_Head->int_cnvrt[j]];
505  c1 += sizeof(int);
506  c2 += PORT_INT;
507  }
508  if (dig_fwrite(buffer, PORT_INT, cnt, fp) == cnt)
509  return 1;
510  }
511  return 0;
512 }
513 
514 int dig__fwrite_port_S(short *buf, /* SHORT */
515  int cnt, GVFILE * fp)
516 {
517  int i, j;
518  unsigned char *c1, *c2;
519 
520  if (Cur_Head->shrt_quick) {
521  if (nat_shrt == PORT_SHORT) {
522  if (dig_fwrite(buf, PORT_SHORT, cnt, fp) == cnt)
523  return 1;
524  }
525  else {
526  buf_alloc(cnt * PORT_SHORT);
527  if (shrt_order == ENDIAN_LITTLE)
528  c1 = (unsigned char *)buf;
529  else
530  c1 = (unsigned char *)buf + nat_shrt - PORT_SHORT;
531  c2 = (unsigned char *)buffer;
532  for (i = 0; i < cnt; i++) {
533  memcpy(c2, c1, PORT_SHORT);
534  c1 += PORT_SHORT;
535  c2 += sizeof(short);
536  }
537  if (dig_fwrite(buffer, PORT_SHORT, cnt, fp) == cnt)
538  return 1;
539  }
540  }
541  else {
542  buf_alloc(cnt * PORT_SHORT);
543  c1 = (unsigned char *)buf;
544  c2 = (unsigned char *)buffer;
545  for (i = 0; i < cnt; i++) {
546  for (j = 0; j < PORT_SHORT; j++)
547  c2[j] = c1[Cur_Head->shrt_cnvrt[j]];
548  c1 += sizeof(short);
549  c2 += PORT_SHORT;
550  }
551  if (dig_fwrite(buffer, PORT_SHORT, cnt, fp) == cnt)
552  return 1;
553  }
554  return 0;
555 }
556 
557 /* plus_t is defined as int so we only retype pointer and use int function */
558 int dig__fwrite_port_P(plus_t * buf, /* PLUS_T->INT */
559  int cnt, GVFILE * fp)
560 {
561  return (dig__fwrite_port_I((int *)buf, cnt, fp));
562 }
563 
564 int dig__fwrite_port_C(char *buf, /* CHAR */
565  int cnt, GVFILE * fp)
566 {
567  if (dig_fwrite(buf, PORT_CHAR, cnt, fp) == cnt)
568  return 1;
569 
570  return 0;
571 }
572 
573 /* set portable info structure to byte order of file */
574 void dig_init_portable(struct Port_info *port, int byte_order)
575 {
576  int i;
577 
578  port_init();
579 
580  port->byte_order = byte_order;
581 
582  if (port->byte_order == dbl_order)
583  port->dbl_quick = TRUE;
584  else
585  port->dbl_quick = FALSE;
586 
587  for (i = 0; i < PORT_DOUBLE; i++) {
588  if (port->byte_order == ENDIAN_BIG)
589  port->dbl_cnvrt[i] = dbl_cnvrt[i];
590  else
591  port->dbl_cnvrt[i] = dbl_cnvrt[PORT_DOUBLE - i - 1];
592  }
593 
594  if (port->byte_order == flt_order)
595  port->flt_quick = TRUE;
596  else
597  port->flt_quick = FALSE;
598 
599  for (i = 0; i < PORT_FLOAT; i++) {
600  if (port->byte_order == ENDIAN_BIG)
601  port->flt_cnvrt[i] = flt_cnvrt[i];
602  else
603  port->flt_cnvrt[i] = flt_cnvrt[PORT_FLOAT - i - 1];
604  }
605 
606  if (port->byte_order == lng_order)
607  port->lng_quick = TRUE;
608  else
609  port->lng_quick = FALSE;
610 
611  for (i = 0; i < PORT_LONG; i++) {
612  if (port->byte_order == ENDIAN_BIG)
613  port->lng_cnvrt[i] = lng_cnvrt[i];
614  else
615  port->lng_cnvrt[i] = lng_cnvrt[PORT_LONG - i - 1];
616  }
617 
618  if (port->byte_order == int_order)
619  port->int_quick = TRUE;
620  else
621  port->int_quick = FALSE;
622 
623  for (i = 0; i < PORT_INT; i++) {
624  if (port->byte_order == ENDIAN_BIG)
625  port->int_cnvrt[i] = int_cnvrt[i];
626  else
627  port->int_cnvrt[i] = int_cnvrt[PORT_INT - i - 1];
628  }
629 
630  if (port->byte_order == shrt_order)
631  port->shrt_quick = TRUE;
632  else
633  port->shrt_quick = FALSE;
634 
635  for (i = 0; i < PORT_SHORT; i++) {
636  if (port->byte_order == ENDIAN_BIG)
637  port->shrt_cnvrt[i] = shrt_cnvrt[i];
638  else
639  port->shrt_cnvrt[i] = shrt_cnvrt[PORT_SHORT - i - 1];
640  }
641 
642  return;
643 }
644 
645 /* set current portable info */
646 int dig_set_cur_port(struct Port_info *port)
647 {
648  Cur_Head = port;
649  return 0;
650 }
651 
653 {
654  if (dbl_order == ENDIAN_LITTLE)
655  return (ENDIAN_LITTLE);
656  else
657  return (ENDIAN_BIG);
658 }