LLVM API Documentation

Endian.h
Go to the documentation of this file.
00001 //===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file declares generic functions to read and write endian specific data.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_SUPPORT_ENDIAN_H
00015 #define LLVM_SUPPORT_ENDIAN_H
00016 
00017 #include "llvm/Support/AlignOf.h"
00018 #include "llvm/Support/Host.h"
00019 #include "llvm/Support/SwapByteOrder.h"
00020 
00021 namespace llvm {
00022 namespace support {
00023 enum endianness {big, little, native};
00024 
00025 // These are named values for common alignments.
00026 enum {aligned = 0, unaligned = 1};
00027 
00028 namespace detail {
00029   /// \brief ::value is either alignment, or alignof(T) if alignment is 0.
00030   template<class T, int alignment>
00031   struct PickAlignment {
00032     enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment};
00033   };
00034 } // end namespace detail
00035 
00036 namespace endian {
00037 /// Swap the bytes of value to match the given endianness.
00038 template<typename value_type, endianness endian>
00039 inline value_type byte_swap(value_type value) {
00040   if (endian != native && sys::IsBigEndianHost != (endian == big))
00041     sys::swapByteOrder(value);
00042   return value;
00043 }
00044 
00045 /// Read a value of a particular endianness from memory.
00046 template<typename value_type,
00047          endianness endian,
00048          std::size_t alignment>
00049 inline value_type read(const void *memory) {
00050   value_type ret;
00051 
00052   memcpy(&ret,
00053          LLVM_ASSUME_ALIGNED(memory,
00054            (detail::PickAlignment<value_type, alignment>::value)),
00055          sizeof(value_type));
00056   return byte_swap<value_type, endian>(ret);
00057 }
00058 
00059 /// Read a value of a particular endianness from a buffer, and increment the
00060 /// buffer past that value.
00061 template<typename value_type, endianness endian, std::size_t alignment>
00062 inline value_type readNext(const unsigned char *&memory) {
00063   value_type ret = read<value_type, endian, alignment>(memory);
00064   memory += sizeof(value_type);
00065   return ret;
00066 }
00067 
00068 /// Write a value to memory with a particular endianness.
00069 template<typename value_type,
00070          endianness endian,
00071          std::size_t alignment>
00072 inline void write(void *memory, value_type value) {
00073   value = byte_swap<value_type, endian>(value);
00074   memcpy(LLVM_ASSUME_ALIGNED(memory,
00075            (detail::PickAlignment<value_type, alignment>::value)),
00076          &value,
00077          sizeof(value_type));
00078 }
00079 } // end namespace endian
00080 
00081 namespace detail {
00082 template<typename value_type,
00083          endianness endian,
00084          std::size_t alignment>
00085 struct packed_endian_specific_integral {
00086   operator value_type() const {
00087     return endian::read<value_type, endian, alignment>(
00088       (const void*)Value.buffer);
00089   }
00090 
00091   void operator=(value_type newValue) {
00092     endian::write<value_type, endian, alignment>(
00093       (void*)Value.buffer, newValue);
00094   }
00095 
00096   packed_endian_specific_integral &operator+=(value_type newValue) {
00097     *this = *this + newValue;
00098     return *this;
00099   }
00100 
00101   packed_endian_specific_integral &operator-=(value_type newValue) {
00102     *this = *this - newValue;
00103     return *this;
00104   }
00105 
00106 private:
00107   AlignedCharArray<PickAlignment<value_type, alignment>::value,
00108                    sizeof(value_type)> Value;
00109 
00110 public:
00111   struct ref {
00112     explicit ref(void *Ptr) : Ptr(Ptr) {}
00113 
00114     operator value_type() const {
00115       return endian::read<value_type, endian, alignment>(Ptr);
00116     }
00117 
00118     void operator=(value_type NewValue) {
00119       endian::write<value_type, endian, alignment>(Ptr, NewValue);
00120     }
00121 
00122   private:
00123     void *Ptr;
00124   };
00125 };
00126 
00127 } // end namespace detail
00128 
00129 typedef detail::packed_endian_specific_integral
00130                   <uint16_t, little, unaligned> ulittle16_t;
00131 typedef detail::packed_endian_specific_integral
00132                   <uint32_t, little, unaligned> ulittle32_t;
00133 typedef detail::packed_endian_specific_integral
00134                   <uint64_t, little, unaligned> ulittle64_t;
00135 
00136 typedef detail::packed_endian_specific_integral
00137                    <int16_t, little, unaligned> little16_t;
00138 typedef detail::packed_endian_specific_integral
00139                    <int32_t, little, unaligned> little32_t;
00140 typedef detail::packed_endian_specific_integral
00141                    <int64_t, little, unaligned> little64_t;
00142 
00143 typedef detail::packed_endian_specific_integral
00144                     <uint16_t, little, aligned> aligned_ulittle16_t;
00145 typedef detail::packed_endian_specific_integral
00146                     <uint32_t, little, aligned> aligned_ulittle32_t;
00147 typedef detail::packed_endian_specific_integral
00148                     <uint64_t, little, aligned> aligned_ulittle64_t;
00149 
00150 typedef detail::packed_endian_specific_integral
00151                      <int16_t, little, aligned> aligned_little16_t;
00152 typedef detail::packed_endian_specific_integral
00153                      <int32_t, little, aligned> aligned_little32_t;
00154 typedef detail::packed_endian_specific_integral
00155                      <int64_t, little, aligned> aligned_little64_t;
00156 
00157 typedef detail::packed_endian_specific_integral
00158                   <uint16_t, big, unaligned>    ubig16_t;
00159 typedef detail::packed_endian_specific_integral
00160                   <uint32_t, big, unaligned>    ubig32_t;
00161 typedef detail::packed_endian_specific_integral
00162                   <uint64_t, big, unaligned>    ubig64_t;
00163 
00164 typedef detail::packed_endian_specific_integral
00165                    <int16_t, big, unaligned>    big16_t;
00166 typedef detail::packed_endian_specific_integral
00167                    <int32_t, big, unaligned>    big32_t;
00168 typedef detail::packed_endian_specific_integral
00169                    <int64_t, big, unaligned>    big64_t;
00170 
00171 typedef detail::packed_endian_specific_integral
00172                     <uint16_t, big, aligned>    aligned_ubig16_t;
00173 typedef detail::packed_endian_specific_integral
00174                     <uint32_t, big, aligned>    aligned_ubig32_t;
00175 typedef detail::packed_endian_specific_integral
00176                     <uint64_t, big, aligned>    aligned_ubig64_t;
00177 
00178 typedef detail::packed_endian_specific_integral
00179                      <int16_t, big, aligned>    aligned_big16_t;
00180 typedef detail::packed_endian_specific_integral
00181                      <int32_t, big, aligned>    aligned_big32_t;
00182 typedef detail::packed_endian_specific_integral
00183                      <int64_t, big, aligned>    aligned_big64_t;
00184 
00185 typedef detail::packed_endian_specific_integral
00186                   <uint16_t, native, unaligned> unaligned_uint16_t;
00187 typedef detail::packed_endian_specific_integral
00188                   <uint32_t, native, unaligned> unaligned_uint32_t;
00189 typedef detail::packed_endian_specific_integral
00190                   <uint64_t, native, unaligned> unaligned_uint64_t;
00191 
00192 typedef detail::packed_endian_specific_integral
00193                    <int16_t, native, unaligned> unaligned_int16_t;
00194 typedef detail::packed_endian_specific_integral
00195                    <int32_t, native, unaligned> unaligned_int32_t;
00196 typedef detail::packed_endian_specific_integral
00197                    <int64_t, native, unaligned> unaligned_int64_t;
00198 } // end namespace llvm
00199 } // end namespace support
00200 
00201 #endif