• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Adapted from the patch of kenton@google.com (Kenton Varda)
9 // See https://github.com/protocolbuffers/protobuf/pull/710 for details.
10 
11 #include "google/protobuf/util/delimited_message_util.h"
12 
13 #include "google/protobuf/io/coded_stream.h"
14 
15 namespace google {
16 namespace protobuf {
17 namespace util {
18 
SerializeDelimitedToFileDescriptor(const MessageLite & message,int file_descriptor)19 bool SerializeDelimitedToFileDescriptor(const MessageLite& message,
20                                         int file_descriptor) {
21   io::FileOutputStream output(file_descriptor);
22   return SerializeDelimitedToZeroCopyStream(message, &output);
23 }
24 
SerializeDelimitedToOstream(const MessageLite & message,std::ostream * output)25 bool SerializeDelimitedToOstream(const MessageLite& message,
26                                  std::ostream* output) {
27   {
28     io::OstreamOutputStream zero_copy_output(output);
29     if (!SerializeDelimitedToZeroCopyStream(message, &zero_copy_output))
30       return false;
31   }
32   return output->good();
33 }
34 
ParseDelimitedFromZeroCopyStream(MessageLite * message,io::ZeroCopyInputStream * input,bool * clean_eof)35 bool ParseDelimitedFromZeroCopyStream(MessageLite* message,
36                                       io::ZeroCopyInputStream* input,
37                                       bool* clean_eof) {
38   io::CodedInputStream coded_input(input);
39   return ParseDelimitedFromCodedStream(message, &coded_input, clean_eof);
40 }
41 
ParseDelimitedFromCodedStream(MessageLite * message,io::CodedInputStream * input,bool * clean_eof)42 bool ParseDelimitedFromCodedStream(MessageLite* message,
43                                    io::CodedInputStream* input,
44                                    bool* clean_eof) {
45   if (clean_eof != nullptr) *clean_eof = false;
46   int start = input->CurrentPosition();
47 
48   // Read the size.
49   uint32_t size;
50   if (!input->ReadVarint32(&size)) {
51     if (clean_eof != nullptr) *clean_eof = input->CurrentPosition() == start;
52     return false;
53   }
54 
55   // Get the position after any size bytes have been read (and only the message
56   // itself remains).
57   int position_after_size = input->CurrentPosition();
58 
59   // Tell the stream not to read beyond that size.
60   io::CodedInputStream::Limit limit = input->PushLimit(static_cast<int>(size));
61 
62   // Parse the message.
63   if (!message->MergeFromCodedStream(input)) return false;
64   if (!input->ConsumedEntireMessage()) return false;
65   if (input->CurrentPosition() - position_after_size != static_cast<int>(size))
66     return false;
67 
68   // Release the limit.
69   input->PopLimit(limit);
70 
71   return true;
72 }
73 
SerializeDelimitedToZeroCopyStream(const MessageLite & message,io::ZeroCopyOutputStream * output)74 bool SerializeDelimitedToZeroCopyStream(const MessageLite& message,
75                                         io::ZeroCopyOutputStream* output) {
76   io::CodedOutputStream coded_output(output);
77   return SerializeDelimitedToCodedStream(message, &coded_output);
78 }
79 
SerializeDelimitedToCodedStream(const MessageLite & message,io::CodedOutputStream * output)80 bool SerializeDelimitedToCodedStream(const MessageLite& message,
81                                      io::CodedOutputStream* output) {
82   // Write the size.
83   size_t size = message.ByteSizeLong();
84   if (size > INT_MAX) return false;
85 
86   output->WriteVarint32(static_cast<uint32_t>(size));
87 
88   // Write the content.
89   uint8_t* buffer =
90       output->GetDirectBufferForNBytesAndAdvance(static_cast<int>(size));
91   if (buffer != nullptr) {
92     // Optimization: The message fits in one buffer, so use the faster
93     // direct-to-array serialization path.
94     message.SerializeWithCachedSizesToArray(buffer);
95   } else {
96     // Slightly-slower path when the message is multiple buffers.
97     message.SerializeWithCachedSizes(output);
98     if (output->HadError()) return false;
99   }
100 
101   return true;
102 }
103 
104 }  // namespace util
105 }  // namespace protobuf
106 }  // namespace google
107