В этой ветке кто-то заметил, что следующий код должен использоваться только в «игрушечных» проектах. К сожалению, он не вернулся, чтобы сказать, почему он не имеет производственного качества, поэтому я надеялся, что кто-то в сообществе сможет либо заверить меня, что код в порядке (потому что он мне очень нравится), либо определить, что не так. *
template< class T1, class T2>
void hexascii( T1& out, const T2& in )
{
out.resize( in.size() * 2 );
const char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7','8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
T1::iterator outit = out.begin();
for( T2::const_iterator it = in.begin(); it != in.end(); ++it )
{
*outit++ = hexDigits[*it >> 4];
*outit++ = hexDigits[*it & 0xF];
}
}
template<class T1, class T2>
void asciihex( T1& out, const T2& in )
{
size_t size = in.size;
assert( !(size % 2) );
out.resize( size / 2 );
T1::iterator outit = out.begin();
for( T2::const_iterator it = in.begin(); it != in.end(); it += 2, ++outit )
{
*outit = ((( (*it > '9' ? *it - 0x07 : *it) - 0x30) << 4) & 0x00f0) +
(((*(it+1) > '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f);
}
}
Edit: Спасибо за вашу помощь, ребята, вы сделали несколько больших улучшений. Я написал функции в двух предложенных стилях из ваших ответов. Некоторые грубые тесты показывают, что второй метод несколько быстрее, чем первый, но IMO перевешивает улучшенную читаемость первого.
template<class T1>
void asciihex2( T1& out, const std::string& in )
{
dassert( sizeof(T1::value_type)==1 );
size_t size = in.size();
assert( !(size % 2) );
out.resize( size / 2 );
T1::iterator outit = out.begin();
for( size_t i = 0; i < in.size(); i += 2 )
{
int tmp;
sscanf( in.c_str() + i, "%02X", &tmp );
*outit++ = tmp;
}
}
template<class T1>
void asciihex3( T1& out, const std::string& in )
{
dassert( sizeof(T1::value_type)==1 );
size_t size = in.size();
assert( !(size % 2) );
out.resize( size / 2 );
T1::iterator outit = out.begin();
const char hexDigits[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
for( std::string::const_iterator it = in.begin(); it != in.end(); it += 2, ++outit )
{
*outit = (hexDigits[(*it - 0x30) & 0x1f] << 4) +
hexDigits[((*(it+1) - 0x30) & 0x1f)];
}
}
Некоторые из предположений, дополняющих этот код:
1: они не предназначены для общего использования, но используются в анонимном пространстве имен для перевода данных для определенного класса.
2: Шаблонирование требуется, так как используются два отдельных типа контейнера (один - std :: vector, другой - аналогичный контейнер типа байтового массива из сторонней библиотеки.
3: Цель состоит в том, чтобы иметь возможность преобразовывать двоичные данные неопределенной длины в строки и обратно (0x1234abcd <-> "1234abcd")
4: утвердить ошибки в режимах отладки и выпуска
5: к моменту вызова этих функций размер строки уже будет проверен, assert используется для прекращения обработки, если что-то серьезное пошло не так
6: Нужно прокомментировать
Любые другие идеи приветствуются.