/* **************************************************************************** * * MODULE: Vector library * * AUTHOR(S): Original author CERL, probably Dave Gerdes. * Update to GRASS 5.7 Radim Blazek. * * PURPOSE: Lower level functions for reading/writing/manipulating vectors. * * COPYRIGHT: (C) 2001 by the GRASS Development Team * * This program is free software under the GNU General Public * License (>=v2). Read the file COPYING that comes with GRASS * for details. * *****************************************************************************/ #include #include /* ** Written by Dave Gerdes 9/1988 ** US Army Construction Engineering Research Lab */ /* ** ** This code is a quick hack to allow the writing of portable ** binary data files. ** The approach is to take known values and compare them against ** the current machine's internal representation. A cross reference ** table is then built, and then all file reads and writes must go through ** through these routines to correct the numbers if need be. ** ** As long as the byte switching is symetrical, the conversion routines ** will work both directions. ** The integer test patterns are quite simple, and their choice was ** arbitrary, but the float and double valued were more critical. ** I did not have a specification for IEEE to go by, so it is possible ** that I have missed something. My criteria were: ** ** First, true IEEE numbers had to be chosen to avoid getting an FPE. ** Second, every byte in the test pattern had to be unique. And ** finally, the number had to not be sensitive to rounding by the ** specific hardware implementation. ** ** By experimentation it was found that the number 1.3333 met ** all these criteria for both floats and doubles ** See the discourse at the end of this file for more information ** ** */ #define TEST_PATTERN 1.3333 #define LONG_TEST 0x01020304 #define INT_TEST 0x01020304 #define SHORT_TEST 0x0102 static double u_d = TEST_PATTERN; static float u_f = TEST_PATTERN; static long u_l = LONG_TEST; static int u_i = INT_TEST; static short u_s = SHORT_TEST; /* dbl_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */ static const unsigned char dbl_cmpr [] = {0x3f, 0xf5, 0x55, 0x32, 0x61, 0x7c, 0x1b, 0xda}; /* flt_cmpr holds the bytes of an IEEE representation of TEST_PATTERN */ static const unsigned char flt_cmpr [] = {0x3f, 0xaa, 0xa9, 0x93}; static const unsigned char lng_cmpr [] = {0x01, 0x02, 0x03, 0x04}; static const unsigned char int_cmpr [] = {0x01, 0x02, 0x03, 0x04}; static const unsigned char shrt_cmpr[] = {0x01, 0x02}; /* Find native sizes */ int nat_dbl = sizeof(double); int nat_flt = sizeof(float); int nat_lng = sizeof(long); int nat_int = sizeof(int); int nat_shrt = sizeof(short); int dbl_order; int flt_order; int lng_order; int int_order; int shrt_order; unsigned char dbl_cnvrt [sizeof(double)]; unsigned char flt_cnvrt [sizeof(float )]; unsigned char lng_cnvrt [sizeof(long )]; unsigned char int_cnvrt [sizeof(int )]; unsigned char shrt_cnvrt[sizeof(short )]; /* * match search_value against each char in basis. * return offset or -1 if not found */ static int find_offset(const unsigned char *basis, unsigned char search_value, int size) { int i; for (i = 0; i < size; i++) if (basis[i] == search_value) return (i); return (-1); } static int find_offsets( const void *pattern, unsigned char *cnvrt, const unsigned char *cmpr, int port_size, int nat_size, const char *typename) { int big, ltl; int i; for (i = 0; i < port_size; i++) { int off = find_offset(pattern, cmpr[i], nat_size); if (off < 0) G_fatal_error("could not find '%x' in %s", cmpr[i], typename); cnvrt[i] = off; } big = ltl = 1; for (i = 0; i < port_size; i++) { if (cnvrt[i] != (nat_size - port_size + i)) big = 0; /* isn't big endian */ if (cnvrt[i] != (port_size - 1 - i)) ltl = 0; /* isn't little endian */ } if (big) return ENDIAN_BIG; if (ltl) return ENDIAN_LITTLE; return ENDIAN_OTHER; } void port_init(void) { static int done; if (done) return; done = 1; /* Following code checks only if all assumptions are fullfilled */ /* Check sizes */ if (nat_dbl != PORT_DOUBLE) G_fatal_error("sizeof(double) != %d", PORT_DOUBLE); if (nat_flt != PORT_FLOAT) G_fatal_error("sizeof(float) != %d", PORT_DOUBLE); if (nat_lng < PORT_LONG) G_fatal_error("sizeof(long) < %d", PORT_LONG); if (nat_int < PORT_INT) G_fatal_error("sizeof(int) < %d", PORT_INT); if (nat_shrt < PORT_SHORT) G_fatal_error("sizeof(short) < %d", PORT_SHORT); /* Find for each byte in big endian test pattern (*_cmpr) * offset of corresponding byte in machine native order. * Look if native byte order is little or big or some other (pdp) * endian. */ dbl_order = find_offsets(&u_d, dbl_cnvrt, dbl_cmpr, PORT_DOUBLE, nat_dbl, "double"); flt_order = find_offsets(&u_f, flt_cnvrt, flt_cmpr, PORT_FLOAT, nat_flt, "float" ); lng_order = find_offsets(&u_l, lng_cnvrt, lng_cmpr, PORT_LONG, nat_lng, "long" ); int_order = find_offsets(&u_i, int_cnvrt, int_cmpr, PORT_INT, nat_int, "int" ); shrt_order = find_offsets(&u_s, shrt_cnvrt, shrt_cmpr, PORT_SHORT, nat_shrt, "short" ); }