libmoost
|
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__