libmoost
/home/mhx/git/github/libmoost/include/moost/algorithm/variable_length_encoding.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 #ifndef MOOST_ALGORITHM_VARIABLE_LENGTH_ENCODING_HPP__
00029 #define MOOST_ALGORITHM_VARIABLE_LENGTH_ENCODING_HPP__
00030 
00031 #include <stdexcept>
00032 #include <limits>
00033 #include <boost/cstdint.hpp>
00034 #include <boost/static_assert.hpp>
00035 
00036 namespace moost { namespace algorithm {
00037 
00040 struct variable_length_encoding
00041 {
00042    // DEPRECATED! Use the one below!
00043    template <class T, class InputIterator>
00044    inline static void read(T& value, InputIterator & p_in)
00045    {
00046       BOOST_STATIC_ASSERT(
00047             sizeof(T) == 4 &&
00048             std::numeric_limits<T>::is_integer &&
00049             std::numeric_limits<T>::is_signed
00050          );
00051 
00052       value = *p_in & 0x7F; // 1
00053 
00054       // unroll the loop since we know a VLE uint can occupy at most 5 bytes!
00055       if (*p_in & 0x80)
00056       {
00057          ++p_in;
00058          value = ((value << 7) | (*p_in & 0x7F)); // 2
00059          if (*p_in & 0x80)
00060          {
00061             ++p_in;
00062             value = ((value << 7) | (*p_in & 0x7F)); // 3
00063             if (*p_in & 0x80)
00064             {
00065                ++p_in;
00066                value = ((value << 7) | (*p_in & 0x7F)); // 4
00067                if (*p_in & 0x80)
00068                {
00069                   ++p_in;
00070                   value = ((value << 7) | (*p_in & 0x7F)); // 5
00071                   if (*p_in & 0x80)
00072                      throw std::overflow_error("overflow");
00073                }
00074             }
00075          }
00076       }
00077       ++p_in;
00078    }
00079 
00080 
00081   template <class InputIterator>
00082   inline static boost::int32_t read(InputIterator & p_in)
00083   {
00084     boost::int32_t value = *p_in & 0x7F; // 1
00085 
00086     // unroll the loop since we know a VLE uint can occupy at most 5 bytes!
00087     if (*p_in & 0x80)
00088     {
00089       ++p_in;
00090       value = ((value << 7) | (*p_in & 0x7F)); // 2
00091       if (*p_in & 0x80)
00092       {
00093         ++p_in;
00094         value = ((value << 7) | (*p_in & 0x7F)); // 3
00095         if (*p_in & 0x80)
00096         {
00097           ++p_in;
00098           value = ((value << 7) | (*p_in & 0x7F)); // 4
00099           if (*p_in & 0x80)
00100           {
00101             ++p_in;
00102             value = ((value << 7) | (*p_in & 0x7F)); // 5
00103             if (*p_in & 0x80)
00104               throw std::overflow_error("overflow");
00105           }
00106         }
00107       }
00108     }
00109     ++p_in;
00110     return value;
00111   }
00112 
00113   template <class OutputIterator>
00114   inline static void write(boost::int32_t value, OutputIterator & p_out)
00115   {
00116     if ((value & 0xFFFFFF80) == 0) // only occupying lower 7 bits?
00117     {
00118       *p_out = static_cast<char>(value); ++p_out;
00119     }
00120     else if ((value & 0xFFFFC000) == 0) // 14?
00121     {
00122       *p_out = static_cast<char>(value >> 7 | 0x80); ++p_out;
00123       *p_out = static_cast<char>(value & 0x7F);      ++p_out;
00124     }
00125     else if ((value & 0xFFE00000) == 0) // 21!?!
00126     {
00127       *p_out = static_cast<char>(value >> 14 | 0x80); ++p_out;
00128       *p_out = static_cast<char>(value >> 7  | 0x80); ++p_out;
00129       *p_out = static_cast<char>(value & 0x7F);       ++p_out;
00130     }
00131     else if ((value & 0xF0000000) == 0) // 28!?!??!?
00132     {
00133       *p_out = static_cast<char>(value >> 21 | 0x80); ++p_out;
00134       *p_out = static_cast<char>(value >> 14 | 0x80); ++p_out;
00135       *p_out = static_cast<char>(value >> 7  | 0x80); ++p_out;
00136       *p_out = static_cast<char>(value & 0x7F);       ++p_out;
00137     }
00138     else
00139     {
00140       *p_out = static_cast<char>(value >> 28 | 0x80); ++p_out;
00141       *p_out = static_cast<char>(value >> 21 | 0x80); ++p_out;
00142       *p_out = static_cast<char>(value >> 14 | 0x80); ++p_out;
00143       *p_out = static_cast<char>(value >> 7  | 0x80); ++p_out;
00144       *p_out = static_cast<char>(value & 0x7F);       ++p_out;
00145     }
00146   }
00147 };
00148 
00149 }} // moost::algorithm
00150 
00151 #endif // MOOST_ALGORITHM_VARIABLE_LENGTH_ENCODING_HPP__