Converting between vectors

L

LR

Andrea said:
long intsToLong(int x, int y)
{
long tmp = x;
tmp <<= int_bits;
tmp += y;

The above line will almost certainly cause problems. Try calling
intsToLong(-1,-1).
return tmp;
}

void longToInts(long l)
{
int second = l >> int_bits;
long mask = (2 >> (int_bits + 1)) - 1;

I don't think the above will do what you want. I think you ought to
consider making mask, static const, since you probably don't want to
compute it everytime you call longToInts.
int first = l & mask;
std::cout << " first " << first << " second " << second << std::endl;
}

Can you please tell me what sizeof(short), sizeof(int) and sizeof(long)
are on your platform?

LR
 
A

Andrea Crotti

LR said:
This makes me feel a little uncertain as to the problem you actually
want to solve, since what you posted converts packs and unpacks long and
int.

LR

I'm sorry yes I created some confusion.
The main task is what I wrote, which is basically a serialization of
generic long types in a stream of chars and the other way around.

The other example with the longToInt was just a toy example to let me
understand how this can be done...
 
K

Kai-Uwe Bux

Andrea said:
I'm sorry yes I created some confusion.
The main task is what I wrote, which is basically a serialization of
generic long types in a stream of chars and the other way around.

The other example with the longToInt was just a toy example to let me
understand how this can be done...

Here is a (bad) idea:

#include <utility>

template < typename InIter, typename OutIter >
std::pair<InIter, OutIter >
copy_n ( InIter from, OutIter where, std::size_t n ) {
for ( std::size_t i = 0; i < n; ++i ) {
*where = *from;
++ where;
++ from;
}
return ( std::pair< InIter, OutIter >( from, where ) );
}


template < typename InIter >
class binary_writer {

InIter where;

public:

binary_writer ( InIter from )
: where ( from )
{}

template < typename IntegerType >
binary_writer & operator<< ( IntegerType const & value ) {
unsigned char const * from =
static_cast < unsigned char const * >
( static_cast < void const * > ( &value ) );
where = copy_n( from, where, sizeof( IntegerType ) ).second;
return ( *this );
}

InIter position ( void ) const {
return ( where );
}

};

template < typename OutIter >
class binary_reader {

OutIter where;

public:

binary_reader ( OutIter from )
: where ( from )
{}

template < typename IntegerType >
binary_reader & operator>>( IntegerType & value ) {
unsigned char * from =
static_cast < unsigned char * >
( static_cast < void * > ( &value ) );
where = copy_n( where, from, sizeof( IntegerType ) ).first;
return ( *this );
}

OutIter position ( void ) const {
return ( where );
}

};

#include <vector>
#include <iostream>
#include <iterator>

int main ( void ) {
typedef std::vector< unsigned char > buffer_t;
typedef std::back_insert_iterator< buffer_t > out_iterator;
typedef buffer_t::const_iterator in_iterator;

int i = 1231414;
short j = 12341;

buffer_t the_buffer;

binary_writer< out_iterator > bw ( std::back_inserter( the_buffer ) );
bw << i << j;

int k;
short l;
binary_reader< in_iterator > br ( the_buffer.begin() );
br >> k >> l;

std::cout << "i = " << i << " k = " << k << "\n";
std::cout << "j = " << j << " l = " << l << "\n";
}

It is very clear that this code is in a state of sin: the casting testifies
to that. Drawbacks include, but may not be limited to:

(a) The code relies on binary representation and type sizes. So, if you use
this to transmit data through a network, both sides have to agree on that.
E.g., you could not use it to transmit ints from a 2-complement machine to a
signed magnitude machine.

(b) The code can be argued to invoke undefined behavior as it accesses an
object as an array of unsigned characters. This is usually fine for POD
types without padding, such as integer types of various sizes.


Generally, you should rather settle on a machine-independent protocol and
write conversion routines from and to the protocol.


Best,

Kai-Uwe
 
J

Jeff Flinn

Kai-Uwe Bux said:
Here is a (bad) idea:

#include <utility>

template < typename InIter, typename OutIter >
std::pair<InIter, OutIter >
copy_n ( InIter from, OutIter where, std::size_t n ) {
for ( std::size_t i = 0; i < n; ++i ) {
*where = *from;
++ where;
++ from;
}
return ( std::pair< InIter, OutIter >( from, where ) );
}


template < typename InIter >
class binary_writer {

InIter where;

public:

binary_writer ( InIter from )
: where ( from )
{}

template < typename IntegerType >
binary_writer & operator<< ( IntegerType const & value ) {
unsigned char const * from =
static_cast < unsigned char const * >
( static_cast < void const * > ( &value ) );
where = copy_n( from, where, sizeof( IntegerType ) ).second;
return ( *this );
}

InIter position ( void ) const {
return ( where );
}

};

template < typename OutIter >
class binary_reader {

OutIter where;

public:

binary_reader ( OutIter from )
: where ( from )
{}

template < typename IntegerType >
binary_reader & operator>>( IntegerType & value ) {
unsigned char * from =
static_cast < unsigned char * >
( static_cast < void * > ( &value ) );
where = copy_n( where, from, sizeof( IntegerType ) ).first;
return ( *this );
}

OutIter position ( void ) const {
return ( where );
}

};

#include <vector>
#include <iostream>
#include <iterator>

int main ( void ) {
typedef std::vector< unsigned char > buffer_t;
typedef std::back_insert_iterator< buffer_t > out_iterator;
typedef buffer_t::const_iterator in_iterator;

int i = 1231414;
short j = 12341;

buffer_t the_buffer;

binary_writer< out_iterator > bw ( std::back_inserter( the_buffer ) );
bw << i << j;

int k;
short l;
binary_reader< in_iterator > br ( the_buffer.begin() );
br >> k >> l;

std::cout << "i = " << i << " k = " << k << "\n";
std::cout << "j = " << j << " l = " << l << "\n";
}

It is very clear that this code is in a state of sin: the casting testifies
to that. Drawbacks include, but may not be limited to:

(a) The code relies on binary representation and type sizes. So, if you use
this to transmit data through a network, both sides have to agree on that.
E.g., you could not use it to transmit ints from a 2-complement machine to a
signed magnitude machine.

(b) The code can be argued to invoke undefined behavior as it accesses an
object as an array of unsigned characters. This is usually fine for POD
types without padding, such as integer types of various sizes.


Generally, you should rather settle on a machine-independent protocol and
write conversion routines from and to the protocol.


Best,

Kai-Uwe

Since all the op's examples imply only integer types, and assuming the
integral value of the source can fit in a variable of destination type,
why not just use the standard technique:

The sender:

std::eek:stringsteam os;

std::copy
( v_from.begin()
, v_from.end()
, std::eek:stream_iterator<char>(os)
);

// send os.str().c_str with size os.str().size()

The receiver:

std::istringstream is(source_data);

std::copy
( std::istream_iterator<DESTTYPE>(is)
, std::istream_iterator<DESTTYPE>()
, std::back_inserter(v_to)
);

FYI boost's license allows you to copy and modify concepts and code to
your hearts content. Just because you aren't allowed to use boost
wholesale in your organization, doesn't mean 'you' can't use it.

Jeff
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top