/* *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* */ /* ** Copyright UCAR (c) 1990 - 2016 */ /* ** University Corporation for Atmospheric Research (UCAR) */ /* ** National Center for Atmospheric Research (NCAR) */ /* ** Boulder, Colorado, USA */ /* ** BSD licence applies - redistribution and use in source and binary */ /* ** forms, with or without modification, are permitted provided that */ /* ** the following conditions are met: */ /* ** 1) If the software is modified to produce derivative works, */ /* ** such modified software should be clearly marked, so as not */ /* ** to confuse it with the version available from UCAR. */ /* ** 2) Redistributions of source code must retain the above copyright */ /* ** notice, this list of conditions and the following disclaimer. */ /* ** 3) Redistributions in binary form must reproduce the above copyright */ /* ** notice, this list of conditions and the following disclaimer in the */ /* ** documentation and/or other materials provided with the distribution. */ /* ** 4) Neither the name of UCAR nor the names of its contributors, */ /* ** if any, may be used to endorse or promote products derived from */ /* ** this software without specific prior written permission. */ /* ** DISCLAIMER: THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS */ /* ** OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* */ /* * Module: bigend.c * * Author: Gerry Wiener * * Date: Jan 26, 1995 * * Modified by Mike Dixon, Jan 1996. * 64 Bit support - F. Hage 1999 * * See bigend.h for details * */ #include #include #include #include static int BigEnd = 1; /*********************************************** * BE_reverse() * * Reverses the sense of this library. Therefore, * is called once, SmallEndian values are set. * If called twice, goes back to BigEndian. */ void BE_reverse(void) { BigEnd = !BigEnd; } /************************************************ * Return 1 if host is big_endian and 0 otherwise * * For debugging, if FORCE_SWAP is set, this routine will * always return FALSE, forcing a swap. */ int BE_is_big_endian() { #ifdef FORCE_SWAP return (0); #else union { ui16 d; ui08 bytes[2]; } short_int; short_int.d = 1; if (short_int.bytes[1] != 0) return (BigEnd); else return (!BigEnd); #endif } /*********************** 64 Bit Values ***************/ /*********************** 64 Bit Values ***************/ /*********************** 64 Bit Values ***************/ /**************************************************** * BE_swap_array_64() * * Performs an in-place 64-bit value byte swap. * * Array must be aligned. * * Returns the number of bytes converted. */ si32 BE_swap_array_64(void *array, ui32 nbytes) { char *ptr = (char*) array; ui32 i, l1,l2, ndoubles; /* check for little or big endian */ if(BE_is_big_endian()) { return (0); } ndoubles = nbytes / 8; for (i = 0; i < ndoubles; i++) { /* Copy the 8 bytes to 2 ui32's - Reversing 1st & 2nd */ /* PTR L1 L2 */ /* 1 2 3 4 5 6 7 8 -> 5 6 7 8 1 2 3 4 */ memcpy((void*)&l2,(void*)ptr,4); memcpy((void*)&l1,(void*)(ptr+4),4); /* Reverse the 4 bytes of each ui32 */ /* 5 6 7 8 -> 8 7 6 5 */ l1 = (((l1 & 0xff000000) >> 24) | ((l1 & 0x00ff0000) >> 8) | ((l1 & 0x0000ff00) << 8) | ((l1 & 0x000000ff) << 24)); /* 1 2 3 4 -> 4 3 2 1 */ l2 = (((l2 & 0xff000000) >> 24) | ((l2 & 0x00ff0000) >> 8) | ((l2 & 0x0000ff00) << 8) | ((l2 & 0x000000ff) << 24)); /* Copy the reversed value back into place */ memcpy((void*)ptr,(void*)&l1,4); memcpy((void*)(ptr+4),(void*)&l2,4); ptr+=8; /* Move to the next 8 byte value */ } return (nbytes); } /******************** * BE_from_fl64() * Converts a single fl64 */ void BE_from_fl64(fl64 *dst, fl64 *src) { memcpy( dst, src, sizeof(fl64)); BE_swap_array_64(dst, sizeof(fl64)); } /****************************** * BE_to_fl64 * Converts a single fl64 */ void BE_to_fl64(fl64 *src, fl64 *dst) { memcpy( dst, src, sizeof(fl64) ); BE_swap_array_64(dst, sizeof(fl64)); } /******************************** * BE_from_si64 * Converts a single si64 */ si64 BE_from_si64(si64 x) { BE_swap_array_64((void *) &x, sizeof(si64)); return (x); } /****************************** * BE_to_si64 * Converts a single si64 */ si64 BE_to_si64(si64 x) { BE_swap_array_64(&x, sizeof(si64)); return (x); } /******************************** * BE_from_ti64 * Converts a single ti32 */ ti64 BE_from_ti64(ti64 x) { BE_swap_array_64((void *) &x, sizeof(ti64)); return (x); } /****************************** * BE_to_ti64 * Converts a single ti64 */ ti64 BE_to_ti64(ti64 x) { BE_swap_array_64(&x, sizeof(ti64)); return (x); } /*********************** 32 Bit Values ***************/ /*********************** 32 Bit Values ***************/ /*********************** 32 Bit Values ***************/ /***************************************************** * BE_swap_array_32() * * Performs an in-place 32-bit word byte swap, if necessary, to produce * BE representation from machine representation, or vice-versa. * * Array must be aligned. * * Returns the number of bytes converted. */ si32 BE_swap_array_32(void *array, ui32 nbytes) { ui32 i, l, nlongs; ui32 *this_long; ui32 *array32 = array; /* check for little or big endian */ if(BE_is_big_endian()) { return (0); } nlongs = nbytes / sizeof(ui32); this_long = array32; for (i = 0; i < nlongs; i++) { l = *this_long; *this_long = (((l & 0xff000000) >> 24) | ((l & 0x00ff0000) >> 8) | ((l & 0x0000ff00) << 8) | ((l & 0x000000ff) << 24)); this_long++; } return (nbytes); } /******************** * BE_from_fl32() * Converts a single fl32 */ void BE_from_fl32(fl32 *dst, fl32 *src) { memcpy( dst, src, sizeof(fl32) ); BE_swap_array_32(dst, sizeof(fl32)); } /****************************** * BE_to_fl32 * Converts a single fl32 */ void BE_to_fl32(fl32 *src, fl32 *dst) { memcpy( dst, src, sizeof(fl32) ); BE_swap_array_32(dst, sizeof(fl32)); } /******************************** * BE_from_si32 replaces htonl() * Converts a single si32 */ si32 BE_from_si32(si32 x) { BE_swap_array_32((void *) &x, sizeof(si32)); return (x); } /****************************** * BE_to_si32 replaces ntohl() * Converts a single si32 */ si32 BE_to_si32(si32 x) { BE_swap_array_32(&x, sizeof(si32)); return (x); } /******************************** * BE_from_ti32 * Converts a single ti32 */ ti32 BE_from_ti32(ti32 x) { BE_swap_array_32((void *) &x, sizeof(ti32)); return (x); } /****************************** * BE_to_ti32 * Converts a single ti32 */ ti32 BE_to_ti32(ti32 x) { BE_swap_array_32(&x, sizeof(ti32)); return (x); } /*********************** 16 Bit Values ***************/ /*********************** 16 Bit Values ***************/ /*********************** 16 Bit Values ***************/ /***************************************************** * BE_swap_array_16() * * Performs an in-place 16-bit word byte swap, if necessary, to produce * BE representation from machine representation, or vice-versa. * * Array must be aligned. * * Returns the number of bytes converted. * */ si32 BE_swap_array_16(void *array, ui32 nbytes) { ui32 i, l, nlongs, nshorts; ui32 *this_long; ui16 *array16 = array; ui16 s; /* check for little or big endian */ if(BE_is_big_endian()) { return (0); } nlongs = nbytes / sizeof(ui32); this_long = (ui32 *)array16; for (i = 0; i < nlongs; i++) { l = *this_long; *this_long = (((l & 0xff000000) >> 8) | ((l & 0x00ff0000) << 8) | ((l & 0x0000ff00) >> 8) | ((l & 0x000000ff) << 8)); this_long++; } if (nlongs * sizeof(ui32) != nbytes) { nshorts = nbytes / sizeof(ui16); s = array16[nshorts-1]; array16[nshorts-1]= (((s & 0xff00) >> 8) | ((s & 0x00ff) << 8)); } return (nbytes); } /******************************** * BE_from_si16 replaces htons() * Converts a single si16 */ si16 BE_from_si16(si16 x) { BE_swap_array_16(&x, sizeof(si16)); return (x); } /****************************** * BE_to_si16 replaces ntohs() * Converts a single si16 */ si16 BE_to_si16(si16 x) { BE_swap_array_16(&x, sizeof(si16)); return (x); } /******************************** * BE_from_ui32 * Converts a single ui32 */ ui32 BE_from_ui32(ui32 x) { BE_swap_array_32(&x, sizeof(ui32)); return (x); } /****************************** * BE_to_ui32 * Converts a single ui32 */ ui32 BE_to_ui32(ui32 x) { BE_swap_array_32(&x, sizeof(ui32)); return (x); } /******************************** * BE_from_ui16 * Converts a single ui16 */ ui16 BE_from_ui16(ui16 x) { BE_swap_array_16(&x, sizeof(ui16)); return (x); } /****************************** * BE_to_ui16 * Converts a single ui16 */ ui16 BE_to_ui16(ui16 x) { BE_swap_array_16(&x, sizeof(ui16)); return (x); }