|
Boost Users : |
Subject: [Boost-users] boost::multiprecision::cpp_int encoding and decoding little endian byte arrays
From: Steffen Heil (Mailinglisten) (lists_at_[hidden])
Date: 2013-09-04 13:55:18
Hello
I need to decode/encode cpp_int values from/into byte arrays.
The encoding must be shortest little endian two's complement representation of the value.
For example:
00 = 0
01 = 1
ff = -1
ff:7f = 32767
01:80 = -32767
00:80:00 = 32768
00:80 = -32768
01:80:00 = 32769
ff:7f:ff = -32769
ff:ff:ef:9c:d2:40:43:da:4f:40:6b:06:6a:cd:92:c2:93:bf:a4:5c:c3:f1:29:63:1d = 184467440737095516151844674407370955161518446744073709551615
01:00:10:63:2d:bf:bc:25:b0:bf:94:f9:95:32:6d:3d:6c:40:5b:a3:3c:0e:d6:9c:e2 = -184467440737095516151844674407370955161518446744073709551615
I found a way to archive my goal (see below), but it seems way to complex and too inefficient.
For encoding I basically converting the cpp_int to a uint8_t to get 8 bit and then shift the cpp_int by 8, creating a new cpp_int... Twice (once to compute it's length, again to encode it).
For decoding I already shift the byte read to the "right" position and "|=" it into the existing cpp_int.
Isn't there an easier way access the binary representation of an cpp_int?
Regards,
Steffen
--- #include <iostream> #include <boost/multiprecision/cpp_int.hpp> using namespace std; using namespace boost::multiprecision; size_t binLength( cpp_int value ) { if ( value.is_zero() ) return 1; if ( value.sign() < 0 ) value = ~ value; size_t length = 0; uint8_t lastByte; do { lastByte = value.convert_to<uint8_t>(); value >>= 8; length ++; } while ( ! value.is_zero() ); if ( lastByte >= 0x80 ) length ++; return length; } void binEncode( cpp_int value, uint8_t* output, size_t length ) { if ( value.is_zero() ) *output = 0; else if ( value.sign() > 0 ) while ( length -- > 0 ) { *( output ++ ) = value.convert_to<uint8_t>(); value >>= 8; } else { value = ~ value; while ( length -- > 0 ) { *( output ++ ) = ~ value.convert_to<uint8_t>(); value >>= 8; } } } cpp_int binDecode( uint8_t* input, size_t length ) { boost::multiprecision::cpp_int result( 0 ); int bits = - 8; while ( length -- > 1 ) result |= (boost::multiprecision::cpp_int) *( input ++ ) << ( bits += 8 ); uint8_t a = *( input ++ ); result |= (boost::multiprecision::cpp_int) a << ( bits += 8 ); if ( a >= 0x80 ) result |= (boost::multiprecision::cpp_int) - 1 << ( bits + 8 ); return result; } void test( string s ) { cpp_int x( s ); uint8_t buffer[ 100 ]; size_t length = binLength( x ), index = 0; binEncode( x, buffer, length ); cpp_int y = binDecode( buffer, length ); cout << hex << setw( 2 ) << setfill( '0' ) << (int) buffer[ 0 ]; while ( -- length > 0 ) cout << ':' << setw( 2 ) << setfill( '0' ) << (int) buffer[ ++ index ]; cout << " = " << dec << setw( 1 ) << x << endl; if ( x != y ) cerr << "failed" << endl; } int main( int argc, const char* argv[] ) { test( "0" ); test( "1" ); test( "-1" ); test( "32767" ); test( "-32767" ); test( "32768" ); test( "-32768" ); test( "32769" ); test( "-32769" ); test( "184467440737095516151844674407370955161518446744073709551615" ); test( "-184467440737095516151844674407370955161518446744073709551615" ); }
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net