1- /*
1+ /*
22 Copyright (c) Marshall Clow 2011-2012.
33
44 Distributed under the Boost Software License, Version 1.0. (See accompanying
55 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6-
6+
77 Thanks to Nevin for his comments/help.
88*/
99
1313*/
1414
1515// / \file hex.hpp
16- // / \brief Convert sequence of integral types into a sequence of hexadecimal
16+ // / \brief Convert sequence of integral types into a sequence of hexadecimal
1717// / characters and back. Based on the MySQL functions HEX and UNHEX
1818// / \author Marshall Clow
1919
3333
3434namespace boost { namespace algorithm {
3535
36- /* !
37- \struct hex_decode_error
38- \brief Base exception class for all hex decoding errors
36+ /* !
37+ \struct hex_decode_error
38+ \brief Base exception class for all hex decoding errors
3939*/ /* !
40- \struct non_hex_input
40+ \struct non_hex_input
4141 \brief Thrown when a non-hex value (0-9, A-F) encountered when decoding.
4242 Contains the offending character
43- */ /* !
44- \struct not_enough_input
43+ */ /* !
44+ \struct not_enough_input
4545 \brief Thrown when the input sequence unexpectedly ends
46-
46+
4747*/
4848struct hex_decode_error : virtual boost::exception, virtual std::exception {};
4949struct not_enough_input : virtual hex_decode_error {};
@@ -54,12 +54,12 @@ namespace detail {
5454// / \cond DOXYGEN_HIDE
5555
5656 template <typename T, typename OutputIterator>
57- OutputIterator encode_one ( T val, OutputIterator out ) {
57+ OutputIterator encode_one ( T val, OutputIterator out, const char * hexDigits ) {
5858 const std::size_t num_hex_digits = 2 * sizeof ( T );
5959 char res [ num_hex_digits ];
6060 char *p = res + num_hex_digits;
6161 for ( std::size_t i = 0 ; i < num_hex_digits; ++i, val >>= 4 )
62- *--p = " 0123456789ABCDEF " [ val & 0x0F ];
62+ *--p = hexDigits [ val & 0x0F ];
6363 return std::copy ( res, res + num_hex_digits, out );
6464 }
6565
@@ -106,12 +106,12 @@ namespace detail {
106106 typedef T value_type;
107107 };
108108
109- template <typename Iterator>
109+ template <typename Iterator>
110110 bool iter_end ( Iterator current, Iterator last ) { return current == last; }
111-
111+
112112 template <typename T>
113113 bool ptr_end ( const T* ptr, const T* /* end*/ ) { return *ptr == ' \0 ' ; }
114-
114+
115115// What can we assume here about the inputs?
116116// is std::iterator_traits<InputIterator>::value_type always 'char' ?
117117// Could it be wchar_t, say? Does it matter?
@@ -124,11 +124,11 @@ namespace detail {
124124
125125 // Need to make sure that we get can read that many chars here.
126126 for ( std::size_t i = 0 ; i < 2 * sizeof ( T ); ++i, ++first ) {
127- if ( pred ( first, last ))
127+ if ( pred ( first, last ))
128128 BOOST_THROW_EXCEPTION (not_enough_input ());
129129 res = ( 16 * res ) + hex_char_to_int (*first);
130130 }
131-
131+
132132 *out = res;
133133 return ++out;
134134 }
@@ -138,7 +138,7 @@ namespace detail {
138138
139139// / \fn hex ( InputIterator first, InputIterator last, OutputIterator out )
140140// / \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
141- // /
141+ // /
142142// / \param first The start of the input sequence
143143// / \param last One past the end of the input sequence
144144// / \param out An output iterator to the results into
@@ -148,14 +148,31 @@ template <typename InputIterator, typename OutputIterator>
148148typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<InputIterator>::value_type>, OutputIterator>::type
149149hex ( InputIterator first, InputIterator last, OutputIterator out ) {
150150 for ( ; first != last; ++first )
151- out = detail::encode_one ( *first, out );
151+ out = detail::encode_one ( *first, out, " 0123456789ABCDEF" );
152+ return out;
153+ }
154+
155+
156+ // / \fn hex_lower ( InputIterator first, InputIterator last, OutputIterator out )
157+ // / \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters.
158+ // /
159+ // / \param first The start of the input sequence
160+ // / \param last One past the end of the input sequence
161+ // / \param out An output iterator to the results into
162+ // / \return The updated output iterator
163+ // / \note Based on the MySQL function of the same name
164+ template <typename InputIterator, typename OutputIterator>
165+ typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<InputIterator>::value_type>, OutputIterator>::type
166+ hex_lower ( InputIterator first, InputIterator last, OutputIterator out ) {
167+ for ( ; first != last; ++first )
168+ out = detail::encode_one ( *first, out, " 0123456789abcdef" );
152169 return out;
153170 }
154-
171+
155172
156173// / \fn hex ( const T *ptr, OutputIterator out )
157174// / \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
158- // /
175+ // /
159176// / \param ptr A pointer to a 0-terminated sequence of data.
160177// / \param out An output iterator to the results into
161178// / \return The updated output iterator
@@ -164,13 +181,30 @@ template <typename T, typename OutputIterator>
164181typename boost::enable_if<boost::is_integral<T>, OutputIterator>::type
165182hex ( const T *ptr, OutputIterator out ) {
166183 while ( *ptr )
167- out = detail::encode_one ( *ptr++, out );
184+ out = detail::encode_one ( *ptr++, out, " 0123456789ABCDEF" );
185+ return out;
186+ }
187+
188+
189+ // / \fn hex_lower ( const T *ptr, OutputIterator out )
190+ // / \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters.
191+ // /
192+ // / \param ptr A pointer to a 0-terminated sequence of data.
193+ // / \param out An output iterator to the results into
194+ // / \return The updated output iterator
195+ // / \note Based on the MySQL function of the same name
196+ template <typename T, typename OutputIterator>
197+ typename boost::enable_if<boost::is_integral<T>, OutputIterator>::type
198+ hex_lower ( const T *ptr, OutputIterator out ) {
199+ while ( *ptr )
200+ out = detail::encode_one ( *ptr++, out, " 0123456789abcdef" );
168201 return out;
169202 }
170203
204+
171205// / \fn hex ( const Range &r, OutputIterator out )
172206// / \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
173- // /
207+ // /
174208// / \param r The input range
175209// / \param out An output iterator to the results into
176210// / \return The updated output iterator
@@ -182,9 +216,23 @@ hex ( const Range &r, OutputIterator out ) {
182216}
183217
184218
219+ // / \fn hex_lower ( const Range &r, OutputIterator out )
220+ // / \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters.
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+ typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<typename Range::iterator>::value_type>, OutputIterator>::type
228+ hex_lower ( const Range &r, OutputIterator out ) {
229+ return hex_lower (boost::begin (r), boost::end (r), out);
230+ }
231+
232+
185233// / \fn unhex ( InputIterator first, InputIterator last, OutputIterator out )
186234// / \brief Converts a sequence of hexadecimal characters into a sequence of integers.
187- // /
235+ // /
188236// / \param first The start of the input sequence
189237// / \param last One past the end of the input sequence
190238// / \param out An output iterator to the results into
@@ -200,7 +248,7 @@ OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator o
200248
201249// / \fn unhex ( const T *ptr, OutputIterator out )
202250// / \brief Converts a sequence of hexadecimal characters into a sequence of integers.
203- // /
251+ // /
204252// / \param ptr A pointer to a null-terminated input sequence.
205253// / \param out An output iterator to the results into
206254// / \return The updated output iterator
@@ -218,7 +266,7 @@ OutputIterator unhex ( const T *ptr, OutputIterator out ) {
218266
219267// / \fn OutputIterator unhex ( const Range &r, OutputIterator out )
220268// / \brief Converts a sequence of hexadecimal characters into a sequence of integers.
221- // /
269+ // /
222270// / \param r The input range
223271// / \param out An output iterator to the results into
224272// / \return The updated output iterator
@@ -231,7 +279,7 @@ OutputIterator unhex ( const Range &r, OutputIterator out ) {
231279
232280// / \fn String hex ( const String &input )
233281// / \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
234- // /
282+ // /
235283// / \param input A container to be converted
236284// / \return A container with the encoded text
237285template <typename String>
@@ -242,9 +290,24 @@ String hex ( const String &input ) {
242290 return output;
243291 }
244292
293+
294+ // / \fn String hex_lower ( const String &input )
295+ // / \brief Converts a sequence of integral types into a lower case hexadecimal sequence of characters.
296+ // /
297+ // / \param input A container to be converted
298+ // / \return A container with the encoded text
299+ template <typename String>
300+ String hex_lower ( const String &input ) {
301+ String output;
302+ output.reserve (input.size () * (2 * sizeof (typename String::value_type)));
303+ (void ) hex_lower (input, std::back_inserter (output));
304+ return output;
305+ }
306+
307+
245308// / \fn String unhex ( const String &input )
246309// / \brief Converts a sequence of hexadecimal characters into a sequence of characters.
247- // /
310+ // /
248311// / \param input A container to be converted
249312// / \return A container with the decoded text
250313template <typename String>
0 commit comments