From c0a50de92300080a1cf11bf4ff0ec3b2d6240c10 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Tue, 21 Aug 2018 14:47:50 -0700 Subject: Removed a bunch of obsolete code. A lot of this code was experimental or temporarily useful, but is no longer needed. --- upb/bindings/googlepb/proto2.cc | 1395 --------------------------------------- 1 file changed, 1395 deletions(-) delete mode 100644 upb/bindings/googlepb/proto2.cc (limited to 'upb/bindings/googlepb/proto2.cc') diff --git a/upb/bindings/googlepb/proto2.cc b/upb/bindings/googlepb/proto2.cc deleted file mode 100644 index ebfedca..0000000 --- a/upb/bindings/googlepb/proto2.cc +++ /dev/null @@ -1,1395 +0,0 @@ -// -// Note that we have received an exception from c-style-artiters regarding -// dynamic_cast<> in this file: -// https://groups.google.com/a/google.com/d/msg/c-style/7Zp_XCX0e7s/I6dpzno4l-MJ -// -// IMPORTANT NOTE! This file is compiled TWICE, once with UPB_GOOGLE3 defined -// and once without! This allows us to provide functionality against proto2 -// and protobuf opensource both in a single binary without the two conflicting. -// However we must be careful not to violate the ODR. - -#include "upb/bindings/googlepb/proto2.int.h" - -#include - -#include "upb/bindings/googlepb/proto1.int.h" -#include "upb/def.h" -#include "upb/handlers.h" -#include "upb/msg.h" -#include "upb/sink.h" - -namespace { - -template To CheckDownCast(From* f) { - UPB_ASSERT(f == NULL || dynamic_cast(f) != NULL); - return static_cast(f); -} - -} - -// Unconditionally evaluate, but also assert in debug mode. -#define CHKRET(x) do { bool ok = (x); UPB_ASSERT(ok); } while (0) - -namespace upb { -namespace google_google3 { class GMR_Handlers; } -namespace google_opensource { class GMR_Handlers; } -} // namespace upb - -// BEGIN DOUBLE COMPILATION TRICKERY. ////////////////////////////////////////// - -#ifdef UPB_GOOGLE3 - -// TODO(haberman): Add public functionality to ExtensionSet for populating -// LazyFields. -#define private public -#include "net/proto2/public/extension_set.h" -#undef private - -#include "net/proto2/proto/descriptor.pb.h" -#include "net/proto2/public/descriptor.h" -#include "net/proto2/public/generated_message_reflection.h" -#include "net/proto2/public/lazy_field.h" -#include "net/proto2/public/message.h" -#include "net/proto2/public/repeated_field.h" -#include "net/proto2/public/string_piece_field_support.h" - -namespace goog = ::proto2; -namespace me = ::upb::google_google3; - -#else - -// TODO(haberman): remove these once new versions of protobuf that "friend" -// upb are pervasive in the wild. -#define protected public -#include "google/protobuf/repeated_field.h" -#undef protected - -#define private public -#include "google/protobuf/generated_message_reflection.h" -#undef private - -#define private public -#include "google/protobuf/extension_set.h" -#undef private - -#include "google/protobuf/descriptor.h" -#include "google/protobuf/descriptor.pb.h" -#include "google/protobuf/message.h" - -namespace goog = ::google::protobuf; -namespace me = ::upb::google_opensource; - -using goog::int32; -using goog::int64; -using goog::uint32; -using goog::uint64; -using goog::scoped_ptr; - -#endif // ifdef UPB_GOOGLE3 - -// END DOUBLE COMPILATION TRICKERY. //////////////////////////////////////////// - -// Have to define this manually since older versions of proto2 didn't define -// an enum value for STRING. -#define UPB_CTYPE_STRING 0 - -template static T* GetPointer(void* message, size_t offset) { - return reinterpret_cast(static_cast(message) + offset); -} -template -static const T* GetConstPointer(const void* message, size_t offset) { - return reinterpret_cast(static_cast(message) + offset); -} - -// This class contains handlers that can write into a proto2 class whose -// reflection class is GeneratedMessageReflection. (Despite the name, even -// DynamicMessage uses GeneratedMessageReflection, so this covers all proto2 -// messages generated by the compiler.) To do this it must break the -// encapsulation of GeneratedMessageReflection and therefore depends on -// internal interfaces that are not guaranteed to be stable. This class will -// need to be updated if any non-backward-compatible changes are made to -// GeneratedMessageReflection. -class me::GMR_Handlers { - public: - // Returns true if we were able to set an accessor and any other properties - // of the FieldDef that are necessary to read/write this field to a - // proto2::Message. - static bool TrySet(const goog::FieldDescriptor* proto2_f, - const goog::Message& m, const upb::FieldDef* upb_f, - upb::Handlers* h) { - const goog::Reflection* base_r = m.GetReflection(); - // See file comment re: dynamic_cast. - const goog::internal::GeneratedMessageReflection* r = - dynamic_cast(base_r); - if (!r) return false; - -#define PRIMITIVE_TYPE(cpptype, cident) \ -case goog::FieldDescriptor::cpptype: \ - SetPrimitiveHandlers(proto2_f, r, upb_f, h); \ - return true; - - switch (proto2_f->cpp_type()) { - PRIMITIVE_TYPE(CPPTYPE_INT32, int32); - PRIMITIVE_TYPE(CPPTYPE_INT64, int64); - PRIMITIVE_TYPE(CPPTYPE_UINT32, uint32); - PRIMITIVE_TYPE(CPPTYPE_UINT64, uint64); - PRIMITIVE_TYPE(CPPTYPE_DOUBLE, double); - PRIMITIVE_TYPE(CPPTYPE_FLOAT, float); - PRIMITIVE_TYPE(CPPTYPE_BOOL, bool); - case goog::FieldDescriptor::CPPTYPE_ENUM: - if (proto2_f->is_extension()) { - SetEnumExtensionHandlers(proto2_f, r, upb_f, h); - } else { - SetEnumHandlers(proto2_f, r, upb_f, h); - } - return true; - case goog::FieldDescriptor::CPPTYPE_STRING: { - if (proto2_f->is_extension()) { -#ifdef UPB_GOOGLE3 - SetStringExtensionHandlers(proto2_f, r, upb_f, h); -#else - SetStringExtensionHandlers(proto2_f, r, upb_f, h); -#endif - return true; - } - - // Old versions of the open-source protobuf release erroneously default - // to Cord even though that has never been supported in the open-source - // release. - int32_t ctype = proto2_f->options().has_ctype() ? - proto2_f->options().ctype() - : UPB_CTYPE_STRING; - switch (ctype) { -#ifdef UPB_GOOGLE3 - case goog::FieldOptions::STRING: - SetStringHandlers(proto2_f, r, upb_f, h); - return true; - case goog::FieldOptions::CORD: - SetCordHandlers(proto2_f, r, upb_f, h); - return true; - case goog::FieldOptions::STRING_PIECE: - SetStringPieceHandlers(proto2_f, r, upb_f, h); - return true; -#else - case UPB_CTYPE_STRING: - SetStringHandlers(proto2_f, r, upb_f, h); - return true; -#endif - default: - return false; - } - } - case goog::FieldDescriptor::CPPTYPE_MESSAGE: -#ifdef UPB_GOOGLE3 - if (proto2_f->options().lazy() && - // proto2 lets you set lazy=true on a repeated field, but doesn't - // actually support lazy repeated messages, so just ignore - // lazy=true for repeated messages. - !proto2_f->is_repeated()) { - // Supports lazy fields and lazy extensions. - SetLazyFieldHandlers(proto2_f, m, r, upb_f, h); - return true; - } -#endif - if (proto2_f->is_extension()) { - SetSubMessageExtensionHandlers(proto2_f, m, r, upb_f, h); - return true; - } - SetSubMessageHandlers(proto2_f, m, r, upb_f, h); - return true; - default: - return false; - } - } - -#undef PRIMITIVE_TYPE - - static const goog::Message* GetFieldPrototype( - const goog::Message& m, const goog::FieldDescriptor* f) { - // We assume that all submessages (and extensions) will be constructed - // using the same MessageFactory as this message. This doesn't cover the - // case of CodedInputStream::SetExtensionRegistry(). - // See file comment re: dynamic_cast. - const goog::internal::GeneratedMessageReflection* r = - dynamic_cast( - m.GetReflection()); - if (!r) return NULL; - return r->message_factory_->GetPrototype(f->message_type()); - } - - private: - static upb_selector_t GetSelector(const upb::FieldDef* f, - upb::Handlers::Type type) { - upb::Handlers::Selector selector; - bool ok = upb::Handlers::GetSelector(f, type, &selector); - UPB_ASSERT(ok); - return selector; - } - - static int64_t GetHasbit( - const goog::FieldDescriptor* f, - const goog::internal::GeneratedMessageReflection* r) { - // proto2 does not store hasbits for repeated fields. - UPB_ASSERT(!f->is_repeated()); - return (r->has_bits_offset_ * 8) + f->index(); - } - -#ifdef GOOGLE_PROTOBUF_HAS_ONEOF - static size_t GetOneofDiscriminantOffset( - const goog::FieldDescriptor* f, - const goog::internal::GeneratedMessageReflection* r) { - UPB_ASSERT(f->containing_oneof()); - return r->oneof_case_offset_ + f->containing_oneof()->index(); - } -#endif - - static uint16_t GetOffset( - const goog::FieldDescriptor* f, - const goog::internal::GeneratedMessageReflection* r) { - int index = f->index(); -#ifdef GOOGLE_PROTOBUF_HAS_ONEOF - if (f->containing_oneof()) { - index = - f->containing_type()->field_count() + f->containing_oneof()->index(); - } -#endif - return r->offsets_[index]; - } - - // Base class that provides access to elements of the message as a whole, such - // as the unknown-field set, and is inherited by context classes for specific - // field handlers. - class FieldDataBase { - public: - FieldDataBase(const goog::internal::GeneratedMessageReflection* r) - : unknown_fields_offset_(r->unknown_fields_offset_) -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - , arena_offset_(r->arena_offset_) -#endif // GOOGLE_PROTOBUF_HAS_ARENAS - {} - -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - goog::Arena* GetArena(const goog::Message& message) const { - if (unknown_fields_offset_ == - goog::internal::GeneratedMessageReflection:: - kUnknownFieldSetInMetadata) { - const goog::internal::InternalMetadataWithArena* metadata = - GetConstPointer( - &message, arena_offset_); - return metadata->arena(); - } else if (arena_offset_ != - goog::internal::GeneratedMessageReflection::kNoArenaPointer) { - return *GetConstPointer(&message, arena_offset_); - } else { - return NULL; - } - } - - goog::UnknownFieldSet* GetUnknownFieldSet(goog::Message* message) const { - if (unknown_fields_offset_ == - goog::internal::GeneratedMessageReflection:: - kUnknownFieldSetInMetadata) { - goog::internal::InternalMetadataWithArena* metadata = - GetPointer( - message, arena_offset_); - return metadata->mutable_unknown_fields(); - } - return GetPointer(message, unknown_fields_offset_); - } -#else // ifdef GOOGLE_PROTOBUF_HAS_ARENAS - goog::UnknownFieldSet* GetUnknownFieldSet(goog::Message* message) const { - return GetPointer(message, unknown_fields_offset_); - } -#endif // ifdef !GOOGLE_PROTOBUF_HAS_ARENAS - private: - int unknown_fields_offset_; -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - int arena_offset_; -#endif // GOOGLE_PROTOBUF_HAS_ARENAS - }; - - class FieldOffset : public FieldDataBase { - public: - FieldOffset(const goog::FieldDescriptor* f, - const goog::internal::GeneratedMessageReflection* r) - : FieldDataBase(r), - offset_(GetOffset(f, r)), is_repeated_(f->is_repeated()) { - if (!is_repeated_) { - int64_t hasbit = GetHasbit(f, r); - hasbyte_ = hasbit / 8; - mask_ = 1 << (hasbit % 8); - } - } - - template T* GetFieldPointer(goog::Message* message) const { - return GetPointer(message, offset_); - } - - void SetHasbit(void* m) const { - UPB_ASSERT(!is_repeated_); - uint8_t* byte = GetPointer(m, hasbyte_); - *byte |= mask_; - } - - private: - const size_t offset_; - bool is_repeated_; - - // Only for non-repeated fields. - int32_t hasbyte_; - int8_t mask_; - }; - -#ifdef GOOGLE_PROTOBUF_HAS_ONEOF - class OneofFieldData : public FieldDataBase { - public: - OneofFieldData(const goog::FieldDescriptor* f, - const goog::internal::GeneratedMessageReflection* r) - : FieldDataBase(r), - field_number_offset_(GetOneofDiscriminantOffset(f, r)), - field_number_(f->number()) { - const goog::OneofDescriptor* oneof = f->containing_oneof(); - - // Determine the type of each discriminant value, so we know what kind of - // value to delete if we are changing the type. - // - // For example, we may find that the oneof has three possible values: an - // int32, a message, and a string. For the int32 there is nothing to - // delete, but the message and the string need to be deleted when we - // switch to another oneof type, to avoid leaking it. - // - // TODO(haberman): share this map of types between all fields in the - // oneof. Right now we duplicate it for each one, which is wasteful. - for (int i = 0; i < oneof->field_count(); i++) { - const goog::FieldDescriptor* oneof_f = oneof->field(i); - OneofType& type = types_[oneof_f->number()]; - - switch (oneof_f->cpp_type()) { - case goog::FieldDescriptor::CPPTYPE_STRING: - type = GetTypeForString(oneof_f); - break; - case goog::FieldDescriptor::CPPTYPE_MESSAGE: -#ifdef UPB_GOOGLE3 - if (oneof_f->options().lazy()) { - type = ONEOF_TYPE_LAZYFIELD; - break; - } -#endif - type = ONEOF_TYPE_MESSAGE; - break; - - default: - type = ONEOF_TYPE_NONE; - break; - } - } - - // "0" indicates that the field is not set. - types_[0] = ONEOF_TYPE_NONE; - } - - int32_t* GetFieldPointer(goog::Message* message) const { - return GetPointer(message, field_number_offset_); - } - - void ClearOneof(goog::Message* m, const FieldOffset* ofs, - int field_number) const { -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - if (GetArena(*m) != NULL) { - return; - } -#endif - switch (types_.at(field_number)) { - case ONEOF_TYPE_NONE: - break; - case ONEOF_TYPE_STRING: - delete *ofs->GetFieldPointer(m); - break; - case ONEOF_TYPE_MESSAGE: - delete *ofs->GetFieldPointer(m); - break; -#ifdef UPB_GOOGLE3 - case ONEOF_TYPE_GLOBALSTRING: - delete *ofs->GetFieldPointer(m); - break; - case ONEOF_TYPE_CORD: - delete *ofs->GetFieldPointer(m); - break; - case ONEOF_TYPE_STRINGPIECE: - delete *ofs->GetFieldPointer< - goog::internal::StringPieceField*>(m); - break; - case ONEOF_TYPE_LAZYFIELD: - delete *ofs->GetFieldPointer(m); - break; -#endif - } - } - - // Returns whether this is different than the previous value of the - // field_number; this implies that the current value was freed (if - // necessary) and the caller should allocate a new instance. - bool SetOneofHas(goog::Message* m, const FieldOffset* ofs) const { - int32_t *field_number = GetFieldPointer(m); - if (*field_number == field_number_) { - return false; - } else { - ClearOneof(m, ofs, *field_number); - *field_number = field_number_; - return true; - } - } - - private: - enum OneofType { - ONEOF_TYPE_NONE, - ONEOF_TYPE_STRING, - ONEOF_TYPE_MESSAGE -#ifdef UPB_GOOGLE3 - , - ONEOF_TYPE_GLOBALSTRING, - ONEOF_TYPE_CORD, - ONEOF_TYPE_STRINGPIECE, - ONEOF_TYPE_LAZYFIELD -#endif - }; - - OneofType GetTypeForString(const goog::FieldDescriptor* f) { - switch (f->options().ctype()) { - case goog::FieldOptions::STRING: -#ifdef UPB_GOOGLE3 - return ONEOF_TYPE_GLOBALSTRING; -#else - return ONEOF_TYPE_STRING; -#endif - -#ifdef UPB_GOOGLE3 - case goog::FieldOptions::CORD: - return ONEOF_TYPE_CORD; - case goog::FieldOptions::STRING_PIECE: - return ONEOF_TYPE_STRINGPIECE; -#endif - default: - UPB_ASSERT(false); - return ONEOF_TYPE_NONE; - } - } - - // Offset of the uint32 that specifies which field is set. - size_t field_number_offset_; - - // Field number for this field. - int32_t field_number_; - - // The types of the oneof fields, indexed by field_number_. - std::map types_; - }; - - class OneofFieldHandlerData : public FieldOffset { - public: - OneofFieldHandlerData(const goog::FieldDescriptor* f, - const goog::internal::GeneratedMessageReflection* r) - : FieldOffset(f, r), - oneof_data_(f, r) {} - - bool SetOneofHas(goog::Message* message) const { - return oneof_data_.SetOneofHas(message, this); - } - - public: - OneofFieldData oneof_data_; - }; -#endif // GOOGLE_PROTOBUF_HAS_ONEOF - - class ExtensionFieldData { - public: - ExtensionFieldData( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r) - : offset_(r->extensions_offset_), - field_descriptor_(proto2_f) { - } - - int number() const { return field_descriptor_->number(); } - goog::internal::FieldType type() const { return field_descriptor_->type(); } - const goog::FieldDescriptor* field_descriptor() const { - return field_descriptor_; - } - - goog::internal::ExtensionSet* GetExtensionSet(goog::Message* m) const { - return GetPointer(m, offset_); - } - - private: - const size_t offset_; - // We know it will outlive because we require that the input message used to - // build these handlers outlives us, and the descriptor will outlive the - // message. - const goog::FieldDescriptor* field_descriptor_; - }; - - // StartSequence ///////////////////////////////////////////////////////////// - - template - static void SetStartRepeatedField( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - CHKRET(h->SetStartSequenceHandler( - f, UpbBindT(&PushOffset >, - new FieldOffset(proto2_f, r)))); - } - - template - static void SetStartRepeatedPtrField( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - CHKRET(h->SetStartSequenceHandler( - f, UpbBindT(&PushOffset >, - new FieldOffset(proto2_f, r)))); - } - - static void SetStartRepeatedSubmessageField( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - CHKRET(h->SetStartSequenceHandler( - f, UpbBind(&PushOffset, - new FieldOffset(proto2_f, r)))); - } - - template - static T* PushOffset(goog::Message* message, const FieldOffset* offset) { - return offset->GetFieldPointer(message); - } - - // Primitive Value (numeric, bool) /////////////////////////////////////////// - - template static void SetPrimitiveHandlers( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - if (proto2_f->is_extension()) { - scoped_ptr data(new ExtensionFieldData(proto2_f, r)); - if (f->IsSequence()) { - CHKRET(h->SetValueHandler( - f, UpbBindT(AppendPrimitiveExtension, data.release()))); - } else { - CHKRET(h->SetValueHandler( - f, UpbBindT(SetPrimitiveExtension, data.release()))); - } - } -#ifdef GOOGLE_PROTOBUF_HAS_ONEOF - else if (proto2_f->containing_oneof()) { - UPB_ASSERT(!proto2_f->is_repeated()); - CHKRET(h->SetValueHandler( - f, UpbBindT(SetOneofPrimitive, - new OneofFieldHandlerData(proto2_f, r)))); - } -#endif - else { - if (f->IsSequence()) { - SetStartRepeatedField(proto2_f, r, f, h); - CHKRET(h->SetValueHandler(f, UpbMakeHandlerT(AppendPrimitive))); - } else { - CHKRET(upb_msg_setscalarhandler(h, f, GetOffset(proto2_f, r), - GetHasbit(proto2_f, r))); - } - } - } - - template - static void AppendPrimitive(goog::RepeatedField* r, T val) { r->Add(val); } - - template - static void AppendPrimitiveExtension(goog::Message* m, - const ExtensionFieldData* data, T val) { - goog::internal::ExtensionSet* set = data->GetExtensionSet(m); - // TODO(haberman): give an accurate value for "packed" - goog::internal::RepeatedPrimitiveTypeTraits::Add( - data->number(), data->type(), true, val, set); - } - - template - static void SetPrimitiveExtension(goog::Message* m, - const ExtensionFieldData* data, T val) { - goog::internal::ExtensionSet* set = data->GetExtensionSet(m); - goog::internal::PrimitiveTypeTraits::Set(data->number(), data->type(), - val, set); - } - -#ifdef GOOGLE_PROTOBUF_HAS_ONEOF - template - static void SetOneofPrimitive(goog::Message* m, - const OneofFieldHandlerData* data, T val) { - data->SetOneofHas(m); - const FieldOffset* ofs = data; - T* ptr = ofs->GetFieldPointer(m); - *ptr = val; - } -#endif - - // Enum ////////////////////////////////////////////////////////////////////// - - class EnumHandlerData : public FieldOffset { - public: - EnumHandlerData(const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f) - : FieldOffset(proto2_f, r), - field_number_(f->number()), - enum_(upb_downcast_enumdef(f->subdef())) {} - - bool IsValidValue(int32_t val) const { - return enum_->FindValueByNumber(val) != NULL; - } - - int32_t field_number() const { return field_number_; } - - private: - int32_t field_number_; - const upb::EnumDef* enum_; - }; - - static void SetEnumHandlers( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - UPB_ASSERT(!proto2_f->is_extension()); - scoped_ptr data(new EnumHandlerData(proto2_f, r, f)); - if (f->IsSequence()) { - CHKRET(h->SetInt32Handler(f, UpbBind(AppendEnum, data.release()))); - } else { - CHKRET(h->SetInt32Handler(f, UpbBind(SetEnum, data.release()))); - } - } - - static void SetEnum(goog::Message* m, const EnumHandlerData* data, - int32_t val) { - if (data->IsValidValue(val)) { - int32_t* message_val = data->GetFieldPointer(m); - *message_val = val; - data->SetHasbit(m); - } else { - data->GetUnknownFieldSet(m)->AddVarint(data->field_number(), val); - } - } - - static void AppendEnum(goog::Message* m, const EnumHandlerData* data, - int32_t val) { - // Closure is the enclosing message. We can't use the RepeatedField<> as - // the closure because we need to go back to the message for unrecognized - // enum values, which go into the unknown field set. - if (data->IsValidValue(val)) { - goog::RepeatedField* r = - data->GetFieldPointer >(m); - r->Add(val); - } else { - data->GetUnknownFieldSet(m)->AddVarint(data->field_number(), val); - } - } - - // EnumExtension ///////////////////////////////////////////////////////////// - - static void SetEnumExtensionHandlers( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - UPB_ASSERT(proto2_f->is_extension()); - scoped_ptr data(new ExtensionFieldData(proto2_f, r)); - if (f->IsSequence()) { - CHKRET( - h->SetInt32Handler(f, UpbBind(AppendEnumExtension, data.release()))); - } else { - CHKRET(h->SetInt32Handler(f, UpbBind(SetEnumExtension, data.release()))); - } - } - - static void SetEnumExtension(goog::Message* m, const ExtensionFieldData* data, - int32_t val) { - goog::internal::ExtensionSet* set = data->GetExtensionSet(m); - set->SetEnum(data->number(), data->type(), val, NULL); - } - - static void AppendEnumExtension(goog::Message* m, - const ExtensionFieldData* data, int32_t val) { - goog::internal::ExtensionSet* set = data->GetExtensionSet(m); - // TODO(haberman): give an accurate value for "packed" - set->AddEnum(data->number(), data->type(), true, val, NULL); - } - - // String //////////////////////////////////////////////////////////////////// - - // For scalar (non-repeated) string fields. - template class StringHandlerData : public FieldOffset { - public: - StringHandlerData(const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r) - : FieldOffset(proto2_f, r), - prototype_(*GetConstPointer(r->default_instance_, - GetOffset(proto2_f, r))) {} - - const T* prototype() const { return prototype_; } - - T** GetStringPointer(goog::Message* message) const { - return GetFieldPointer(message); - } - - private: - const T* prototype_; - }; - - template static void SetStringHandlers( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, - upb::Handlers* h) { - UPB_ASSERT(!proto2_f->is_extension()); - CHKRET(h->SetStringHandler(f, UpbMakeHandlerT(&OnStringBuf))); -#ifdef GOOGLE_PROTOBUF_HAS_ONEOF - if (proto2_f->containing_oneof()) { - UPB_ASSERT(!f->IsSequence()); - CHKRET(h->SetStartStringHandler( - f, UpbBindT(&StartOneofString, - new OneofFieldHandlerData(proto2_f, r)))); - } else -#endif - if (f->IsSequence()) { - SetStartRepeatedPtrField(proto2_f, r, f, h); - CHKRET( - h->SetStartStringHandler(f, UpbMakeHandlerT(StartRepeatedString))); - } else { - CHKRET(h->SetStartStringHandler( - f, UpbBindT(StartString, new StringHandlerData(proto2_f, r)))); - } - } - - // This needs to be templated because google3 string is not std::string. - template - static T* StartString(goog::Message* m, const StringHandlerData* data, - size_t size_hint) { - UPB_UNUSED(size_hint); - T** str = data->GetStringPointer(m); - data->SetHasbit(m); - // If it points to the default instance, we must create a new instance. - if (*str == data->prototype()) { - *str = new T(); -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - if (data->GetArena(*m)) { - data->GetArena(*m)->Own(*str); - } -#endif - } - (*str)->clear(); - // reserve() here appears to hurt performance rather than help. - return *str; - } - - template - static void OnStringBuf(T* str, const char* buf, size_t n) { - str->append(buf, n); - } - - template - static T* StartRepeatedString(goog::RepeatedPtrField* r, - size_t size_hint) { - UPB_UNUSED(size_hint); - T* str = r->Add(); - str->clear(); - // reserve() here appears to hurt performance rather than help. - return str; - } - -#ifdef GOOGLE_PROTOBUF_HAS_ONEOF - template - static T* StartOneofString(goog::Message* m, - const OneofFieldHandlerData* data, - size_t size_hint) { - UPB_UNUSED(size_hint); - const FieldOffset* ofs = data; - T** str = ofs->GetFieldPointer(m); - if (data->SetOneofHas(m)) { - *str = new T(); -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - // Note that in the main proto2-arenas implementation, the parsing code - // creates ArenaString instances for string field data, and the - // implementation later dynamically converts to ::string if a mutable - // version is requested. To keep complexity down in this binding, we - // create an ordinary string and allow the arena to own its destruction. - if (data->GetArena(*m) != NULL) { - data->GetArena(*m)->Own(*str); - } -#endif - } else { - (*str)->clear(); - } - return *str; - } -#endif - - // StringExtension /////////////////////////////////////////////////////////// - - template - static void SetStringExtensionHandlers( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - UPB_ASSERT(proto2_f->is_extension()); - CHKRET(h->SetStringHandler(f, UpbMakeHandlerT(OnStringBuf))); - scoped_ptr data(new ExtensionFieldData(proto2_f, r)); - if (f->IsSequence()) { - CHKRET(h->SetStartStringHandler( - f, UpbBindT(StartRepeatedStringExtension, data.release()))); - } else { - CHKRET(h->SetStartStringHandler( - f, UpbBindT(StartStringExtension, data.release()))); - } - } - - // Templated because google3 is not std::string. - template - static T* StartStringExtension(goog::Message* m, - const ExtensionFieldData* data, - size_t size_hint) { - UPB_UNUSED(size_hint); - goog::internal::ExtensionSet* set = data->GetExtensionSet(m); - return set->MutableString(data->number(), data->type(), NULL); - } - - template - static T* StartRepeatedStringExtension(goog::Message* m, - const ExtensionFieldData* data, - size_t size_hint) { - UPB_UNUSED(size_hint); - goog::internal::ExtensionSet* set = data->GetExtensionSet(m); - return set->AddString(data->number(), data->type(), NULL); - } - - // SubMessage //////////////////////////////////////////////////////////////// - - class SubMessageHandlerData : public FieldOffset { - public: - SubMessageHandlerData(const goog::FieldDescriptor* f, - const goog::internal::GeneratedMessageReflection* r, - const goog::Message* prototype) - : FieldOffset(f, r), prototype_(prototype) {} - - const goog::Message* prototype() const { return prototype_; } - - private: - const goog::Message* const prototype_; - }; - -#ifdef GOOGLE_PROTOBUF_HAS_ONEOF - class OneofSubMessageHandlerData : public SubMessageHandlerData { - public: - OneofSubMessageHandlerData(const goog::FieldDescriptor* f, - const goog::internal::GeneratedMessageReflection* r, - const goog::Message* prototype) - : SubMessageHandlerData(f, r, prototype), - oneof_data_(f, r) {} - - bool SetOneofHas(goog::Message* m) const { - return oneof_data_.SetOneofHas(m, this); - } - - private: - OneofFieldData oneof_data_; - }; -#endif - - static void SetSubMessageHandlers( - const goog::FieldDescriptor* proto2_f, const goog::Message& m, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f); - scoped_ptr data( - new SubMessageHandlerData(proto2_f, r, field_prototype)); -#ifdef GOOGLE_PROTOBUF_HAS_ONEOF - if (proto2_f->containing_oneof()) { - UPB_ASSERT(!f->IsSequence()); - CHKRET(h->SetStartSubMessageHandler( - f, UpbBind(StartOneofSubMessage, new OneofSubMessageHandlerData( - proto2_f, r, field_prototype)))); - } else -#endif - if (f->IsSequence()) { - SetStartRepeatedSubmessageField(proto2_f, r, f, h); - CHKRET(h->SetStartSubMessageHandler( - f, UpbBind(StartRepeatedSubMessage, data.release()))); - } else { - CHKRET(h->SetStartSubMessageHandler( - f, UpbBind(StartSubMessage, data.release()))); - } - } - - static goog::Message* StartSubMessage(goog::Message* m, - const SubMessageHandlerData* data) { - data->SetHasbit(m); - goog::Message** subm = data->GetFieldPointer(m); - if (*subm == NULL || *subm == data->prototype()) { -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - *subm = data->prototype()->New(data->GetArena(*m)); -#else - *subm = data->prototype()->New(); -#endif - } - return *subm; - } - - class RepeatedMessageTypeHandler { - public: - typedef goog::Message Type; -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - static goog::Arena* GetArena(Type* t) { - return t->GetArena(); - } - static void* GetMaybeArenaPointer(Type* t) { - return t->GetMaybeArenaPointer(); - } - static inline Type* NewFromPrototype( - const Type* prototype, goog::Arena* arena = NULL) { - return prototype->New(arena); - } - static void Delete(Type* t, goog::Arena* arena = NULL) { - if (arena == NULL) { - delete t; - } - } -#else // ifdef GOOGLE_PROTOBUF_HAS_ARENAS - static inline Type* NewFromPrototype(const Type* prototype) { - return prototype->New(); - } - // AddAllocated() calls this, but only if other objects are sitting - // around waiting for reuse, which we will not do. - static void Delete(Type* t) { - UPB_UNUSED(t); - UPB_ASSERT(false); - } -#endif // ifdef GOOGLE_PROTOBUF_HAS_ARENAS - - static void Merge(const Type& from, Type* to) { - to->MergeFrom(from); - } - }; - - // Closure is a RepeatedPtrField*, but we access it through - // its base class RepeatedPtrFieldBase*. - static goog::Message* StartRepeatedSubMessage( - goog::internal::RepeatedPtrFieldBase* r, - const SubMessageHandlerData* data) { -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - return r->Add( - const_cast(data->prototype())); -#else - // This code path is required not because of arena-related API changes but - // because the variant of Add<>() that takes a prototype object was added - // only recently. Without the prototype, there's no way for Add<>() to - // create a new submessage with out typehandler implementation because we - // don't have New() (because we don't template-specialize our typehandler - // class on concrete message types). So we have to implement the runtime - // polymorphism externally (in this function) and then use AddAllocated to - // insert the pointer. - goog::Message* submsg = r->AddFromCleared(); - if (!submsg) { - submsg = data->prototype()->New(); - r->AddAllocated(submsg); - } - return submsg; -#endif - } - -#ifdef GOOGLE_PROTOBUF_HAS_ONEOF - static goog::Message* StartOneofSubMessage( - goog::Message* m, const OneofSubMessageHandlerData* data) { - const FieldOffset* ofs = data; - goog::Message** subm = ofs->GetFieldPointer(m); - if (data->SetOneofHas(m)) { -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - *subm = data->prototype()->New(data->GetArena(*m)); -#else - *subm = data->prototype()->New(); -#endif - } - return *subm; - } -#endif - - // SubMessageExtension /////////////////////////////////////////////////////// - - class SubMessageExtensionHandlerData : public ExtensionFieldData { - public: - SubMessageExtensionHandlerData( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const goog::Message* prototype) - : ExtensionFieldData(proto2_f, r), - prototype_(prototype) { - } - - const goog::Message* prototype() const { return prototype_; } - - private: - const goog::Message* const prototype_; - }; - - static void SetSubMessageExtensionHandlers( - const goog::FieldDescriptor* proto2_f, - const goog::Message& m, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, - upb::Handlers* h) { - const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f); - scoped_ptr data( - new SubMessageExtensionHandlerData(proto2_f, r, field_prototype)); - if (f->IsSequence()) { - CHKRET(h->SetStartSubMessageHandler( - f, UpbBind(StartRepeatedSubMessageExtension, data.release()))); - } else { - CHKRET(h->SetStartSubMessageHandler( - f, UpbBind(StartSubMessageExtension, data.release()))); - } - } - - static goog::Message* StartRepeatedSubMessageExtension( - goog::Message* m, const SubMessageExtensionHandlerData* data) { - goog::internal::ExtensionSet* set = data->GetExtensionSet(m); - // Because we found this message via a descriptor, we know it has a - // descriptor and is therefore a Message and not a MessageLite. - // Alternatively we could just use goog::MessageLite everywhere to avoid - // this, but since they are in fact goog::Messages, it seems most clear - // to refer to them as such. - return CheckDownCast(set->AddMessage( - data->number(), data->type(), *data->prototype(), NULL)); - } - - static goog::Message* StartSubMessageExtension( - goog::Message* m, const SubMessageExtensionHandlerData* data) { - goog::internal::ExtensionSet* set = data->GetExtensionSet(m); - // See comment above re: this down cast. - return CheckDownCast(set->MutableMessage( - data->number(), data->type(), *data->prototype(), NULL)); - } - - // TODO(haberman): handle Unknown Fields. - -#ifdef UPB_GOOGLE3 - // Handlers for types/features only included in internal proto2 release: - // Cord, StringPiece, LazyField, and MessageSet. - // TODO(haberman): MessageSet. - - // Cord ////////////////////////////////////////////////////////////////////// - - static void AppendBufToCord(const char* buf, size_t n, - const upb::BufferHandle* handle, Cord* c) { - const Cord* source_cord = handle->GetAttachedObject(); - if (source_cord) { - // This TODO is copied from CordReader::CopyToCord(): - // "We could speed this up by using CordReader internals." - Cord piece(*source_cord); - piece.RemovePrefix(handle->object_offset() + (buf - handle->buffer())); - UPB_ASSERT(piece.size() >= n); - piece.RemoveSuffix(piece.size() - n); - - c->Append(piece); - } else { - c->Append(StringPiece(buf, n)); - } - } - - static void SetCordHandlers( - const proto2::FieldDescriptor* proto2_f, - const proto2::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - UPB_ASSERT(!proto2_f->is_extension()); - CHKRET(h->SetStringHandler(f, UpbMakeHandler(&OnCordBuf))); - if (f->IsSequence()) { - SetStartRepeatedField(proto2_f, r, f, h); - CHKRET(h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedCord))); - } else { - CHKRET(h->SetStartStringHandler( - f, UpbBind(StartCord, new FieldOffset(proto2_f, r)))); - } - } - - static Cord* StartCord(goog::Message* m, const FieldOffset* offset, - size_t size_hint) { - UPB_UNUSED(size_hint); - offset->SetHasbit(m); - Cord* field = offset->GetFieldPointer(m); - field->Clear(); - return field; - } - - static void OnCordBuf(Cord* c, const char* buf, size_t n, - const upb::BufferHandle* handle) { - AppendBufToCord(buf, n, handle, c); - } - - static Cord* StartRepeatedCord(proto2::RepeatedField* r, - size_t size_hint) { - UPB_UNUSED(size_hint); - return r->Add(); - } - - // StringPiece /////////////////////////////////////////////////////////////// - - static void SetStringPieceHandlers( - const proto2::FieldDescriptor* proto2_f, - const proto2::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - UPB_ASSERT(!proto2_f->is_extension()); - CHKRET(h->SetStringHandler(f, UpbMakeHandler(OnStringPieceBuf))); - if (f->IsSequence()) { - SetStartRepeatedPtrField(proto2_f, r, - f, h); - CHKRET(h->SetStartStringHandler( - f, UpbMakeHandler(StartRepeatedStringPiece))); - } else { - CHKRET(h->SetStartStringHandler( - f, UpbBind(StartStringPiece, new FieldOffset(proto2_f, r)))); - } - } - - static void OnStringPieceBuf(proto2::internal::StringPieceField* field, - const char* buf, size_t len) { - // TODO(haberman): alias if possible and enabled on the input stream. - // TODO(haberman): add a method to StringPieceField that lets us avoid - // this copy/malloc/free. - size_t new_len = field->size() + len; - char* data = new char[new_len]; - memcpy(data, field->data(), field->size()); - memcpy(data + field->size(), buf, len); - field->CopyFrom(StringPiece(data, new_len)); - delete[] data; - } - - static proto2::internal::StringPieceField* StartStringPiece( - goog::Message* m, const FieldOffset* offset, size_t size_hint) { - UPB_UNUSED(size_hint); - offset->SetHasbit(m); - proto2::internal::StringPieceField* field = - offset->GetFieldPointer(m); - field->Clear(); - return field; - } - - static proto2::internal::StringPieceField* StartRepeatedStringPiece( - proto2::RepeatedPtrField* r, - size_t size_hint) { - UPB_UNUSED(size_hint); - proto2::internal::StringPieceField* field = r->Add(); - field->Clear(); - return field; - } - - // LazyField ///////////////////////////////////////////////////////////////// - - // For lazy fields we set both lazy and eager handlers. The user can - // configure the data source to call either, though lazy handlers may only be - // used when the source data is binary protobuf. - static void SetLazyFieldHandlers( - const proto2::FieldDescriptor* proto2_f, - const proto2::Message& m, - const proto2::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, upb::Handlers* h) { - UPB_ASSERT(!proto2_f->is_repeated()); - const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f); - CHKRET(h->SetStringHandler(f, UpbMakeHandler(OnLazyFieldBuf))); - if (proto2_f->is_extension()) { - CHKRET(h->SetStartStringHandler( - f, UpbBind(StartLazyExtension, new ExtensionFieldData(proto2_f, r)))); - CHKRET(h->SetStartSubMessageHandler( - f, UpbBind(StartSubMessageExtension, - new SubMessageExtensionHandlerData(proto2_f, r, - field_prototype)))); - } else { - CHKRET(h->SetStartStringHandler( - f, UpbBind(StartLazyField, new FieldOffset(proto2_f, r)))); - CHKRET(h->SetStartSubMessageHandler( - f, UpbBind(StartLazyFieldEager, - new SubMessageHandlerData(proto2_f, r, field_prototype)))); - } - } - - static proto2::internal::LazyField* StartLazyField(proto2::Message* m, - const FieldOffset* offset, - size_t size_hint) { - UPB_UNUSED(size_hint); - offset->SetHasbit(m); - proto2::internal::LazyField* field = - offset->GetFieldPointer(m); - field->Clear(); - return field; - } - - // For when the field has a lazy representation but we parse it eagerly anyway - // (either because we want to or because we're parsing from a format other - // than binary protobuf). - static proto2::Message* StartLazyFieldEager( - proto2::Message* m, const SubMessageHandlerData* data) { - data->SetHasbit(m); - proto2::internal::LazyField* field = - data->GetFieldPointer(m); - return field->MutableByPrototype(*data->prototype()); - } - - class LazyMessageExtensionImpl - : public proto2::internal::ExtensionSet::LazyMessageExtension { - public: - LazyMessageExtensionImpl() {} - virtual ~LazyMessageExtensionImpl() {} - -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - virtual LazyMessageExtension* New() const { - return New(NULL); - } - - virtual LazyMessageExtension* New(proto2::Arena* arena) const { - LazyMessageExtensionImpl* message = - ::proto2::Arena::Create(arena); - return message; - } -#else // ifdef GOOGLE_PROTOBUF_HAS_ARENAS - virtual LazyMessageExtension* New() const { - return new LazyMessageExtensionImpl(); - } -#endif // ifdef GOOGLE_PROTOBUF_HAS_ARENAS - - virtual const proto2::MessageLite& GetMessage( - const proto2::MessageLite& prototype) const { - return lazy_field_.GetByPrototype( - static_cast(prototype)); - } - - virtual proto2::MessageLite* MutableMessage( - const proto2::MessageLite& prototype) { - return lazy_field_.MutableByPrototype( - static_cast(prototype)); - } - - virtual void SetAllocatedMessage(proto2::MessageLite* message) { - return lazy_field_.SetAllocated(static_cast(message)); - } - - virtual void UnsafeArenaSetAllocatedMessage(proto2::MessageLite* message) { - return lazy_field_.UnsafeArenaSetAllocated( - static_cast(message)); - } - - virtual proto2::MessageLite* ReleaseMessage( - const proto2::MessageLite& prototype) { - return lazy_field_.ReleaseByPrototype( - static_cast(prototype)); - } - - virtual proto2::MessageLite* UnsafeArenaReleaseMessage( - const proto2::MessageLite& prototype) { - return lazy_field_.UnsafeArenaReleaseByPrototype( - static_cast(prototype)); - } - - virtual bool IsInitialized() const { return true; } - - virtual int ByteSize() const { return lazy_field_.MessageByteSize(); } - - int SpaceUsed() const { - return sizeof(*this) + lazy_field_.SpaceUsedExcludingSelf(); - } - - virtual void MergeFrom(const LazyMessageExtension& other) { - MergeFrom(*static_cast(&other)); - } - - virtual void MergeFrom(const LazyMessageExtensionImpl& other) { - lazy_field_.MergeFrom(other.lazy_field_); - } - - virtual void Clear() { lazy_field_.Clear(); } - - virtual bool ReadMessage(const proto2::MessageLite& prototype, - proto2::io::CodedInputStream* input) { - return lazy_field_.Read(input); - } - - virtual void WriteMessage(int number, - proto2::io::CodedOutputStream* output) const { - lazy_field_.Write(number, output); - } - - virtual uint8* WriteMessageToArray(int number, uint8* target) const { - return lazy_field_.WriteToArray(number, target); - } - - proto2::internal::LazyField& lazy_field() { return lazy_field_; } - - private: - proto2::internal::LazyField lazy_field_; - DISALLOW_COPY_AND_ASSIGN(LazyMessageExtensionImpl); - }; - - static proto2::internal::LazyField* StartLazyExtension( - proto2::Message* m, const ExtensionFieldData* data, size_t size_hint) { - proto2::internal::ExtensionSet* set = data->GetExtensionSet(m); - - // We have to break encapsulation here since no public accessors expose the - // LazyField. - // - // TODO(haberman): add a function to ExtensionSet that allows us to set the - // lazy field directly. - proto2::internal::ExtensionSet::Extension* item; - LazyMessageExtensionImpl* lazy_extension; - if (set->MaybeNewExtension(data->number(), data->field_descriptor(), - &item)) { -#ifdef GOOGLE_PROTOBUF_HAS_ARENAS - lazy_extension = - ::proto2::Arena::Create( - m->GetArena()); -#else - lazy_extension = new LazyMessageExtensionImpl(); -#endif - item->type = UPB_DESCRIPTOR_TYPE_MESSAGE; - item->is_repeated = false; - item->is_lazy = true; - item->lazymessage_value = lazy_extension; - } else { - lazy_extension = - CheckDownCast(item->lazymessage_value); - } - - item->is_cleared = false; - - return &lazy_extension->lazy_field(); - } - - static void OnLazyFieldBuf(proto2::internal::LazyField* field, - const char* buf, size_t len, - const upb::BufferHandle* handle) { - Cord encoded(field->GetEncoded()); - AppendBufToCord(buf, len, handle, &encoded); - field->SetEncoded(encoded); - } - -#endif // UPB_GOOGLE3 -}; - -namespace upb { -namespace googlepb { - -bool TrySetWriteHandlers(const goog::FieldDescriptor* proto2_f, - const goog::Message& prototype, - const upb::FieldDef* upb_f, upb::Handlers* h) { - return me::GMR_Handlers::TrySet(proto2_f, prototype, upb_f, h); -} - -const goog::Message* GetProto2FieldPrototype(const goog::Message& m, - const goog::FieldDescriptor* f) { - if (f->cpp_type() != goog::FieldDescriptor::CPPTYPE_MESSAGE) { - return NULL; - } - return me::GMR_Handlers::GetFieldPrototype(m, f); -} - -} // namespace googlepb -} // namespace upb -- cgit v1.2.3