File indexing completed on 2025-12-17 09:38:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #ifndef BOOST_ALGORITHM_HEXHPP
0021 #define BOOST_ALGORITHM_HEXHPP
0022
0023 #include <iterator> // for std::iterator_traits
0024 #include <stdexcept>
0025
0026 #include <boost/config.hpp>
0027 #include <boost/range/begin.hpp>
0028 #include <boost/range/end.hpp>
0029 #include <boost/exception/exception.hpp>
0030 #include <boost/exception/info.hpp>
0031 #include <boost/throw_exception.hpp>
0032
0033 #include <boost/core/enable_if.hpp>
0034 #include <boost/type_traits/is_integral.hpp>
0035
0036
0037 namespace boost { namespace algorithm {
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 struct BOOST_SYMBOL_VISIBLE hex_decode_error : virtual boost::exception, virtual std::exception {};
0052 struct BOOST_SYMBOL_VISIBLE not_enough_input : virtual hex_decode_error {};
0053 struct BOOST_SYMBOL_VISIBLE non_hex_input : virtual hex_decode_error {};
0054 typedef boost::error_info<struct bad_char_,char> bad_char;
0055
0056 namespace detail {
0057
0058
0059 template <typename T, typename OutputIterator>
0060 OutputIterator encode_one ( T val, OutputIterator out, const char * hexDigits ) {
0061 const std::size_t num_hex_digits = 2 * sizeof ( T );
0062 char res [ num_hex_digits ];
0063 char *p = res + num_hex_digits;
0064 for ( std::size_t i = 0; i < num_hex_digits; ++i, val >>= 4 )
0065 *--p = hexDigits [ val & 0x0F ];
0066 return std::copy ( res, res + num_hex_digits, out );
0067 }
0068
0069 template <typename T>
0070 unsigned char hex_char_to_int ( T val ) {
0071 char c = static_cast<char> ( val );
0072 unsigned retval = 0;
0073 if ( c >= '0' && c <= '9' ) retval = c - '0';
0074 else if ( c >= 'A' && c <= 'F' ) retval = c - 'A' + 10;
0075 else if ( c >= 'a' && c <= 'f' ) retval = c - 'a' + 10;
0076 else BOOST_THROW_EXCEPTION (non_hex_input() << bad_char (c));
0077 return static_cast<char>(retval);
0078 }
0079
0080
0081
0082
0083 template <typename Iterator>
0084 struct hex_iterator_traits {
0085 typedef typename std::iterator_traits<Iterator>::value_type value_type;
0086 };
0087
0088 template<typename Container>
0089 struct hex_iterator_traits< std::back_insert_iterator<Container> > {
0090 typedef typename Container::value_type value_type;
0091 };
0092
0093 template<typename Container>
0094 struct hex_iterator_traits< std::front_insert_iterator<Container> > {
0095 typedef typename Container::value_type value_type;
0096 };
0097
0098 template<typename Container>
0099 struct hex_iterator_traits< std::insert_iterator<Container> > {
0100 typedef typename Container::value_type value_type;
0101 };
0102
0103
0104
0105
0106
0107 template<typename T, typename charType, typename traits>
0108 struct hex_iterator_traits< std::ostream_iterator<T, charType, traits> > {
0109 typedef T value_type;
0110 };
0111
0112 template <typename Iterator>
0113 bool iter_end ( Iterator current, Iterator last ) { return current == last; }
0114
0115 template <typename T>
0116 bool ptr_end ( const T* ptr, const T* ) { return *ptr == '\0'; }
0117
0118
0119
0120
0121
0122 template <typename InputIterator, typename OutputIterator, typename EndPred>
0123 typename boost::enable_if<boost::is_integral<typename hex_iterator_traits<OutputIterator>::value_type>, OutputIterator>::type
0124 decode_one ( InputIterator &first, InputIterator last, OutputIterator out, EndPred pred ) {
0125 typedef typename hex_iterator_traits<OutputIterator>::value_type T;
0126 T res (0);
0127
0128
0129 for ( std::size_t i = 0; i < 2 * sizeof ( T ); ++i, ++first ) {
0130 if ( pred ( first, last ))
0131 BOOST_THROW_EXCEPTION (not_enough_input ());
0132 res = ( 16 * res ) + hex_char_to_int (*first);
0133 }
0134
0135 *out = res;
0136 return ++out;
0137 }
0138
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150 template <typename InputIterator, typename OutputIterator>
0151 typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<InputIterator>::value_type>, OutputIterator>::type
0152 hex ( InputIterator first, InputIterator last, OutputIterator out ) {
0153 for ( ; first != last; ++first )
0154 out = detail::encode_one ( *first, out, "0123456789ABCDEF" );
0155 return out;
0156 }
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 template <typename InputIterator, typename OutputIterator>
0168 typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<InputIterator>::value_type>, OutputIterator>::type
0169 hex_lower ( InputIterator first, InputIterator last, OutputIterator out ) {
0170 for ( ; first != last; ++first )
0171 out = detail::encode_one ( *first, out, "0123456789abcdef" );
0172 return out;
0173 }
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 template <typename T, typename OutputIterator>
0184 typename boost::enable_if<boost::is_integral<T>, OutputIterator>::type
0185 hex ( const T *ptr, OutputIterator out ) {
0186 while ( *ptr )
0187 out = detail::encode_one ( *ptr++, out, "0123456789ABCDEF" );
0188 return out;
0189 }
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199 template <typename T, typename OutputIterator>
0200 typename boost::enable_if<boost::is_integral<T>, OutputIterator>::type
0201 hex_lower ( const T *ptr, OutputIterator out ) {
0202 while ( *ptr )
0203 out = detail::encode_one ( *ptr++, out, "0123456789abcdef" );
0204 return out;
0205 }
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 template <typename Range, typename OutputIterator>
0216 typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<typename Range::iterator>::value_type>, OutputIterator>::type
0217 hex ( const Range &r, OutputIterator out ) {
0218 return hex (boost::begin(r), boost::end(r), out);
0219 }
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 template <typename Range, typename OutputIterator>
0230 typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<typename Range::iterator>::value_type>, OutputIterator>::type
0231 hex_lower ( const Range &r, OutputIterator out ) {
0232 return hex_lower (boost::begin(r), boost::end(r), out);
0233 }
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 template <typename InputIterator, typename OutputIterator>
0245 OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator out ) {
0246 while ( first != last )
0247 out = detail::decode_one ( first, last, out, detail::iter_end<InputIterator> );
0248 return out;
0249 }
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 template <typename T, typename OutputIterator>
0260 OutputIterator unhex ( const T *ptr, OutputIterator out ) {
0261
0262
0263
0264 while ( *ptr )
0265 out = detail::decode_one ( ptr, (const T *) NULL, out, detail::ptr_end<T> );
0266 return out;
0267 }
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 template <typename Range, typename OutputIterator>
0278 OutputIterator unhex ( const Range &r, OutputIterator out ) {
0279 return unhex (boost::begin(r), boost::end(r), out);
0280 }
0281
0282
0283
0284
0285
0286
0287
0288 template<typename String>
0289 String hex ( const String &input ) {
0290 String output;
0291 output.reserve (input.size () * (2 * sizeof (typename String::value_type)));
0292 (void) hex (input, std::back_inserter (output));
0293 return output;
0294 }
0295
0296
0297
0298
0299
0300
0301
0302 template<typename String>
0303 String hex_lower ( const String &input ) {
0304 String output;
0305 output.reserve (input.size () * (2 * sizeof (typename String::value_type)));
0306 (void) hex_lower (input, std::back_inserter (output));
0307 return output;
0308 }
0309
0310
0311
0312
0313
0314
0315
0316 template<typename String>
0317 String unhex ( const String &input ) {
0318 String output;
0319 output.reserve (input.size () / (2 * sizeof (typename String::value_type)));
0320 (void) unhex (input, std::back_inserter (output));
0321 return output;
0322 }
0323
0324 }}
0325
0326 #endif