forked from protocolbuffers/protobuf
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
migrate delimited messages functions to util package
- Loading branch information
Showing
6 changed files
with
207 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Adapted from the patch of [email protected] (Kenton Varda) | ||
// See https://github.com/google/protobuf/pull/710 for details. | ||
|
||
#include <google/protobuf/util/delimited_message_util.h> | ||
|
||
namespace google { | ||
namespace protobuf { | ||
namespace util { | ||
|
||
bool SerializeDelimitedToFileDescriptor(const Message* message, int file_descriptor) { | ||
io::FileOutputStream output(file_descriptor); | ||
return SerializeDelimitedToZeroCopyStream(message, &output); | ||
} | ||
|
||
bool SerializeDelimitedToOstream(const Message* message, ostream* output) { | ||
{ | ||
io::OstreamOutputStream zero_copy_output(output); | ||
if (!SerializeDelimitedToZeroCopyStream(message, &zero_copy_output)) return false; | ||
} | ||
return output->good(); | ||
} | ||
|
||
bool ParseDelimitedFromZeroCopyStream(MessageLite* message, io::ZeroCopyInputStream* input, bool* clean_eof) { | ||
google::protobuf::io::CodedInputStream coded_input(input); | ||
return ParseDelimitedFromCodedStream(message, &coded_input, clean_eof); | ||
} | ||
|
||
bool ParseDelimitedFromCodedStream(MessageLite* message, io::CodedInputStream* input, bool* clean_eof) { | ||
if (clean_eof != NULL) *clean_eof = false; | ||
int start = input->CurrentPosition(); | ||
|
||
// Read the size. | ||
uint32 size; | ||
if (!input->ReadVarint32(&size)) { | ||
if (clean_eof != NULL) *clean_eof = input->CurrentPosition() == start; | ||
return false; | ||
} | ||
|
||
// Tell the stream not to read beyond that size. | ||
google::protobuf::io::CodedInputStream::Limit limit = input->PushLimit(size); | ||
|
||
// Parse the message. | ||
if (!message->MergeFromCodedStream(input)) return false; | ||
if (!input->ConsumedEntireMessage()) return false; | ||
|
||
// Release the limit. | ||
input->PopLimit(limit); | ||
|
||
return true; | ||
} | ||
|
||
bool SerializeDelimitedToZeroCopyStream(const MessageLite* message, io::ZeroCopyOutputStream* output) { | ||
google::protobuf::io::CodedOutputStream coded_output(output); | ||
return SerializeDelimitedToCodedStream(message, &coded_output); | ||
} | ||
|
||
bool SerializeDelimitedToCodedStream(const MessageLite* message, io::CodedOutputStream* output) { | ||
// Write the size. | ||
int size = message->ByteSize(); | ||
output->WriteVarint32(size); | ||
|
||
// Write the content. | ||
uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size); | ||
if (buffer != NULL) { | ||
// Optimization: The message fits in one buffer, so use the faster | ||
// direct-to-array serialization path. | ||
message->SerializeWithCachedSizesToArray(buffer); | ||
} else { | ||
// Slightly-slower path when the message is multiple buffers. | ||
message->SerializeWithCachedSizes(output); | ||
if (output->HadError()) return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
} // namespace util | ||
} // namespace protobuf | ||
} // namespace google |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Adapted from the patch of [email protected] (Kenton Varda) | ||
// See https://github.com/google/protobuf/pull/710 for details. | ||
|
||
#ifndef GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__ | ||
#define GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__ | ||
|
||
#include <ostream> | ||
|
||
#include <google/protobuf/message.h> | ||
#include <google/protobuf/io/coded_stream.h> | ||
#include <google/protobuf/io/zero_copy_stream_impl.h> | ||
|
||
namespace google { | ||
namespace protobuf { | ||
namespace util { | ||
|
||
// Write a single size-delimited message from the given stream. Delimited | ||
// format allows a single file or stream to contain multiple messages, | ||
// whereas normally writing multiple non-delimited messages to the same | ||
// stream would cause them to be merged. A delimited message is a varint | ||
// encoding the message size followed by a message of exactly that size. | ||
// | ||
// Note that if you want to *read* a delimited message from a file descriptor | ||
// or istream, you will need to construct an io::FileInputStream or | ||
// io::OstreamInputStream (implementations of io::ZeroCopyStream) and use the | ||
// MessageLite method ParseDelimitedFromZeroCopyStream(). You must then | ||
// continue to use the same ZeroCopyInputStream to read all further data from | ||
// the stream until EOF. This is because these ZeroCopyInputStream | ||
// implementations are buffered: they read a big chunk of data at a time, | ||
// then parse it. As a result, they may read past the end of the delimited | ||
// message. There is no way for them to push the extra data back into the | ||
// underlying source, so instead you must keep using the same stream object. | ||
bool SerializeDelimitedToFileDescriptor(const Message* message, int file_descriptor); | ||
|
||
bool SerializeDelimitedToOstream(const Message* message, ostream* output); | ||
|
||
// Read a single size-delimited message from the given stream. Delimited | ||
// format allows a single file or stream to contain multiple messages, | ||
// whereas normally parsing consumes the entire input. A delimited message | ||
// is a varint encoding the message size followed by a message of exactly | ||
// that size. | ||
// | ||
// If |clean_eof| is not NULL, then it will be set to indicate whether the | ||
// stream ended cleanly. That is, if the stream ends without this method | ||
// having read any data at all from it, then *clean_eof will be set true, | ||
// otherwise it will be set false. Note that these methods return false | ||
// on EOF, but they also return false on other errors, so |clean_eof| is | ||
// needed to distinguish a clean end from errors. | ||
bool ParseDelimitedFromZeroCopyStream(MessageLite* message, io::ZeroCopyInputStream* input, bool* clean_eof); | ||
|
||
bool ParseDelimitedFromCodedStream(MessageLite* message, io::CodedInputStream* input, bool* clean_eof); | ||
|
||
// Write a single size-delimited message from the given stream. Delimited | ||
// format allows a single file or stream to contain multiple messages, | ||
// whereas normally writing multiple non-delimited messages to the same | ||
// stream would cause them to be merged. A delimited message is a varint | ||
// encoding the message size followed by a message of exactly that size. | ||
bool SerializeDelimitedToZeroCopyStream(const MessageLite* message, io::ZeroCopyOutputStream* output); | ||
|
||
bool SerializeDelimitedToCodedStream(const MessageLite* message, io::CodedOutputStream* output); | ||
|
||
} // namespace util | ||
} // namespace protobuf | ||
} // namespace google | ||
|
||
#endif // GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Adapted from the patch of [email protected] (Kenton Varda) | ||
// See https://github.com/google/protobuf/pull/710 for details. | ||
|
||
#include <google/protobuf/util/delimited_message_util.h> | ||
|
||
#include <sstream> | ||
|
||
#include <google/protobuf/test_util.h> | ||
#include <google/protobuf/unittest.pb.h> | ||
#include <google/protobuf/testing/googletest.h> | ||
#include <gtest/gtest.h> | ||
|
||
namespace google { | ||
namespace protobuf { | ||
namespace util { | ||
|
||
TEST(MessageTest, DelimitedMessages) { | ||
stringstream stream; | ||
|
||
{ | ||
protobuf_unittest::TestAllTypes message1; | ||
TestUtil::SetAllFields(&message1); | ||
EXPECT_TRUE(SerializeDelimitedToOstream(&message1, &stream)); | ||
|
||
protobuf_unittest::TestPackedTypes message2; | ||
TestUtil::SetPackedFields(&message2); | ||
EXPECT_TRUE(SerializeDelimitedToOstream(&message2, &stream)); | ||
} | ||
|
||
{ | ||
bool clean_eof; | ||
io::IstreamInputStream zstream(&stream); | ||
|
||
protobuf_unittest::TestAllTypes message1; | ||
clean_eof = true; | ||
EXPECT_TRUE(ParseDelimitedFromZeroCopyStream(&message1, | ||
&zstream, &clean_eof)); | ||
EXPECT_FALSE(clean_eof); | ||
TestUtil::ExpectAllFieldsSet(message1); | ||
|
||
protobuf_unittest::TestPackedTypes message2; | ||
clean_eof = true; | ||
EXPECT_TRUE(ParseDelimitedFromZeroCopyStream(&message2, | ||
&zstream, &clean_eof)); | ||
EXPECT_FALSE(clean_eof); | ||
TestUtil::ExpectPackedFieldsSet(message2); | ||
|
||
clean_eof = false; | ||
EXPECT_FALSE(ParseDelimitedFromZeroCopyStream(&message2, | ||
&zstream, &clean_eof)); | ||
EXPECT_TRUE(clean_eof); | ||
} | ||
} | ||
|
||
} // namespace util | ||
} // namespace protobuf | ||
} // namespace google |