From 09354db1434859a31a3c81abebcc4018d42f2715 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Tue, 18 Jul 2017 15:38:30 -0700 Subject: Merge from Google internal for 3.4 release --- src/google/protobuf/io/coded_stream.h | 74 ++++++++++++++--------------------- 1 file changed, 29 insertions(+), 45 deletions(-) (limited to 'src/google/protobuf/io/coded_stream.h') diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 20d86143..bce05a39 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -184,7 +184,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Skips a number of bytes. Returns false if an underlying read error // occurs. - bool Skip(int count); + inline bool Skip(int count); // Sets *data to point directly at the unread part of the CodedInputStream's // underlying buffer, and *size to the size of that buffer, but does not @@ -261,7 +261,10 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Always inline because this is only called in one place per parse loop // but it is called for every iteration of said loop, so it should be fast. // GCC doesn't want to inline this by default. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTag(); + GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTag() { + return last_tag_ = ReadTagNoLastTag(); + } + GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTagNoLastTag(); @@ -274,7 +277,12 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // because that can arise in several ways, and for best performance we want // to avoid an extra "is tag == 0?" check here.) GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair ReadTagWithCutoff( - uint32 cutoff); + uint32 cutoff) { + std::pair result = ReadTagWithCutoffNoLastTag(cutoff); + last_tag_ = result.first; + return result; + } + GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair ReadTagWithCutoffNoLastTag( uint32 cutoff); @@ -316,6 +324,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // tag to make sure it had the right number, so it calls LastTagWas() on // return from the embedded parser to check. bool LastTagWas(uint32 expected); + void SetLastTag(uint32 tag) { last_tag_ = tag; } // When parsing message (but NOT a group), this method must be called // immediately after MergeFromCodedStream() returns (if it returns true) @@ -584,6 +593,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Private member functions. + // Fallback when Skip() goes past the end of the current buffer. + bool SkipFallback(int count, int original_buffer_size); + // Advance the buffer by a given number of bytes. void Advance(int amount); @@ -621,12 +633,6 @@ class LIBPROTOBUF_EXPORT CodedInputStream { bool ReadLittleEndian32Fallback(uint32* value); bool ReadLittleEndian64Fallback(uint64* value); - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTagImplementation(); - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE - std::pair ReadTagWithCutoffImplementation(uint32 cutoff); - // Fallback/slow methods for reading tags. These do not update last_tag_, // but will set legitimate_message_end_ if we are at the end of the input // stream. @@ -1018,48 +1024,21 @@ inline bool CodedInputStream::ReadLittleEndian64(uint64* value) { #endif } -inline uint32 CodedInputStream::ReadTag() { - return ReadTagImplementation(); -} - inline uint32 CodedInputStream::ReadTagNoLastTag() { - return ReadTagImplementation(); -} - -template -inline uint32 CodedInputStream::ReadTagImplementation() { uint32 v = 0; if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) { v = *buffer_; if (v < 0x80) { - if (update_last_tag) { - last_tag_ = v; - } Advance(1); return v; } } v = ReadTagFallback(v); - if (update_last_tag) { - last_tag_ = v; - } return v; } -inline std::pair CodedInputStream::ReadTagWithCutoff( - uint32 cutoff) { - return ReadTagWithCutoffImplementation(cutoff); -} - inline std::pair CodedInputStream::ReadTagWithCutoffNoLastTag( uint32 cutoff) { - return ReadTagWithCutoffImplementation(cutoff); -} - -template -inline std::pair -CodedInputStream::ReadTagWithCutoffImplementation( - uint32 cutoff) { // In performance-sensitive code we can expect cutoff to be a compile-time // constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at // compile time. @@ -1072,9 +1051,6 @@ CodedInputStream::ReadTagWithCutoffImplementation( if (static_cast(buffer_[0]) > 0) { const uint32 kMax1ByteVarint = 0x7f; uint32 tag = buffer_[0]; - if (update_last_tag) { - last_tag_ = tag; - } Advance(1); return std::make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff); } @@ -1086,9 +1062,6 @@ CodedInputStream::ReadTagWithCutoffImplementation( GOOGLE_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) { const uint32 kMax2ByteVarint = (0x7f << 7) + 0x7f; uint32 tag = (1u << 7) * buffer_[1] + (buffer_[0] - 0x80); - if (update_last_tag) { - last_tag_ = tag; - } Advance(2); // It might make sense to test for tag == 0 now, but it is so rare that // that we don't bother. A varint-encoded 0 should be one byte unless @@ -1102,9 +1075,6 @@ CodedInputStream::ReadTagWithCutoffImplementation( } // Slow path const uint32 tag = ReadTagFallback(first_byte_or_zero); - if (update_last_tag) { - last_tag_ = tag; - } return std::make_pair(tag, static_cast(tag - 1) < cutoff); } @@ -1430,6 +1400,20 @@ inline bool CodedInputStream::IsFlat() const { return input_ == NULL; } +inline bool CodedInputStream::Skip(int count) { + if (count < 0) return false; // security: count is often user-supplied + + const int original_buffer_size = BufferSize(); + + if (count <= original_buffer_size) { + // Just skipping within the current buffer. Easy. + Advance(count); + return true; + } + + return SkipFallback(count, original_buffer_size); +} + } // namespace io } // namespace protobuf -- cgit v1.2.3