From 40ee551715c3a784ea6132dbf604b0e665ca2def Mon Sep 17 00:00:00 2001 From: temporal Date: Thu, 10 Jul 2008 02:12:20 +0000 Subject: Initial checkin. --- src/google/protobuf/message.cc | 345 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 src/google/protobuf/message.cc (limited to 'src/google/protobuf/message.cc') diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc new file mode 100644 index 00000000..f740ef18 --- /dev/null +++ b/src/google/protobuf/message.cc @@ -0,0 +1,345 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +using internal::WireFormat; +using internal::ReflectionOps; + +static string InitializationErrorMessage(const char* action, + const Message& message) { + return strings::Substitute( + "Can't $0 message of type \"$1\" because it is missing required " + "fields: $2", + action, message.GetDescriptor()->full_name(), + message.InitializationErrorString()); +} + +Message::~Message() {} +Message::Reflection::~Reflection() {} + +void Message::MergeFrom(const Message& from) { + const Descriptor* descriptor = GetDescriptor(); + GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) + << ": Tried to merge from a message with a different type. " + "to: " << descriptor->full_name() << ", " + "from:" << from.GetDescriptor()->full_name(); + ReflectionOps::Merge(descriptor, *from.GetReflection(), GetReflection()); +} + +void Message::CopyFrom(const Message& from) { + const Descriptor* descriptor = GetDescriptor(); + GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) + << ": Tried to copy from a message with a different type." + "to: " << descriptor->full_name() << ", " + "from:" << from.GetDescriptor()->full_name(); + ReflectionOps::Copy(descriptor, *from.GetReflection(), GetReflection()); +} + +void Message::Clear() { + ReflectionOps::Clear(GetDescriptor(), GetReflection()); +} + +bool Message::IsInitialized() const { + return ReflectionOps::IsInitialized(GetDescriptor(), *GetReflection()); +} + +void Message::FindInitializationErrors(vector* errors) const { + return ReflectionOps::FindInitializationErrors( + GetDescriptor(), *GetReflection(), "", errors); +} + +string Message::InitializationErrorString() const { + vector errors; + FindInitializationErrors(&errors); + return JoinStrings(errors, ", "); +} + +void Message::CheckInitialized() const { + GOOGLE_CHECK(IsInitialized()) + << "Message of type \"" << GetDescriptor()->full_name() + << "\" is missing required fields: " << InitializationErrorString(); +} + +void Message::DiscardUnknownFields() { + return ReflectionOps::DiscardUnknownFields(GetDescriptor(), GetReflection()); +} + +bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) { + return WireFormat::ParseAndMergePartial( + GetDescriptor(), input, GetReflection()); +} + +bool Message::MergeFromCodedStream(io::CodedInputStream* input) { + if (!MergePartialFromCodedStream(input)) return false; + if (!IsInitialized()) { + GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *this); + return false; + } + return true; +} + +bool Message::ParseFromCodedStream(io::CodedInputStream* input) { + Clear(); + return MergeFromCodedStream(input); +} + +bool Message::ParsePartialFromCodedStream(io::CodedInputStream* input) { + Clear(); + return MergePartialFromCodedStream(input); +} + +bool Message::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { + io::CodedInputStream decoder(input); + return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage(); +} + +bool Message::ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input) { + io::CodedInputStream decoder(input); + return ParsePartialFromCodedStream(&decoder) && + decoder.ConsumedEntireMessage(); +} + +bool Message::ParseFromString(const string& data) { + io::ArrayInputStream input(data.data(), data.size()); + return ParseFromZeroCopyStream(&input); +} + +bool Message::ParsePartialFromString(const string& data) { + io::ArrayInputStream input(data.data(), data.size()); + return ParsePartialFromZeroCopyStream(&input); +} + +bool Message::ParseFromArray(const void* data, int size) { + io::ArrayInputStream input(data, size); + return ParseFromZeroCopyStream(&input); +} + +bool Message::ParsePartialFromArray(const void* data, int size) { + io::ArrayInputStream input(data, size); + return ParsePartialFromZeroCopyStream(&input); +} + +bool Message::ParseFromFileDescriptor(int file_descriptor) { + io::FileInputStream input(file_descriptor); + return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0; +} + +bool Message::ParsePartialFromFileDescriptor(int file_descriptor) { + io::FileInputStream input(file_descriptor); + return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0; +} + +bool Message::ParseFromIstream(istream* input) { + io::IstreamInputStream zero_copy_input(input); + return ParseFromZeroCopyStream(&zero_copy_input) && input->eof(); +} + +bool Message::ParsePartialFromIstream(istream* input) { + io::IstreamInputStream zero_copy_input(input); + return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof(); +} + + + +bool Message::SerializeWithCachedSizes( + io::CodedOutputStream* output) const { + return WireFormat::SerializeWithCachedSizes( + GetDescriptor(), GetReflection(), GetCachedSize(), output); +} + +int Message::ByteSize() const { + int size = WireFormat::ByteSize(GetDescriptor(), GetReflection()); + SetCachedSize(size); + return size; +} + +void Message::SetCachedSize(int size) const { + GOOGLE_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name() + << "\" implements neither SetCachedSize() nor ByteSize(). " + "Must implement one or the other."; +} + +bool Message::SerializeToCodedStream(io::CodedOutputStream* output) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return SerializePartialToCodedStream(output); +} + +bool Message::SerializePartialToCodedStream( + io::CodedOutputStream* output) const { + ByteSize(); // Force size to be cached. + if (!SerializeWithCachedSizes(output)) return false; + return true; +} + +bool Message::SerializeToZeroCopyStream( + io::ZeroCopyOutputStream* output) const { + io::CodedOutputStream encoder(output); + return SerializeToCodedStream(&encoder); +} + +bool Message::SerializePartialToZeroCopyStream( + io::ZeroCopyOutputStream* output) const { + io::CodedOutputStream encoder(output); + return SerializePartialToCodedStream(&encoder); +} + +bool Message::AppendToString(string* output) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return AppendPartialToString(output); +} + +bool Message::AppendPartialToString(string* output) const { + // For efficiency, we'd like to reserve the exact amount of space we need + // in the string. + int total_size = output->size() + ByteSize(); + output->reserve(total_size); + + io::StringOutputStream output_stream(output); + + { + io::CodedOutputStream encoder(&output_stream); + if (!SerializeWithCachedSizes(&encoder)) return false; + } + + GOOGLE_CHECK_EQ(output_stream.ByteCount(), total_size); + return true; +} + +bool Message::SerializeToString(string* output) const { + output->clear(); + return AppendToString(output); +} + +bool Message::SerializePartialToString(string* output) const { + output->clear(); + return AppendPartialToString(output); +} + +bool Message::SerializeToArray(void* data, int size) const { + io::ArrayOutputStream output_stream(data, size); + return SerializeToZeroCopyStream(&output_stream); +} + +bool Message::SerializePartialToArray(void* data, int size) const { + io::ArrayOutputStream output_stream(data, size); + return SerializePartialToZeroCopyStream(&output_stream); +} + +bool Message::SerializeToFileDescriptor(int file_descriptor) const { + io::FileOutputStream output(file_descriptor); + return SerializeToZeroCopyStream(&output); +} + +bool Message::SerializePartialToFileDescriptor(int file_descriptor) const { + io::FileOutputStream output(file_descriptor); + return SerializePartialToZeroCopyStream(&output); +} + +bool Message::SerializeToOstream(ostream* output) const { + io::OstreamOutputStream zero_copy_output(output); + return SerializeToZeroCopyStream(&zero_copy_output); +} + +bool Message::SerializePartialToOstream(ostream* output) const { + io::OstreamOutputStream zero_copy_output(output); + return SerializePartialToZeroCopyStream(&zero_copy_output); +} + + +// =================================================================== +// MessageFactory + +MessageFactory::~MessageFactory() {} + +namespace { + +class GeneratedMessageFactory : public MessageFactory { + public: + GeneratedMessageFactory(); + ~GeneratedMessageFactory(); + + static GeneratedMessageFactory* singleton(); + + void RegisterType(const Descriptor* descriptor, const Message* prototype); + + // implements MessageFactory --------------------------------------- + const Message* GetPrototype(const Descriptor* type); + + private: + hash_map type_map_; +}; + +GeneratedMessageFactory::GeneratedMessageFactory() {} +GeneratedMessageFactory::~GeneratedMessageFactory() {} + +GeneratedMessageFactory* GeneratedMessageFactory::singleton() { + // No need for thread-safety here because this will be called at static + // initialization time. (And GCC4 makes this thread-safe anyway.) + static GeneratedMessageFactory singleton; + return &singleton; +} + +void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor, + const Message* prototype) { + GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool()) + << "Tried to register a non-generated type with the generated " + "type registry."; + + if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) { + GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name(); + } +} + +const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) { + return FindPtrOrNull(type_map_, type); +} + +} // namespace + +MessageFactory* MessageFactory::generated_factory() { + return GeneratedMessageFactory::singleton(); +} + +void MessageFactory::InternalRegisterGeneratedMessage( + const Descriptor* descriptor, const Message* prototype) { + GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype); +} + + +} // namespace protobuf +} // namespace google -- cgit v1.2.3