Connecting Tech Pros Worldwide Help | Site Map

istringstream question

Luther Baker
Guest
 
Posts: n/a
#1: Jul 22 '05
Hi,

My question is regarding std::istringstream. I am serializing data to
an ostringstream and the resulting buffer turns out just fine.

But, when I try the reverse, when the istringstream encounters the two
byte shorts, it either thinks it has reached the null terminator? or
eof and consequently stops reading values back in. It doesn't matter
whether or not I use the std::ios::binary flag when opening the
istringstream or the readsome method which does in-fact, not report
eof. It still can't build the shorts back up.

Any suggestions would be appreciated. Here is a brief example:


#include <cstring>
#include <sstream>

int
main(int argc, char** argv)
{
typedef unsigned short uint;

char* key = new char[8];
strncpy (key, "the key", 7)[7] = '\0';
uint var1 = 'a';
uint var2 = 'b';

std::ostringstream os;
os.write(key, 8);
os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
std::cout << "stream string: " << os.str() << std::endl;
std::cout << "stream c_str: " << os.str().c_str() << std::endl;

char* keytwo = new char[8];
keytwo[7] = 0;
uint feedme1 = 0;
uint feedme2 = 0;

//
// Here is where my question lies - how to initialize istringstream?
//
std::istringstream is (os.str().c_str(), std::ios::binary);
is.read(keytwo, 8);
std::cout << "\n\nkeytwo: " << keytwo << std::endl;
if (is.eof())
{
std::cout << "END OF FILE!!!" << std::endl;
}

is.read(reinterpret_cast<char*>(&feedme1), sizeof(feedme1));
std::cout << "feedme1: " << feedme1 << std::endl;

is.read(reinterpret_cast<char*>(&feedme2), sizeof(feedme2));
std::cout << "feedme2: " << feedme2 << std::endl;

//
// but it is clear the both shorts are present in the c_str
//
for (int i = 0; i < 12; ++i)
{
std::cout << os.str().c_str()[i] << std::endl;
}

//
// and my favorite way to see what's happening
//
for (int i = 0; i < 12; ++i)
{
std::cout << (int)os.str().c_str()[i] << std::endl;
}

delete [] key;
delete [] keytwo;

return 0;
}



Thanks,

-Luther
Victor Bazarov
Guest
 
Posts: n/a
#2: Jul 22 '05

re: istringstream question


"Luther Baker" <lutherbaker@yahoo.com> wrote...[color=blue]
> My question is regarding std::istringstream. I am serializing data to
> an ostringstream and the resulting buffer turns out just fine.
>
> But, when I try the reverse, when the istringstream encounters the two
> byte shorts, it either thinks it has reached the null terminator? or
> eof and consequently stops reading values back in. It doesn't matter
> whether or not I use the std::ios::binary flag when opening the
> istringstream or the readsome method which does in-fact, not report
> eof. It still can't build the shorts back up.
>
> Any suggestions would be appreciated. Here is a brief example:
>
>
> #include <cstring>
> #include <sstream>
>
> int
> main(int argc, char** argv)
> {
> typedef unsigned short uint;
>
> char* key = new char[8];
> strncpy (key, "the key", 7)[7] = '\0';
> uint var1 = 'a';
> uint var2 = 'b';
>
> std::ostringstream os;
> os.write(key, 8);
> os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
> os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
> std::cout << "stream string: " << os.str() << std::endl;
> std::cout << "stream c_str: " << os.str().c_str() << std::endl;
>
> char* keytwo = new char[8];
> keytwo[7] = 0;
> uint feedme1 = 0;
> uint feedme2 = 0;
>
> //
> // Here is where my question lies - how to initialize istringstream?
> //
> std::istringstream is (os.str().c_str(), std::ios::binary);[/color]

As soon as you use .c_str() here, you lose everything after the first
zero character, which becomes the terminator. You need to use the
string directly:

std::istringstream is(os.str(), std::ios::binary);

HTH
[color=blue]
> is.read(keytwo, 8);
> std::cout << "\n\nkeytwo: " << keytwo << std::endl;
> if (is.eof())
> {
> std::cout << "END OF FILE!!!" << std::endl;
> }
>
> is.read(reinterpret_cast<char*>(&feedme1), sizeof(feedme1));
> std::cout << "feedme1: " << feedme1 << std::endl;
>
> is.read(reinterpret_cast<char*>(&feedme2), sizeof(feedme2));
> std::cout << "feedme2: " << feedme2 << std::endl;
>
> //
> // but it is clear the both shorts are present in the c_str
> //
> for (int i = 0; i < 12; ++i)
> {
> std::cout << os.str().c_str()[i] << std::endl;
> }
>
> //
> // and my favorite way to see what's happening
> //
> for (int i = 0; i < 12; ++i)
> {
> std::cout << (int)os.str().c_str()[i] << std::endl;
> }
>
> delete [] key;
> delete [] keytwo;
>
> return 0;
> }
>
>
>
> Thanks,
>
> -Luther[/color]


