ByteOrderConversion.h
Go to the documentation of this file.
00001 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
00002 
00003 // -- BEGIN LICENSE BLOCK ----------------------------------------------
00004 // This file is part of FZIs ic_workspace.
00005 //
00006 // This program is free software licensed under the LGPL
00007 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
00008 // You can find a copy of this license in LICENSE folder in the top
00009 // directory of the source code.
00010 //
00011 // © Copyright 2014 FZI Forschungszentrum Informatik, Karlsruhe, Germany
00012 //
00013 // -- END LICENSE BLOCK ------------------------------------------------
00014 
00015 //----------------------------------------------------------------------
00023 //----------------------------------------------------------------------
00024 #ifndef ICL_COMM_BYTE_ORDER_CONVERISON_H_INCLUDED
00025 #define ICL_COMM_BYTE_ORDER_CONVERISON_H_INCLUDED
00026 
00027 #include <icl_core/BaseTypes.h>
00028 #include <icl_core/Vector.h>
00029 
00030 #include "icl_comm/ImportExport.h"
00031 
00032 #include <boost/detail/endian.hpp>
00033 #include <iostream>
00034 #include <iomanip>
00035 #include <assert.h>
00036 
00037 // For type limiting
00038 #include <boost/type_traits/is_arithmetic.hpp>
00039 
00040 namespace icl_comm {
00041 
00043 template <typename T>
00044 size_t toLittleEndian(const T& data, std::vector<uint8_t>& array, size_t& write_pos)
00045 {
00046   // Resize the target array in case it it to small to avoid out of bounds acces
00047   if (write_pos + sizeof(T) > array.size())
00048   {
00049     // TODO: Remove Debug
00050     //std::cout << "To Little Endian has to extend the Array. Current array Size: "<< (int)array.size() << " Pos: " << (int)pos << " Size_T: "<< sizeof(T) << " New array Size: "<< (int)(pos + sizeof(T)) << std::endl;
00051     array.resize(write_pos + sizeof(T) );
00052   }
00053 
00054   // Endianess Conversion
00055   for (size_t i= 0; i< sizeof(T);++i)
00056   {
00057     // Copy each byte into the bytearray, always convert byte order to little endian regardles of source architecture
00058     array[write_pos+i] = static_cast<uint8_t>((data>>(i*8)) & 0xFF);
00059   }
00060 
00061   return write_pos + sizeof(T);
00062 }
00063 
00065 template <>
00066 ICL_COMM_IMPORT_EXPORT
00067 size_t toLittleEndian<float>(const float& data, std::vector<uint8_t>& array, size_t& write_pos);
00068 
00070 template <>
00071 ICL_COMM_IMPORT_EXPORT
00072 size_t toLittleEndian<double>(const double& data, std::vector<uint8_t>& array, size_t& write_pos);
00073 
00074 
00076 template <typename T>
00077 size_t fromLittleEndian(T& data, std::vector<uint8_t>& array, size_t& read_pos)
00078 {
00079   // TODO: Remove once everything is tested :)
00080   //std::cout << "From Little Endian Called with: "<<" Size_T: "<< sizeof(T) << " Pos: " << (int)read_pos << "Current Array Size: "<< (int)array.size() << std::endl;
00081 
00082   // Reset data as we only write with or
00083   data = 0;
00084 
00085   // Check if ArrayBuilder has enough data
00086   if (read_pos + sizeof(T) > array.size())
00087   {
00088     // TODO: better error handling?
00089     return read_pos;
00090   }
00091 
00092 
00093   // Endianess Conversion
00094   for (size_t i= 0; i< sizeof(T);++i)
00095   {
00096     // Copy each byte into the bytearray, always convert byte order back from little endian
00097     data |= (array[read_pos+i]& 0xFF) <<(i*8);
00098     //std::cout << "Converting Value: 0x" << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>((array[read_pos+i]& 0xFF) <<(i*8)) << " At the position i="<<static_cast<int>(i) << "resulting in the variable data: " << static_cast<int>(data)  << std::dec <<" Or on DEC :" << static_cast<int>(data) << std::endl;
00099   }
00100 
00101   // Note: The Vector still contains the elements at this point maybe we would like to delete that? But its expensive
00102   return read_pos + sizeof(T);
00103 }
00104 
00106 template <>
00107 ICL_COMM_IMPORT_EXPORT
00108 size_t fromLittleEndian<float>(float& data, std::vector<uint8_t>& array, size_t& read_pos);
00109 
00111 template <>
00112 ICL_COMM_IMPORT_EXPORT
00113 size_t fromLittleEndian<double>(double& data, std::vector<uint8_t>& array, size_t& read_pos);
00114 
00130 class ArrayBuilder
00131 {
00132 public:
00133   ArrayBuilder(size_t array_size = 1) :
00134     write_pos(0),
00135     read_pos(0),
00136     array(array_size, 0)
00137   { }
00138 
00140   size_t write_pos;
00141 
00143   size_t read_pos;
00144 
00146   std::vector<uint8_t>  array;
00147 
00148 
00152   void reset(size_t array_size = 1);
00153 
00155   template <typename T>
00156   void appendWithoutConversion(const T& data)
00157   {
00158     // Resize the target array in case it it to small to avoid out of bounds acces
00159     if (write_pos + sizeof(T) > array.size())
00160     {
00161       array.resize(write_pos + sizeof(T) );
00162     }
00163 
00164     // write data to array without conversion
00165     *(reinterpret_cast<T*>(&array[write_pos])) = data;
00166     write_pos += sizeof(T);
00167   }
00168 
00170   template <typename T>
00171   void appendWithoutConversion(const std::vector<T>& data)
00172   {
00173     // Just insert every element of the Vector individually
00174     for (typename std::vector<T>::const_iterator it = data.begin() ; it != data.end(); ++it)
00175     {
00176       appendWithoutConversion(*it);
00177     }
00178   }
00179 
00181   template <typename T>
00182   ArrayBuilder& operator << (const T& data);
00183 
00185   template <typename T>
00186   ArrayBuilder& operator << (const std::vector<T>& data);
00187 
00188 
00190   template <typename T>
00191   ArrayBuilder& operator >> (T& data);
00192 
00194   template <typename T>
00195   ArrayBuilder& operator >> (std::vector<T>& data);
00196 
00199   template <typename T>
00200   T readBack();
00201 };
00202 
00203 
00205 template <typename T>
00206 ArrayBuilder& ArrayBuilder::operator << (const T& data)
00207 {
00208   // Convert the type to correct encoding and poit it into the Array
00209   write_pos = toLittleEndian<T>(data, array, write_pos);
00210 
00211   // TODO: Remove debug output
00212   //std::cout << "Arraybuilder got a generic type of length: "<< sizeof(data) << " and With data Packet: "<< (int)data << std::endl;
00213 
00214   return *this;
00215 }
00216 
00217 
00219 template <typename T>
00220 ArrayBuilder& ArrayBuilder::operator << (const std::vector<T>& data)
00221 {
00222   // Just insert every element of the Vector individually
00223   for (typename std::vector<T>::const_iterator it = data.begin() ; it != data.end(); ++it)
00224   {
00225     *this << *it;
00226   }
00227 
00228   // TODO: Remove Debug output
00229   //std::cout << "ArrayBuilder got a vector of length: "<< data.size() << std::endl;
00230 
00231   return *this;
00232 }
00233 
00234 
00236 template <typename T>
00237 ArrayBuilder& ArrayBuilder::operator >> (T& data)
00238 {
00239   read_pos = fromLittleEndian<T>(data, array, read_pos);
00240   return *this;
00241 }
00242 
00244 template <typename T>
00245 ArrayBuilder& ArrayBuilder::operator >> (std::vector<T>& data)
00246 {
00247   // Todo: For u_int8 Vectors this could also just be handled by an insert -> faster :)
00248   // Just insert every element of the Vector individually --> Do it in reverse order as we read from the end of the list :)
00249   for (typename std::vector<T>::iterator it = data.begin() ; it != data.end(); ++it)
00250   {
00251     *this >> *it;
00252   }
00253 
00254  return *this;
00255 }
00256 
00257 
00258 template <typename T>
00259 T ArrayBuilder::readBack()
00260 {
00261   T data;
00262   size_t read_back_pos = write_pos-sizeof(T);
00263   fromLittleEndian<T>(data, array, read_back_pos);
00264   return data;
00265 }
00266 
00267 
00269 std::ostream& operator << (std::ostream& o, const ArrayBuilder& ab);
00270 
00271 }
00272 
00273 #endif


fzi_icl_comm
Author(s):
autogenerated on Thu Jun 6 2019 21:31:31