port_init.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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 [] = {0x3f, 0xf5, 0x55, 0x32, 0x61, 0x7c, 0x1b, 0xda};
  62. /* flt_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */
  63. static const unsigned char flt_cmpr [] = {0x3f, 0xaa, 0xa9, 0x93};
  64. static const unsigned char lng_cmpr [] = {0x01, 0x02, 0x03, 0x04};
  65. static const unsigned char int_cmpr [] = {0x01, 0x02, 0x03, 0x04};
  66. static const unsigned char shrt_cmpr[] = {0x01, 0x02};
  67. /* Find native sizes */
  68. int nat_dbl = sizeof(double);
  69. int nat_flt = sizeof(float);
  70. int nat_lng = sizeof(long);
  71. int nat_int = sizeof(int);
  72. int nat_shrt = sizeof(short);
  73. int dbl_order;
  74. int flt_order;
  75. int lng_order;
  76. int int_order;
  77. int shrt_order;
  78. unsigned char dbl_cnvrt [sizeof(double)];
  79. unsigned char flt_cnvrt [sizeof(float )];
  80. unsigned char lng_cnvrt [sizeof(long )];
  81. unsigned char int_cnvrt [sizeof(int )];
  82. unsigned char shrt_cnvrt[sizeof(short )];
  83. /*
  84. * match search_value against each char in basis.
  85. * return offset or -1 if not found
  86. */
  87. static int find_offset(const unsigned char *basis, unsigned char search_value, int size)
  88. {
  89. int i;
  90. for (i = 0; i < size; i++)
  91. if (basis[i] == search_value)
  92. return (i);
  93. return (-1);
  94. }
  95. static int find_offsets(
  96. const void *pattern, unsigned char *cnvrt, const unsigned char *cmpr,
  97. int port_size, int nat_size, const char *typename)
  98. {
  99. int big, ltl;
  100. int i;
  101. for (i = 0; i < port_size; i++)
  102. {
  103. int off = find_offset(pattern, cmpr[i], nat_size);
  104. if (off < 0)
  105. G_fatal_error("could not find '%x' in %s", cmpr[i], typename);
  106. cnvrt[i] = off;
  107. }
  108. big = ltl = 1;
  109. for (i = 0; i < port_size; i++)
  110. {
  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 = find_offsets(&u_d, dbl_cnvrt, dbl_cmpr, PORT_DOUBLE, nat_dbl, "double");
  146. flt_order = find_offsets(&u_f, flt_cnvrt, flt_cmpr, PORT_FLOAT, nat_flt, "float" );
  147. lng_order = find_offsets(&u_l, lng_cnvrt, lng_cmpr, PORT_LONG, nat_lng, "long" );
  148. int_order = find_offsets(&u_i, int_cnvrt, int_cmpr, PORT_INT, nat_int, "int" );
  149. shrt_order = find_offsets(&u_s, shrt_cnvrt, shrt_cmpr, PORT_SHORT, nat_shrt, "short" );
  150. }