From ce9bba3cb5409844f8f3d7dcc235a9ea30cad090 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Fri, 20 Dec 2013 17:40:40 -0800 Subject: Sync from Google-internal development. --- upb/google/bridge.cc | 381 +++++++++++++++++++++++++-------------------------- upb/google/bridge.h | 191 +++++++++++++++++++++----- upb/google/proto1.cc | 12 +- upb/google/proto2.cc | 23 +--- 4 files changed, 360 insertions(+), 247 deletions(-) (limited to 'upb/google') diff --git a/upb/google/bridge.cc b/upb/google/bridge.cc index caf4935..bb5c631 100644 --- a/upb/google/bridge.cc +++ b/upb/google/bridge.cc @@ -4,10 +4,11 @@ // Copyright (c) 2011-2012 Google Inc. See LICENSE for details. // Author: Josh Haberman // -// 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. +// IMPORTANT NOTE! Inside Google, 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/google/bridge.h" @@ -21,204 +22,84 @@ #define ASSERT_STATUS(status) do { \ if (!upb_ok(status)) { \ - fprintf(stderr, "upb status failure: %s\n", upb_status_getstr(status)); \ + fprintf(stderr, "upb status failure: %s\n", upb_status_errmsg(status)); \ assert(upb_ok(status)); \ } \ } while (0) - -namespace upb { -namespace proto2_bridge_google3 { class Defs; } -namespace proto2_bridge_opensource { class Defs; } -} // namespace upb - #ifdef UPB_GOOGLE3 #include "net/proto2/public/descriptor.h" #include "net/proto2/public/message.h" #include "net/proto2/proto/descriptor.pb.h" namespace goog = ::proto2; -namespace me = ::upb::proto2_bridge_google3; #else #include "google/protobuf/descriptor.h" #include "google/protobuf/message.h" #include "google/protobuf/descriptor.pb.h" namespace goog = ::google::protobuf; -namespace me = ::upb::proto2_bridge_opensource; #endif -class me::Defs { - public: - void OnMessage(Handlers* h) { - const upb::MessageDef* md = h->message_def(); - const goog::Message& m = *message_map_[md]; - const goog::Descriptor* d = m.GetDescriptor(); - for (upb::MessageDef::const_iterator i = md->begin(); i != md->end(); ++i) { - const upb::FieldDef* upb_f = *i; - 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) +namespace { + +const goog::Message* GetPrototype(const goog::Message& m, + const goog::FieldDescriptor* f) { + const goog::Message* ret = NULL; #ifdef UPB_GOOGLE3 - && !upb::google::TrySetProto1WriteHandlers(proto2_f, m, upb_f, h) + ret = upb::google::GetProto1WeakPrototype(m, f); + if (ret) return ret; #endif - ) { - // Unsupported reflection class. - // - // Should we fall back to using the public Reflection interface in this - // case? It's unclear whether it's supported behavior for users to - // create their own Reflection classes. - assert(false); - } - } - } - - static void StaticOnMessage(void* closure, upb::Handlers* handlers) { - me::Defs* defs = static_cast(closure); - defs->OnMessage(handlers); - } - - void AddSymbol(const std::string& name, upb::Def* def) { - assert(symbol_map_.find(name) == symbol_map_.end()); - symbol_map_[name] = def; - } - void AddMessage(const goog::Message* m, upb::MessageDef* md) { - assert(message_map_.find(md) == message_map_.end()); - message_map_[md] = m; - AddSymbol(m->GetDescriptor()->full_name(), md->Upcast()); - } - - upb::Def* FindSymbol(const std::string& name) { - SymbolMap::iterator iter = symbol_map_.find(name); - return iter != symbol_map_.end() ? iter->second : NULL; - } - - void Flatten(std::vector* defs) { - SymbolMap::iterator iter; - for (iter = symbol_map_.begin(); iter != symbol_map_.end(); ++iter) { - defs->push_back(iter->second); - } + if (f->cpp_type() == goog::FieldDescriptor::CPPTYPE_MESSAGE) { + ret = upb::google::GetFieldPrototype(m, f); +#ifdef UPB_GOOGLE3 + if (!ret) ret = upb::google::GetProto1FieldPrototype(m, f); +#endif + assert(ret); } + return ret; +} - private: - // Maps a new upb::MessageDef* to a corresponding proto2 Message* whose - // derived class is of the correct type according to the message the user - // gave us. - typedef std::map MessageMap; - MessageMap message_map_; - - // Maps a type name to a upb Def we have constructed to represent it. - typedef std::map SymbolMap; - SymbolMap symbol_map_; -}; +} // namespace namespace upb { namespace google { -// For submessage fields, stores a pointer to an instance of the submessage in -// *subm (but it is *not* guaranteed to be a prototype). -FieldDef* AddFieldDef(const goog::Message& m, const goog::FieldDescriptor* f, - upb::MessageDef* md, const goog::Message** subm) { - // To parse weak submessages effectively, we need to represent them in the - // upb::Def schema even though they are not reflected in the proto2 - // descriptors (weak fields are represented as FieldDescriptor::TYPE_BYTES). - const goog::Message* weak_prototype = NULL; -#ifdef UPB_GOOGLE3 - weak_prototype = upb::google::GetProto1WeakPrototype(m, f); -#endif - - upb::FieldDef* upb_f = upb::FieldDef::New(&upb_f); - upb::Status status; - upb_f->set_number(f->number(), &status); - upb_f->set_name(f->name(), &status); - upb_f->set_label(upb::FieldDef::ConvertLabel(f->label())); - upb_f->set_descriptor_type( - weak_prototype ? UPB_DESCRIPTOR_TYPE_MESSAGE - : upb::FieldDef::ConvertDescriptorType(f->type())); - - if (weak_prototype) { - upb_f->set_subdef_name( - weak_prototype->GetDescriptor()->full_name(), &status); - } else { - switch (upb_f->type()) { - case UPB_TYPE_INT32: - upb_f->set_default_int32(f->default_value_int32()); - break; - case UPB_TYPE_INT64: - upb_f->set_default_int64(f->default_value_int64()); - break; - case UPB_TYPE_UINT32: - upb_f->set_default_uint32(f->default_value_uint32()); - break; - case UPB_TYPE_UINT64: - upb_f->set_default_uint64(f->default_value_uint64()); - break; - case UPB_TYPE_DOUBLE: - upb_f->set_default_double(f->default_value_double()); - break; - case UPB_TYPE_FLOAT: - upb_f->set_default_float(f->default_value_float()); - break; - case UPB_TYPE_BOOL: - upb_f->set_default_bool(f->default_value_bool()); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - upb_f->set_default_string(f->default_value_string(), &status); - break; - case UPB_TYPE_MESSAGE: - upb_f->set_subdef_name(f->message_type()->full_name(), &status); - break; - case UPB_TYPE_ENUM: - // We set the enum default numerically. - upb_f->set_default_int32(f->default_value_enum()->number()); - upb_f->set_subdef_name(f->enum_type()->full_name(), &status); - break; - } - } - md->AddField(upb_f, &upb_f, &status); - ASSERT_STATUS(&status); +/* DefBuilder ****************************************************************/ - if (weak_prototype) { - *subm = weak_prototype; - } 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); -#endif - assert(*subm); - } +const EnumDef* DefBuilder::GetOrCreateEnumDef(const goog::EnumDescriptor* ed) { + const EnumDef* cached = FindInCache(ed); + if (cached) return cached; - return upb_f; -} + EnumDef* e = AddToCache(ed, EnumDef::New()); -upb::EnumDef* NewEnumDef(const goog::EnumDescriptor* desc, const void* owner) { - upb::EnumDef* e = upb::EnumDef::New(owner); - upb::Status status; - e->set_full_name(desc->full_name(), &status); - for (int i = 0; i < desc->value_count(); i++) { - const goog::EnumValueDescriptor* val = desc->value(i); + Status status; + e->set_full_name(ed->full_name(), &status); + for (int i = 0; i < ed->value_count(); i++) { + const goog::EnumValueDescriptor* val = ed->value(i); bool success = e->AddValue(val->name(), val->number(), &status); UPB_ASSERT_VAR(success, success); } + + e->Freeze(&status); + ASSERT_STATUS(&status); return e; } -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(); - upb::Status status; - md->set_full_name(m.GetDescriptor()->full_name(), &status); +const MessageDef* DefBuilder::GetOrCreateMaybeUnfrozenMessageDef( + const goog::Descriptor* d, const goog::Message* m) { + const MessageDef* cached = FindInCache(d); + if (cached) return cached; - // Must do this before processing submessages to prevent infinite recursion. - defs->AddMessage(&m, md); + MessageDef* md = AddToCache(d, MessageDef::New()); + to_freeze_.push_back(upb::upcast(md)); + Status status; + md->set_full_name(d->full_name(), &status); + ASSERT_STATUS(&status); + + // Find all regular fields and extensions for this message. std::vector fields; d->file()->pool()->FindAllExtensions(d, &fields); for (int i = 0; i < d->field_count(); i++) { @@ -232,49 +113,161 @@ static upb::MessageDef* NewMessageDef(const goog::Message& m, const void* owner, // Skip lazy fields for now since we can't properly handle them. if (proto2_f->options().lazy()) continue; #endif - const goog::Message* subm_prototype; - upb::FieldDef* f = AddFieldDef(m, proto2_f, md, &subm_prototype); - - if (!f->HasSubDef()) continue; - - upb::Def* subdef = defs->FindSymbol(f->subdef_name()); - if (!subdef) { - if (f->type() == UPB_TYPE_ENUM) { - subdef = NewEnumDef(proto2_f->enum_type(), owner)->Upcast(); - defs->AddSymbol(subdef->full_name(), subdef); - } else { - assert(f->IsSubMessage()); - assert(subm_prototype); - subdef = NewMessageDef(*subm_prototype, owner, defs)->Upcast(); - } - } - f->set_subdef(subdef, &status); + md->AddField(NewFieldDef(proto2_f, m), &status); } ASSERT_STATUS(&status); return md; } -const upb::Handlers* NewWriteHandlers(const goog::Message& m, - const void* owner) { - me::Defs defs; - const upb::MessageDef* md = NewMessageDef(m, owner, &defs); +reffed_ptr DefBuilder::NewFieldDef(const goog::FieldDescriptor* f, + const goog::Message* m) { + const goog::Message* subm = NULL; + const goog::Message* weak_prototype = NULL; - std::vector defs_vec; - defs.Flatten(&defs_vec); + if (m) { +#ifdef UPB_GOOGLE3 + weak_prototype = upb::google::GetProto1WeakPrototype(*m, f); +#endif + subm = GetPrototype(*m, f); + } + + reffed_ptr upb_f(FieldDef::New()); Status status; - bool success = Def::Freeze(defs_vec, &status); - UPB_ASSERT_VAR(success, success); + upb_f->set_number(f->number(), &status); + upb_f->set_name(f->name(), &status); + upb_f->set_label(FieldDef::ConvertLabel(f->label())); + + // For weak fields, weak_prototype will be non-NULL even though the proto2 + // descriptor does not indicate a submessage field. + upb_f->set_descriptor_type(weak_prototype + ? UPB_DESCRIPTOR_TYPE_MESSAGE + : FieldDef::ConvertDescriptorType(f->type())); + + switch (upb_f->type()) { + case UPB_TYPE_INT32: + upb_f->set_default_int32(f->default_value_int32()); + break; + case UPB_TYPE_INT64: + upb_f->set_default_int64(f->default_value_int64()); + break; + case UPB_TYPE_UINT32: + upb_f->set_default_uint32(f->default_value_uint32()); + break; + case UPB_TYPE_UINT64: + upb_f->set_default_uint64(f->default_value_uint64()); + break; + case UPB_TYPE_DOUBLE: + upb_f->set_default_double(f->default_value_double()); + break; + case UPB_TYPE_FLOAT: + upb_f->set_default_float(f->default_value_float()); + break; + case UPB_TYPE_BOOL: + upb_f->set_default_bool(f->default_value_bool()); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + upb_f->set_default_string(f->default_value_string(), &status); + break; + case UPB_TYPE_MESSAGE: + upb_f->set_message_subdef( + GetOrCreateMaybeUnfrozenMessageDef(subm->GetDescriptor(), subm), + &status); + break; + case UPB_TYPE_ENUM: + // We set the enum default numerically. + upb_f->set_default_int32(f->default_value_enum()->number()); + upb_f->set_enum_subdef(GetOrCreateEnumDef(f->enum_type()), &status); + break; + } + + ASSERT_STATUS(&status); + return upb_f; +} - const upb::Handlers* ret = upb::Handlers::NewFrozen( - md, NULL, owner, me::Defs::StaticOnMessage, &defs); +void DefBuilder::Freeze() { + upb::Status status; + upb::Def::Freeze(to_freeze_, &status); + ASSERT_STATUS(&status); + to_freeze_.clear(); +} - // Unref all defs, since they're now ref'd by the handlers. - for (int i = 0; i < static_cast(defs_vec.size()); i++) { - defs_vec[i]->Unref(owner); +const MessageDef* DefBuilder::GetOrCreateMessageDef(const goog::Descriptor* d) { + const MessageDef* ret = GetOrCreateMaybeUnfrozenMessageDef(d, NULL); + Freeze(); + return ret; +} + +const MessageDef* DefBuilder::GetOrCreateMessageDefExpandWeak( + const goog::Message& m) { + const MessageDef* ret = + GetOrCreateMaybeUnfrozenMessageDef(m.GetDescriptor(), &m); + Freeze(); + return ret; +} + + +/* CodeCache *****************************************************************/ + +const Handlers* CodeCache::GetOrCreateMaybeUnfrozenWriteHandlers( + const MessageDef* md, const goog::Message& m) { + const Handlers* cached = FindInCache(md); + if (cached) return cached; + + Handlers* h = AddToCache(md, upb::Handlers::New(md)); + to_freeze_.push_back(h); + const goog::Descriptor* d = m.GetDescriptor(); + + for (upb::MessageDef::const_iterator i = md->begin(); i != md->end(); ++i) { + const FieldDef* upb_f = *i; + + 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 + // case? It's unclear whether it's supported behavior for users to + // create their own Reflection classes. + assert(false); + } + + if (upb_f->type() == UPB_TYPE_MESSAGE) { + const goog::Message* prototype = GetPrototype(m, proto2_f); + assert(prototype); + const upb::Handlers* sub_handlers = GetOrCreateMaybeUnfrozenWriteHandlers( + upb_f->message_subdef(), *prototype); + h->SetSubHandlers(upb_f, sub_handlers); + } } + return h; +} + +const Handlers* CodeCache::GetOrCreateWriteHandlers(const goog::Message& m) { + const MessageDef* md = def_builder_.GetOrCreateMessageDefExpandWeak(m); + const Handlers* ret = GetOrCreateMaybeUnfrozenWriteHandlers(md, m); + upb::Status status; + upb::Handlers::Freeze(to_freeze_, &status); + ASSERT_STATUS(&status); + to_freeze_.clear(); return ret; } +upb::reffed_ptr NewWriteHandlers(const goog::Message& m) { + CodeCache cache; + return upb::reffed_ptr( + cache.GetOrCreateWriteHandlers(m)); +} + } // namespace google } // namespace upb diff --git a/upb/google/bridge.h b/upb/google/bridge.h index 5091e23..c8bdd47 100644 --- a/upb/google/bridge.h +++ b/upb/google/bridge.h @@ -11,33 +11,22 @@ // read/write only a subset of the fields for higher performance when only some // fields are needed. // -// Example usage (FIX XXX): -// -// // Build a def that will have all fields and parse just like proto2 would. -// const upb::MessageDef* md = upb::proto2_bridge::NewMessageDef(&MyProto()); +// Example usage: // // // JIT the parser; should only be done once ahead-of-time. -// upb::Handlers* handlers = upb::NewHandlersForMessage(md); -// upb::DecoderPlan* plan = upb::DecoderPlan::New(handlers); -// handlers->Unref(); +// upb::reffed_ptr write_myproto( +// upb::google::NewWriteHandlers(MyProto())); +// upb::reffed_ptr parse_myproto( +// upb::Decoder::NewDecoderHandlers(write_myproto.get(), true)); // // // The actual parsing. // MyProto proto; -// upb::Decoder decoder; -// upb::StringSource source(buf, len); -// decoder.ResetPlan(plan, 0); -// decoder.ResetInput(source.AllBytes(), &proto); -// CHECK(decoder.Decode() == UPB_OK) << decoder.status(); -// -// To parse only one field and skip all others: -// -// const upb::MessageDef* md = -// upb::proto2_bridge::NewEmptyMessageDef(MyProto().GetPrototype()); -// upb::proto2_bridge::AddFieldDef( -// MyProto::descriptor()->FindFieldByName("my_field"), md); -// upb::Freeze(md); -// -// // Now continue with "JIT the parser" from above. +// upb::SeededPipeline<8192> pipeline(upb_realloc, NULL); +// upb::Sink* write_sink = pipeline.NewSink(write_myproto.get()); +// upb::Sink* parse_sink = pipeline.NewSink(parse_myproto.get()); +// upb::pb::Decoder* decoder = decoder_sink->GetObject(); +// upb::pb::ResetDecoderSink(decoder, write_sink); +// write_sink->Reset(&proto); // // Note that there is currently no support for // CodedInputStream::SetExtensionRegistry(), which allows specifying a separate @@ -49,27 +38,167 @@ #ifndef UPB_GOOGLE_BRIDGE_H_ #define UPB_GOOGLE_BRIDGE_H_ +#include +#include +#include "upb/upb.h" + namespace google { -namespace protobuf { class Message; } +namespace protobuf { +class FieldDescriptor; +class Descriptor; +class EnumDescriptor; +class Message; +} // namespace protobuf } // namespace google -namespace proto2 { class Message; } +namespace proto2 { +class FieldDescriptor; +class Descriptor; +class EnumDescriptor; +class Message; +} namespace upb { +class Def; +class EnumDef; +class FieldDef; +class MessageDef; class Handlers; namespace google { // Returns a upb::Handlers object that can be used to populate a proto2::Message -// object of the same type as "m." +// object of the same type as "m." For more control over handler caching and +// reuse, instantiate a CodeCache object below. +upb::reffed_ptr NewWriteHandlers(const proto2::Message& m); +upb::reffed_ptr NewWriteHandlers( + const ::google::protobuf::Message& m); + +// Builds upb::Defs from proto2::Descriptors, and caches all built Defs for +// reuse. CodeCache (below) uses this internally; there is no need to use this +// class directly unless you only want Defs without corresponding Handlers. +// +// This class is NOT thread-safe. +class DefBuilder { + public: + // Functions to get or create a Def from a corresponding proto2 Descriptor. + // The returned def will be frozen. + // + // The caller must take a ref on the returned value if it needs it long-term. + // The DefBuilder will retain a ref so it can keep the Def cached, but + // garbage-collection functionality may be added to DefBuilder later that + // could unref the returned pointer. + const EnumDef* GetOrCreateEnumDef(const proto2::EnumDescriptor* d); + const EnumDef* GetOrCreateEnumDef( + const ::google::protobuf::EnumDescriptor* d); + const MessageDef* GetOrCreateMessageDef(const proto2::Descriptor* d); + const MessageDef* GetOrCreateMessageDef( + const ::google::protobuf::Descriptor* d); + + // Gets or creates a frozen MessageDef, properly expanding weak fields. + // + // Weak fields are only represented as BYTES fields in the Descriptor (unless + // you construct your descriptors in a somewhat complicated way; see + // https://goto.google.com/weak-field-descriptor), but we can get their true + // definitions relatively easily from the proto Message class. + const MessageDef* GetOrCreateMessageDefExpandWeak(const proto2::Message& m); + const MessageDef* GetOrCreateMessageDefExpandWeak( + const ::google::protobuf::Message& m); + + private: + // Like GetOrCreateMessageDef*(), except the returned def might not be frozen. + // We need this function because circular graphs of MessageDefs need to all + // be frozen together, to we have to create the graphs of defs in an unfrozen + // state first. + // + // If m is non-NULL, expands weak message fields. + const MessageDef* GetOrCreateMaybeUnfrozenMessageDef( + const proto2::Descriptor* d, const proto2::Message* m); + const MessageDef* GetOrCreateMaybeUnfrozenMessageDef( + const ::google::protobuf::Descriptor* d, + const ::google::protobuf::Message* m); + + // Returns a new-unfrozen FieldDef corresponding to this FieldDescriptor. + // The return value is always newly created (never cached) and the returned + // pointer is the only owner of it. + // + // If "m" is non-NULL, expands the weak field if it is one, and populates + // *subm_prototype with a prototype of the submessage if this is a weak or + // non-weak MESSAGE or GROUP field. + reffed_ptr NewFieldDef(const proto2::FieldDescriptor* f, + const proto2::Message* m); + reffed_ptr NewFieldDef(const ::google::protobuf::FieldDescriptor* f, + const ::google::protobuf::Message* m); + + // Freeze all defs that haven't been frozen yet. + void Freeze(); + + template + T* AddToCache(const void *proto2_descriptor, reffed_ptr def) { + assert(def_cache_.find(proto2_descriptor) == def_cache_.end()); + def_cache_[proto2_descriptor] = def; + return def.get(); // Continued lifetime is guaranteed by cache. + } + + template + const T* FindInCache(const void *proto2_descriptor) { + DefCache::iterator iter = def_cache_.find(proto2_descriptor); + return iter == def_cache_.end() ? NULL : + upb::down_cast(iter->second.get()); + } + + private: + // Maps a proto2 descriptor to the corresponding upb Def we have constructed. + // The proto2 descriptor is void* because the proto2 descriptor types do not + // share a common base. + typedef std::map > DefCache; + DefCache def_cache_; + + // Defs that have not been frozen yet. + vector to_freeze_; +}; + +// Builds and caches upb::Handlers for populating proto2 generated classes. // -// 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, - const void* owner); -const upb::Handlers* NewWriteHandlers(const ::google::protobuf::Message& m, - const void* owner); +// This class is NOT thread-safe. +class CodeCache { + public: + // Gets or creates handlers for populating messages of the given message type. + // + // The caller must take a ref on the returned value if it needs it long-term. + // The CodeCache will retain a ref so it can keep the Def cached, but + // garbage-collection functionality may be added to CodeCache later that could + // unref the returned pointer. + const Handlers* GetOrCreateWriteHandlers(const proto2::Message& m); + const Handlers* GetOrCreateWriteHandlers( + const ::google::protobuf::Message& m); + + private: + const Handlers* GetOrCreateMaybeUnfrozenWriteHandlers( + const MessageDef* md, const proto2::Message& m); + const Handlers* GetOrCreateMaybeUnfrozenWriteHandlers( + const MessageDef* md, const ::google::protobuf::Message& m); + + Handlers* AddToCache(const MessageDef* md, reffed_ptr handlers) { + assert(handlers_cache_.find(md) == handlers_cache_.end()); + handlers_cache_[md] = handlers; + return handlers.get(); // Continue lifetime is guaranteed by the cache. + } + + const Handlers* FindInCache(const MessageDef* md) { + HandlersCache::iterator iter = handlers_cache_.find(md); + return iter == handlers_cache_.end() ? NULL : iter->second.get(); + } + + DefBuilder def_builder_; + + typedef std::map > + HandlersCache; + HandlersCache handlers_cache_; + + vector to_freeze_; +}; } // namespace google } // namespace upb diff --git a/upb/google/proto1.cc b/upb/google/proto1.cc index 51b221a..80a44d8 100644 --- a/upb/google/proto1.cc +++ b/upb/google/proto1.cc @@ -18,6 +18,8 @@ #include "upb/google/proto1.h" +#include + #include "net/proto2/public/repeated_field.h" #include "net/proto/internal_layout.h" #include "net/proto/proto2_reflection.h" @@ -226,10 +228,9 @@ class P2R_Handlers { } template - static bool Append(proto2::RepeatedField* r, T val) { + static void Append(proto2::RepeatedField* r, T val) { // Proto1's ProtoArray class derives from proto2::RepeatedField. r->Add(val); - return true; } // String //////////////////////////////////////////////////////////////////// @@ -316,9 +317,8 @@ class P2R_Handlers { return field; } - static size_t OnCordBuf(Cord* c, const char* buf, size_t n) { + static void OnCordBuf(Cord* c, const char* buf, size_t n) { c->Append(StringPiece(buf, n)); - return true; } static Cord* StartRepeatedCord(proto2::RepeatedField* r, @@ -370,7 +370,7 @@ class P2R_Handlers { const proto2::Message& m, const _pi::Proto2Reflection* r, const upb::FieldDef* f, upb::Handlers* h) { - scoped_ptr data( + std::unique_ptr data( new SubMessageHandlerData(m, proto2_f, r)); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); @@ -385,7 +385,7 @@ class P2R_Handlers { const proto2::Message& m, const _pi::Proto2Reflection* r, const upb::FieldDef* f, upb::Handlers* h) { - scoped_ptr data( + std::unique_ptr data( new SubMessageHandlerData(m, proto2_f, r)); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); diff --git a/upb/google/proto2.cc b/upb/google/proto2.cc index e878a65..d138123 100644 --- a/upb/google/proto2.cc +++ b/upb/google/proto2.cc @@ -314,28 +314,23 @@ case goog::FieldDescriptor::cpptype: \ } template - static bool AppendPrimitive(goog::RepeatedField* r, T val) { - r->Add(val); - return true; - } + static void AppendPrimitive(goog::RepeatedField* r, T val) { r->Add(val); } template - static bool AppendPrimitiveExtension(goog::Message* m, + 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); - return true; } template - static bool SetPrimitiveExtension(goog::Message* m, + 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); - return true; } // Enum ////////////////////////////////////////////////////////////////////// @@ -379,7 +374,7 @@ case goog::FieldDescriptor::cpptype: \ } } - static bool SetEnum(goog::Message* m, const EnumHandlerData* data, + static void SetEnum(goog::Message* m, const EnumHandlerData* data, int32_t val) { if (data->IsValidValue(val)) { int32_t* message_val = data->GetFieldPointer(m); @@ -388,10 +383,9 @@ case goog::FieldDescriptor::cpptype: \ } else { data->mutable_unknown_fields(m)->AddVarint(data->field_number(), val); } - return true; } - static bool AppendEnum(goog::Message* m, const EnumHandlerData* data, + 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 @@ -403,7 +397,6 @@ case goog::FieldDescriptor::cpptype: \ } else { data->mutable_unknown_fields(m)->AddVarint(data->field_number(), val); } - return true; } // EnumExtension ///////////////////////////////////////////////////////////// @@ -421,19 +414,17 @@ case goog::FieldDescriptor::cpptype: \ } } - static bool SetEnumExtension(goog::Message* m, const ExtensionFieldData* data, + 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); - return true; } - static bool AppendEnumExtension(goog::Message* m, + 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); - return true; } // String //////////////////////////////////////////////////////////////////// -- cgit v1.2.3