aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/io/coded_stream.h
diff options
context:
space:
mode:
authorGravatar Jisi Liu <jisi.liu@gmail.com>2017-07-18 15:38:30 -0700
committerGravatar Jisi Liu <jisi.liu@gmail.com>2017-07-18 15:38:30 -0700
commit09354db1434859a31a3c81abebcc4018d42f2715 (patch)
treeb87c7cdc2255e6c8062ab92b4082665cd698d753 /src/google/protobuf/io/coded_stream.h
parent9053033a5076f82cf18b823c31f352e95e5bfd8d (diff)
Merge from Google internal for 3.4 release
Diffstat (limited to 'src/google/protobuf/io/coded_stream.h')
-rw-r--r--src/google/protobuf/io/coded_stream.h74
1 files changed, 29 insertions, 45 deletions
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<uint32, bool> ReadTagWithCutoff(
- uint32 cutoff);
+ uint32 cutoff) {
+ std::pair<uint32, bool> result = ReadTagWithCutoffNoLastTag(cutoff);
+ last_tag_ = result.first;
+ return result;
+ }
+
GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair<uint32, bool> 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<bool update_last_tag>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTagImplementation();
- template<bool update_last_tag>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- std::pair<uint32, bool> 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<true>();
-}
-
inline uint32 CodedInputStream::ReadTagNoLastTag() {
- return ReadTagImplementation<false>();
-}
-
-template<bool update_last_tag>
-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<uint32, bool> CodedInputStream::ReadTagWithCutoff(
- uint32 cutoff) {
- return ReadTagWithCutoffImplementation<true>(cutoff);
-}
-
inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoffNoLastTag(
uint32 cutoff) {
- return ReadTagWithCutoffImplementation<false>(cutoff);
-}
-
-template<bool update_last_tag>
-inline std::pair<uint32, bool>
-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<int8>(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<uint32>(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