$search
00001 #ifndef TYPELIB_ENDIANSWAP_HH 00002 #define TYPELIB_ENDIANSWAP_HH 00003 00004 #include <typelib/value.hh> 00005 #include <utilmm/system/endian.hh> 00006 #include <limits> 00007 00008 namespace Typelib 00009 { 00010 struct UnsupportedEndianSwap : public std::runtime_error 00011 { 00012 UnsupportedEndianSwap(std::string const& what) : std::runtime_error("cannot swap " + what) { } 00013 }; 00014 00015 /* This visitor swaps the endianness of the given value in-place */ 00016 class EndianSwapVisitor : public ValueVisitor 00017 { 00018 protected: 00019 bool visit_ (int8_t & value) { value = utilmm::endian::swap(value); return true; } 00020 bool visit_ (uint8_t & value) { value = utilmm::endian::swap(value); return true; } 00021 bool visit_ (int16_t & value) { value = utilmm::endian::swap(value); return true; } 00022 bool visit_ (uint16_t& value) { value = utilmm::endian::swap(value); return true; } 00023 bool visit_ (int32_t & value) { value = utilmm::endian::swap(value); return true; } 00024 bool visit_ (uint32_t& value) { value = utilmm::endian::swap(value); return true; } 00025 bool visit_ (int64_t & value) { value = utilmm::endian::swap(value); return true; } 00026 bool visit_ (uint64_t& value) { value = utilmm::endian::swap(value); return true; } 00027 bool visit_ (float & value) { value = utilmm::endian::swap(value); return true; } 00028 bool visit_ (double & value) { value = utilmm::endian::swap(value); return true; } 00029 bool visit_ (Value const& v, Pointer const& t) { throw UnsupportedEndianSwap("pointers"); } 00030 bool visit_ (Enum::integral_type& v, Enum const& e) { v = utilmm::endian::swap(v); return true; } 00031 }; 00032 00034 void endian_swap(Value v) 00035 { 00036 EndianSwapVisitor swapper; 00037 swapper.apply(v); 00038 } 00039 00040 class CompileEndianSwapVisitor : public TypeVisitor 00041 { 00042 // The current place into the output: the next element which are to be 00043 // byte-swapped will be written at this index in the output data 00044 // buffer. 00045 size_t m_output_index; 00046 00047 public: 00048 // The compiled-in description of the byte-swap operation 00049 // 00050 // Given an output index, an element of compiled is the absolute 00051 // index of the input byte which should be written at this output index: 00052 // output_buffer[output_index] = input_buffer[*it_compiled] 00053 // 00054 // After a "normal" operation (i.e. neither a skip nor an array), 00055 // output index is incremented and we handle the next operation 00056 // found in compiled 00057 std::vector<size_t> m_compiled; 00058 00063 static size_t const FLAG_SKIP = ((size_t) -1); 00071 static size_t const FLAG_ARRAY = ((size_t) -2); 00072 static size_t const FLAG_END = ((size_t) -3); 00073 static size_t const FLAG_SWAP_4 = ((size_t) -4); 00074 static size_t const FLAG_SWAP_8 = ((size_t) -5); 00075 static const size_t SizeOfEnum = sizeof(int);; 00076 00077 protected: 00078 void skip(int skip_size); 00079 bool visit_ (OpaqueType const& type); 00080 bool visit_ (Numeric const& type); 00081 bool visit_ (Enum const& type); 00082 bool visit_ (Pointer const& type); 00083 bool visit_ (Array const& type); 00084 bool visit_ (Compound const& type); 00085 bool visit_ (Container const& type); 00086 00087 public: 00088 ~CompileEndianSwapVisitor() { } 00089 void apply(Type const& type); 00090 00091 void swap(Value in, Value out) 00092 { 00093 CompileEndianSwapVisitor::swap(0, 0, 00094 m_compiled.begin(), m_compiled.end(), 00095 in, out); 00096 } 00097 00098 std::pair<size_t, std::vector<size_t>::const_iterator> 00099 swap(size_t output_offset, size_t input_offset, 00100 std::vector<size_t>::const_iterator it, 00101 std::vector<size_t>::const_iterator end, 00102 Value in, Value out); 00103 00104 void display(); 00105 }; 00106 } 00107 00108 #endif 00109