port_init.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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 <stdio.h>
  19. #include <grass/Vect.h>
  20. /*
  21. ** Written by Dave Gerdes 9/1988
  22. ** US Army Construction Engineering Research Lab
  23. */
  24. /*
  25. **
  26. ** This code is a quick hack to allow the writing of portable
  27. ** binary data files.
  28. ** The approach is to take known values and compare them against
  29. ** the current machine's internal representation. A cross reference
  30. ** table is then built, and then all file reads and writes must go through
  31. ** through these routines to correct the numbers if need be.
  32. **
  33. ** As long as the byte switching is symetrical, the conversion routines
  34. ** will work both directions.
  35. ** The integer test patterns are quite simple, and their choice was
  36. ** arbitrary, but the float and double valued were more critical.
  37. ** I did not have a specification for IEEE to go by, so it is possible
  38. ** that I have missed something. My criteria were:
  39. **
  40. ** First, true IEEE numbers had to be chosen to avoid getting an FPE.
  41. ** Second, every byte in the test pattern had to be unique. And
  42. ** finally, the number had to not be sensitive to rounding by the
  43. ** specific hardware implementation.
  44. **
  45. ** By experimentation it was found that the number 1.3333 met
  46. ** all these criteria for both floats and doubles
  47. ** See the discourse at the end of this file for more information
  48. **
  49. **
  50. */
  51. #define TEST_PATTERN 1.3333
  52. #define LONG_TEST 0x01020304
  53. #define INT_TEST 0x01020304
  54. #define SHORT_TEST 0x0102
  55. static double u_d = TEST_PATTERN;
  56. static float u_f = TEST_PATTERN;
  57. static long u_l = LONG_TEST;
  58. static int u_i = INT_TEST;
  59. static short u_s = SHORT_TEST;
  60. /* dbl_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */
  61. static const unsigned char dbl_cmpr[] =
  62. { 0x3f, 0xf5, 0x55, 0x32, 0x61, 0x7c, 0x1b, 0xda };
  63. /* flt_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */
  64. static const unsigned char flt_cmpr[] = { 0x3f, 0xaa, 0xa9, 0x93 };
  65. static const unsigned char lng_cmpr[] = { 0x01, 0x02, 0x03, 0x04 };
  66. static const unsigned char int_cmpr[] = { 0x01, 0x02, 0x03, 0x04 };
  67. static const unsigned char shrt_cmpr[] = { 0x01, 0x02 };
  68. /* Find native sizes */
  69. int nat_dbl = sizeof(double);
  70. int nat_flt = sizeof(float);
  71. int nat_lng = sizeof(long);
  72. int nat_int = sizeof(int);
  73. int nat_shrt = sizeof(short);
  74. int dbl_order;
  75. int flt_order;
  76. int lng_order;
  77. int int_order;
  78. int shrt_order;
  79. unsigned char dbl_cnvrt[sizeof(double)];
  80. unsigned char flt_cnvrt[sizeof(float)];
  81. unsigned char lng_cnvrt[sizeof(long)];
  82. unsigned char int_cnvrt[sizeof(int)];
  83. unsigned char shrt_cnvrt[sizeof(short)];
  84. /*
  85. * match search_value against each char in basis.
  86. * return offset or -1 if not found
  87. */
  88. static int find_offset(const unsigned char *basis, unsigned char search_value,
  89. int size)
  90. {
  91. int i;
  92. for (i = 0; i < size; i++)
  93. if (basis[i] == search_value)
  94. return (i);
  95. return (-1);
  96. }
  97. static int find_offsets(const void *pattern, unsigned char *cnvrt,
  98. const unsigned char *cmpr, int port_size,
  99. int nat_size, const char *typename)
  100. {
  101. int big, ltl;
  102. int i;
  103. for (i = 0; i < port_size; i++) {
  104. int off = find_offset(pattern, cmpr[i], nat_size);
  105. if (off < 0)
  106. G_fatal_error("could not find '%x' in %s", cmpr[i], typename);
  107. cnvrt[i] = off;
  108. }
  109. big = ltl = 1;
  110. for (i = 0; i < port_size; i++) {
  111. if (cnvrt[i] != (nat_size - port_size + i))
  112. big = 0; /* isn't big endian */
  113. if (cnvrt[i] != (port_size - 1 - i))
  114. ltl = 0; /* isn't little endian */
  115. }
  116. if (big)
  117. return ENDIAN_BIG;
  118. if (ltl)
  119. return ENDIAN_LITTLE;
  120. return ENDIAN_OTHER;
  121. }
  122. void port_init(void)
  123. {
  124. static int done;
  125. if (done)
  126. return;
  127. done = 1;
  128. /* Following code checks only if all assumptions are fullfilled */
  129. /* Check sizes */
  130. if (nat_dbl != PORT_DOUBLE)
  131. G_fatal_error("sizeof(double) != %d", PORT_DOUBLE);
  132. if (nat_flt != PORT_FLOAT)
  133. G_fatal_error("sizeof(float) != %d", PORT_DOUBLE);
  134. if (nat_lng < PORT_LONG)
  135. G_fatal_error("sizeof(long) < %d", PORT_LONG);
  136. if (nat_int < PORT_INT)
  137. G_fatal_error("sizeof(int) < %d", PORT_INT);
  138. if (nat_shrt < PORT_SHORT)
  139. G_fatal_error("sizeof(short) < %d", PORT_SHORT);
  140. /* Find for each byte in big endian test pattern (*_cmpr)
  141. * offset of corresponding byte in machine native order.
  142. * Look if native byte order is little or big or some other (pdp)
  143. * endian.
  144. */
  145. dbl_order =
  146. find_offsets(&u_d, dbl_cnvrt, dbl_cmpr, PORT_DOUBLE, nat_dbl,
  147. "double");
  148. flt_order =
  149. find_offsets(&u_f, flt_cnvrt, flt_cmpr, PORT_FLOAT, nat_flt, "float");
  150. lng_order =
  151. find_offsets(&u_l, lng_cnvrt, lng_cmpr, PORT_LONG, nat_lng, "long");
  152. int_order =
  153. find_offsets(&u_i, int_cnvrt, int_cmpr, PORT_INT, nat_int, "int");
  154. shrt_order =
  155. find_offsets(&u_s, shrt_cnvrt, shrt_cmpr, PORT_SHORT, nat_shrt,
  156. "short");
  157. }