I had a hard time trying to serialize multiple messages in a
std::ostream, and then trying to parse them one at a time from an
std::istream, so I'm sharing my code for two reasons:
- It may be useful for someone else.
- To receive comments from more experienced people.

template <typename TMessage>
bool serialize_delimited(std::ostream& stream, TMessage& message)
{
        assert(message.IsInitialized());

        google::protobuf::io::OstreamOutputStream ostreamWrapper(&stream);
        google::protobuf::io::CodedOutputStream
codedOStream(&ostreamWrapper);

        // Write the message size first.
        int messageSize = message.ByteSize();
        assert(messageSize > 0);
        codedOStream.WriteLittleEndian32(messageSize);

        // Write the message.
        message.SerializeWithCachedSizes(&codedOStream);

        return stream.good();
}

template <typename TMessage>
bool parse_delimited(std::istream& stream, TMessage& message)
{
        uint32_t messageSize = 0;

        // Read the message size.
        {
                google::protobuf::io::IstreamInputStream istreamWrapper(&stream,
sizeof(uint32_t));
                google::protobuf::io::CodedInputStream
codedIStream(&istreamWrapper);

                // Don't consume more than sizeof(uint32_t) from the stream.
                google::protobuf::io::CodedInputStream::Limit oldLimit =
codedIStream.PushLimit(sizeof(uint32_t));
                codedIStream.ReadLittleEndian32(&messageSize);
                codedIStream.PopLimit(oldLimit);
                assert(messageSize > 0);
                assert(istreamWrapper.ByteCount() == sizeof(uint32_t));
        }

        // Read the message.
        {
                google::protobuf::io::IstreamInputStream istreamWrapper(&stream,
messageSize);
                google::protobuf::io::CodedInputStream
codedIStream(&istreamWrapper);

                // Read the message, but don't consume more than messageSize 
bytes
from the stream.
                google::protobuf::io::CodedInputStream::Limit oldLimit =
codedIStream.PushLimit(messageSize);
                message.ParseFromCodedStream(&codedIStream);
                codedIStream.PopLimit(oldLimit);
                assert(istreamWrapper.ByteCount() == messageSize);
        }

        return stream.good();
}

serialize_delimited is pretty simple. I write the message size first,
and then the message.

The tricky part was parsing from a stream. The problem that I was
facing was that after CodedInputStream got constructed, my stream was
consumed more than I wanted to. The first message was parsed
correctly, but for the rest the stream was not in the right position.
 The only way I found to avoid that was by setting the block_size
parameter while constructing IstreamInputStream instances, and that is
why I construct them twice (first to parse the size, then to parse the
message).

-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To post to this group, send email to protobuf@googlegroups.com.
To unsubscribe from this group, send email to 
protobuf+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en.

Reply via email to