1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
/*
****************************************************************************
*
* 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 <stdio.h>
#include <grass/Vect.h>
/*
** 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");
}
|