From cfdb9907cb87d15eaab72ceefbfa42fd7a4c3127 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Sat, 11 May 2013 16:45:38 -0700 Subject: Synced with 3 months of Google-internal development. Major changes: - Got rid of all bytestream interfaces in favor of using regular handlers. - new Pipeline object represents a upb pipeline, does bump allocation internally to manage memory. - proto2 support now can handle extensions. --- upb/google/bridge.cc | 82 ++++---- upb/google/bridge.h | 5 +- upb/google/cord.h | 48 ----- upb/google/proto1.cc | 281 +++++++++++++-------------- upb/google/proto1.h | 8 +- upb/google/proto2.cc | 540 ++++++++++++++++++++++++++++++++++----------------- upb/google/proto2.h | 5 +- 7 files changed, 554 insertions(+), 415 deletions(-) delete mode 100644 upb/google/cord.h (limited to 'upb/google') diff --git a/upb/google/bridge.cc b/upb/google/bridge.cc index 4d64ab8..f5b664c 100644 --- a/upb/google/bridge.cc +++ b/upb/google/bridge.cc @@ -47,11 +47,15 @@ class me::Defs { const upb::FieldDef* upb_f = i.field(); const goog::FieldDescriptor* proto2_f = d->FindFieldByNumber(upb_f->number()); + if (!proto2_f) { + proto2_f = d->file()->pool()->FindExtensionByNumber(d, upb_f->number()); + } + assert(proto2_f); if (!upb::google::TrySetWriteHandlers(proto2_f, m, upb_f, h) #ifdef UPB_GOOGLE3 && !upb::google::TrySetProto1WriteHandlers(proto2_f, m, upb_f, h) #endif - ) { + ) { // Unsupported reflection class. // // Should we fall back to using the public Reflection interface in this @@ -62,7 +66,7 @@ class me::Defs { } } - static void StaticOnMessage(void *closure, upb::Handlers* handlers) { + static void StaticOnMessage(void* closure, upb::Handlers* handlers) { me::Defs* defs = static_cast(closure); defs->OnMessage(handlers); } @@ -121,51 +125,53 @@ FieldDef* AddFieldDef(const goog::Message& m, const goog::FieldDescriptor* f, upb_f->set_number(f->number()); upb_f->set_name(f->name()); upb_f->set_label(static_cast(f->label())); - upb_f->set_type(weak_prototype ? - UPB_TYPE_MESSAGE : static_cast(f->type())); + upb_f->set_descriptor_type( + weak_prototype ? UPB_DESCRIPTOR_TYPE_MESSAGE : + static_cast(f->type())); if (weak_prototype) { upb_f->set_subdef_name(weak_prototype->GetDescriptor()->full_name()); - } else if (upb_f->IsSubMessage()) { - upb_f->set_subdef_name(f->message_type()->full_name()); - } else if (upb_f->type() == UPB_TYPE(ENUM)) { - // We set the enum default numerically. - upb_f->set_default_value( - MakeValue(static_cast(f->default_value_enum()->number()))); - upb_f->set_subdef_name(f->enum_type()->full_name()); } else { - // Set field default for primitive types. Need to switch on the upb type - // rather than the proto2 type, because upb_f->type() may have been changed - // from BYTES to MESSAGE for a weak field. - switch (upb_types[upb_f->type()].inmemory_type) { - case UPB_CTYPE_INT32: + switch (upb_f->type()) { + case UPB_TYPE_INT32: upb_f->set_default_value(MakeValue(f->default_value_int32())); break; - case UPB_CTYPE_INT64: + case UPB_TYPE_INT64: upb_f->set_default_value( MakeValue(static_cast(f->default_value_int64()))); break; - case UPB_CTYPE_UINT32: + case UPB_TYPE_UINT32: upb_f->set_default_value(MakeValue(f->default_value_uint32())); break; - case UPB_CTYPE_UINT64: + case UPB_TYPE_UINT64: upb_f->set_default_value( MakeValue(static_cast(f->default_value_uint64()))); break; - case UPB_CTYPE_DOUBLE: + case UPB_TYPE_DOUBLE: upb_f->set_default_value(MakeValue(f->default_value_double())); break; - case UPB_CTYPE_FLOAT: + case UPB_TYPE_FLOAT: upb_f->set_default_value(MakeValue(f->default_value_float())); break; - case UPB_CTYPE_BOOL: + case UPB_TYPE_BOOL: upb_f->set_default_value(MakeValue(f->default_value_bool())); break; - case UPB_CTYPE_BYTEREGION: + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: upb_f->set_default_string(f->default_value_string()); break; + case UPB_TYPE_MESSAGE: + upb_f->set_subdef_name(f->message_type()->full_name()); + break; + case UPB_TYPE_ENUM: + // We set the enum default numerically. + upb_f->set_default_value( + MakeValue(static_cast(f->default_value_enum()->number()))); + upb_f->set_subdef_name(f->enum_type()->full_name()); + break; } } + bool ok = md->AddField(upb_f, &upb_f); UPB_ASSERT_VAR(ok, ok); @@ -174,8 +180,7 @@ FieldDef* AddFieldDef(const goog::Message& m, const goog::FieldDescriptor* f, } else if (f->cpp_type() == goog::FieldDescriptor::CPPTYPE_MESSAGE) { *subm = upb::google::GetFieldPrototype(m, f); #ifdef UPB_GOOGLE3 - if (!*subm) - *subm = upb::google::GetProto1FieldPrototype(m, f); + if (!*subm) *subm = upb::google::GetProto1FieldPrototype(m, f); #endif assert(*subm); } @@ -183,7 +188,7 @@ FieldDef* AddFieldDef(const goog::Message& m, const goog::FieldDescriptor* f, return upb_f; } -upb::EnumDef* NewEnumDef(const goog::EnumDescriptor* desc, void *owner) { +upb::EnumDef* NewEnumDef(const goog::EnumDescriptor* desc, const void* owner) { upb::EnumDef* e = upb::EnumDef::New(owner); e->set_full_name(desc->full_name()); for (int i = 0; i < desc->value_count(); i++) { @@ -194,25 +199,28 @@ upb::EnumDef* NewEnumDef(const goog::EnumDescriptor* desc, void *owner) { return e; } -static upb::MessageDef* NewMessageDef(const goog::Message& m, void *owner, +static upb::MessageDef* NewMessageDef(const goog::Message& m, const void* owner, me::Defs* defs) { upb::MessageDef* md = upb::MessageDef::New(owner); + const goog::Descriptor* d = m.GetDescriptor(); md->set_full_name(m.GetDescriptor()->full_name()); // Must do this before processing submessages to prevent infinite recursion. defs->AddMessage(&m, md); - const goog::Descriptor* d = m.GetDescriptor(); + vector fields; + d->file()->pool()->FindAllExtensions(d, &fields); for (int i = 0; i < d->field_count(); i++) { - const goog::FieldDescriptor* proto2_f = d->field(i); + fields.push_back(d->field(i)); + } + for (int i = 0; i < fields.size(); i++) { + const goog::FieldDescriptor* proto2_f = fields[i]; + assert(proto2_f); #ifdef UPB_GOOGLE3 // Skip lazy fields for now since we can't properly handle them. if (proto2_f->options().lazy()) continue; #endif - // Extensions not supported yet. - if (proto2_f->is_extension()) continue; - const goog::Message* subm_prototype; upb::FieldDef* f = AddFieldDef(m, proto2_f, md, &subm_prototype); @@ -220,7 +228,7 @@ static upb::MessageDef* NewMessageDef(const goog::Message& m, void *owner, upb::Def* subdef = defs->FindSymbol(f->subdef_name()); if (!subdef) { - if (f->type() == UPB_TYPE(ENUM)) { + if (f->type() == UPB_TYPE_ENUM) { subdef = NewEnumDef(proto2_f->enum_type(), owner)->Upcast(); defs->AddSymbol(subdef->full_name(), subdef); } else { @@ -231,11 +239,11 @@ static upb::MessageDef* NewMessageDef(const goog::Message& m, void *owner, } f->set_subdef(subdef); } - return md; } -const upb::Handlers* NewWriteHandlers(const goog::Message& m, void *owner) { +const upb::Handlers* NewWriteHandlers(const goog::Message& m, + const void* owner) { me::Defs defs; const upb::MessageDef* md = NewMessageDef(m, owner, &defs); @@ -245,8 +253,8 @@ const upb::Handlers* NewWriteHandlers(const goog::Message& m, void *owner) { bool success = Def::Freeze(defs_vec, &status); UPB_ASSERT_VAR(success, success); - const upb::Handlers* ret = - upb::Handlers::NewFrozen(md, owner, me::Defs::StaticOnMessage, &defs); + const upb::Handlers* ret = upb::Handlers::NewFrozen( + md, NULL, owner, me::Defs::StaticOnMessage, &defs); // Unref all defs, since they're now ref'd by the handlers. for (int i = 0; i < static_cast(defs_vec.size()); i++) { diff --git a/upb/google/bridge.h b/upb/google/bridge.h index 8a2256f..5091e23 100644 --- a/upb/google/bridge.h +++ b/upb/google/bridge.h @@ -66,9 +66,10 @@ namespace google { // // TODO(haberman): Add handler caching functionality so that we don't use // O(n^2) memory in the worst case when incrementally building handlers. -const upb::Handlers* NewWriteHandlers(const proto2::Message& m, void *owner); +const upb::Handlers* NewWriteHandlers(const proto2::Message& m, + const void* owner); const upb::Handlers* NewWriteHandlers(const ::google::protobuf::Message& m, - void *owner); + const void* owner); } // namespace google } // namespace upb diff --git a/upb/google/cord.h b/upb/google/cord.h deleted file mode 100644 index c579c0c..0000000 --- a/upb/google/cord.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// upb - a minimalist implementation of protocol buffers. -// -// Copyright (c) 2011-2012 Google Inc. See LICENSE for details. -// Author: Josh Haberman -// -// Functionality for interoperating with Cord. Only needed inside Google. - -#ifndef UPB_GOOGLE_CORD_H -#define UPB_GOOGLE_CORD_H - -#include "strings/cord.h" -#include "upb/bytestream.h" - -namespace upb { - -namespace proto2_bridge_google3 { class FieldAccessor; } -namespace proto2_bridge_opensource { class FieldAccessor; } - -namespace google { - -class P2R_Handlers; - -class CordSupport { - private: - UPB_DISALLOW_POD_OPS(CordSupport); - - inline static void AssignToCord(const upb::ByteRegion* r, Cord* cord) { - // TODO(haberman): ref source data if source is a cord. - cord->Clear(); - uint64_t ofs = r->start_ofs(); - while (ofs < r->end_ofs()) { - size_t len; - const char *buf = r->GetPtr(ofs, &len); - cord->Append(StringPiece(buf, len)); - ofs += len; - } - } - - friend class ::upb::proto2_bridge_google3::FieldAccessor; - friend class ::upb::proto2_bridge_opensource::FieldAccessor; - friend class P2R_Handlers; -}; - -} // namespace google -} // namespace upb - -#endif // UPB_GOOGLE_CORD_H diff --git a/upb/google/proto1.cc b/upb/google/proto1.cc index bb9ff75..3967723 100644 --- a/upb/google/proto1.cc +++ b/upb/google/proto1.cc @@ -18,23 +18,14 @@ #include "upb/google/proto1.h" -// TODO(haberman): friend upb so that this isn't required. -#define protected public #include "net/proto2/public/repeated_field.h" -#undef private - -// TODO(haberman): friend upb so that this isn't required. -#define private public -#include "net/proto/proto2_reflection.h" -#undef private - #include "net/proto/internal_layout.h" -#include "upb/bytestream.h" +#include "net/proto/proto2_reflection.h" #include "upb/def.h" -#include "upb/google/cord.h" #include "upb/handlers.h" +#include "upb/sink.h" -template static T* GetPointer(void *message, size_t offset) { +template static T* GetPointer(void* message, size_t offset) { return reinterpret_cast(static_cast(message) + offset); } @@ -47,31 +38,32 @@ class P2R_Handlers { // of the FieldDef that are necessary to read/write this field to a // proto2::Message. static bool TrySet(const proto2::FieldDescriptor* proto2_f, - const proto2::Message& m, - const upb::FieldDef* upb_f, upb::Handlers* h) { + const proto2::Message& m, const upb::FieldDef* upb_f, + upb::Handlers* h) { const proto2::Reflection* base_r = m.GetReflection(); // See file comment re: dynamic_cast. const _pi::Proto2Reflection* r = dynamic_cast(base_r); if (!r) return false; - // Extensions not supported yet. - if (proto2_f->is_extension()) return false; + // Extensions don't exist in proto1. + assert(!proto2_f->is_extension()); + +#define PRIMITIVE(name, type_name) \ + case _pi::CREP_REQUIRED_##name: \ + case _pi::CREP_OPTIONAL_##name: \ + case _pi::CREP_REPEATED_##name: \ + SetPrimitiveHandlers(proto2_f, r, upb_f, h); \ + return true; switch (r->GetFieldLayout(proto2_f)->crep) { -#define PRIMITIVE(name, type_name) \ - case _pi::CREP_REQUIRED_ ## name: \ - case _pi::CREP_OPTIONAL_ ## name: \ - case _pi::CREP_REPEATED_ ## name: \ - SetPrimitiveHandlers(proto2_f, r, upb_f, h); return true; - PRIMITIVE(DOUBLE, double); - PRIMITIVE(FLOAT, float); - PRIMITIVE(INT64, int64_t); - PRIMITIVE(UINT64, uint64_t); - PRIMITIVE(INT32, int32_t); - PRIMITIVE(FIXED64, uint64_t); - PRIMITIVE(FIXED32, uint32_t); - PRIMITIVE(BOOL, bool); -#undef PRIMITIVE + PRIMITIVE(DOUBLE, double); + PRIMITIVE(FLOAT, float); + PRIMITIVE(INT64, int64_t); + PRIMITIVE(UINT64, uint64_t); + PRIMITIVE(INT32, int32_t); + PRIMITIVE(FIXED64, uint64_t); + PRIMITIVE(FIXED32, uint32_t); + PRIMITIVE(BOOL, bool); case _pi::CREP_REQUIRED_STRING: case _pi::CREP_OPTIONAL_STRING: case _pi::CREP_REPEATED_STRING: @@ -102,16 +94,19 @@ class P2R_Handlers { case _pi::CREP_OPTIONAL_FOREIGN_WEAK_PROTO2: SetWeakMessageHandlers(proto2_f, m, r, upb_f, h); return true; - default: assert(false); return false; + default: + assert(false); + return false; } } +#undef PRIMITIVE + // If the field "f" in the message "m" is a weak field, returns the prototype // of the submessage (which may be a specific type or may be OpaqueMessage). // Otherwise returns NULL. static const proto2::Message* GetWeakPrototype( - const proto2::Message& m, - const proto2::FieldDescriptor* f) { + const proto2::Message& m, const proto2::FieldDescriptor* f) { // See file comment re: dynamic_cast. const _pi::Proto2Reflection* r = dynamic_cast(m.GetReflection()); @@ -132,8 +127,7 @@ class P2R_Handlers { // the submessage (which may be OpaqueMessage for a weak field that is not // linked in). Otherwise returns NULL. static const proto2::Message* GetFieldPrototype( - const proto2::Message& m, - const proto2::FieldDescriptor* f) { + const proto2::Message& m, const proto2::FieldDescriptor* f) { // See file comment re: dynamic_cast. const proto2::Message* ret = GetWeakPrototype(m, f); if (ret) { @@ -143,7 +137,7 @@ class P2R_Handlers { // factory. assert(f->cpp_type() == proto2::FieldDescriptor::CPPTYPE_MESSAGE); ret = proto2::MessageFactory::generated_factory()->GetPrototype( - f->message_type()); + f->message_type()); assert(ret); return ret; } else { @@ -154,11 +148,9 @@ class P2R_Handlers { private: class FieldOffset { public: - FieldOffset( - const proto2::FieldDescriptor* f, - const _pi::Proto2Reflection* r) - : offset_(GetOffset(f, r)), - is_repeated_(f->is_repeated()) { + FieldOffset(const proto2::FieldDescriptor* f, + const _pi::Proto2Reflection* r) + : offset_(GetOffset(f, r)), is_repeated_(f->is_repeated()) { if (!is_repeated_) { int64_t hasbit = GetHasbit(f, r); hasbyte_ = hasbit / 8; @@ -166,7 +158,7 @@ class P2R_Handlers { } } - template T* GetFieldPointer(void* message) const { + template T* GetFieldPointer(void* message) const { return GetPointer(message, offset_); } @@ -193,7 +185,6 @@ class P2R_Handlers { return selector; } - static int16_t GetHasbit(const proto2::FieldDescriptor* f, const _pi::Proto2Reflection* r) { assert(!f->is_repeated()); @@ -211,60 +202,60 @@ class P2R_Handlers { const proto2::FieldDescriptor* proto2_f, const _pi::Proto2Reflection* r, const upb::FieldDef* f, upb::Handlers* h) { assert(f->IsSequence()); - h->SetStartSequenceHandler( - f, &PushOffset, new FieldOffset(proto2_f, r), - &upb::DeletePointer); + h->SetStartSequenceHandler(f, &PushOffset, new FieldOffset(proto2_f, r), + &upb::DeletePointer); } - static void* PushOffset(void *m, void *fval) { - const FieldOffset* offset = static_cast(fval); - return offset->GetFieldPointer(m); + static void* PushOffset(const upb::SinkFrame* frame) { + const FieldOffset* offset = + static_cast(frame->handler_data()); + return offset->GetFieldPointer(frame->userdata()); } // Primitive Value (numeric, enum, bool) ///////////////////////////////////// - template static void SetPrimitiveHandlers( - const proto2::FieldDescriptor* proto2_f, - const _pi::Proto2Reflection* r, - const upb::FieldDef* f, upb::Handlers* h) { + template + static void SetPrimitiveHandlers(const proto2::FieldDescriptor* proto2_f, + const _pi::Proto2Reflection* r, + const upb::FieldDef* f, upb::Handlers* h) { if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); h->SetValueHandler(f, &Append, NULL, NULL); } else { - upb::SetStoreValueHandler( - f, GetOffset(proto2_f, r), GetHasbit(proto2_f, r), h); + upb::SetStoreValueHandler(f, GetOffset(proto2_f, r), + GetHasbit(proto2_f, r), h); } } template - static bool Append(void *_r, void *fval, T val) { - UPB_UNUSED(fval); + static bool Append(const upb::SinkFrame* frame, T val) { // Proto1's ProtoArray class derives from proto2::RepeatedField. - proto2::RepeatedField* r = static_cast*>(_r); + proto2::RepeatedField* r = + static_cast*>(frame->userdata()); r->Add(val); return true; } // String //////////////////////////////////////////////////////////////////// - static void SetStringHandlers( - const proto2::FieldDescriptor* proto2_f, - const _pi::Proto2Reflection* r, - const upb::FieldDef* f, upb::Handlers* h) { + static void SetStringHandlers(const proto2::FieldDescriptor* proto2_f, + const _pi::Proto2Reflection* r, + const upb::FieldDef* f, upb::Handlers* h) { h->SetStringHandler(f, &OnStringBuf, NULL, NULL); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); h->SetStartStringHandler(f, &StartRepeatedString, NULL, NULL); } else { - h->SetStartStringHandler( - f, &StartString, new FieldOffset(proto2_f, r), - &upb::DeletePointer); + h->SetStartStringHandler(f, &StartString, new FieldOffset(proto2_f, r), + &upb::DeletePointer); } } - static void* StartString(void *m, void *fval, size_t size_hint) { + static void* StartString(const upb::SinkFrame* frame, size_t size_hint) { UPB_UNUSED(size_hint); - const FieldOffset* info = static_cast(fval); + void* m = frame->userdata(); + const FieldOffset* info = + static_cast(frame->handler_data()); info->SetHasbit(m); string* str = info->GetFieldPointer(m); str->clear(); @@ -272,16 +263,18 @@ class P2R_Handlers { return str; } - static size_t OnStringBuf(void *_s, void *fval, const char *buf, size_t n) { - string* s = static_cast(_s); + static size_t OnStringBuf(const upb::SinkFrame* frame, + const char* buf, + size_t n) { + string* s = static_cast(frame->userdata()); s->append(buf, n); return n; } - static void* StartRepeatedString(void *_r, void *fval, size_t size_hint) { - UPB_UNUSED(fval); + static void* StartRepeatedString(const upb::SinkFrame* frame, + size_t size_hint) { proto2::RepeatedPtrField* r = - static_cast*>(_r); + static_cast*>(frame->userdata()); string* str = r->Add(); // reserve() here appears to hurt performance rather than help. return str; @@ -290,22 +283,24 @@ class P2R_Handlers { // Out-of-line string //////////////////////////////////////////////////////// static void SetOutOfLineStringHandlers( - const proto2::FieldDescriptor* proto2_f, - const _pi::Proto2Reflection* r, + const proto2::FieldDescriptor* proto2_f, const _pi::Proto2Reflection* r, const upb::FieldDef* f, upb::Handlers* h) { // This type is only used for non-repeated string fields. assert(!f->IsSequence()); - h->SetStartStringHandler( - f, &StartOutOfLineString, new FieldOffset(proto2_f, r), - &upb::DeletePointer); + h->SetStartStringHandler(f, &StartOutOfLineString, + new FieldOffset(proto2_f, r), + &upb::DeletePointer); h->SetStringHandler(f, &OnStringBuf, NULL, NULL); } - static void* StartOutOfLineString(void *m, void *fval, size_t size_hint) { - const FieldOffset* info = static_cast(fval); + static void* StartOutOfLineString(const upb::SinkFrame* frame, + size_t size_hint) { + const FieldOffset* info = + static_cast(frame->handler_data()); + void* m = frame->userdata(); info->SetHasbit(m); - string **str = info->GetFieldPointer(m); - if (*str == &::ProtocolMessage::___empty_internal_proto_string_) + string** str = info->GetFieldPointer(m); + if (*str == &::proto2::internal::GetEmptyString()) *str = new string(); (*str)->clear(); // reserve() here appears to hurt performance rather than help. @@ -314,43 +309,43 @@ class P2R_Handlers { // Cord ////////////////////////////////////////////////////////////////////// - static void SetCordHandlers( - const proto2::FieldDescriptor* proto2_f, - const _pi::Proto2Reflection* r, - const upb::FieldDef* f, upb::Handlers* h) { + static void SetCordHandlers(const proto2::FieldDescriptor* proto2_f, + const _pi::Proto2Reflection* r, + const upb::FieldDef* f, upb::Handlers* h) { h->SetStringHandler(f, &OnCordBuf, NULL, NULL); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); h->SetStartStringHandler(f, &StartRepeatedCord, NULL, NULL); } else { - h->SetStartStringHandler( - f, &StartCord, new FieldOffset(proto2_f, r), - &upb::DeletePointer); + h->SetStartStringHandler(f, &StartCord, new FieldOffset(proto2_f, r), + &upb::DeletePointer); } } - static void* StartCord(void *m, void *fval, size_t size_hint) { + static void* StartCord(const upb::SinkFrame* frame, size_t size_hint) { UPB_UNUSED(size_hint); - UPB_UNUSED(fval); - const FieldOffset* offset = static_cast(fval); + void* m = frame->userdata(); + const FieldOffset* offset = + static_cast(frame->handler_data()); offset->SetHasbit(m); Cord* field = offset->GetFieldPointer(m); field->Clear(); return field; } - static size_t OnCordBuf(void *_c, void *fval, const char *buf, size_t n) { - UPB_UNUSED(fval); - Cord* c = static_cast(_c); + static size_t OnCordBuf(const upb::SinkFrame* frame, + const char* buf, + size_t n) { + Cord* c = static_cast(frame->userdata()); c->Append(StringPiece(buf, n)); return true; } - static void* StartRepeatedCord(void *_r, void *fval, size_t size_hint) { + static void* StartRepeatedCord(const upb::SinkFrame* frame, + size_t size_hint) { UPB_UNUSED(size_hint); - UPB_UNUSED(fval); proto2::RepeatedField* r = - static_cast*>(_r); + static_cast*>(frame->userdata()); return r->Add(); } @@ -358,14 +353,12 @@ class P2R_Handlers { class SubMessageHandlerData : public FieldOffset { public: - SubMessageHandlerData( - const proto2::Message& prototype, - const proto2::FieldDescriptor* f, - const _pi::Proto2Reflection* r) + SubMessageHandlerData(const proto2::Message& prototype, + const proto2::FieldDescriptor* f, + const _pi::Proto2Reflection* r) : FieldOffset(f, r) { prototype_ = GetWeakPrototype(prototype, f); - if (!prototype_) - prototype_ = GetFieldPrototype(prototype, f); + if (!prototype_) prototype_ = GetFieldPrototype(prototype, f); } const proto2::Message* prototype() const { return prototype_; } @@ -375,43 +368,40 @@ class P2R_Handlers { }; static void SetStartSubMessageHandler( - const proto2::FieldDescriptor* proto2_f, - const proto2::Message& m, - const _pi::Proto2Reflection* r, - upb::Handlers::StartFieldHandler* handler, + const proto2::FieldDescriptor* proto2_f, const proto2::Message& m, + const _pi::Proto2Reflection* r, upb::Handlers::StartFieldHandler* handler, const upb::FieldDef* f, upb::Handlers* h) { - h->SetStartSubMessageHandler( - f, handler, - new SubMessageHandlerData(m, proto2_f, r), - &upb::DeletePointer); + h->SetStartSubMessageHandler(f, handler, + new SubMessageHandlerData(m, proto2_f, r), + &upb::DeletePointer); } static void SetRequiredMessageHandlers( - const proto2::FieldDescriptor* proto2_f, - const proto2::Message& m, - const _pi::Proto2Reflection* r, - const upb::FieldDef* f, upb::Handlers* h) { + const proto2::FieldDescriptor* proto2_f, const proto2::Message& m, + const _pi::Proto2Reflection* r, const upb::FieldDef* f, + upb::Handlers* h) { if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); SetStartSubMessageHandler(proto2_f, m, r, &StartRepeatedSubMessage, f, h); } else { - h->SetStartSubMessageHandler( - f, &StartRequiredSubMessage, new FieldOffset(proto2_f, r), - &upb::DeletePointer); + h->SetStartSubMessageHandler(f, &StartRequiredSubMessage, + new FieldOffset(proto2_f, r), + &upb::DeletePointer); } } - static void* StartRequiredSubMessage(void *m, void *fval) { - const FieldOffset* offset = static_cast(fval); + static void* StartRequiredSubMessage(const upb::SinkFrame* frame) { + const FieldOffset* offset = + static_cast(frame->handler_data()); + void* m = frame->userdata(); offset->SetHasbit(m); return offset->GetFieldPointer(m); } - static void SetMessageHandlers( - const proto2::FieldDescriptor* proto2_f, - const proto2::Message& m, - const _pi::Proto2Reflection* r, - const upb::FieldDef* f, upb::Handlers* h) { + static void SetMessageHandlers(const proto2::FieldDescriptor* proto2_f, + const proto2::Message& m, + const _pi::Proto2Reflection* r, + const upb::FieldDef* f, upb::Handlers* h) { if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); SetStartSubMessageHandler(proto2_f, m, r, &StartRepeatedSubMessage, f, h); @@ -420,11 +410,10 @@ class P2R_Handlers { } } - static void SetWeakMessageHandlers( - const proto2::FieldDescriptor* proto2_f, - const proto2::Message& m, - const _pi::Proto2Reflection* r, - const upb::FieldDef* f, upb::Handlers* h) { + static void SetWeakMessageHandlers(const proto2::FieldDescriptor* proto2_f, + const proto2::Message& m, + const _pi::Proto2Reflection* r, + const upb::FieldDef* f, upb::Handlers* h) { if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); SetStartSubMessageHandler(proto2_f, m, r, &StartRepeatedSubMessage, f, h); @@ -433,20 +422,22 @@ class P2R_Handlers { } } - static void* StartSubMessage(void *m, void *fval) { + static void* StartSubMessage(const upb::SinkFrame* frame) { + void* m = frame->userdata(); const SubMessageHandlerData* info = - static_cast(fval); + static_cast(frame->handler_data()); info->SetHasbit(m); - proto2::Message **subm = info->GetFieldPointer(m); + proto2::Message** subm = info->GetFieldPointer(m); if (*subm == info->prototype()) *subm = (*subm)->New(); return *subm; } - static void* StartWeakSubMessage(void *m, void *fval) { + static void* StartWeakSubMessage(const upb::SinkFrame* frame) { + void* m = frame->userdata(); const SubMessageHandlerData* info = - static_cast(fval); + static_cast(frame->handler_data()); info->SetHasbit(m); - proto2::Message **subm = info->GetFieldPointer(m); + proto2::Message** subm = info->GetFieldPointer(m); if (*subm == NULL) { *subm = info->prototype()->New(); } @@ -459,19 +450,19 @@ class P2R_Handlers { // AddAllocated() calls this, but only if other objects are sitting // around waiting for reuse, which we will not do. static void Delete(Type* t) { - (void)t; + UPB_UNUSED(t); assert(false); } }; // Closure is a RepeatedPtrField*, but we access it through // its base class RepeatedPtrFieldBase*. - static void* StartRepeatedSubMessage(void* _r, void *fval) { + static void* StartRepeatedSubMessage(const upb::SinkFrame* frame) { const SubMessageHandlerData* info = - static_cast(fval); - proto2::internal::RepeatedPtrFieldBase *r = - static_cast(_r); - void *submsg = r->AddFromCleared(); + static_cast(frame->handler_data()); + proto2::internal::RepeatedPtrFieldBase* r = + static_cast(frame->userdata()); + void* submsg = r->AddFromCleared(); if (!submsg) { submsg = info->prototype()->New(); r->AddAllocated(submsg); @@ -487,14 +478,12 @@ bool TrySetProto1WriteHandlers(const proto2::FieldDescriptor* proto2_f, } const proto2::Message* GetProto1WeakPrototype( - const proto2::Message& m, - const proto2::FieldDescriptor* f) { + const proto2::Message& m, const proto2::FieldDescriptor* f) { return P2R_Handlers::GetWeakPrototype(m, f); } const proto2::Message* GetProto1FieldPrototype( - const proto2::Message& m, - const proto2::FieldDescriptor* f) { + const proto2::Message& m, const proto2::FieldDescriptor* f) { return P2R_Handlers::GetFieldPrototype(m, f); } diff --git a/upb/google/proto1.h b/upb/google/proto1.h index f35fb13..eb550ac 100644 --- a/upb/google/proto1.h +++ b/upb/google/proto1.h @@ -38,14 +38,12 @@ bool TrySetProto1WriteHandlers(const proto2::FieldDescriptor* proto2_f, // Returns a prototype for the given field in "m", if it is weak. The returned // message could be the linked-in message type or OpaqueMessage, if the weak // message is *not* linked in. Otherwise returns NULL. -const proto2::Message* GetProto1WeakPrototype( - const proto2::Message& m, - const proto2::FieldDescriptor* f); +const proto2::Message* GetProto1WeakPrototype(const proto2::Message& m, + const proto2::FieldDescriptor* f); // Returns a prototype for the given non-weak field in "m". const proto2::Message* GetProto1FieldPrototype( - const proto2::Message& m, - const proto2::FieldDescriptor* f); + const proto2::Message& m, const proto2::FieldDescriptor* f); } // namespace google } // namespace upb diff --git a/upb/google/proto2.cc b/upb/google/proto2.cc index 264530c..d7ad919 100644 --- a/upb/google/proto2.cc +++ b/upb/google/proto2.cc @@ -15,42 +15,36 @@ #include "upb/google/proto2.h" -#include "upb/google/proto1.h" -#include "upb/bytestream.h" #include "upb/def.h" +#include "upb/google/proto1.h" #include "upb/handlers.h" +#include "upb/sink.h" namespace upb { -namespace proto2_bridge_google3 { class FieldAccessor; } -namespace proto2_bridge_opensource { class FieldAccessor; } +namespace google_google3 { class GMR_Handlers; } +namespace google_opensource { class GMR_Handlers; } } // namespace upb // BEGIN DOUBLE COMPILATION TRICKERY. ////////////////////////////////////////// #ifdef UPB_GOOGLE3 -// TODO(haberman): friend upb so that this isn't required. -#define protected public -#include "net/proto2/public/repeated_field.h" -#undef protected - -#define private public -#include "net/proto2/public/generated_message_reflection.h" -#undef private - #include "net/proto2/proto/descriptor.pb.h" #include "net/proto2/public/descriptor.h" +#include "net/proto2/public/extension_set.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" -#include "upb/google/cord.h" namespace goog = ::proto2; -namespace me = ::upb::proto2_bridge_google3; +namespace me = ::upb::google_google3; #else -// TODO(haberman): friend upb so that this isn't required. +// 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 @@ -61,10 +55,16 @@ namespace me = ::upb::proto2_bridge_google3; #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/extension_set.h" #include "google/protobuf/message.h" namespace goog = ::google::protobuf; -namespace me = ::upb::proto2_bridge_opensource; +namespace me = ::upb::google_opensource; + +using goog::int32; +using goog::int64; +using goog::uint32; +using goog::uint64; #endif // ifdef UPB_GOOGLE3 @@ -74,9 +74,13 @@ namespace me = ::upb::proto2_bridge_opensource; // an enum value for STRING. #define UPB_CTYPE_STRING 0 -template static T* GetPointer(void *message, size_t offset) { +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 @@ -86,57 +90,60 @@ template static T* GetPointer(void *message, size_t offset) { // 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. -// -// TODO(haberman): change class name? In retrospect, "FieldAccessor" isn't the -// best (something more specific like GeneratedMessageReflectionHandlers or -// GMR_Handlers would be better) but we're depending on a "friend" declaration -// in proto2 that already specifies "FieldAccessor." No versions of proto2 have -// been released that include the "friend FieldAccessor" declaration, so there's -// still time to change this. On the other hand, perhaps it's simpler to just -// rely on "#define private public" since it may be a long time before new -// versions of proto2 open source are pervasive enough that we can remove this -// anyway. -class me::FieldAccessor { +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::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; - // Extensions not supported yet. - if (proto2_f->is_extension()) 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()) { -#define PRIMITIVE_TYPE(cpptype, cident) \ - case goog::FieldDescriptor::cpptype: \ - SetPrimitiveHandlers(proto2_f, r, upb_f, h); return true; - PRIMITIVE_TYPE(CPPTYPE_INT32, int32_t); - PRIMITIVE_TYPE(CPPTYPE_INT64, int64_t); - PRIMITIVE_TYPE(CPPTYPE_UINT32, uint32_t); - PRIMITIVE_TYPE(CPPTYPE_UINT64, uint64_t); + 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); -#undef PRIMITIVE_TYPE + PRIMITIVE_TYPE(CPPTYPE_FLOAT, float); + PRIMITIVE_TYPE(CPPTYPE_BOOL, bool); case goog::FieldDescriptor::CPPTYPE_ENUM: - SetEnumHandlers(proto2_f, r, upb_f, h); + 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; + proto2_f->options().ctype() + : UPB_CTYPE_STRING; switch (ctype) { #ifdef UPB_GOOGLE3 case goog::FieldOptions::STRING: - SetStringHandlers(proto2_f, m, r, upb_f, h); + SetStringHandlers(proto2_f, r, upb_f, h); return true; case goog::FieldOptions::CORD: SetCordHandlers(proto2_f, r, upb_f, h); @@ -146,7 +153,7 @@ class me::FieldAccessor { return true; #else case UPB_CTYPE_STRING: - SetStringHandlers(proto2_f, m, r, upb_f, h); + SetStringHandlers(proto2_f, r, upb_f, h); return true; #endif default: @@ -156,23 +163,25 @@ class me::FieldAccessor { case goog::FieldDescriptor::CPPTYPE_MESSAGE: #ifdef UPB_GOOGLE3 if (proto2_f->options().lazy()) { + assert(false); return false; // Not yet implemented. - } else { - SetSubMessageHandlers(proto2_f, m, r, upb_f, h); + } +#endif + if (proto2_f->is_extension()) { + SetSubMessageExtensionHandlers(proto2_f, m, r, upb_f, h); return true; } -#else SetSubMessageHandlers(proto2_f, m, r, upb_f, h); return true; -#endif default: return false; } } +#undef PRIMITIVE_TYPE + static const goog::Message* GetFieldPrototype( - const goog::Message& m, - const goog::FieldDescriptor* f) { + 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(). @@ -209,11 +218,9 @@ class me::FieldAccessor { class FieldOffset { public: - FieldOffset( - const goog::FieldDescriptor* f, - const goog::internal::GeneratedMessageReflection* r) - : offset_(GetOffset(f, r)), - is_repeated_(f->is_repeated()) { + FieldOffset(const goog::FieldDescriptor* f, + const goog::internal::GeneratedMessageReflection* r) + : offset_(GetOffset(f, r)), is_repeated_(f->is_repeated()) { if (!is_repeated_) { int64_t hasbit = GetHasbit(f, r); hasbyte_ = hasbit / 8; @@ -221,7 +228,7 @@ class me::FieldAccessor { } } - template T* GetFieldPointer(void *message) const { + template T* GetFieldPointer(void* message) const { return GetPointer(message, offset_); } @@ -240,6 +247,29 @@ class me::FieldAccessor { int8_t mask_; }; + class ExtensionFieldData { + public: + ExtensionFieldData( + const goog::FieldDescriptor* proto2_f, + const goog::internal::GeneratedMessageReflection* r) + : offset_(r->extensions_offset_), + number_(proto2_f->number()), + type_(proto2_f->type()) { + } + + int number() const { return number_; } + goog::internal::FieldType type() const { return type_; } + + goog::internal::ExtensionSet* GetExtensionSet(goog::Message* m) const { + return GetPointer(m, offset_); + } + + private: + const size_t offset_; + int number_; + goog::internal::FieldType type_; + }; + // StartSequence ///////////////////////////////////////////////////////////// static void SetStartSequenceHandler( @@ -247,14 +277,14 @@ class me::FieldAccessor { const goog::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { assert(f->IsSequence()); - h->SetStartSequenceHandler( - f, &PushOffset, new FieldOffset(proto2_f, r), - &upb::DeletePointer); + h->SetStartSequenceHandler(f, &PushOffset, new FieldOffset(proto2_f, r), + &upb::DeletePointer); } - static void* PushOffset(void *m, void *fval) { - const FieldOffset* offset = static_cast(fval); - return offset->GetFieldPointer(m); + static void* PushOffset(const upb::SinkFrame* frame) { + const FieldOffset* offset = + static_cast(frame->handler_data()); + return offset->GetFieldPointer(frame->userdata()); } // Primitive Value (numeric, bool) /////////////////////////////////////////// @@ -262,38 +292,68 @@ class me::FieldAccessor { template static void SetPrimitiveHandlers( const goog::FieldDescriptor* proto2_f, const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, - upb::Handlers* h) { - if (f->IsSequence()) { - SetStartSequenceHandler(proto2_f, r, f, h); - h->SetValueHandler(f, &AppendPrimitive, NULL, NULL); + const upb::FieldDef* f, upb::Handlers* h) { + if (proto2_f->is_extension()) { + ExtensionFieldData* data = new ExtensionFieldData(proto2_f, r); + upb::Handlers::Free* free = &upb::DeletePointer; + if (f->IsSequence()) { + h->SetValueHandler(f, &AppendPrimitiveExtension, data, free); + } else { + h->SetValueHandler(f, &SetPrimitiveExtension, data, free); + } } else { - upb::SetStoreValueHandler( - f, GetOffset(proto2_f, r), GetHasbit(proto2_f, r), h); + if (f->IsSequence()) { + SetStartSequenceHandler(proto2_f, r, f, h); + h->SetValueHandler(f, &AppendPrimitive, NULL, NULL); + } else { + upb::SetStoreValueHandler(f, GetOffset(proto2_f, r), + GetHasbit(proto2_f, r), h); + } } } template - static bool AppendPrimitive(void *_r, void *fval, T val) { - UPB_UNUSED(fval); - goog::RepeatedField* r = static_cast*>(_r); + static bool AppendPrimitive(const upb::SinkFrame* frame, T val) { + goog::RepeatedField* r = + static_cast*>(frame->userdata()); r->Add(val); return true; } + template + static bool AppendPrimitiveExtension(const upb::SinkFrame* frame, T val) { + goog::Message* m = frame->GetUserdata(); + ExtensionFieldData* data = + static_cast(frame->handler_data()); + 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); + return true; + } + + template + static bool SetPrimitiveExtension(const upb::SinkFrame* frame, T val) { + goog::Message* m = frame->GetUserdata(); + ExtensionFieldData* data = + static_cast(frame->handler_data()); + goog::internal::ExtensionSet* set = data->GetExtensionSet(m); + goog::internal::PrimitiveTypeTraits::Set(data->number(), data->type(), + val, set); + return true; + } + // Enum ////////////////////////////////////////////////////////////////////// class EnumHandlerData : public FieldOffset { public: - EnumHandlerData( - const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f) + EnumHandlerData(const goog::FieldDescriptor* proto2_f, + const goog::internal::GeneratedMessageReflection* r, + const upb::FieldDef* f) : FieldOffset(proto2_f, r), field_number_(f->number()), unknown_fields_offset_(r->unknown_fields_offset_), - enum_(upb_downcast_enumdef(f->subdef())) { - } + enum_(upb_downcast_enumdef(f->subdef())) {} bool IsValidValue(int32_t val) const { return enum_->FindValueByNumber(val) != NULL; @@ -314,21 +374,22 @@ class me::FieldAccessor { static void SetEnumHandlers( const goog::FieldDescriptor* proto2_f, const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, - upb::Handlers* h) { + const upb::FieldDef* f, upb::Handlers* h) { + assert(!proto2_f->is_extension()); EnumHandlerData* data = new EnumHandlerData(proto2_f, r, f); if (f->IsSequence()) { - h->SetInt32Handler( - f, &AppendEnum, data, &upb::DeletePointer); + h->SetInt32Handler(f, &AppendEnum, data, + &upb::DeletePointer); } else { - h->SetInt32Handler( - f, &SetEnum, data, &upb::DeletePointer); + h->SetInt32Handler(f, &SetEnum, data, + &upb::DeletePointer); } } - static bool SetEnum(void *_m, void *fval, int32_t val) { - goog::Message* m = static_cast(_m); - const EnumHandlerData* data = static_cast(fval); + static bool SetEnum(const upb::SinkFrame* frame, int32_t val) { + goog::Message* m = static_cast(frame->userdata()); + const EnumHandlerData* data = + static_cast(frame->handler_data()); if (data->IsValidValue(val)) { int32_t* message_val = data->GetFieldPointer(m); *message_val = val; @@ -339,15 +400,16 @@ class me::FieldAccessor { return true; } - static bool AppendEnum(void *_m, void *fval, int32_t val) { + static bool AppendEnum(const upb::SinkFrame* frame, 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. - goog::Message* m = static_cast(_m); - const EnumHandlerData* data = static_cast(fval); + goog::Message* m = static_cast(frame->userdata()); + const EnumHandlerData* data = + static_cast(frame->handler_data()); if (data->IsValidValue(val)) { goog::RepeatedField* r = - data->GetFieldPointer >(m); + data->GetFieldPointer>(m); r->Add(val); } else { data->mutable_unknown_fields(m)->AddVarint(data->field_number(), val); @@ -355,26 +417,56 @@ class me::FieldAccessor { return true; } + // EnumExtension ///////////////////////////////////////////////////////////// + + static void SetEnumExtensionHandlers( + const goog::FieldDescriptor* proto2_f, + const goog::internal::GeneratedMessageReflection* r, + const upb::FieldDef* f, upb::Handlers* h) { + assert(proto2_f->is_extension()); + ExtensionFieldData* data = new ExtensionFieldData(proto2_f, r); + if (f->IsSequence()) { + h->SetInt32Handler(f, &AppendEnumExtension, data, + upb::DeletePointer); + } else { + h->SetInt32Handler(f, &SetEnumExtension, data, + upb::DeletePointer); + } + } + + static bool SetEnumExtension(const upb::SinkFrame* frame, int32_t val) { + goog::Message* m = frame->GetUserdata(); + const ExtensionFieldData* data = + static_cast(frame->handler_data()); + goog::internal::ExtensionSet* set = data->GetExtensionSet(m); + set->SetEnum(data->number(), data->type(), val, NULL); + return true; + } + + static bool AppendEnumExtension(const upb::SinkFrame* frame, int32_t val) { + goog::Message* m = frame->GetUserdata(); + const ExtensionFieldData* data = + static_cast(frame->handler_data()); + goog::internal::ExtensionSet* set = data->GetExtensionSet(m); + // TODO(haberman): give an accurate value for "packed" + set->AddEnum(data->number(), data->type(), true, val, NULL); + return true; + } + // String //////////////////////////////////////////////////////////////////// // For scalar (non-repeated) string fields. - template - class StringHandlerData : public FieldOffset { + template class StringHandlerData : public FieldOffset { public: StringHandlerData(const goog::FieldDescriptor* proto2_f, - const goog::internal::GeneratedMessageReflection* r, - const goog::Message& prototype) - : FieldOffset(proto2_f, r) { - // "prototype" isn't guaranteed to be empty, so we create a copy to get - // the default string instance. - goog::Message* empty = prototype.New(); - prototype_ = &r->GetStringReference(*empty, proto2_f, NULL); - delete empty; - } + 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(void *message) const { + T** GetStringPointer(void* message) const { return GetFieldPointer(message); } @@ -384,27 +476,28 @@ class me::FieldAccessor { template static void SetStringHandlers( const goog::FieldDescriptor* proto2_f, - const goog::Message& m, const goog::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { + assert(!proto2_f->is_extension()); h->SetStringHandler(f, &OnStringBuf, NULL, NULL); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); h->SetStartStringHandler(f, &StartRepeatedString, NULL, NULL); } else { - StringHandlerData* data = new StringHandlerData(proto2_f, r, m); - h->SetStartStringHandler( - f, &StartString, data, &upb::DeletePointer >); + StringHandlerData* data = new StringHandlerData(proto2_f, r); + h->SetStartStringHandler(f, &StartString, data, + &upb::DeletePointer>); } } // This needs to be templated because google3 string is not std::string. - template static void* StartString( - void *m, void *fval, size_t size_hint) { + template + static void* StartString(const upb::SinkFrame* frame, size_t size_hint) { UPB_UNUSED(size_hint); + goog::Message* m = static_cast(frame->userdata()); const StringHandlerData* data = - static_cast*>(fval); + static_cast*>(frame->handler_data()); T** str = data->GetStringPointer(m); data->SetHasbit(m); // If it points to the default instance, we must create a new instance. @@ -414,37 +507,75 @@ class me::FieldAccessor { return *str; } - template static size_t OnStringBuf( - void *_str, void *fval, const char *buf, size_t n) { - UPB_UNUSED(fval); - T* str = static_cast(_str); + template + static size_t OnStringBuf(const upb::SinkFrame* frame, + const char* buf, size_t n) { + T* str = static_cast(frame->userdata()); str->append(buf, n); return n; } - template - static void* StartRepeatedString(void *_r, void *fval, size_t size_hint) { + static void* StartRepeatedString(const upb::SinkFrame* frame, + size_t size_hint) { UPB_UNUSED(size_hint); - UPB_UNUSED(fval); - goog::RepeatedPtrField* r = static_cast*>(_r); + goog::RepeatedPtrField* r = + static_cast*>(frame->userdata()); T* str = r->Add(); str->clear(); // reserve() here appears to hurt performance rather than help. return str; } + // StringExtension /////////////////////////////////////////////////////////// + + template + static void SetStringExtensionHandlers( + const goog::FieldDescriptor* proto2_f, + const goog::internal::GeneratedMessageReflection* r, + const upb::FieldDef* f, upb::Handlers* h) { + assert(proto2_f->is_extension()); + h->SetStringHandler(f, &OnStringBuf, NULL, NULL); + ExtensionFieldData* data = new ExtensionFieldData(proto2_f, r); + if (f->IsSequence()) { + h->SetStartStringHandler(f, &StartRepeatedStringExtension, data, + upb::DeletePointer); + } else { + h->SetStartStringHandler(f, &StartStringExtension, data, + upb::DeletePointer); + } + } + + // google3 string is not std::string, but we avoid needing to template + // because we do not actually have to declare the string type. + static void* StartStringExtension(const upb::SinkFrame* frame, + size_t size_hint) { + UPB_UNUSED(size_hint); + goog::Message* m = frame->GetUserdata(); + const ExtensionFieldData* data = + static_cast(frame->handler_data()); + goog::internal::ExtensionSet* set = data->GetExtensionSet(m); + return set->MutableString(data->number(), data->type(), NULL); + } + + static void* StartRepeatedStringExtension(const upb::SinkFrame* frame, + size_t size_hint) { + UPB_UNUSED(size_hint); + goog::Message* m = frame->GetUserdata(); + const ExtensionFieldData* data = + static_cast(frame->handler_data()); + 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) { - } + 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_; } @@ -453,13 +584,12 @@ class me::FieldAccessor { }; static void SetSubMessageHandlers( - const goog::FieldDescriptor* proto2_f, - const goog::Message& m, + const goog::FieldDescriptor* proto2_f, const goog::Message& m, const goog::internal::GeneratedMessageReflection* r, - const upb::FieldDef* f, - upb::Handlers* h) { + const upb::FieldDef* f, upb::Handlers* h) { + const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f); SubMessageHandlerData* data = - new SubMessageHandlerData(proto2_f, r, GetFieldPrototype(m, proto2_f)); + new SubMessageHandlerData(proto2_f, r, field_prototype); upb::Handlers::Free* free = &upb::DeletePointer; if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); @@ -469,11 +599,13 @@ class me::FieldAccessor { } } - static void* StartSubMessage(void *m, void *fval) { + static void* StartSubMessage(const upb::SinkFrame* frame) { + void* m = frame->userdata(); const SubMessageHandlerData* data = - static_cast(fval); + static_cast(frame->handler_data()); data->SetHasbit(m); - goog::Message **subm = data->GetFieldPointer(m); + goog::Message** subm = + data->GetFieldPointer(frame->userdata()); if (*subm == NULL || *subm == data->prototype()) { *subm = data->prototype()->New(); } @@ -486,19 +618,19 @@ class me::FieldAccessor { // AddAllocated() calls this, but only if other objects are sitting // around waiting for reuse, which we will not do. static void Delete(Type* t) { - (void)t; + UPB_UNUSED(t); assert(false); } }; // Closure is a RepeatedPtrField*, but we access it through // its base class RepeatedPtrFieldBase*. - static void* StartRepeatedSubMessage(void* _r, void *fval) { + static void* StartRepeatedSubMessage(const upb::SinkFrame* frame) { const SubMessageHandlerData* data = - static_cast(fval); - goog::internal::RepeatedPtrFieldBase *r = - static_cast(_r); - void *submsg = r->AddFromCleared(); + static_cast(frame->handler_data()); + goog::internal::RepeatedPtrFieldBase* r = + static_cast(frame->userdata()); + void* submsg = r->AddFromCleared(); if (!submsg) { submsg = data->prototype()->New(); r->AddAllocated(submsg); @@ -506,7 +638,63 @@ class me::FieldAccessor { return submsg; } - // TODO(haberman): handle Extensions, Unknown Fields. + // 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); + SubMessageExtensionHandlerData* data = + new SubMessageExtensionHandlerData(proto2_f, r, field_prototype); + upb::Handlers::Free* free = &upb::DeletePointer; + if (f->IsSequence()) { + h->SetStartSubMessageHandler(f, &StartRepeatedSubMessageExtension, data, + free); + } else { + h->SetStartSubMessageHandler(f, &StartSubMessageExtension, data, free); + } + } + + static void* StartRepeatedSubMessageExtension(const upb::SinkFrame* frame) { + goog::Message* m = frame->GetUserdata(); + const SubMessageExtensionHandlerData* data = + static_cast( + frame->handler_data()); + goog::internal::ExtensionSet* set = data->GetExtensionSet(m); + return set->AddMessage(data->number(), data->type(), *data->prototype(), + NULL); + } + + static void* StartSubMessageExtension(const upb::SinkFrame* frame) { + goog::Message* m = frame->GetUserdata(); + const SubMessageExtensionHandlerData* data = + static_cast( + frame->handler_data()); + goog::internal::ExtensionSet* set = data->GetExtensionSet(m); + return 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: @@ -519,38 +707,40 @@ class me::FieldAccessor { const proto2::FieldDescriptor* proto2_f, const proto2::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { + assert(!proto2_f->is_extension()); h->SetStringHandler(f, &OnCordBuf, NULL, NULL); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); h->SetStartStringHandler(f, &StartRepeatedCord, NULL, NULL); } else { - h->SetStartStringHandler( - f, &StartCord, new FieldOffset(proto2_f, r), - &upb::DeletePointer); + h->SetStartStringHandler(f, &StartCord, new FieldOffset(proto2_f, r), + &upb::DeletePointer); } } - static void* StartCord(void *m, void *fval, size_t size_hint) { + static void* StartCord(const upb::SinkFrame* frame, size_t size_hint) { UPB_UNUSED(size_hint); - const FieldOffset* offset = static_cast(fval); + void* m = frame->userdata(); + const FieldOffset* offset = + static_cast(frame->handler_data()); offset->SetHasbit(m); Cord* field = offset->GetFieldPointer(m); field->Clear(); return field; } - static size_t OnCordBuf(void *_c, void *fval, const char *buf, size_t n) { - UPB_UNUSED(fval); - Cord* c = static_cast(_c); + static size_t OnCordBuf(const upb::SinkFrame* frame, + const char* buf, size_t n) { + Cord* c = static_cast(frame->userdata()); c->Append(StringPiece(buf, n)); return n; } - static void* StartRepeatedCord(void *_r, void *fval, size_t size_hint) { + static void* StartRepeatedCord(const upb::SinkFrame* frame, + size_t size_hint) { UPB_UNUSED(size_hint); - UPB_UNUSED(fval); proto2::RepeatedField* r = - static_cast*>(_r); + static_cast*>(frame->userdata()); return r->Add(); } @@ -560,27 +750,27 @@ class me::FieldAccessor { const proto2::FieldDescriptor* proto2_f, const proto2::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { + assert(!proto2_f->is_extension()); h->SetStringHandler(f, &OnStringPieceBuf, NULL, NULL); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); h->SetStartStringHandler(f, &StartRepeatedStringPiece, NULL, NULL); } else { - h->SetStartStringHandler( - f, &StartStringPiece, new FieldOffset(proto2_f, r), - &upb::DeletePointer); + h->SetStartStringHandler(f, &StartStringPiece, + new FieldOffset(proto2_f, r), + &upb::DeletePointer); } } - static size_t OnStringPieceBuf(void *_f, void *fval, - const char *buf, size_t len) { - UPB_UNUSED(fval); + static size_t OnStringPieceBuf(const upb::SinkFrame* frame, + 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. proto2::internal::StringPieceField* field = - static_cast(_f); + static_cast(frame->userdata()); size_t new_len = field->size() + len; - char *data = new char[new_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)); @@ -588,9 +778,12 @@ class me::FieldAccessor { return len; } - static void* StartStringPiece(void *m, void *fval, size_t size_hint) { + static void* StartStringPiece(const upb::SinkFrame* frame, + size_t size_hint) { UPB_UNUSED(size_hint); - const FieldOffset* offset = static_cast(fval); + void* m = frame->userdata(); + const FieldOffset* offset = + static_cast(frame->handler_data()); offset->SetHasbit(m); proto2::internal::StringPieceField* field = offset->GetFieldPointer(m); @@ -598,13 +791,13 @@ class me::FieldAccessor { return field; } - static void* StartRepeatedStringPiece(void* _r, void *fval, + static void* StartRepeatedStringPiece(const upb::SinkFrame* frame, size_t size_hint) { UPB_UNUSED(size_hint); - UPB_UNUSED(fval); - typedef proto2::RepeatedPtrField - RepeatedStringPiece; - RepeatedStringPiece* r = static_cast(_r); + typedef proto2::RepeatedPtrField< + proto2::internal::StringPieceField> RepeatedStringPiece; + RepeatedStringPiece* r = + static_cast(frame->userdata()); proto2::internal::StringPieceField* field = r->Add(); field->Clear(); return field; @@ -619,13 +812,12 @@ namespace google { bool TrySetWriteHandlers(const goog::FieldDescriptor* proto2_f, const goog::Message& prototype, const upb::FieldDef* upb_f, upb::Handlers* h) { - return me::FieldAccessor::TrySet(proto2_f, prototype, upb_f, h); + return me::GMR_Handlers::TrySet(proto2_f, prototype, upb_f, h); } -const goog::Message* GetFieldPrototype( - const goog::Message& m, - const goog::FieldDescriptor* f) { - return me::FieldAccessor::GetFieldPrototype(m, f); +const goog::Message* GetFieldPrototype(const goog::Message& m, + const goog::FieldDescriptor* f) { + return me::GMR_Handlers::GetFieldPrototype(m, f); } } // namespace google diff --git a/upb/google/proto2.h b/upb/google/proto2.h index f2662ea..516b7fd 100644 --- a/upb/google/proto2.h +++ b/upb/google/proto2.h @@ -49,9 +49,8 @@ bool TrySetWriteHandlers(const ::google::protobuf::FieldDescriptor* proto2_f, // Returns a prototype for the given field in "m", if it is weak. The returned // message could be the linked-in message type or OpaqueMessage, if the weak // message is *not* linked in. Otherwise returns NULL. -const proto2::Message* GetFieldPrototype( - const proto2::Message& m, - const proto2::FieldDescriptor* f); +const proto2::Message* GetFieldPrototype(const proto2::Message& m, + const proto2::FieldDescriptor* f); const ::google::protobuf::Message* GetFieldPrototype( const ::google::protobuf::Message& m, const ::google::protobuf::FieldDescriptor* f); -- cgit v1.2.3