How to get the count of a stringstream

I am creating a BINARY string stream that can do both input and output. I want to create a function that would give me the current size in bytes anytime I do an input or/and output when you do a read() or a write().

I have created this small example and I expected the gcount() would do that. But did not.

#include <string>
#include <iostream>
#include <sstream>
 
int main ()
{
  std::stringstream sstr(std::stringstream::in  |  std::stringstream::out | std::stringstream::binary );

  sstr.write("50", sizeof (int));
  std::cout << "Count " << sstr.gcount() << std::endl;   //Expected 4, but I get 0

  char readString[10];
  sstr.read(readString, sizeof (int));;
  std::cout << "Count " << sstr.gcount() << std::endl;  // This is OK.
   return 0;
}

Any ideas how to do that?
prainAsked:
Who is Participating?
 
Infinity08Connect With a Mentor Commented:
It sounds like you're using the wrong tool for the job.

std::stringstream's are streams, not containers. Getting their size is not relevant for streams.

You can however find out how many bytes can be read from the stream using :

        sstr.rdbuf()->in_avail()

Don't be surprised if it doesn't behave exactly like what you'd expect though, because it does not get the amount of bytes that have been written into the buffer, but rather the amount that are immediately available to be read in the internal buffer (or an estimation if the number of bytes expected to be available of the internal buffer is empty).

For more details, refer to these reference pages :

        http://www.cplusplus.com/reference/iostream/stringstream/rdbuf/
        http://www.cplusplus.com/reference/iostream/streambuf/in_avail/

If this does not do what you want, then a stream is not what you want to use. You might want some kind of circular buffer.
0
 
jkrCommented:
What about 'sstr.str().size()'?
0
 
Infinity08Commented:
gcount gets the number of characters that were obtained by the last (unformatted) input operation. Doing a write is not an input operation.
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
prainAuthor Commented:
jkr,
Thanks. But what I am expecting is to internal buffer to change when you do a write and a read.

In the following example I am expecting after the two reads, the buffer size() to be 0, because to me read() means "you read out" completely from the buffer.
Seems it's not hapenning in stringstreams. So I was thinking to create my own function to do that.

#include <string>
#include <iostream>
#include <sstream>
 
int main ()
{
  std::stringstream sstr(std::stringstream::in  |  std::stringstream::out | std::stringstream::binary );

  sstr.write("50", sizeof (int));
  std::cout << "Internal Buffer 1 : " << sstr.str().size() << std::endl;

  sstr.write("12.34", sizeof (float));
  std::cout << "Internal Buffer 2 : " << sstr.str().size() << std::endl;

  char readString[10];
  sstr.read(readString, sizeof (int));;
  std::cout << "Internal Buffer 3 : " << sstr.str().size() << std::endl;
//I am expecting the size() to be 4


  sstr.read(readString, sizeof (float));;
  std::cout << "Internal Buffer 4 : " << sstr.str().size() << std::endl;
//I am expecting the size() to be 0

 
  return 0;
}
0
 
jkrCommented:
Hmmm, your assumptions are wrong for one simple reason:

#include <string>
#include <iostream>
#include <sstream>
 
int main ()
{
  std::stringstream sstr(std::stringstream::in  |  std::stringstream::out | std::stringstream::binary );

  sstr.write("50", sizeof (int)); // writes 4 bytes, since 'sizeof(int) == 4'
  std::cout << "Internal Buffer 1 : " << sstr.str().size() << std::endl;

  sstr.write("12.34", sizeof (float)); // writes 4 bytes, since 'sizeof(float) == 4'
  std::cout << "Internal Buffer 2 : " << sstr.str().size() << std::endl;

  char readString[10];
  sstr.read(readString, sizeof (int));; // reads 4 bytes, since 'sizeof(int) == 4'
  std::cout << "Internal Buffer 3 : " << sstr.str().size() << std::endl;
//I am expecting the size() to be 4


  sstr.read(readString, sizeof (float));; // reads 4 bytes, since 'sizeof(int) == 4'
  std::cout << "Internal Buffer 4 : " << sstr.str().size() << std::endl;
//I am expecting the size() to be 0

 
  return 0;
}

Open in new window


But anyway, 'size()' does not seem to work...
0
 
sarabandeCommented:
if you want to write binary data to stringstream do

int i = 50;
ss.write((char*)&i, sizeof(i));

Open in new window


