summaryrefslogtreecommitdiff
path: root/upb/bindings/googlepb
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2014-06-26 20:24:32 -0700
committerJosh Haberman <jhaberman@gmail.com>2014-06-26 20:24:32 -0700
commit2d10fa33071d52d7a35ce3b13bc459cd16a0aa33 (patch)
treebf47d38e2e1cc8ddb4711b23b26e7fd10742e07d /upb/bindings/googlepb
parent7d565f1e7a0f107506d3cf31ef2e33e22a504d2b (diff)
Sync from internal Google development.
Diffstat (limited to 'upb/bindings/googlepb')
-rw-r--r--upb/bindings/googlepb/bridge.cc114
-rw-r--r--upb/bindings/googlepb/bridge.h65
-rw-r--r--upb/bindings/googlepb/proto1.cc27
-rw-r--r--upb/bindings/googlepb/proto1.int.h (renamed from upb/bindings/googlepb/proto1.h)16
-rw-r--r--upb/bindings/googlepb/proto2.cc271
-rw-r--r--upb/bindings/googlepb/proto2.int.h (renamed from upb/bindings/googlepb/proto2.h)18
6 files changed, 409 insertions, 102 deletions
diff --git a/upb/bindings/googlepb/bridge.cc b/upb/bindings/googlepb/bridge.cc
index c8e3474..a666ff6 100644
--- a/upb/bindings/googlepb/bridge.cc
+++ b/upb/bindings/googlepb/bridge.cc
@@ -16,8 +16,8 @@
#include <map>
#include <string>
#include "upb/def.h"
-#include "upb/bindings/googlepb/proto1.h"
-#include "upb/bindings/googlepb/proto2.h"
+#include "upb/bindings/googlepb/proto1.int.h"
+#include "upb/bindings/googlepb/proto2.int.h"
#include "upb/handlers.h"
#define ASSERT_STATUS(status) do { \
@@ -39,31 +39,24 @@ namespace goog = ::proto2;
namespace goog = ::google::protobuf;
#endif
-namespace {
-
-const goog::Message* GetPrototype(const goog::Message& m,
- const goog::FieldDescriptor* f) {
- const goog::Message* ret = NULL;
-#ifdef UPB_GOOGLE3
- ret = upb::google::GetProto1WeakPrototype(m, f);
- if (ret) return ret;
-#endif
+namespace upb {
+namespace googlepb {
- if (f->cpp_type() == goog::FieldDescriptor::CPPTYPE_MESSAGE) {
- ret = upb::google::GetFieldPrototype(m, f);
+const goog::Message* TryGetFieldPrototype(const goog::Message& m,
+ const goog::FieldDescriptor* f) {
+ const goog::Message* ret = upb::googlepb::GetProto2FieldPrototype(m, f);
#ifdef UPB_GOOGLE3
- if (!ret) ret = upb::google::GetProto1FieldPrototype(m, f);
+ if (!ret) ret = upb::googlepb::GetProto1FieldPrototype(m, f);
#endif
- assert(ret);
- }
return ret;
}
-} // namespace
-
-namespace upb {
-namespace googlepb {
-
+const goog::Message* GetFieldPrototype(const goog::Message& m,
+ const goog::FieldDescriptor* f) {
+ const goog::Message* ret = TryGetFieldPrototype(m, f);
+ assert(ret);
+ return ret;
+}
/* DefBuilder ****************************************************************/
@@ -117,20 +110,11 @@ const MessageDef* DefBuilder::GetMaybeUnfrozenMessageDef(
reffed_ptr<FieldDef> DefBuilder::NewFieldDef(const goog::FieldDescriptor* f,
const goog::Message* m) {
- const goog::Message* subm = NULL;
- const goog::Message* weak_prototype = NULL;
-
- if (m) {
-#ifdef UPB_GOOGLE3
- weak_prototype = upb::google::GetProto1WeakPrototype(*m, f);
-#endif
- subm = GetPrototype(*m, f);
- }
-
reffed_ptr<FieldDef> upb_f(FieldDef::New());
Status status;
upb_f->set_number(f->number(), &status);
upb_f->set_label(FieldDef::ConvertLabel(f->label()));
+ upb_f->set_descriptor_type(FieldDef::ConvertDescriptorType(f->type()));
#ifdef UPB_GOOGLE3
upb_f->set_lazy(f->options().lazy());
#endif
@@ -142,11 +126,19 @@ reffed_ptr<FieldDef> DefBuilder::NewFieldDef(const goog::FieldDescriptor* f,
upb_f->set_name(f->name(), &status);
}
- // 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()));
+ const goog::Message* subm = NULL;
+
+ if (m) {
+ subm = TryGetFieldPrototype(*m, f);
+
+ if (upb_f->type() == UPB_TYPE_MESSAGE) {
+ assert(subm);
+ } else if (subm) {
+ // Weak field: subm will be weak prototype even though the proto2
+ // descriptor does not indicate a submessage field.
+ upb_f->set_descriptor_type(UPB_DESCRIPTOR_TYPE_MESSAGE);
+ }
+ }
switch (upb_f->type()) {
case UPB_TYPE_INT32:
@@ -213,6 +205,35 @@ const MessageDef* DefBuilder::GetMessageDefExpandWeak(
}
+/* WriteHandlers *************************************************************/
+
+// static
+bool WriteHandlers::AddFieldHandler(const goog::Message& m,
+ const goog::FieldDescriptor* f,
+ upb::Handlers* h) {
+ const FieldDef* upb_f = h->message_def()->FindFieldByNumber(f->number());
+ if (!upb_f) return false;
+ if (upb::googlepb::TrySetWriteHandlers(f, m, upb_f, h)) return true;
+#ifdef UPB_GOOGLE3
+ if (upb::googlepb::TrySetProto1WriteHandlers(f, m, upb_f, h)) return true;
+#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.
+ return false;
+}
+
+// static
+upb::reffed_ptr<const upb::Handlers> WriteHandlers::New(
+ const goog::Message& m) {
+ CodeCache cache;
+ return upb::reffed_ptr<const upb::Handlers>(cache.GetWriteHandlers(m));
+}
+
+
/* CodeCache *****************************************************************/
const Handlers* CodeCache::GetMaybeUnfrozenWriteHandlers(
@@ -234,21 +255,11 @@ const Handlers* CodeCache::GetMaybeUnfrozenWriteHandlers(
}
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);
- }
+ bool ok = WriteHandlers::AddFieldHandler(m, proto2_f, h);
+ UPB_ASSERT_VAR(ok, ok);
if (upb_f->type() == UPB_TYPE_MESSAGE) {
- const goog::Message* prototype = GetPrototype(m, proto2_f);
+ const goog::Message* prototype = GetFieldPrototype(m, proto2_f);
assert(prototype);
const upb::Handlers* sub_handlers =
GetMaybeUnfrozenWriteHandlers(upb_f->message_subdef(), *prototype);
@@ -269,10 +280,5 @@ const Handlers* CodeCache::GetWriteHandlers(const goog::Message& m) {
return ret;
}
-upb::reffed_ptr<const upb::Handlers> NewWriteHandlers(const goog::Message& m) {
- CodeCache cache;
- return upb::reffed_ptr<const upb::Handlers>(cache.GetWriteHandlers(m));
-}
-
} // namespace googlepb
} // namespace upb
diff --git a/upb/bindings/googlepb/bridge.h b/upb/bindings/googlepb/bridge.h
index 9eed51b..9878247 100644
--- a/upb/bindings/googlepb/bridge.h
+++ b/upb/bindings/googlepb/bridge.h
@@ -63,13 +63,6 @@ namespace upb {
namespace googlepb {
-// Returns a upb::Handlers object that can be used to populate a proto2::Message
-// object of the same type as "m." For more control over handler caching and
-// reuse, instantiate a CodeCache object below.
-upb::reffed_ptr<const upb::Handlers> NewWriteHandlers(const proto2::Message& m);
-upb::reffed_ptr<const upb::Handlers> 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.
@@ -159,6 +152,41 @@ class DefBuilder {
std::vector<Def*> to_freeze_;
};
+// Handlers to populate a proto2::Message with incoming data.
+class WriteHandlers {
+ public:
+ // Returns a upb::Handlers object that can be used to populate a
+ // proto2::Message object of the same type as "m." For more control over
+ // handler caching and reuse, instantiate a CodeCache object below.
+ static upb::reffed_ptr<const upb::Handlers> New(const proto2::Message& m);
+ static upb::reffed_ptr<const upb::Handlers> New(
+ const ::google::protobuf::Message& m);
+
+ // TODO(haberman): add an interface that takes a list of field paths,
+ // something like:
+ //
+ // // Returns a Handlers instance that will populate the given field paths
+ // // only, dropping data for all other field paths on the floor.
+ // static upb::reffed_ptr<const upb::Handlers> New(
+ // const proto2::Message& m,
+ // const std::vector<std::string>& paths);
+
+ // A lower-level interface with field granularity.
+ //
+ // Adds a handler to the given upb::Handlers for parsing the given field. If
+ // you only want to write certain fields into the proto2 message at parse
+ // time, call these methods ONLY for the fields you want to parse.
+ //
+ // The given field can be either a regular field or an extension, as long as
+ // its containing_type() matches this message.
+ static bool AddFieldHandler(const proto2::Message& m,
+ const proto2::FieldDescriptor* f,
+ upb::Handlers* h);
+ static bool AddFieldHandler(const ::google::protobuf::Message& m,
+ const ::google::protobuf::FieldDescriptor* f,
+ upb::Handlers* h);
+};
+
// Builds and caches upb::Handlers for populating proto2 generated classes.
//
// This class is NOT thread-safe.
@@ -199,6 +227,29 @@ class CodeCache {
std::vector<Handlers*> to_freeze_;
};
+// Functions for getting prototypes; these are only necessary if you are
+// building handlers manually, field by field.
+
+// Given a message and a field descriptor for that message, returns a prototype
+// for the submessage. Requires that this is a submessage field or a weak
+// field.
+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);
+
+// Given a message and a field descriptor for that message, returns a prototype
+// for the submessage, or NULL if this is not a submessage field or a weak
+// field. If this returns non-NULL even though the descriptor's type is not a
+// submessage, then this is a weak field. If you don't know what a weak field
+// is, you are probably not using one.
+const proto2::Message* TryGetFieldPrototype(const proto2::Message& m,
+ const proto2::FieldDescriptor* f);
+const ::google::protobuf::Message* TryGetFieldPrototype(
+ const ::google::protobuf::Message& m,
+ const ::google::protobuf::FieldDescriptor* f);
+
} // namespace googlepb
} // namespace upb
diff --git a/upb/bindings/googlepb/proto1.cc b/upb/bindings/googlepb/proto1.cc
index c317cdf..0b46fed 100644
--- a/upb/bindings/googlepb/proto1.cc
+++ b/upb/bindings/googlepb/proto1.cc
@@ -16,13 +16,20 @@
// dynamic_cast<> in this file:
// https://groups.google.com/a/google.com/d/msg/c-style/7Zp_XCX0e7s/I6dpzno4l-MJ
-#include "upb/bindings/googlepb/proto1.h"
+#include "upb/bindings/googlepb/proto1.int.h"
#include <memory>
+// TEMPORARY measure until we update the friend declarations in proto1.
+// Can't do in a single CL because of components.
+#define private public
+#define protected public
#include "net/proto2/public/repeated_field.h"
#include "net/proto/internal_layout.h"
#include "net/proto/proto2_reflection.h"
+#undef private
+#undef protected
+
#include "upb/def.h"
#include "upb/handlers.h"
#include "upb/shim/shim.h"
@@ -36,7 +43,7 @@ template <class T> static T* GetPointer(void* message, size_t offset) {
}
namespace upb {
-namespace google {
+namespace googlepb {
class P2R_Handlers {
public:
@@ -466,18 +473,18 @@ class P2R_Handlers {
bool TrySetProto1WriteHandlers(const proto2::FieldDescriptor* proto2_f,
const proto2::Message& m,
const upb::FieldDef* upb_f, upb::Handlers* h) {
- return P2R_Handlers::TrySet(proto2_f, m, upb_f, h);
-}
-
-const proto2::Message* GetProto1WeakPrototype(
- const proto2::Message& m, const proto2::FieldDescriptor* f) {
- return P2R_Handlers::GetWeakPrototype(m, f);
+ return googlepb::P2R_Handlers::TrySet(proto2_f, m, upb_f, h);
}
const proto2::Message* GetProto1FieldPrototype(
const proto2::Message& m, const proto2::FieldDescriptor* f) {
- return P2R_Handlers::GetFieldPrototype(m, f);
+ const proto2::Message *weak = googlepb::P2R_Handlers::GetWeakPrototype(m, f);
+ if (weak) return weak;
+ if (f->cpp_type() != proto2::FieldDescriptor::CPPTYPE_MESSAGE) {
+ return NULL;
+ }
+ return googlepb::P2R_Handlers::GetFieldPrototype(m, f);
}
-} // namespace google
+} // namespace googlepb
} // namespace upb
diff --git a/upb/bindings/googlepb/proto1.h b/upb/bindings/googlepb/proto1.int.h
index eb550ac..64ebb2f 100644
--- a/upb/bindings/googlepb/proto1.h
+++ b/upb/bindings/googlepb/proto1.int.h
@@ -7,8 +7,7 @@
// Support for registering field handlers that can write into a legacy proto1
// message. This functionality is only needed inside Google.
//
-// This is a low-level interface; the high-level interface in google.h is
-// more user-friendly.
+// This is an internal-only interface.
#ifndef UPB_GOOGLE_PROTO1_H_
#define UPB_GOOGLE_PROTO1_H_
@@ -24,7 +23,7 @@ class Handlers;
}
namespace upb {
-namespace google {
+namespace googlepb {
// Sets field handlers in the given Handlers object for writing to a single
// field (as described by "proto2_f" and "upb_f") into a message constructed
@@ -35,17 +34,12 @@ bool TrySetProto1WriteHandlers(const proto2::FieldDescriptor* proto2_f,
const proto2::Message& prototype,
const upb::FieldDef* upb_f, upb::Handlers* h);
-// 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);
-
-// Returns a prototype for the given non-weak field in "m".
+// Returns a prototype for the given this (possibly-weak) field. Returns NULL
+// if this is not a submessage field of any kind (weak or no).
const proto2::Message* GetProto1FieldPrototype(
const proto2::Message& m, const proto2::FieldDescriptor* f);
-} // namespace google
+} // namespace googlepb
} // namespace upb
#endif // UPB_GOOGLE_PROTO1_H_
diff --git a/upb/bindings/googlepb/proto2.cc b/upb/bindings/googlepb/proto2.cc
index 04e504b..224e2b9 100644
--- a/upb/bindings/googlepb/proto2.cc
+++ b/upb/bindings/googlepb/proto2.cc
@@ -13,10 +13,12 @@
// 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.h"
+#include "upb/bindings/googlepb/proto2.int.h"
+
+#include <map>
#include "upb/def.h"
-#include "upb/bindings/googlepb/proto1.h"
+#include "upb/bindings/googlepb/proto1.int.h"
#include "upb/handlers.h"
#include "upb/shim/shim.h"
#include "upb/sink.h"
@@ -237,10 +239,26 @@ case goog::FieldDescriptor::cpptype: \
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) {
+ 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) {
- return r->offsets_[f->index()];
+ 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];
}
class FieldOffset {
@@ -274,6 +292,154 @@ case goog::FieldDescriptor::cpptype: \
int8_t mask_;
};
+#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
+ class OneofFieldData {
+ public:
+ OneofFieldData(const goog::FieldDescriptor* f,
+ const goog::internal::GeneratedMessageReflection* 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<int32_t>(message, field_number_offset_);
+ }
+
+ // 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 {
+ switch (types_.at(*field_number)) {
+ case ONEOF_TYPE_NONE:
+ break;
+ case ONEOF_TYPE_STRING:
+ delete *ofs->GetFieldPointer<std::string*>(m);
+ break;
+ case ONEOF_TYPE_MESSAGE:
+ delete *ofs->GetFieldPointer<goog::Message*>(m);
+ break;
+#ifdef UPB_GOOGLE3
+ case ONEOF_TYPE_GLOBALSTRING:
+ delete *ofs->GetFieldPointer<string*>(m);
+ break;
+ case ONEOF_TYPE_CORD:
+ delete *ofs->GetFieldPointer<Cord*>(m);
+ break;
+ case ONEOF_TYPE_STRINGPIECE:
+ delete *ofs->GetFieldPointer<goog::internal::StringPieceField*>(m);
+ break;
+ case ONEOF_TYPE_LAZYFIELD:
+ delete *ofs->GetFieldPointer<goog::internal::LazyField*>(m);
+ break;
+#endif
+ }
+ *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:
+ 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<int32_t, OneofType> 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(
@@ -352,7 +518,16 @@ case goog::FieldDescriptor::cpptype: \
CHKRET(h->SetValueHandler<T>(
f, UpbBindT(SetPrimitiveExtension<T>, data.release())));
}
- } else {
+ }
+#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
+ else if (proto2_f->containing_oneof()) {
+ assert(!proto2_f->is_repeated());
+ CHKRET(h->SetValueHandler<T>(
+ f, UpbBindT(SetOneofPrimitive<T>,
+ new OneofFieldHandlerData(proto2_f, r))));
+ }
+#endif
+ else {
if (f->IsSequence()) {
SetStartRepeatedField<T>(proto2_f, r, f, h);
CHKRET(h->SetValueHandler<T>(f, UpbMakeHandlerT(AppendPrimitive<T>)));
@@ -383,6 +558,17 @@ case goog::FieldDescriptor::cpptype: \
val, set);
}
+#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
+ template <typename T>
+ static void SetOneofPrimitive(goog::Message* m,
+ const OneofFieldHandlerData* data, T val) {
+ data->SetOneofHas(m);
+ const FieldOffset* ofs = data;
+ T* ptr = ofs->GetFieldPointer<T>(m);
+ *ptr = val;
+ }
+#endif
+
// Enum //////////////////////////////////////////////////////////////////////
class EnumHandlerData : public FieldOffset {
@@ -506,7 +692,15 @@ case goog::FieldDescriptor::cpptype: \
upb::Handlers* h) {
assert(!proto2_f->is_extension());
CHKRET(h->SetStringHandler(f, UpbMakeHandlerT(&OnStringBuf<T>)));
- if (f->IsSequence()) {
+#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
+ if (proto2_f->containing_oneof()) {
+ assert(!f->IsSequence());
+ CHKRET(h->SetStartStringHandler(
+ f, UpbBindT(&StartOneofString<T>,
+ new OneofFieldHandlerData(proto2_f, r))));
+ } else
+#endif
+ if (f->IsSequence()) {
SetStartRepeatedPtrField<T>(proto2_f, r, f, h);
CHKRET(
h->SetStartStringHandler(f, UpbMakeHandlerT(StartRepeatedString<T>)));
@@ -545,6 +739,22 @@ case goog::FieldDescriptor::cpptype: \
return str;
}
+#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
+ template <typename T>
+ static T* StartOneofString(goog::Message* m,
+ const OneofFieldHandlerData* data,
+ size_t size_hint) {
+ const FieldOffset* ofs = data;
+ T** str = ofs->GetFieldPointer<T*>(m);
+ if (data->SetOneofHas(m)) {
+ *str = new T();
+ } else {
+ (*str)->clear();
+ }
+ return *str;
+ }
+#endif
+
// StringExtension ///////////////////////////////////////////////////////////
template <typename T>
@@ -598,6 +808,24 @@ case goog::FieldDescriptor::cpptype: \
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,
@@ -605,7 +833,15 @@ case goog::FieldDescriptor::cpptype: \
const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f);
scoped_ptr<SubMessageHandlerData> data(
new SubMessageHandlerData(proto2_f, r, field_prototype));
- if (f->IsSequence()) {
+#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
+ if (proto2_f->containing_oneof()) {
+ 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())));
@@ -649,6 +885,18 @@ case goog::FieldDescriptor::cpptype: \
return submsg;
}
+#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
+ static goog::Message* StartOneofSubMessage(
+ goog::Message* m, const OneofSubMessageHandlerData* data) {
+ const FieldOffset* ofs = data;
+ goog::Message** subm = ofs->GetFieldPointer<goog::Message*>(m);
+ if (data->SetOneofHas(m)) {
+ *subm = data->prototype()->New();
+ }
+ return *subm;
+ }
+#endif
+
// SubMessageExtension ///////////////////////////////////////////////////////
class SubMessageExtensionHandlerData : public ExtensionFieldData {
@@ -979,7 +1227,7 @@ case goog::FieldDescriptor::cpptype: \
};
namespace upb {
-namespace google {
+namespace googlepb {
bool TrySetWriteHandlers(const goog::FieldDescriptor* proto2_f,
const goog::Message& prototype,
@@ -987,10 +1235,13 @@ bool TrySetWriteHandlers(const goog::FieldDescriptor* proto2_f,
return me::GMR_Handlers::TrySet(proto2_f, prototype, upb_f, h);
}
-const goog::Message* GetFieldPrototype(const goog::Message& m,
- const goog::FieldDescriptor* f) {
+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 google
+} // namespace googlepb
} // namespace upb
diff --git a/upb/bindings/googlepb/proto2.h b/upb/bindings/googlepb/proto2.int.h
index 516b7fd..5ce44c4 100644
--- a/upb/bindings/googlepb/proto2.h
+++ b/upb/bindings/googlepb/proto2.int.h
@@ -8,8 +8,7 @@
// message that uses GeneratedMessageReflection (which includes all messages
// generated by the proto2 compiler as well as DynamicMessage).
//
-// This is a low-level interface; the high-level interface in google.h is
-// more user-friendly.
+// This is an internal-only interface.
#ifndef UPB_GOOGLE_PROTO2_H_
#define UPB_GOOGLE_PROTO2_H_
@@ -32,7 +31,7 @@ class Handlers;
}
namespace upb {
-namespace google {
+namespace googlepb {
// Sets field handlers in the given Handlers object for writing to a single
// field (as described by "proto2_f" and "upb_f") into a message constructed
@@ -46,16 +45,15 @@ bool TrySetWriteHandlers(const ::google::protobuf::FieldDescriptor* proto2_f,
const ::google::protobuf::Message& prototype,
const upb::FieldDef* upb_f, upb::Handlers* h);
-// 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 ::google::protobuf::Message* GetFieldPrototype(
+// Returns a prototype for the given field in "m", if the given message uses
+// GeneratedMessageReflection. Otherwise returns NULL.
+const proto2::Message* GetProto2FieldPrototype(
+ const proto2::Message& m, const proto2::FieldDescriptor* f);
+const ::google::protobuf::Message* GetProto2FieldPrototype(
const ::google::protobuf::Message& m,
const ::google::protobuf::FieldDescriptor* f);
-} // namespace google
+} // namespace googlepb
} // namespace upb
#endif // UPB_GOOGLE_PROTO2_H_
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback