GRASS Programmer's Manual 6.4.1(2011)
|
00001 /* 00002 **************************************************************************** 00003 * 00004 * MODULE: Vector library 00005 * 00006 * AUTHOR(S): Original author CERL, probably Dave Gerdes. 00007 * Update to GRASS 5.7 Radim Blazek. 00008 * 00009 * PURPOSE: Lower level functions for reading/writing/manipulating vectors. 00010 * 00011 * COPYRIGHT: (C) 2001 by the GRASS Development Team 00012 * 00013 * This program is free software under the GNU General Public 00014 * License (>=v2). Read the file COPYING that comes with GRASS 00015 * for details. 00016 * 00017 *****************************************************************************/ 00018 #include <stdio.h> 00019 #include <grass/Vect.h> 00020 00021 /* 00022 ** Written by Dave Gerdes 9/1988 00023 ** US Army Construction Engineering Research Lab 00024 */ 00025 00026 00027 /* 00028 ** 00029 ** This code is a quick hack to allow the writing of portable 00030 ** binary data files. 00031 ** The approach is to take known values and compare them against 00032 ** the current machine's internal representation. A cross reference 00033 ** table is then built, and then all file reads and writes must go through 00034 ** through these routines to correct the numbers if need be. 00035 ** 00036 ** As long as the byte switching is symetrical, the conversion routines 00037 ** will work both directions. 00038 00039 ** The integer test patterns are quite simple, and their choice was 00040 ** arbitrary, but the float and double valued were more critical. 00041 00042 ** I did not have a specification for IEEE to go by, so it is possible 00043 ** that I have missed something. My criteria were: 00044 ** 00045 ** First, true IEEE numbers had to be chosen to avoid getting an FPE. 00046 ** Second, every byte in the test pattern had to be unique. And 00047 ** finally, the number had to not be sensitive to rounding by the 00048 ** specific hardware implementation. 00049 ** 00050 ** By experimentation it was found that the number 1.3333 met 00051 ** all these criteria for both floats and doubles 00052 00053 ** See the discourse at the end of this file for more information 00054 ** 00055 ** 00056 */ 00057 00058 #define TEST_PATTERN 1.3333 00059 #define LONG_TEST 0x01020304 00060 #define INT_TEST 0x01020304 00061 #define SHORT_TEST 0x0102 00062 00063 static double u_d = TEST_PATTERN; 00064 static float u_f = TEST_PATTERN; 00065 static long u_l = LONG_TEST; 00066 static int u_i = INT_TEST; 00067 static short u_s = SHORT_TEST; 00068 00069 /* dbl_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */ 00070 static const unsigned char dbl_cmpr[] = 00071 { 0x3f, 0xf5, 0x55, 0x32, 0x61, 0x7c, 0x1b, 0xda }; 00072 /* flt_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */ 00073 static const unsigned char flt_cmpr[] = { 0x3f, 0xaa, 0xa9, 0x93 }; 00074 static const unsigned char lng_cmpr[] = { 0x01, 0x02, 0x03, 0x04 }; 00075 static const unsigned char int_cmpr[] = { 0x01, 0x02, 0x03, 0x04 }; 00076 static const unsigned char shrt_cmpr[] = { 0x01, 0x02 }; 00077 00078 /* Find native sizes */ 00079 int nat_dbl = sizeof(double); 00080 int nat_flt = sizeof(float); 00081 int nat_lng = sizeof(long); 00082 int nat_int = sizeof(int); 00083 int nat_shrt = sizeof(short); 00084 00085 int dbl_order; 00086 int flt_order; 00087 int lng_order; 00088 int int_order; 00089 int shrt_order; 00090 00091 unsigned char dbl_cnvrt[sizeof(double)]; 00092 unsigned char flt_cnvrt[sizeof(float)]; 00093 unsigned char lng_cnvrt[sizeof(long)]; 00094 unsigned char int_cnvrt[sizeof(int)]; 00095 unsigned char shrt_cnvrt[sizeof(short)]; 00096 00097 /* 00098 * match search_value against each char in basis. 00099 * return offset or -1 if not found 00100 */ 00101 00102 static int find_offset(const unsigned char *basis, unsigned char search_value, 00103 int size) 00104 { 00105 int i; 00106 00107 for (i = 0; i < size; i++) 00108 if (basis[i] == search_value) 00109 return (i); 00110 00111 return (-1); 00112 } 00113 00114 static int find_offsets(const void *pattern, unsigned char *cnvrt, 00115 const unsigned char *cmpr, int port_size, 00116 int nat_size, const char *typename) 00117 { 00118 int big, ltl; 00119 int i; 00120 00121 for (i = 0; i < port_size; i++) { 00122 int off = find_offset(pattern, cmpr[i], nat_size); 00123 00124 if (off < 0) 00125 G_fatal_error("could not find '%x' in %s", cmpr[i], typename); 00126 00127 cnvrt[i] = off; 00128 } 00129 00130 big = ltl = 1; 00131 00132 for (i = 0; i < port_size; i++) { 00133 if (cnvrt[i] != (nat_size - port_size + i)) 00134 big = 0; /* isn't big endian */ 00135 if (cnvrt[i] != (port_size - 1 - i)) 00136 ltl = 0; /* isn't little endian */ 00137 } 00138 00139 if (big) 00140 return ENDIAN_BIG; 00141 00142 if (ltl) 00143 return ENDIAN_LITTLE; 00144 00145 return ENDIAN_OTHER; 00146 } 00147 00148 void port_init(void) 00149 { 00150 static int done; 00151 00152 if (done) 00153 return; 00154 00155 done = 1; 00156 00157 /* Following code checks only if all assumptions are fullfilled */ 00158 /* Check sizes */ 00159 if (nat_dbl != PORT_DOUBLE) 00160 G_fatal_error("sizeof(double) != %d", PORT_DOUBLE); 00161 if (nat_flt != PORT_FLOAT) 00162 G_fatal_error("sizeof(float) != %d", PORT_DOUBLE); 00163 if (nat_lng < PORT_LONG) 00164 G_fatal_error("sizeof(long) < %d", PORT_LONG); 00165 if (nat_int < PORT_INT) 00166 G_fatal_error("sizeof(int) < %d", PORT_INT); 00167 if (nat_shrt < PORT_SHORT) 00168 G_fatal_error("sizeof(short) < %d", PORT_SHORT); 00169 00170 /* Find for each byte in big endian test pattern (*_cmpr) 00171 * offset of corresponding byte in machine native order. 00172 * Look if native byte order is little or big or some other (pdp) 00173 * endian. 00174 */ 00175 00176 dbl_order = 00177 find_offsets(&u_d, dbl_cnvrt, dbl_cmpr, PORT_DOUBLE, nat_dbl, 00178 "double"); 00179 flt_order = 00180 find_offsets(&u_f, flt_cnvrt, flt_cmpr, PORT_FLOAT, nat_flt, "float"); 00181 lng_order = 00182 find_offsets(&u_l, lng_cnvrt, lng_cmpr, PORT_LONG, nat_lng, "long"); 00183 int_order = 00184 find_offsets(&u_i, int_cnvrt, int_cmpr, PORT_INT, nat_int, "int"); 00185 shrt_order = 00186 find_offsets(&u_s, shrt_cnvrt, shrt_cmpr, PORT_SHORT, nat_shrt, 00187 "short"); 00188 }