1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 
  27 /*
  28  *
  29  * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
  30  *
  31  */
  32 
  33 #ifndef __LESWAPS_H
  34 #define __LESWAPS_H
  35 
  36 #include "LETypes.h"
  37 
  38 #if !defined(U_IS_BIG_ENDIAN)
  39     #ifdef _LITTLE_ENDIAN
  40         #define U_IS_BIG_ENDIAN 0
  41     #endif
  42 #endif
  43 
  44 /**
  45  * A convenience macro which invokes the swapWord member function
  46  * from a concise call.
  47  *
  48  * @stable ICU 2.8
  49  */
  50 
  51 #if defined(U_IS_BIG_ENDIAN)
  52     #if U_IS_BIG_ENDIAN
  53         #define SWAPW(value) (value)
  54     #else
  55         #define SWAPW(value) LESwaps::swapWord(value)
  56     #endif
  57 #else
  58     #define SWAPW(value) (LESwaps::isBigEndian() ? (value) : LESwaps::swapWord(value))
  59 #endif
  60 
  61 /**
  62  * A convenience macro which invokes the swapLong member function
  63  * from a concise call.
  64  *
  65  * @stable ICU 2.8
  66  */
  67 
  68 #if defined(U_IS_BIG_ENDIAN)
  69     #if U_IS_BIG_ENDIAN
  70         #define SWAPL(value) (value)
  71     #else
  72         #define SWAPL(value) LESwaps::swapLong(value)
  73     #endif
  74 #else
  75     #define SWAPL(value) (LESwaps::isBigEndian() ? (value) : LESwaps::swapLong(value))
  76 #endif
  77 
  78 /**
  79  * This class is used to access data which stored in big endian order
  80  * regardless of the conventions of the platform. It has been designed
  81  * to automatically detect the endian-ness of the platform, so that a
  82  * compilation flag is not needed.
  83  *
  84  * All methods are static and inline in an attempt to induce the compiler
  85  * to do most of the calculations at compile time.
  86  *
  87  * @stable ICU 2.8
  88  */
  89 class LESwaps
  90 {
  91 public:
  92 
  93 #if !defined(U_IS_BIG_ENDIAN)
  94     /**
  95      * This method detects the endian-ness of the platform by
  96      * casting a pointer to a word to a pointer to a byte. On
  97      * big endian platforms the FF will be in the byte with the
  98      * lowest address. On little endian platforms, the FF will
  99      * be in the byte with the highest address.
 100      *
 101      * @return TRUE if the platform is big endian
 102      *
 103      * @stable ICU 2.8
 104      */
 105     static le_uint8 isBigEndian()
 106     {
 107         const le_uint16 word = 0xFF00;
 108 
 109         return *((le_uint8 *) &word);
 110     };
 111 #endif
 112 
 113     /**
 114      * This method does the byte swap required on little endian platforms
 115      * to correctly access a (16-bit) word.
 116      *
 117      * @param value - the word to be byte swapped
 118      *
 119      * @return the byte swapped word
 120      *
 121      * @stable ICU 2.8
 122      */
 123     static le_uint16 swapWord(le_uint16 value)
 124     {
 125         return (((le_uint8) (value >> 8)) | (value << 8));
 126     };
 127 
 128     /**
 129      * This method does the byte swapping required on little endian platforms
 130      * to correctly access a (32-bit) long.
 131      *
 132      * @param value - the long to be byte swapped
 133      *
 134      * @return the byte swapped long
 135      *
 136      * @stable ICU 2.8
 137      */
 138     static le_uint32 swapLong(le_uint32 value)
 139     {
 140         return swapWord((le_uint16) (value >> 16)) | (swapWord((le_uint16) value) << 16);
 141     };
 142 
 143 private:
 144     LESwaps() {} // private - forbid instantiation
 145 };
 146 
 147 #endif