you wouldn't need the binary flag to store binary data cause the binary flag rules only line endings when reading from/writing to files.  

at windows if opening files in text mode a read operation would convert a  CRLF pair in the file  (hex 0x0D 0x0A or '\r' '\n'  in c++) to a single '\n'  in buffer. in a write operation windows would convert '\n' to a CRLF pair in file. as far as i know it has no meaning for stringstream.

stringstream is a typedef of basic_stringstream and is derived from basic_iostream which is derived from both basic_istream and basic_ostream. so actually it is two stream objects though both streams do share a member pointer to basic_streambuf via the common virtual baseclass basic_ios.

              basic_ios
        /                         \
basic_istream     basic_ostream
       \                         /
       basic_iostream
                   |
      basic_stringstream

you could not access the streambuf member of basic_ios directly cause it is a private member, but for my STL the member function rdbuf() would return that pointer.

streambuf has some public member functions like sgetn which returns the count of characters up from a given pointer (pointing into buffer). but all that could be specific to my compiler and its standard library and may not have same implementation at your system.

generally, it seemed easier for me to access the buffer via str() member function as you did. after a write operation the str.size() would show size of the output string buffer. after a read operation (if successful) it should show 0 beside your read operation doesn't read all of the string. so if the ss.str().size() was 10 before read and you read 4 byte, i would expect a rest of 6.

Sara
0
 
prainAuthor Commented:
It sounds like this is not what I want. But let me tyest out couple of examples and post back here.

BTW, If I use another data structure such as a Queue so something, how would I store "Binary Data". That's for sure is a requirement for us.
0
 
Infinity08Connect With a Mentor Commented:
>> BTW, If I use another data structure such as a Queue so something, how would I store "Binary Data". That's for sure is a requirement for us.

Containers are usually templated, allowing you to store any type of data you want.

You just need to find the right container for your specific needs.
0
 
Infinity08Connect With a Mentor Commented:
Just noticed sarabande's post. While that post is not really relevant for the most part, I wanted to clear up some things to avoid confusion :

>> so actually it is two stream objects though both streams

No it doesn't. That's what virtual inheritance is for.

>> you could not access the streambuf member of basic_ios directly cause it is a private member

No it's not. rdbuf is a public member function.

>> sgetn which returns the count of characters up from a given pointer (pointing into buffer).

No it doesn't. It copies data from the buffer into the provided memory location.
0
 
sarabandeCommented:
the basic_ostream and basic_istream part are two objects which share a common basic_ios.

the rdbuf is a member function, the streambuf member is a data member. while the first is public, the second is private (at my system) and could not accessed directly. that is exactly what was told.

the sgetn rightly does a copy. it returns streamsize what made me think it returns the current size of the stream buffer. that is not true. it returns the number of character copied.  

for storing binary and text data usually a std::vector<unsigned char> would be a good choice. you could make an own container class which has the vector as a member and some additional 'pointers' into that buffer. that way the class could behave like a stream if that is the goal. if you want to serialize data for exchange in a network you might consider boost library which has excellent solutions for that.

Sara
0
 
sarabandeCommented:
the istream and ostream both add additional members to the shared streambuf which need to be considered cause those determine the interface to the internal buffer. for example, the basic_istream has a member of type streamsize (_Chcount on my system)  which was commented as "character count" and therefore likely is relevant for the question. also in memory there are at least two separated locations where the 'object' was stored. simplification of a complex multi-inheritance class doesn't help avoiding misunderstandings. my understanding of such an object is a graph where each class involved has its own node.

the comment regarding rdbuf was made parallel to the comment of infinity08. it was not intended to add the same information twice. i added the 'obvious' cause oop principles normally would forbid to expose private members by a public getter. i think the rdbuf was provided to allow classes which use a stream class as member to get access to the internal buffer of that stream.

Sara
0
 
prainAuthor Commented:
evilrix,
Thanks. Yes, I finally got this working the way I want by warapping a stringstream and then having my own counter within the class. The reason I wanted to use a stringstream is because of it's performance. we have done some performance testing on other data structures such as deques, stacks, lists etc and the results of those containers are no where near how stringstream performs specially on a network application. So it was worth for me to warpup a stringstream and build my own class to do the operations I wanted.

Thanks again all.
prain
0
 
evilrixSenior Software Engineer (Avast)Commented:
Fab. I'm very pleased you found a solution that worked for you. :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.