source: trunk/src/libsrc/util/swap.c @ 8072

Revision 7382, 11.7 KB checked in by baker, 16 months ago (diff)

using void * pointers and #defines, unify 16/32/64-bit byte swap routines

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
3 *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
4 *
5 *    $Id$
6 *
7 *    Revision history:
8 *     $Log$
9 *     Revision 1.14  2010/03/19 16:42:58  paulf
10 *     whoops, really fixed the max samples check
11 *
12 *     Revision 1.13  2010/03/19 16:30:15  paulf
13 *     added check for nsamps to be smaller than max samples for a tbuf to WaveMsg2MakeLocal()
14 *
15 *     Revision 1.12  2007/12/16 19:26:39  paulf
16 *     made SwapLong check for not 4 bytes for long....previous check was too limiting
17 *
18 *     Revision 1.11  2007/12/16 18:42:19  paulf
19 *     made swap functions long int tolerant where in some OS, long can be 8 bytes
20 *
21 *     Revision 1.10  2005/06/13 18:15:41  dietz
22 *     Changed logging for bad header values in WaveMsg2MakeLocal() to include
23 *     all header values because one never knows which value is bogus.
24 *
25 *     Revision 1.9  2005/06/10 21:41:06  patton
26 *     Modified comment for clarity (at least clear to me).  JMP
27 *
28 *     Revision 1.8  2005/06/10 21:19:30  patton
29 *     Put in more meaningful comment into WaveMsg2MakeLocal to explain to the user
30 *     the case that the tracebuf does not end within 5 samples of the given endtime.
31 *     JMP
32 *
33 *     Revision 1.7  2004/04/13 22:59:38  dietz
34 *     Added WaveMsg2MakeLocal()
35 *
36 *     Revision 1.6  2003/10/20 17:08:06  mark
37 *     Added compiler flags check
38 *
39 *     Revision 1.5  2002/06/18 18:33:55  davidk
40 *     fixed the sanity check of the header in WaveMsgMakeLocal().
41 *     It contained a bug that made it useless.
42 *
43 *     Revision 1.4  2002/06/11 23:08:17  davidk
44 *     Paul Friberg submitted a fix to WaveMsgMakeLocal, that copies the
45 *     TRACE_HEADER to local variables to avoid byte alignment problems
46 *     before examining the header.  (Bug was introduced by most
47 *     recent change by davek that included code which examined the
48 *     contents of the header without 8-byte aligning data.
49 *
50 *     Revision 1.3  2002/03/20 22:13:28  davidk
51 *     Modified WaveMsgMakeLocal():
52 *      Function now converts the header, performs a checksum on the header,
53 *       and then if successful converts the binary data portion of the tracebuf.
54 *      Function now returns -2 if the header checksum conversion fails.
55 *      Function now returns -1 if _INTEL or _SPARC is not defined.
56 *       (Formerly, no conversion was done and success was returned.)
57 *
58 *     Revision 1.2  2000/06/22 17:49:33  kohler
59 *     Modified by WMK to allow in-place swapping of non-byte-alligned data.
60 *
61 *     Revision 1.1  2000/02/14 18:51:48  lucky
62 *     Initial revision
63 *
64 *
65 */
66
67/*
68 * SWAP.C
69 *
70 *  Byte swapping functions
71 */
72 
73/* Make sure one of the platforms is defined properly... */ 
74#ifndef _INTEL
75 #ifndef _SPARC
76  #error _INTEL and _SPARC are both undefined
77 #endif
78#endif
79
80#include <stdio.h>
81#include <stdlib.h>
82#include <string.h>
83
84#include "swap.h"
85
86static int WaveMsgVersionMakeLocal( TRACE2X_HEADER* wvmsg, char version );
87
88int32_t testInt32Var = 0;
89
90/* SwapUint16: Byte swap 2-byte unsigned integer */
91void SwapUint16( void *data )
92{
93   char temp;
94   union {
95      char  c[2];
96   } dat;
97
98   memcpy( &dat, data, 2 );
99   temp     = dat.c[0];
100   dat.c[0] = dat.c[1];
101   dat.c[1] = temp;
102   memcpy( data, &dat, 2 );
103}
104
105/* SwapUint32: Byte swap 4-byte unsigned integer */
106void SwapUint32( void *data )
107{
108   char temp;
109   union {
110      char c[4];
111   } dat;
112
113   memcpy( &dat, data, 4 );
114   temp     = dat.c[0];
115   dat.c[0] = dat.c[3];
116   dat.c[3] = temp;
117   temp     = dat.c[1];
118   dat.c[1] = dat.c[2];
119   dat.c[2] = temp;
120   memcpy( data, &dat, 4 );
121}
122
123/* SwapUint64: Byte swap 8-byte unsigned integer */
124void SwapUint64( EW_UNALIGNED void *data )
125{
126   char temp;
127   union {
128       char   c[8];
129   } dat;
130
131   memcpy( &dat, data, 8 );
132   temp     = dat.c[0];
133   dat.c[0] = dat.c[7];
134   dat.c[7] = temp;
135
136   temp     = dat.c[1];
137   dat.c[1] = dat.c[6];
138   dat.c[6] = temp;
139
140   temp     = dat.c[2];
141   dat.c[2] = dat.c[5];
142   dat.c[5] = temp;
143
144   temp     = dat.c[3];
145   dat.c[3] = dat.c[4];
146   dat.c[4] = temp;
147   memcpy( data, &dat, 8 );
148}
149
150/************************ WaveMsgMakeLocal **************************
151*       Byte-swap a universal TYPE_TRACEBUF message in place.       *
152*       Changes the 'datatype' field in the message header          *
153*       Returns -1 if unknown data type.                            *
154*       Returns -1 if _SPARC or _INTEL not defined.                 *
155*       Returns -2 if checksumish calculation of header fails.      *
156*       Elsewise (SUCCESS) returns 0.                               *
157*********************************************************************/
158
159int WaveMsgMakeLocal( TRACE_HEADER* wvmsg )
160{
161   return WaveMsgVersionMakeLocal((TRACE2X_HEADER *)wvmsg, '1');
162}
163
164
165/************************ WaveMsg2MakeLocal *************************
166*       Byte-swap a universal TYPE_TRACEBUF2 message in place.      *
167*       Changes the 'datatype' field in the message header          *
168*       Returns -1 if unknown data type.                            *
169*       Returns -1 if _SPARC or _INTEL not defined.                 *
170*       Returns -1 if more than max number of samples for tbuf      *
171*        size allowed  2000 or 1000 depending on data type          *
172*       Returns -2 if checksumish calculation of header fails.      *
173*       Elsewise (SUCCESS) returns 0.                               *
174*********************************************************************/
175
176int WaveMsg2MakeLocal( TRACE2_HEADER* wvmsg )
177{
178   return WaveMsgVersionMakeLocal((TRACE2X_HEADER *)wvmsg, wvmsg->version[0]);
179}
180
181/************************ WaveMsg2XMakeLocal *************************
182*       Byte-swap a universal TYPE_TRACEBUF2X message in place.      *
183*       Changes the 'datatype' field in the message header          *
184*       Returns -1 if unknown data type.                            *
185*       Returns -1 if _SPARC or _INTEL not defined.                 *
186*       Returns -1 if more than max number of samples for tbuf      *
187*        size allowed  2000 or 1000 depending on data type          *
188*       Returns -2 if checksumish calculation of header fails.      *
189*       Elsewise (SUCCESS) returns 0.                               *
190*********************************************************************/
191
192int WaveMsg2XMakeLocal( TRACE2X_HEADER* wvmsg )
193{
194   return WaveMsgVersionMakeLocal( wvmsg, wvmsg->version[0]);
195}
196
197static int WaveMsgVersionMakeLocal( TRACE2X_HEADER* wvmsg, char version )
198{
199   int    dataSize;  /* flag telling us how many bytes in the data */
200   char   byteOrder;
201   int*   intPtr;
202   short* shortPtr;
203   int    i;
204   int    nsamp;
205   double samprate,starttime,endtime;
206   double tShouldEnd; 
207   double dFudgeFactor;
208
209   /* See what sort of data it carries
210    **********************************/
211   dataSize=0;
212   if ( strcmp(wvmsg->datatype, "s4")==0)
213   {
214        dataSize=4; byteOrder='s';
215   }
216   else if ( strcmp(wvmsg->datatype, "i4")==0)
217   {
218        dataSize=4; byteOrder='i';
219   }
220   else if ( strcmp(wvmsg->datatype, "s2")==0)
221   {
222        dataSize=2; byteOrder='s';
223   }
224   else if ( strcmp(wvmsg->datatype, "i2")==0)
225   {
226        dataSize=2; byteOrder='i';
227   }
228   else
229        return(-1); /* We don't know this message type*/
230
231   /* SWAP the header (if neccessary) */
232#if defined( _SPARC )
233   if (byteOrder =='i')
234   {
235        /* swap the header
236        *****************/
237        SwapInt( &(wvmsg->pinno) );
238        SwapInt( &(wvmsg->nsamp) );
239        SwapDouble( &(wvmsg->starttime) );
240        SwapDouble( &(wvmsg->endtime)   );
241        SwapDouble( &(wvmsg->samprate)  );
242        if (version == TRACE2_VERSION0) {
243           switch (wvmsg->version[1]) {
244           case TRACE2_VERSION11:
245              SwapFloat( &(wvmsg->x.v21.conversion_factor) );
246              break;
247           }
248        }
249   }
250
251#elif defined( _INTEL )
252   if (byteOrder =='s')
253   {
254        /* swap the header
255        *****************/
256        SwapInt( &(wvmsg->pinno) );
257        SwapInt( &(wvmsg->nsamp) );
258        SwapDouble( &(wvmsg->starttime) );
259        SwapDouble( &(wvmsg->endtime)   );
260        SwapDouble( &(wvmsg->samprate)  );
261        if (version == TRACE2_VERSION0) {
262           switch (wvmsg->version[1]) {
263           case TRACE2_VERSION11:
264              SwapFloat( &(wvmsg->x.v21.conversion_factor) );
265              break;
266           }
267        }
268   }
269#else
270   printf( "WaveMsg2MakeLocal warning: _INTEL and _SPARC are both undefined." );
271   return(-1);
272#endif
273
274  if (wvmsg->nsamp > 4032/dataSize) {
275     logit("et","WaveMsg2MakeLocal: packet from %s.%s.%s.%s has bad number of samples=%d datatype=%s\n",
276                wvmsg->sta, wvmsg->chan, wvmsg->net, wvmsg->loc, wvmsg->nsamp , wvmsg->datatype);
277     return(-1);
278  }
279
280/* Perform a CheckSumish kind of calculation on the header
281 * ensure that the tracebuf ends within 5 samples of the given endtime.
282 * DK 2002/03/18
283 *********************************************************************/
284
285/* moved nsamp memcpy to here to avoid byte-alignment with next statement */
286   memcpy( &nsamp,     &wvmsg->nsamp,     sizeof(int)    );
287   memcpy( &samprate,  &wvmsg->samprate,  sizeof(double) );
288   memcpy( &starttime, &wvmsg->starttime, sizeof(double) );
289   memcpy( &endtime,   &wvmsg->endtime,   sizeof(double) );
290
291   tShouldEnd   = starttime + ((nsamp - 1) / samprate);
292   dFudgeFactor = 5.0 / samprate;
293
294/* This is supposed to be a simple sanity check to ensure that the
295 * endtime is within 5 samples of where it should be.  We're not
296 * trying to be judgemental here, we're just trying to ensure that
297 * we protect ourselves from complete garbage, so that we don't segfault
298 * when allocating samples based on a bad nsamp
299 ***********************************************************************/
300   if( endtime < (tShouldEnd-dFudgeFactor) || 
301       endtime > (tShouldEnd+dFudgeFactor)    )
302   {
303      logit("e","WaveMsg2MakeLocal: packet from %s.%s.%s.%s has inconsistent "
304                "header values!\n", wvmsg->sta, wvmsg->chan, wvmsg->net, wvmsg->loc );
305      logit("e","WaveMsg2MakeLocal: header.starttime  : %.4lf\n", starttime  );
306      logit("e","WaveMsg2MakeLocal: header.samplerate : %.1lf\n", samprate   );
307      logit("e","WaveMsg2MakeLocal: header.nsample    : %d\n",    nsamp      );
308      logit("e","WaveMsg2MakeLocal: header.endtime    : %.4lf\n", endtime    );
309      logit("e","WaveMsg2MakeLocal: computed.endtime  : %.4lf\n", tShouldEnd );
310      logit("e","WaveMsg2MakeLocal: header.endtime is not within 5 sample intervals "
311                "of computed.endtime!\n" );
312      return(-2);
313   }
314 
315   /* SWAP the data (if neccessary) */
316#if defined( _SPARC )
317
318   if (byteOrder =='i')
319   {
320   /* Swap the data.  */
321        intPtr=(int*) ((char*)wvmsg + sizeof(TRACE2_HEADER) );
322        shortPtr=(short*) ((char*)wvmsg + sizeof(TRACE2_HEADER) );
323        for( i=0; i<nsamp; i++)
324        {
325                if(dataSize==2) SwapShort( &(shortPtr[i]) );
326                if(dataSize==4) SwapInt(  &(intPtr[i])  );
327        }
328        /* Re-write the data type field in the message
329        **********************************************/
330        if(dataSize==2) strcpy(wvmsg->datatype,"s2");
331        if(dataSize==4) strcpy(wvmsg->datatype,"s4");
332   }
333
334#elif defined( _INTEL )
335
336   if (byteOrder =='s')
337   {
338   /* Swap the data.  */
339        intPtr=(int*) ((char*)wvmsg + sizeof(TRACE2_HEADER) );
340        shortPtr=(short*) ((char*)wvmsg + sizeof(TRACE2_HEADER) );
341        for( i=0; i<nsamp; i++)
342        {
343                if(dataSize==2) SwapShort( &(shortPtr[i]) );
344                if(dataSize==4) SwapInt(  &(intPtr[i])  );
345        }
346        /* Re-write the data type field in the message
347        **********************************************/
348        if(dataSize==2) strcpy(wvmsg->datatype,"i2");
349        if(dataSize==4) strcpy(wvmsg->datatype,"i4");
350   }
351#else
352   printf( "WaveMsg2MakeLocal warning: _INTEL and _SPARC are both undefined." );
353#endif
354
355   return(0);
356}
Note: See TracBrowser for help on using the repository browser.