diff options
Diffstat (limited to 'src/google/protobuf/wire_format_lite_inl.h')
-rw-r--r-- | src/google/protobuf/wire_format_lite_inl.h | 376 |
1 files changed, 247 insertions, 129 deletions
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h index 79493ca0..6cd2c2fb 100644 --- a/src/google/protobuf/wire_format_lite_inl.h +++ b/src/google/protobuf/wire_format_lite_inl.h @@ -36,11 +36,7 @@ #ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ #define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ -#ifdef _MSC_VER -// This is required for min/max on VS2013 only. #include <algorithm> -#endif - #include <string> #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/logging.h> @@ -251,7 +247,7 @@ inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive( uint32 tag, io::CodedInputStream* input, RepeatedField<CType>* values) { - GOOGLE_DCHECK_EQ(UInt32Size(tag), tag_size); + GOOGLE_DCHECK_EQ(UInt32Size(tag), static_cast<size_t>(tag_size)); CType value; if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; @@ -272,10 +268,11 @@ inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive( if (size > 0) { const uint8* buffer = reinterpret_cast<const uint8*>(void_pointer); // The number of bytes each type occupies on the wire. - const int per_value_size = tag_size + sizeof(value); + const int per_value_size = tag_size + static_cast<int>(sizeof(value)); - int elements_available = min(values->Capacity() - values->size(), - size / per_value_size); + // parentheses around (std::min) prevents macro expansion of min(...) + int elements_available = + (std::min)(values->Capacity() - values->size(), size / per_value_size); int num_read = 0; while (num_read < elements_available && (buffer = io::CodedInputStream::ExpectTagFromArray( @@ -329,8 +326,8 @@ bool WireFormatLite::ReadRepeatedPrimitiveNoInline( template <typename CType, enum WireFormatLite::FieldType DeclaredType> inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input, RepeatedField<CType>* values) { - uint32 length; - if (!input->ReadVarint32(&length)) return false; + int length; + if (!input->ReadVarintSizeAsInt(&length)) return false; io::CodedInputStream::Limit limit = input->PushLimit(length); while (input->BytesUntilLimit() > 0) { CType value; @@ -344,11 +341,11 @@ inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input, template <typename CType, enum WireFormatLite::FieldType DeclaredType> inline bool WireFormatLite::ReadPackedFixedSizePrimitive( io::CodedInputStream* input, RepeatedField<CType>* values) { - uint32 length; - if (!input->ReadVarint32(&length)) return false; - const uint32 old_entries = values->size(); - const uint32 new_entries = length / sizeof(CType); - const uint32 new_bytes = new_entries * sizeof(CType); + int length; + if (!input->ReadVarintSizeAsInt(&length)) return false; + const int old_entries = values->size(); + const int new_entries = length / static_cast<int>(sizeof(CType)); + const int new_bytes = new_entries * static_cast<int>(sizeof(CType)); if (new_bytes != length) return false; // We would *like* to pre-allocate the buffer to write into (for // speed), but *must* avoid performing a very large allocation due @@ -366,8 +363,9 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive( if (bytes_limit == -1) { bytes_limit = input->BytesUntilLimit(); } else { + // parentheses around (std::min) prevents macro expansion of min(...) bytes_limit = - min(bytes_limit, static_cast<int64>(input->BytesUntilLimit())); + (std::min)(bytes_limit, static_cast<int64>(input->BytesUntilLimit())); } if (bytes_limit >= new_bytes) { // Fast-path that pre-allocates *values to the final size. @@ -382,7 +380,7 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive( #else values->Reserve(old_entries + new_entries); CType value; - for (uint32 i = 0; i < new_entries; ++i) { + for (int i = 0; i < new_entries; ++i) { if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; values->AddAlreadyReserved(value); } @@ -392,7 +390,7 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive( // safely allocate. We read as much as we can into *values // without pre-allocating "length" bytes. CType value; - for (uint32 i = 0; i < new_entries; ++i) { + for (int i = 0; i < new_entries; ++i) { if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; values->Add(value); } @@ -428,49 +426,12 @@ bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input, } - -inline bool WireFormatLite::ReadGroup(int field_number, - io::CodedInputStream* input, - MessageLite* value) { - if (!input->IncrementRecursionDepth()) return false; - if (!value->MergePartialFromCodedStream(input)) return false; - input->DecrementRecursionDepth(); - // Make sure the last thing read was an end tag for this group. - if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { - return false; - } - return true; -} -inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input, - MessageLite* value) { - uint32 length; - if (!input->ReadVarint32(&length)) return false; - std::pair<io::CodedInputStream::Limit, int> p = - input->IncrementRecursionDepthAndPushLimit(length); - if (p.second < 0 || !value->MergePartialFromCodedStream(input)) return false; - // Make sure that parsing stopped when the limit was hit, not at an endgroup - // tag. - return input->DecrementRecursionDepthAndPopLimit(p.first); -} - -// We name the template parameter something long and extremely unlikely to occur -// elsewhere because a *qualified* member access expression designed to avoid -// virtual dispatch, C++03 [basic.lookup.classref] 3.4.5/4 requires that the -// name of the qualifying class to be looked up both in the context of the full -// expression (finding the template parameter) and in the context of the object -// whose member we are accessing. This could potentially find a nested type -// within that object. The standard goes on to require these names to refer to -// the same entity, which this collision would violate. The lack of a safe way -// to avoid this collision appears to be a defect in the standard, but until it -// is corrected, we choose the name to avoid accidental collisions. -template<typename MessageType_WorkAroundCppLookupDefect> -inline bool WireFormatLite::ReadGroupNoVirtual( +template<typename MessageType> +inline bool WireFormatLite::ReadGroup( int field_number, io::CodedInputStream* input, - MessageType_WorkAroundCppLookupDefect* value) { + MessageType* value) { if (!input->IncrementRecursionDepth()) return false; - if (!value-> - MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) - return false; + if (!value->MergePartialFromCodedStream(input)) return false; input->UnsafeDecrementRecursionDepth(); // Make sure the last thing read was an end tag for this group. if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { @@ -478,39 +439,18 @@ inline bool WireFormatLite::ReadGroupNoVirtual( } return true; } -template<typename MessageType_WorkAroundCppLookupDefect> -inline bool WireFormatLite::ReadGroupNoVirtualNoRecursionDepth( - int field_number, io::CodedInputStream* input, - MessageType_WorkAroundCppLookupDefect* value) { - return value->MessageType_WorkAroundCppLookupDefect:: - MergePartialFromCodedStream(input) && - input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP)); -} -template<typename MessageType_WorkAroundCppLookupDefect> -inline bool WireFormatLite::ReadMessageNoVirtual( - io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) { - uint32 length; - if (!input->ReadVarint32(&length)) return false; +template<typename MessageType> +inline bool WireFormatLite::ReadMessage( + io::CodedInputStream* input, MessageType* value) { + int length; + if (!input->ReadVarintSizeAsInt(&length)) return false; std::pair<io::CodedInputStream::Limit, int> p = input->IncrementRecursionDepthAndPushLimit(length); - if (p.second < 0 || !value-> - MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) - return false; + if (p.second < 0 || !value->MergePartialFromCodedStream(input)) return false; // Make sure that parsing stopped when the limit was hit, not at an endgroup // tag. return input->DecrementRecursionDepthAndPopLimit(p.first); } -template<typename MessageType_WorkAroundCppLookupDefect> -inline bool WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( - io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) { - io::CodedInputStream::Limit old_limit = input->ReadLengthAndPushLimit(); - if (!value-> - MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) - return false; - // Make sure that parsing stopped when the limit was hit, not at an endgroup - // tag. - return input->CheckEntireMessageConsumedAndPopLimit(old_limit); -} // =================================================================== @@ -669,6 +609,98 @@ inline uint8* WireFormatLite::WriteEnumNoTagToArray(int value, return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); } +template<typename T> +inline uint8* WireFormatLite::WritePrimitiveNoTagToArray( + const RepeatedField<T>& value, + uint8* (*Writer)(T, uint8*), uint8* target) { + const int n = value.size(); + GOOGLE_DCHECK_GT(n, 0); + + const T* ii = value.unsafe_data(); + int i = 0; + do { + target = Writer(ii[i], target); + } while (++i < n); + + return target; +} + +template<typename T> +inline uint8* WireFormatLite::WriteFixedNoTagToArray( + const RepeatedField<T>& value, + uint8* (*Writer)(T, uint8*), uint8* target) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + (void) Writer; + + const int n = value.size(); + GOOGLE_DCHECK_GT(n, 0); + + const T* ii = value.unsafe_data(); + const int bytes = n * static_cast<int>(sizeof(ii[0])); + memcpy(target, ii, static_cast<size_t>(bytes)); + return target + bytes; +#else + return WritePrimitiveNoTagToArray(value, Writer, target); +#endif +} + +inline uint8* WireFormatLite::WriteInt32NoTagToArray( + const RepeatedField< int32>& value, uint8* target) { + return WritePrimitiveNoTagToArray(value, WriteInt32NoTagToArray, target); +} +inline uint8* WireFormatLite::WriteInt64NoTagToArray( + const RepeatedField< int64>& value, uint8* target) { + return WritePrimitiveNoTagToArray(value, WriteInt64NoTagToArray, target); +} +inline uint8* WireFormatLite::WriteUInt32NoTagToArray( + const RepeatedField<uint32>& value, uint8* target) { + return WritePrimitiveNoTagToArray(value, WriteUInt32NoTagToArray, target); +} +inline uint8* WireFormatLite::WriteUInt64NoTagToArray( + const RepeatedField<uint64>& value, uint8* target) { + return WritePrimitiveNoTagToArray(value, WriteUInt64NoTagToArray, target); +} +inline uint8* WireFormatLite::WriteSInt32NoTagToArray( + const RepeatedField< int32>& value, uint8* target) { + return WritePrimitiveNoTagToArray(value, WriteSInt32NoTagToArray, target); +} +inline uint8* WireFormatLite::WriteSInt64NoTagToArray( + const RepeatedField< int64>& value, uint8* target) { + return WritePrimitiveNoTagToArray(value, WriteSInt64NoTagToArray, target); +} +inline uint8* WireFormatLite::WriteFixed32NoTagToArray( + const RepeatedField<uint32>& value, uint8* target) { + return WriteFixedNoTagToArray(value, WriteFixed32NoTagToArray, target); +} +inline uint8* WireFormatLite::WriteFixed64NoTagToArray( + const RepeatedField<uint64>& value, uint8* target) { + return WriteFixedNoTagToArray(value, WriteFixed64NoTagToArray, target); +} +inline uint8* WireFormatLite::WriteSFixed32NoTagToArray( + const RepeatedField< int32>& value, uint8* target) { + return WriteFixedNoTagToArray(value, WriteSFixed32NoTagToArray, target); +} +inline uint8* WireFormatLite::WriteSFixed64NoTagToArray( + const RepeatedField< int64>& value, uint8* target) { + return WriteFixedNoTagToArray(value, WriteSFixed64NoTagToArray, target); +} +inline uint8* WireFormatLite::WriteFloatNoTagToArray( + const RepeatedField< float>& value, uint8* target) { + return WriteFixedNoTagToArray(value, WriteFloatNoTagToArray, target); +} +inline uint8* WireFormatLite::WriteDoubleNoTagToArray( + const RepeatedField<double>& value, uint8* target) { + return WriteFixedNoTagToArray(value, WriteDoubleNoTagToArray, target); +} +inline uint8* WireFormatLite::WriteBoolNoTagToArray( + const RepeatedField< bool>& value, uint8* target) { + return WritePrimitiveNoTagToArray(value, WriteBoolNoTagToArray, target); +} +inline uint8* WireFormatLite::WriteEnumNoTagToArray( + const RepeatedField< int>& value, uint8* target) { + return WritePrimitiveNoTagToArray(value, WriteEnumNoTagToArray, target); +} + inline uint8* WireFormatLite::WriteInt32ToArray(int field_number, int32 value, uint8* target) { @@ -754,6 +786,85 @@ inline uint8* WireFormatLite::WriteEnumToArray(int field_number, return WriteEnumNoTagToArray(value, target); } +template<typename T> +inline uint8* WireFormatLite::WritePrimitiveToArray( + int field_number, + const RepeatedField<T>& value, + uint8* (*Writer)(int, T, uint8*), uint8* target) { + const int n = value.size(); + if (n == 0) { + return target; + } + + const T* ii = value.unsafe_data(); + int i = 0; + do { + target = Writer(field_number, ii[i], target); + } while (++i < n); + + return target; +} + +inline uint8* WireFormatLite::WriteInt32ToArray( + int field_number, const RepeatedField< int32>& value, uint8* target) { + return WritePrimitiveToArray(field_number, value, WriteInt32ToArray, target); +} +inline uint8* WireFormatLite::WriteInt64ToArray( + int field_number, const RepeatedField< int64>& value, uint8* target) { + return WritePrimitiveToArray(field_number, value, WriteInt64ToArray, target); +} +inline uint8* WireFormatLite::WriteUInt32ToArray( + int field_number, const RepeatedField<uint32>& value, uint8* target) { + return WritePrimitiveToArray(field_number, value, WriteUInt32ToArray, target); +} +inline uint8* WireFormatLite::WriteUInt64ToArray( + int field_number, const RepeatedField<uint64>& value, uint8* target) { + return WritePrimitiveToArray(field_number, value, WriteUInt64ToArray, target); +} +inline uint8* WireFormatLite::WriteSInt32ToArray( + int field_number, const RepeatedField< int32>& value, uint8* target) { + return WritePrimitiveToArray(field_number, value, WriteSInt32ToArray, target); +} +inline uint8* WireFormatLite::WriteSInt64ToArray( + int field_number, const RepeatedField< int64>& value, uint8* target) { + return WritePrimitiveToArray(field_number, value, WriteSInt64ToArray, target); +} +inline uint8* WireFormatLite::WriteFixed32ToArray( + int field_number, const RepeatedField<uint32>& value, uint8* target) { + return WritePrimitiveToArray( + field_number, value, WriteFixed32ToArray, target); +} +inline uint8* WireFormatLite::WriteFixed64ToArray( + int field_number, const RepeatedField<uint64>& value, uint8* target) { + return WritePrimitiveToArray( + field_number, value, WriteFixed64ToArray, target); +} +inline uint8* WireFormatLite::WriteSFixed32ToArray( + int field_number, const RepeatedField< int32>& value, uint8* target) { + return WritePrimitiveToArray( + field_number, value, WriteSFixed32ToArray, target); +} +inline uint8* WireFormatLite::WriteSFixed64ToArray( + int field_number, const RepeatedField< int64>& value, uint8* target) { + return WritePrimitiveToArray( + field_number, value, WriteSFixed64ToArray, target); +} +inline uint8* WireFormatLite::WriteFloatToArray( + int field_number, const RepeatedField< float>& value, uint8* target) { + return WritePrimitiveToArray(field_number, value, WriteFloatToArray, target); +} +inline uint8* WireFormatLite::WriteDoubleToArray( + int field_number, const RepeatedField<double>& value, uint8* target) { + return WritePrimitiveToArray(field_number, value, WriteDoubleToArray, target); +} +inline uint8* WireFormatLite::WriteBoolToArray( + int field_number, const RepeatedField< bool>& value, uint8* target) { + return WritePrimitiveToArray(field_number, value, WriteBoolToArray, target); +} +inline uint8* WireFormatLite::WriteEnumToArray( + int field_number, const RepeatedField< int>& value, uint8* target) { + return WritePrimitiveToArray(field_number, value, WriteEnumToArray, target); +} inline uint8* WireFormatLite::WriteStringToArray(int field_number, const string& value, uint8* target) { @@ -772,103 +883,110 @@ inline uint8* WireFormatLite::WriteBytesToArray(int field_number, } -inline uint8* WireFormatLite::WriteGroupToArray(int field_number, - const MessageLite& value, - uint8* target) { +template<typename MessageType> +inline uint8* WireFormatLite::InternalWriteGroupToArray( + int field_number, const MessageType& value, bool deterministic, + uint8* target) { target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); - target = value.SerializeWithCachedSizesToArray(target); + target = value.InternalSerializeWithCachedSizesToArray(deterministic, target); return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); } -inline uint8* WireFormatLite::WriteMessageToArray(int field_number, - const MessageLite& value, - uint8* target) { +template<typename MessageType> +inline uint8* WireFormatLite::InternalWriteMessageToArray( + int field_number, const MessageType& value, bool deterministic, + uint8* target) { target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); target = io::CodedOutputStream::WriteVarint32ToArray( - value.GetCachedSize(), target); - return value.SerializeWithCachedSizesToArray(target); + static_cast<uint32>(value.GetCachedSize()), target); + return value.InternalSerializeWithCachedSizesToArray(deterministic, target); } // See comment on ReadGroupNoVirtual to understand the need for this template // parameter name. template<typename MessageType_WorkAroundCppLookupDefect> -inline uint8* WireFormatLite::WriteGroupNoVirtualToArray( +inline uint8* WireFormatLite::InternalWriteGroupNoVirtualToArray( int field_number, const MessageType_WorkAroundCppLookupDefect& value, - uint8* target) { + bool deterministic, uint8* target) { target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); - target = value.MessageType_WorkAroundCppLookupDefect - ::SerializeWithCachedSizesToArray(target); + target = value.MessageType_WorkAroundCppLookupDefect:: + InternalSerializeWithCachedSizesToArray(deterministic, target); return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); } template<typename MessageType_WorkAroundCppLookupDefect> -inline uint8* WireFormatLite::WriteMessageNoVirtualToArray( +inline uint8* WireFormatLite::InternalWriteMessageNoVirtualToArray( int field_number, const MessageType_WorkAroundCppLookupDefect& value, - uint8* target) { + bool deterministic, uint8* target) { target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); target = io::CodedOutputStream::WriteVarint32ToArray( - value.MessageType_WorkAroundCppLookupDefect::GetCachedSize(), target); - return value.MessageType_WorkAroundCppLookupDefect - ::SerializeWithCachedSizesToArray(target); + static_cast<uint32>( + value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()), + target); + return value.MessageType_WorkAroundCppLookupDefect:: + InternalSerializeWithCachedSizesToArray(deterministic, target); } // =================================================================== -inline int WireFormatLite::Int32Size(int32 value) { +inline size_t WireFormatLite::Int32Size(int32 value) { return io::CodedOutputStream::VarintSize32SignExtended(value); } -inline int WireFormatLite::Int64Size(int64 value) { +inline size_t WireFormatLite::Int64Size(int64 value) { return io::CodedOutputStream::VarintSize64(static_cast<uint64>(value)); } -inline int WireFormatLite::UInt32Size(uint32 value) { +inline size_t WireFormatLite::UInt32Size(uint32 value) { return io::CodedOutputStream::VarintSize32(value); } -inline int WireFormatLite::UInt64Size(uint64 value) { +inline size_t WireFormatLite::UInt64Size(uint64 value) { return io::CodedOutputStream::VarintSize64(value); } -inline int WireFormatLite::SInt32Size(int32 value) { +inline size_t WireFormatLite::SInt32Size(int32 value) { return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value)); } -inline int WireFormatLite::SInt64Size(int64 value) { +inline size_t WireFormatLite::SInt64Size(int64 value) { return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value)); } -inline int WireFormatLite::EnumSize(int value) { +inline size_t WireFormatLite::EnumSize(int value) { return io::CodedOutputStream::VarintSize32SignExtended(value); } -inline int WireFormatLite::StringSize(const string& value) { - return static_cast<int>( - io::CodedOutputStream::VarintSize32(static_cast<uint32>(value.size())) + - value.size()); +inline size_t WireFormatLite::StringSize(const string& value) { + return LengthDelimitedSize(value.size()); } -inline int WireFormatLite::BytesSize(const string& value) { - return static_cast<int>( - io::CodedOutputStream::VarintSize32(static_cast<uint32>(value.size())) + - value.size()); +inline size_t WireFormatLite::BytesSize(const string& value) { + return LengthDelimitedSize(value.size()); } -inline int WireFormatLite::GroupSize(const MessageLite& value) { - return value.ByteSize(); +template<typename MessageType> +inline size_t WireFormatLite::GroupSize(const MessageType& value) { + return value.ByteSizeLong(); } -inline int WireFormatLite::MessageSize(const MessageLite& value) { - return LengthDelimitedSize(value.ByteSize()); +template<typename MessageType> +inline size_t WireFormatLite::MessageSize(const MessageType& value) { + return LengthDelimitedSize(value.ByteSizeLong()); } // See comment on ReadGroupNoVirtual to understand the need for this template // parameter name. template<typename MessageType_WorkAroundCppLookupDefect> -inline int WireFormatLite::GroupSizeNoVirtual( +inline size_t WireFormatLite::GroupSizeNoVirtual( const MessageType_WorkAroundCppLookupDefect& value) { - return value.MessageType_WorkAroundCppLookupDefect::ByteSize(); + return value.MessageType_WorkAroundCppLookupDefect::ByteSizeLong(); } template<typename MessageType_WorkAroundCppLookupDefect> -inline int WireFormatLite::MessageSizeNoVirtual( +inline size_t WireFormatLite::MessageSizeNoVirtual( const MessageType_WorkAroundCppLookupDefect& value) { return LengthDelimitedSize( - value.MessageType_WorkAroundCppLookupDefect::ByteSize()); + value.MessageType_WorkAroundCppLookupDefect::ByteSizeLong()); } -inline int WireFormatLite::LengthDelimitedSize(int length) { - return io::CodedOutputStream::VarintSize32(length) + length; +inline size_t WireFormatLite::LengthDelimitedSize(size_t length) { + // The static_cast here prevents an error in certain compiler configurations + // but is not technically correct--if length is too large to fit in a uint32 + // then it will be silently truncated. We will need to fix this if we ever + // decide to start supporting serialized messages greater than 2 GiB in size. + return length + io::CodedOutputStream::VarintSize32( + static_cast<uint32>(length)); } } // namespace internal |