Luther Baker
Guest
 
Posts: n/a
#3: Jul 22 '05

re: istringstream question


Victor Bazarov wrote:
[color=blue]
> "Luther Baker" <lutherbaker@yahoo.com> wrote...
>[color=green]
>>My question is regarding std::istringstream. I am serializing data to
>>an ostringstream and the resulting buffer turns out just fine.[/color][/color]
....[color=blue][color=green]
>>std::ostringstream os;
>>os.write(key, 8);
>>os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
>>os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
>>std::cout << "stream string: " << os.str() << std::endl;
>>std::cout << "stream c_str: " << os.str().c_str() << std::endl;
>>
>>char* keytwo = new char[8];
>>keytwo[7] = 0;
>>uint feedme1 = 0;
>>uint feedme2 = 0;
>>
>> //
>> // Here is where my question lies - how to initialize istringstream?
>> //
>>std::istringstream is (os.str().c_str(), std::ios::binary);[/color]
>
>
> As soon as you use .c_str() here, you lose everything after the first
> zero character, which becomes the terminator. You need to use the
> string directly:
>
> std::istringstream is(os.str(), std::ios::binary);[/color]

Ah.

So - for my real project, I have the following:

void AnObject::DeSerialize(const void* buffer)
{
std::istringstream ( ? ... );
....
}

Following your lead, I'll try to create a string.

std::string str(reinterpret_cast<const char*>(buffer));

Nope. Loses the tail end ... (NULL terminated)

const int size = X;
std::string str(size, size)
for (int i = 1; i < size; ++i)
{
str[i] = buffer[i];
}

Ah ... that works! And I do, in fact, know exactly how many bytes I need
to copy.

Would you suggest a smoother way or different approach now that you see
a bit more of what I'm after?

Thanks,

-Luther
Victor Bazarov
Guest
 
Posts: n/a
#4: Jul 22 '05

re: istringstream question


"Luther Baker" <lutherbaker@yahoo.com> wrote...[color=blue]
> Victor Bazarov wrote:
>[color=green]
> > "Luther Baker" <lutherbaker@yahoo.com> wrote...
> >[color=darkred]
> >>My question is regarding std::istringstream. I am serializing data to
> >>an ostringstream and the resulting buffer turns out just fine.[/color][/color]
> ...[color=green][color=darkred]
> >>std::ostringstream os;
> >>os.write(key, 8);
> >>os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
> >>os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
> >>std::cout << "stream string: " << os.str() << std::endl;
> >>std::cout << "stream c_str: " << os.str().c_str() << std::endl;
> >>
> >>char* keytwo = new char[8];
> >>keytwo[7] = 0;
> >>uint feedme1 = 0;
> >>uint feedme2 = 0;
> >>
> >> //
> >> // Here is where my question lies - how to initialize[/color][/color][/color]
istringstream?[color=blue][color=green][color=darkred]
> >> //
> >>std::istringstream is (os.str().c_str(), std::ios::binary);[/color]
> >
> >
> > As soon as you use .c_str() here, you lose everything after the first
> > zero character, which becomes the terminator. You need to use the
> > string directly:
> >
> > std::istringstream is(os.str(), std::ios::binary);[/color]
>
> Ah.
>
> So - for my real project, I have the following:
>
> void AnObject::DeSerialize(const void* buffer)
> {
> std::istringstream ( ? ... );
> ....
> }
>
> Following your lead, I'll try to create a string.
>
> std::string str(reinterpret_cast<const char*>(buffer));
>
> Nope. Loses the tail end ... (NULL terminated)
>
> const int size = X;
> std::string str(size, size)
> for (int i = 1; i < size; ++i)
> {
> str[i] = buffer[i];
> }[/color]

Don't you mean

std::string str(buffer, size);

?
[color=blue]
>
> Ah ... that works! And I do, in fact, know exactly how many bytes I need
> to copy.
>
> Would you suggest a smoother way or different approach now that you see
> a bit more of what I'm after?[/color]

I am not sure what way would be "smoother". If you need to have meaningful
zeroes in the "buffer", then you cannot hope to call deserialise without
passing the size of the stream in, btw.

void AnObject::Deserialize(const char *buffer)
{
std::istringstream is(std::string(buffer, size), ios::binary);
// now read from it
}

Victor


Mike Wahler
Guest
 
