00001 /* 00002 * The information in this file is 00003 * Copyright(c) 2007 Ball Aerospace & Technologies Corporation 00004 * and is subject to the terms and conditions of the 00005 * GNU Lesser General Public License Version 2.1 00006 * The license text is available from 00007 * http://www.gnu.org/licenses/lgpl.html 00008 */ 00009 00010 #ifndef ENDIAN_H 00011 #define ENDIAN_H 00012 00013 #include "ComplexData.h" 00014 #include "TypesFile.h" 00015 00016 /** 00017 * A class to perform byte-swapping operations. 00018 * 00019 * The Endian class provides a capability to perform byte-swapping of data 00020 * values based on the endian type of the system. An Endian object should be 00021 * created with the target endian type. The swapping methods can then be 00022 * called to swap data values to the target type. If the target type is the 00023 * same as the system, no swapping is performed. 00024 * 00025 * @see EndianType 00026 */ 00027 class Endian 00028 { 00029 public: 00030 /** 00031 * Creates an Endian object of a given endian type. 00032 * 00033 * @param endian 00034 * The endian type for the object. This type is used as the 00035 * target endian type for the byte-swapping methods. If the given 00036 * type is the same as the system type the byte-swapping methods 00037 * can still be called, but no swapping is performed. 00038 * 00039 * @see EndianType 00040 */ 00041 Endian(EndianType endian); 00042 00043 /** 00044 * Creates an Endian object which will always swap. 00045 * 00046 * @see EndianType 00047 */ 00048 Endian(); 00049 00050 /** 00051 * Destroys the Endian object. 00052 */ 00053 ~Endian(); 00054 00055 /** 00056 * Returns the endian type of <em>this</em>. 00057 * 00058 * @return The endian type. 00059 * 00060 * @see getSystemEndian() 00061 */ 00062 EndianType getEndian() const; 00063 00064 /** 00065 * Queries the endian type of <em>this</em> for EndianType::BIG_ENDIAN_ORDER. 00066 * 00067 * @return Returns true if the endian type is EndianType::BIG_ENDIAN_ORDER, 00068 * otherwise returns false. 00069 */ 00070 bool isBigEndian() const; 00071 00072 /** 00073 * Queries the endian type of <em>this</em> for EndianType::LITTLE_ENDIAN_ORDER. 00074 * 00075 * @return Returns true if the endian type is EndianType::LITTLE_ENDIAN_ORDER, 00076 * otherwise returns false. 00077 */ 00078 bool isLittleEndian() const; 00079 00080 /** 00081 * Swaps the bytes of a single data value. 00082 * 00083 * This method performs in-place byte swapping of a single data value 00084 * by modifying the given element. If the original value should not be 00085 * overwritten, use the swapValue() method instead. 00086 * 00087 * @param value 00088 * A reference to the data value to swap. 00089 * 00090 * @return Returns true if byte swapping was actually performed. Returns 00091 * false if no byte swapping is necessary because the endian type 00092 * is already the same as the system. 00093 * 00094 * @see swapValue(const T &), swapBuffer(T *,size_t) 00095 */ 00096 template <class T> 00097 bool swapValue(T& value) const 00098 { 00099 return swapBuffer(&value, 1); 00100 } 00101 00102 /** 00103 * Swaps the bytes of a single data value. 00104 * 00105 * This method performs byte swapping of a single data value and returns 00106 * the swapped value. The original data element is not modified. For 00107 * performance reasons, if the original data element can be overwritten, 00108 * use the swapValue() method instead. 00109 * 00110 * @param value 00111 * A data value to swap. The value is not modified. 00112 * 00113 * @return Returns the swapped data value. If no swapping is necessary, a 00114 * copy of the original data value is returned. 00115 * 00116 * @see swapValue(T &) 00117 */ 00118 template <class T> 00119 T swapValue(const T& value) const 00120 { 00121 T newValue = value; 00122 swapValue(newValue); 00123 00124 return newValue; 00125 } 00126 00127 /** 00128 * Swaps the bytes of data elements in an array. 00129 * 00130 * This method swaps the bytes of data elements in an array if the endian 00131 * type of the system is different than the endian type of <em>this</em>. 00132 * 00133 * This method is provided as a convenience if the data type is known. 00134 * 00135 * @param pBuffer 00136 * A pointer to the data to be byte swapped. 00137 * @param count 00138 * The number of items in the array to byte swap. 00139 * 00140 * @return Returns true if byte swapping was actually performed. Returns 00141 * false if no byte swapping is necessary because the endian type 00142 * is already the same as the system. 00143 * 00144 * @see swapBuffer(void *,size_t,size_t), swapValue(T &) 00145 */ 00146 template <class T> 00147 bool swapBuffer(T* pBuffer, size_t count) const 00148 { 00149 return swapBuffer(pBuffer, sizeof(T), count); 00150 } 00151 00152 /** 00153 * This override has the same behavior as the templated 00154 * function of the same name. 00155 * 00156 * It is needed because the template definition is incorrect 00157 * for complex data. 00158 * 00159 * @param pBuffer 00160 * The FloatComplex buffer to swap 00161 * @param count 00162 * The number of elements in pBuffer to swap 00163 * 00164 * @return Returns true if byte swapping was actually performed. Returns 00165 * false if no byte swapping is necessary because the endian type 00166 * is already the same as the system. 00167 */ 00168 bool swapBuffer(FloatComplex* pBuffer, size_t count) const 00169 { 00170 return swapBuffer(pBuffer, sizeof(float), 2*count); 00171 } 00172 00173 /** 00174 * This override has the same behavior as the templated 00175 * function of the same name. 00176 * 00177 * It is needed because the template definition is incorrect 00178 * for complex data. 00179 * 00180 * @param pBuffer 00181 * The IntegerComplex buffer to swap 00182 * @param count 00183 * The number of elements in pBuffer to swap 00184 * 00185 * @return Returns true if byte swapping was actually performed. Returns 00186 * false if no byte swapping is necessary because the endian type 00187 * is already the same as the system. 00188 */ 00189 bool swapBuffer(IntegerComplex* pBuffer, size_t count) const 00190 { 00191 return swapBuffer(pBuffer, sizeof(short), 2*count); 00192 } 00193 00194 /** 00195 * Swaps the bytes of data elements in an array. 00196 * 00197 * This method swaps the bytes of data elements in an array if the endian 00198 * type of the system is different than endian type of <em>this</em>. 00199 * 00200 * @param pBuffer 00201 * A pointer to the data to be byte swapped. 00202 * @param dataSize 00203 * The size of each element in the array. 00204 * @param count 00205 * The number of items in the array to byte swap. 00206 * 00207 * @return Returns true if byte swapping was actually performed. Returns 00208 * false if no byte swapping is necessary because the endian type 00209 * is already the same as the system. 00210 * 00211 * @see swapBuffer(T *,size_t), swapValue(T &) 00212 */ 00213 bool swapBuffer(void* pBuffer, size_t dataSize, size_t count) const 00214 { 00215 if ((pBuffer == NULL) || (mSystemType == mType)) 00216 { 00217 return false; 00218 } 00219 00220 for (size_t i = 0; i < count; ++i) 00221 { 00222 unsigned char* pData = reinterpret_cast<unsigned char*>(pBuffer) + (i * dataSize); 00223 for (size_t j = 0; j < dataSize / 2; ++j) 00224 { 00225 size_t index = dataSize - j - 1; 00226 00227 unsigned char byteData = pData[j]; 00228 pData[j] = pData[index]; 00229 pData[index] = byteData; 00230 } 00231 } 00232 00233 return true; 00234 } 00235 00236 /** 00237 * Returns the endian type of the system. 00238 * 00239 * This value is used in the byte-swapping methods to determine whether 00240 * the data values should be swapped or not. 00241 * 00242 * @return The system endian type. 00243 * 00244 * @see getEndian() 00245 */ 00246 static EndianType getSystemEndian(); 00247 00248 private: 00249 EndianType mType; 00250 EndianType mSystemType; 00251 }; 00252 00253 #endif