File: port_init.c

package info (click to toggle)
grass 6.4.4-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 104,028 kB
  • ctags: 40,409
  • sloc: ansic: 419,980; python: 63,559; tcl: 46,692; cpp: 29,791; sh: 18,564; makefile: 7,000; xml: 3,505; yacc: 561; perl: 559; lex: 480; sed: 70; objc: 7
file content (188 lines) | stat: -rw-r--r-- 5,492 bytes parent folder | download | duplicates (3)
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");
}