Posts: n/a
#5: Jul 22 '05

re: istringstream question



"Luther Baker" <lutherbaker@yahoo.com> wrote in message
news:2h7rgrF9uacdU1@uni-berlin.de...[color=blue]
> Victor Bazarov wrote:
>[color=green]
> > "Luther Baker" <lutherbaker@yahoo.com> wrote...
> >[color=darkred]
> >>My question is regarding std::istringstream. I am serializing data to
> >>an ostringstream and the resulting buffer turns out just fine.[/color][/color]
> ...[color=green][color=darkred]
> >>std::ostringstream os;
> >>os.write(key, 8);
> >>os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
> >>os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
> >>std::cout << "stream string: " << os.str() << std::endl;
> >>std::cout << "stream c_str: " << os.str().c_str() << std::endl;
> >>
> >>char* keytwo = new char[8];
> >>keytwo[7] = 0;
> >>uint feedme1 = 0;
> >>uint feedme2 = 0;
> >>
> >> //
> >> // Here is where my question lies - how to initialize[/color][/color][/color]
istringstream?[color=blue][color=green][color=darkred]
> >> //
> >>std::istringstream is (os.str().c_str(), std::ios::binary);[/color]
> >
> >
> > As soon as you use .c_str() here, you lose everything after the first
> > zero character, which becomes the terminator. You need to use the
> > string directly:
> >
> > std::istringstream is(os.str(), std::ios::binary);[/color]
>
> Ah.
>
> So - for my real project, I have the following:
>
> void AnObject::DeSerialize(const void* buffer)
> {
> std::istringstream ( ? ... );
> ....
> }
>
> Following your lead, I'll try to create a string.
>
> std::string str(reinterpret_cast<const char*>(buffer));
>
> Nope. Loses the tail end ... (NULL terminated)
>
> const int size = X;
> std::string str(size, size)
> for (int i = 1; i < size; ++i)
> {
> str[i] = buffer[i];
> }
>
> Ah ... that works! And I do, in fact, know exactly how many bytes I need
> to copy.
>
> Would you suggest a smoother way or different approach now that you see
> a bit more of what I'm after?[/color]

const char *p = static_cast<const char *>buffer;
std::string str(p, p + X);

-Mike


Luther Baker
Guest
 
Posts: n/a
#6: Jul 22 '05

re: istringstream question


Victor Bazarov wrote:[color=blue]
> "Luther Baker" <lutherbaker@yahoo.com> wrote...
>[/color]
....[color=blue][color=green]
>> const int size = X;
>> std::string str(size, size)
>> for (int i = 1; i < size; ++i)
>> {
>> str[i] = buffer[i];
>> }[/color]
>
>
> Don't you mean
>
> std::string str(buffer, size);[/color]
....[color=blue]
>
> I am not sure what way would be "smoother". If you need to have meaningful
> zeroes in the "buffer", then you cannot hope to call deserialise without
> passing the size of the stream in, btw.
>
> void AnObject::Deserialize(const char *buffer)
> {
> std::istringstream is(std::string(buffer, size), ios::binary);
> // now read from it
> }
>[/color]

For some reason, I thought that *std::string str(buffer, size);* would
have strncpy semantics and stop copying buffer at the first null. But as
I'm sure you're aware, it doesn't.

When I said "smoother" I guess I meant more elegant. It seems clunky to
have to create a std::string to get a std::istringstream interface over
the buffer - but I guess it is a *string* stream.

Many Thanks,

-Luther
Luther Baker
Guest
 
Posts: n/a
#7: Jul 22 '05

re: istringstream question


Mike Wahler wrote:
[color=blue]
> "Luther Baker" <lutherbaker@yahoo.com> wrote in message
> news:2h7rgrF9uacdU1@uni-berlin.de...[/color]
....[color=blue][color=green]
>>
>>Would you suggest a smoother way or different approach now that you see
>>a bit more of what I'm after?[/color]
>
>
> const char *p = static_cast<const char *>buffer;
> std::string str(p, p + X);[/color]

Does that imply

string::string (const char* cstrBegin, const char* cstrEnd);

Josuttis pg.509 left that one out! unless that is silently turned into

string::string (InputIterator beg, InputIterator end);

Thanks for your insight,

-Luther



John Harrison
Guest
 
Posts: n/a
#8: Jul 22 '05

re: istringstream question


>[color=blue]
> When I said "smoother" I guess I meant more elegant. It seems clunky to
> have to create a std::string to get a std::istringstream interface over
> the buffer - but I guess it is a *string* stream.
>[/color]

Use an istrstream instead. Reading from a fixed size buffer is about the
only reasonable use of strstream.

john


Closed Thread