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