What can I say? I was bored!
So I decided to use a lookup table for each byte, and to use iterators rather than strings, for flexibility.
Code:
/*
Functions 'to_binary_text' and 'integer_to_binary_text' convert objects and
integers to binary representation using iterators. Class 'additive_iterator'
can be used as an adaptor for std::strings and the like.
*/
/*
TODO: Address localization issues...
*/
#include <string>
#include <iterator>
#include <vector>
/*
Disregard; used internally only
*/
std::vector< std::string > to_binary_text_table_generate_( void ) {
size_t cnt = 1 << CHAR_BIT;
std::vector< std::string > tab( cnt );
for( size_t idx = 0; idx < cnt; ++idx )
for( size_t msk = cnt >> 1; msk; msk >>= 1 )
tab[ idx ] += idx & msk ? "1" : "0";
return tab;
}
/*
Copies the binary representation of an object to an iterator,
ordered from lowest to highest address, by default
*/
template < typename Type, typename OutputIterator >
OutputIterator to_binary_text(
Type const& value,
OutputIterator result,
std::string const & separator = " ",
bool ascending_order = true
) {
typedef unsigned char* Iter;
int inc = 1;
Iter seq = Iter( &value ), fin = seq + sizeof( Type );
if( !ascending_order ) {
inc = -inc;
std::swap( --seq, --fin );
}
static std::vector< std::string > tab = to_binary_text_table_generate_( );
goto skip;
for( ; seq != fin; seq += inc ) {
*result++ = separator;
skip:
*result++ = tab[ *seq ];
}
return result;
}
/*
Copies the binary representation of an integer to an iterator,
in 'standard' (ie: big-endian) position, by default
*/
template < typename Integer, typename OutputIterator >
OutputIterator integer_to_binary_text(
Integer const& value,
OutputIterator result,
std::string const & separator = " ",
bool big_endian = true
) {
static Integer tst = 1;
static bool big = !*( unsigned char* )&tst;
return to_binary_text( value, result, separator, big == big_endian );
}
/*
An iterator interface adaptor for containers that implement operator += (eg: std::string)
*/
template < class Container >
class additive_iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > {
public:
additive_iterator( Container& object )
: ptr( &object ) {
}
template < typename Other >
additive_iterator< Container >& operator = ( Other const& value ) {
*ptr += value;
return *this;
}
additive_iterator< Container >& operator* ( void ) {
return *this;
}
additive_iterator< Container >& operator++ ( void ) {
return *this;
}
additive_iterator< Container > operator++ ( int ) {
return *this;
}
protected:
Container* ptr;
};
/*
Type-deductive generator helper function
*/
template < class Container >
inline additive_iterator< Container > make_additive_iterator( Container& object ) {
return additive_iterator< Container >( object );
}
/*
Example
*/
#include <iostream>
#pragma pack( push, 1 )
struct test {
int i;
char c;
};
#pragma pack( pop )
int main( void ) {
using namespace std;
test tst = { 1024, 'a' };
string sts, sti, stc;
to_binary_text( tst, make_additive_iterator( sts ) );
integer_to_binary_text( tst.i, make_additive_iterator( sti ) );
integer_to_binary_text( tst.c, make_additive_iterator( stc ) );
cout << "- Entire structure, ordered from lowest to highest address -" << endl;
cout << "Bin: " << sts << endl;
cout << "- Integer in structure, in standard (big-endian) position -" << endl;
cout << "Dec: " << tst.i << endl;
cout << "Bin: " << sti << endl;
cout << "- Character in structure -" << endl;
cout << "Dec: " << ( int )tst.c << endl;
cout << "Bin: " << stc << endl;
}
May need some improvement, tho...