custom streambuf implementationâ€

M

ma740988

I'm receiving 60 bytes of data from an interface. For discussion
purposes lets consider.
unsigned char data [ 60 ] = { 0x00, 0x05, 0xFE, 0xCA };

The goal: Store the bytes into an array of unsigned short such that:
typedef std::vector < unsigned short > USHORT_VEC ;
USHORT_VEC us_vec ( 2 ) ;
us_vec [ 0 ] = 0x0005 ;
us_vec [ 1 ] = 0xFECA ;

NOTE: a 'simple' memcpy of the data results in 0x500 and 0xCAFE, for
elements 0 and 1 respectively - which is not what I want.
The question: Can I use a custom streambuf implementation - derived
off streambuf to achieve the objective?

I'll admit that the entire streams facility seems daunting (even while
skimming through Langer/Kreft) so source snippet/any help
appreciated.
Thanks
 
J

James Kanze

I'm receiving 60 bytes of data from an interface. For discussion
purposes lets consider.
unsigned char data [ 60 ] = { 0x00, 0x05, 0xFE, 0xCA };
The goal: Store the bytes into an array of unsigned short such that:
typedef std::vector < unsigned short > USHORT_VEC ;
USHORT_VEC us_vec ( 2 ) ;
us_vec [ 0 ] = 0x0005 ;
us_vec [ 1 ] = 0xFECA ;
NOTE: a 'simple' memcpy of the data results in 0x500 and
0xCAFE, for elements 0 and 1 respectively - which is not what
I want. The question: Can I use a custom streambuf
implementation - derived off streambuf to achieve the
objective?
I'll admit that the entire streams facility seems daunting
(even while skimming through Langer/Kreft) so source
snippet/any help appreciated. Thanks

If you already have the data in memory (in an array of unsigned
char), then streambuf is probably not what you're looking for;
streambuf is for sinking and sourcing data, more than anything
else.

All you really need is a simple loop:

template< typename InputIterator, typename OutputIterator >
void
as_short_array(
std::vector< unsigned char >::const_iterator begin,
std::vector< unsigned char >::const_iterator end,
std::back_inserter< std::vector< short > dest )
{
assert( (end - begin) % 2 == 0 );
while ( begin != end ) {
*dest = *begin | (*(begin + 1) << 8);
++ dest;
begin += 2;
}
}

If you want to get a little bit fancier, it would be pretty
simple to create an iterator which does this on the fly, and use
that with std::copy.
 
V

vcbaby

I'm receiving 60 bytes of data from an interface.  For discussion
purposes lets consider.
   unsigned char data [ 60 ] = { 0x00, 0x05, 0xFE, 0xCA };
The goal: Store the bytes into an array of unsigned short such that:
  typedef std::vector < unsigned short > USHORT_VEC ;
  USHORT_VEC us_vec ( 2 ) ;
  us_vec [ 0 ] = 0x0005 ;
  us_vec [ 1 ] = 0xFECA ;
NOTE: a 'simple' memcpy of the data results in 0x500 and
0xCAFE, for elements 0 and 1 respectively - which is not what
I want.  The question:   Can I use a custom streambuf
implementation - derived off streambuf to achieve the
objective?
I'll admit that the entire streams facility seems daunting
(even while skimming through Langer/Kreft) so source
snippet/any help appreciated.  Thanks

If you already have the data in memory (in an array of unsigned
char), then streambuf is probably not what you're looking for;
streambuf is for sinking and sourcing data, more than anything
else.

All you really need is a simple loop:

        template< typename InputIterator, typename OutputIterator >
        void
        as_short_array(
                std::vector< unsigned char >::const_iterator begin,
                std::vector< unsigned char >::const_iterator end,
                std::back_inserter< std::vector< short > dest )
        {
                assert( (end - begin) % 2 == 0 );
                while ( begin != end ) {
                        *dest = *begin | (*(begin + 1) << 8);
                        ++ dest;
                        begin += 2;
                }
        }

If you want to get a little bit fancier, it would be pretty
simple to create an iterator which does this on the fly, and use
that with std::copy.

the above code snippet copy short value in reverse order,
replace line *dest = *begin | (*(begin + 1) << 8);
with *dest = ((*begin)<<8) | *(begin + 1);
you will get the right result
 
M

ma740988

If you already have the data in memory (in an array of unsigned
char), then streambuf is probably not what you're looking for;
streambuf is for sinking and sourcing data, more than anything
else.

Interesting. My question was somewhat vague, nonetheless my
requirement goes beyond unsigned shorts. Part of the motiviation is
the need for a library (outside of Boost - not able to use that)
that's akin to your response at link below. Having said that I'm
assuming a streambuf is (still) a good way to go.

http://groups.google.com/group/comp...77?hl=en&lnk=gst&q=Kanze+XDR#40c6b0d8c779d377
 
J

James Kanze

Interesting. My question was somewhat vague, nonetheless my
requirement goes beyond unsigned shorts. Part of the
motiviation is the need for a library (outside of Boost - not
able to use that) that's akin to your response at link below.
Having said that I'm assuming a streambuf is (still) a good
way to go.

No, the streambuf is *not* what you're looking for. The
streambuf is for getting bytes into or out of your program.
What you need is a new type of stream (which will probably use
streambuf for synching and sourcing its bytes. The code I
posted in the thread you quote is, in fact, extracted (and
slightly modified) from my xdrstream; the actual function names
would be operator<< and operator>>, with the first argument an
oxdrstream or an ixdrstream. From there, it's pretty
straightforward to modify the standard iostream iterators to
provide xdrstream iterators, so that you can write things like:

std::vector< unsigned short > v(
(ixdrstream_iterator< unsigned short >( mySource )),
(ixdrstream_iterator< unsigned short >()) ) ;

(If the file contains only unsigned short. Otherwise, you might
want to use a filtering streambuf to artificially return end of
file when you reach the end of the unsigned shorts.)
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top