root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / algorithm / hex.hpp @ 2486
History  View  Annotate  Download (10 kB)
1 
/*


2 
Copyright (c) Marshall Clow 20112012.

3 

4 
Distributed under the Boost Software License, Version 1.0. (See accompanying

5 
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

6 

7 
Thanks to Nevin for his comments/help.

8 
*/

9  
10 
/*

11 
General problem  turn a sequence of integral types into a sequence of hexadecimal characters.

12 
 and back.

13 
*/

14  
15 
/// \file hex.hpp

16 
/// \brief Convert sequence of integral types into a sequence of hexadecimal

17 
/// characters and back. Based on the MySQL functions HEX and UNHEX

18 
/// \author Marshall Clow

19  
20 
#ifndef BOOST_ALGORITHM_HEXHPP

21 
#define BOOST_ALGORITHM_HEXHPP

22  
23 
#include <iterator> // for std::iterator_traits 
24 
#include <stdexcept> 
25  
26 
#include <boost/range/begin.hpp> 
27 
#include <boost/range/end.hpp> 
28 
#include <boost/exception/all.hpp> 
29  
30 
#include <boost/utility/enable_if.hpp> 
31 
#include <boost/type_traits/is_integral.hpp> 
32  
33  
34 
namespace boost { namespace algorithm { 
35  
36 
/*!

37 
\struct hex_decode_error

38 
\brief Base exception class for all hex decoding errors

39 
*/ /*! 
40 
\struct non_hex_input

41 
\brief Thrown when a nonhex value (09, AF) encountered when decoding.

42 
Contains the offending character

43 
*/ /*! 
44 
\struct not_enough_input

45 
\brief Thrown when the input sequence unexpectedly ends

46 

47 
*/

48 
struct hex_decode_error : virtual boost::exception, virtual std::exception {}; 
49 
struct not_enough_input : virtual hex_decode_error {}; 
50 
struct non_hex_input : virtual hex_decode_error {}; 
51 
typedef boost::error_info<struct bad_char_,char> bad_char; 
52  
53 
namespace detail {

54 
/// \cond DOXYGEN_HIDE

55  
56 
template <typename T, typename OutputIterator> 
57 
OutputIterator encode_one ( T val, OutputIterator out ) { 
58 
const std::size_t num_hex_digits = 2 * sizeof ( T ); 
59 
char res [ num_hex_digits ];

60 
char *p = res + num_hex_digits;

61 
for ( std::size_t i = 0; i < num_hex_digits; ++i, val >>= 4 ) 
62 
*p = "0123456789ABCDEF" [ val & 0x0F ]; 
63 
return std::copy ( res, res + num_hex_digits, out );

64 
} 
65  
66 
template <typename T> 
67 
unsigned char hex_char_to_int ( T val ) { 
68 
char c = static_cast<char> ( val ); 
69 
unsigned retval = 0; 
70 
if ( c >= '0' && c <= '9' ) retval = c  '0'; 
71 
else if ( c >= 'A' && c <= 'F' ) retval = c  'A' + 10; 
72 
else if ( c >= 'a' && c <= 'f' ) retval = c  'a' + 10; 
73 
else BOOST_THROW_EXCEPTION (non_hex_input() << bad_char (c));

74 
return retval;

75 
} 
76  
77 
// My own iterator_traits class.

78 
// It is here so that I can "reach inside" some kinds of output iterators

79 
// and get the type to write.

80 
template <typename Iterator> 
81 
struct hex_iterator_traits {

82 
typedef typename std::iterator_traits<Iterator>::value_type value_type; 
83 
}; 
84  
85 
template<typename Container> 
86 
struct hex_iterator_traits< std::back_insert_iterator<Container> > {

87 
typedef typename Container::value_type value_type; 
88 
}; 
89  
90 
template<typename Container> 
91 
struct hex_iterator_traits< std::front_insert_iterator<Container> > {

92 
typedef typename Container::value_type value_type; 
93 
}; 
94  
95 
template<typename Container> 
96 
struct hex_iterator_traits< std::insert_iterator<Container> > {

97 
typedef typename Container::value_type value_type; 
98 
}; 
99  
100 
// ostream_iterators have three template parameters.

101 
// The first one is the output type, the second one is the character type of

102 
// the underlying stream, the third is the character traits.

103 
// We only care about the first one.

104 
template<typename T, typename charType, typename traits> 
105 
struct hex_iterator_traits< std::ostream_iterator<T, charType, traits> > {

106 
typedef T value_type;

107 
}; 
108  
109 
template <typename Iterator> 
110 
bool iter_end ( Iterator current, Iterator last ) { return current == last; } 
111 

112 
template <typename T> 
113 
bool ptr_end ( const T* ptr, const T* /*end*/ ) { return *ptr == '\0'; } 
114 

115 
// What can we assume here about the inputs?

116 
// is std::iterator_traits<InputIterator>::value_type always 'char' ?

117 
// Could it be wchar_t, say? Does it matter?

118 
// We are assuming ASCII for the values  but what about the storage?

119 
template <typename InputIterator, typename OutputIterator, typename EndPred> 
120 
typename boost::enable_if<boost::is_integral<typename hex_iterator_traits<OutputIterator>::value_type>, OutputIterator>::type 
121 
decode_one ( InputIterator &first, InputIterator last, OutputIterator out, EndPred pred ) { 
122 
typedef typename hex_iterator_traits<OutputIterator>::value_type T; 
123 
T res (0);

124  
125 
// Need to make sure that we get can read that many chars here.

126 
for ( std::size_t i = 0; i < 2 * sizeof ( T ); ++i, ++first ) { 
127 
if ( pred ( first, last ))

128 
BOOST_THROW_EXCEPTION (not_enough_input ()); 
129 
res = ( 16 * res ) + hex_char_to_int (*first);

130 
} 
131 

132 
*out = res; 
133 
return ++out;

134 
} 
135 
/// \endcond

136 
} 
137  
138  
139 
/// \fn hex ( InputIterator first, InputIterator last, OutputIterator out )

140 
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.

141 
///

142 
/// \param first The start of the input sequence

143 
/// \param last One past the end of the input sequence

144 
/// \param out An output iterator to the results into

145 
/// \return The updated output iterator

146 
/// \note Based on the MySQL function of the same name

147 
template <typename InputIterator, typename OutputIterator> 
148 
typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<InputIterator>::value_type>, OutputIterator>::type 
149 
hex ( InputIterator first, InputIterator last, OutputIterator out ) { 
150 
for ( ; first != last; ++first )

151 
out = detail::encode_one ( *first, out ); 
152 
return out;

153 
} 
154 

155  
156 
/// \fn hex ( const T *ptr, OutputIterator out )

157 
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.

158 
///

159 
/// \param ptr A pointer to a 0terminated sequence of data.

160 
/// \param out An output iterator to the results into

161 
/// \return The updated output iterator

162 
/// \note Based on the MySQL function of the same name

163 
template <typename T, typename OutputIterator> 
164 
typename boost::enable_if<boost::is_integral<T>, OutputIterator>::type

165 
hex ( const T *ptr, OutputIterator out ) {

166 
while ( *ptr )

167 
out = detail::encode_one ( *ptr++, out ); 
168 
return out;

169 
} 
170  
171 
/// \fn hex ( const Range &r, OutputIterator out )

172 
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.

173 
///

174 
/// \param r The input range

175 
/// \param out An output iterator to the results into

176 
/// \return The updated output iterator

177 
/// \note Based on the MySQL function of the same name

178 
template <typename Range, typename OutputIterator> 
179 
typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<typename Range::iterator>::value_type>, OutputIterator>::type 
180 
hex ( const Range &r, OutputIterator out ) {

181 
return hex (boost::begin(r), boost::end(r), out);

182 
} 
183  
184  
185 
/// \fn unhex ( InputIterator first, InputIterator last, OutputIterator out )

186 
/// \brief Converts a sequence of hexadecimal characters into a sequence of integers.

187 
///

188 
/// \param first The start of the input sequence

189 
/// \param last One past the end of the input sequence

190 
/// \param out An output iterator to the results into

191 
/// \return The updated output iterator

192 
/// \note Based on the MySQL function of the same name

193 
template <typename InputIterator, typename OutputIterator> 
194 
OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator out ) { 
195 
while ( first != last )

196 
out = detail::decode_one ( first, last, out, detail::iter_end<InputIterator> ); 
197 
return out;

198 
} 
199  
200  
201 
/// \fn unhex ( const T *ptr, OutputIterator out )

202 
/// \brief Converts a sequence of hexadecimal characters into a sequence of integers.

203 
///

204 
/// \param ptr A pointer to a nullterminated input sequence.

205 
/// \param out An output iterator to the results into

206 
/// \return The updated output iterator

207 
/// \note Based on the MySQL function of the same name

208 
template <typename T, typename OutputIterator> 
209 
OutputIterator unhex ( const T *ptr, OutputIterator out ) {

210 
// If we run into the terminator while decoding, we will throw a

211 
// malformed input exception. It would be nicer to throw a 'Not enough input'

212 
// exception  but how much extra work would that require?

213 
while ( *ptr )

214 
out = detail::decode_one ( ptr, (const T *) NULL, out, detail::ptr_end<T> ); 
215 
return out;

216 
} 
217  
218  
219 
/// \fn OutputIterator unhex ( const Range &r, OutputIterator out )

220 
/// \brief Converts a sequence of hexadecimal characters into a sequence of integers.

221 
///

222 
/// \param r The input range

223 
/// \param out An output iterator to the results into

224 
/// \return The updated output iterator

225 
/// \note Based on the MySQL function of the same name

226 
template <typename Range, typename OutputIterator> 
227 
OutputIterator unhex ( const Range &r, OutputIterator out ) {

228 
return unhex (boost::begin(r), boost::end(r), out);

229 
} 
230  
231  
232 
/// \fn String hex ( const String &input )

233 
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.

234 
///

235 
/// \param input A container to be converted

236 
/// \return A container with the encoded text

237 
template<typename String> 
238 
String hex ( const String &input ) {

239 
String output; 
240 
output.reserve (input.size () * (2 * sizeof (typename String::value_type))); 
241 
(void) hex (input, std::back_inserter (output));

242 
return output;

243 
} 
244  
245 
/// \fn String unhex ( const String &input )

246 
/// \brief Converts a sequence of hexadecimal characters into a sequence of characters.

247 
///

248 
/// \param input A container to be converted

249 
/// \return A container with the decoded text

250 
template<typename String> 
251 
String unhex ( const String &input ) {

252 
String output; 
253 
output.reserve (input.size () / (2 * sizeof (typename String::value_type))); 
254 
(void) unhex (input, std::back_inserter (output));

255 
return output;

256 
} 
257  
258 
}} 
259  
260 
#endif // BOOST_ALGORITHM_HEXHPP 