summaryrefslogtreecommitdiff
path: root/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'bindings')
-rw-r--r--bindings/cpp/upb/bytestream.hpp33
-rw-r--r--bindings/cpp/upb/def.hpp381
-rw-r--r--bindings/cpp/upb/handlers.cc39
-rw-r--r--bindings/cpp/upb/handlers.hpp47
-rw-r--r--bindings/cpp/upb/msg.hpp62
-rw-r--r--bindings/cpp/upb/pb/glue.hpp12
-rw-r--r--bindings/cpp/upb/proto2_bridge.cc892
-rw-r--r--bindings/cpp/upb/proto2_bridge.hpp170
-rw-r--r--bindings/cpp/upb/upb.hpp44
-rw-r--r--bindings/lua/upb.c24
-rw-r--r--bindings/python/upb.c10
11 files changed, 1620 insertions, 94 deletions
diff --git a/bindings/cpp/upb/bytestream.hpp b/bindings/cpp/upb/bytestream.hpp
index 968d542..81134b9 100644
--- a/bindings/cpp/upb/bytestream.hpp
+++ b/bindings/cpp/upb/bytestream.hpp
@@ -68,6 +68,7 @@
#include "upb/bytestream.h"
#include "upb/upb.hpp"
+#include <string>
namespace upb {
@@ -204,6 +205,18 @@ class ByteRegion : public upb_byteregion {
return upb_byteregion_strdup(this);
}
+ template <typename T> void AssignToString(T* str) {
+ uint64_t ofs = start_ofs();
+ str->clear();
+ str->reserve(Length());
+ while (ofs < end_ofs()) {
+ size_t len;
+ const char *ptr = GetPtr(ofs, &len);
+ str->append(ptr, len);
+ ofs += len;
+ }
+ }
+
// TODO: add if/when there is a demonstrated need.
//
// // Pins this byteregion's bytes in memory, allowing it to outlive its
@@ -220,12 +233,24 @@ class ByteRegion : public upb_byteregion {
class StringSource : public upb_stringsrc {
public:
StringSource() : upb_stringsrc() { upb_stringsrc_init(this); }
+ template <typename T> explicit StringSource(const T& str) {
+ upb_stringsrc_init(this);
+ Reset(str);
+ }
+ StringSource(const char *data, size_t len) {
+ upb_stringsrc_init(this);
+ Reset(data, len);
+ }
~StringSource() { upb_stringsrc_uninit(this); }
void Reset(const char* data, size_t len) {
upb_stringsrc_reset(this, data, len);
}
+ template <typename T> void Reset(const T& str) {
+ Reset(str.c_str(), str.size());
+ }
+
ByteRegion* AllBytes() {
return static_cast<ByteRegion*>(upb_stringsrc_allbytes(this));
}
@@ -233,6 +258,14 @@ class StringSource : public upb_stringsrc {
upb_bytesrc* ByteSource() { return upb_stringsrc_bytesrc(this); }
};
+template <> inline ByteRegion* GetValue<ByteRegion*>(Value v) {
+ return static_cast<ByteRegion*>(upb_value_getbyteregion(v));
+}
+
+template <> inline Value MakeValue<ByteRegion*>(ByteRegion* v) {
+ return upb_value_byteregion(v);
+}
+
} // namespace upb
#endif
diff --git a/bindings/cpp/upb/def.hpp b/bindings/cpp/upb/def.hpp
index 030ba40..6998648 100644
--- a/bindings/cpp/upb/def.hpp
+++ b/bindings/cpp/upb/def.hpp
@@ -1,7 +1,7 @@
//
// upb - a minimalist implementation of protocol buffers.
//
-// Copyright (c) 2011 Google Inc. See LICENSE for details.
+// Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
// Author: Josh Haberman <jhaberman@gmail.com>
//
// The set of upb::*Def classes and upb::SymbolTable allow for defining and
@@ -15,21 +15,20 @@
// not be used for any purpose except to set its properties (it can't be
// used to parse anything, create any messages in memory, etc).
//
-// 2. FINALIZED: after being added to a symtab (which links the defs together)
-// the defs become finalized (thread-safe and immutable). Programs may only
-// access defs through a CONST POINTER during this stage -- upb_symtab will
-// help you out with this requirement by only vending const pointers, but
-// you need to make sure not to use any non-const pointers you still have
-// sitting around. In practice this means that you may not call any setters
-// on the defs (or functions that themselves call the setters). If you want
-// to modify an existing immutable def, copy it with upb_*_dup(), modify the
-// copy, and add the modified def to the symtab (replacing the existing
-// def).
+// 2. FINALIZED: the Def::Finzlie() operation finalizes a set of defs,
+// which makes them thread-safe and immutable. Finalized defs may only be
+// accessed through a CONST POINTER. If you want to modify an existing
+// immutable def, copy it with Dup() and modify and finalize the copy.
//
-// You can test for which stage of life a def is in by calling
-// upb::Def::IsMutable(). This is particularly useful for dynamic language
-// bindings, which must properly guarantee that the dynamic language cannot
-// break the rules laid out above.
+// The refcounting of defs works properly no matter what state the def is in.
+// Once the def is finalized it is guaranteed that any def reachable from a
+// live def is also live (so a ref on the base of a message tree keeps the
+// whole tree alive).
+//
+// You can test for which stage of life a def is in by calling IsMutable().
+// This is particularly useful for dynamic language bindings, which must
+// properly guarantee that the dynamic language cannot break the rules laid out
+// above.
//
// It would be possible to make the defs thread-safe during stage 1 by using
// mutexes internally and changing any methods returning pointers to return
@@ -48,63 +47,213 @@
namespace upb {
+class Def;
class MessageDef;
+typedef upb_fieldtype_t FieldType;
+typedef upb_label_t Label;
+
class FieldDef : public upb_fielddef {
public:
- static FieldDef* Cast(upb_fielddef *f) { return (FieldDef*)f; }
- static const FieldDef* Cast(const upb_fielddef *f) { return (FieldDef*)f; }
+ static FieldDef* Cast(upb_fielddef *f) { return static_cast<FieldDef*>(f); }
+ static const FieldDef* Cast(const upb_fielddef *f) {
+ return static_cast<const FieldDef*>(f);
+ }
+
+ static FieldDef* New(void *owner) { return Cast(upb_fielddef_new(owner)); }
+ FieldDef* Dup(void *owner) const {
+ return Cast(upb_fielddef_dup(this, owner));
+ }
+ void Ref(void *owner) { upb_fielddef_ref(this, owner); }
+ void Unref(void *owner) { upb_fielddef_unref(this, owner); }
- static FieldDef* New() { return Cast(upb_fielddef_new()); }
- FieldDef* Dup() { return Cast(upb_fielddef_dup(this)); }
+ bool IsMutable() const { return upb_fielddef_ismutable(this); }
+ bool IsFinalized() const { return upb_fielddef_isfinalized(this); }
+ bool IsString() const { return upb_isstring(this); }
+ bool IsSequence() const { return upb_isseq(this); }
+ bool IsSubmessage() const { return upb_issubmsg(this); }
- // Read accessors -- may be called at any time.
- uint8_t type() const { return upb_fielddef_type(this); }
- uint8_t label() const { return upb_fielddef_label(this); }
+ // Simple accessors. /////////////////////////////////////////////////////////
+
+ FieldType type() const { return upb_fielddef_type(this); }
+ Label label() const { return upb_fielddef_label(this); }
int32_t number() const { return upb_fielddef_number(this); }
std::string name() const { return std::string(upb_fielddef_name(this)); }
Value default_() const { return upb_fielddef_default(this); }
Value bound_value() const { return upb_fielddef_fval(this); }
+ uint16_t offset() const { return upb_fielddef_offset(this); }
+ int16_t hasbit() const { return upb_fielddef_hasbit(this); }
+
+ bool set_type(FieldType type) { return upb_fielddef_settype(this, type); }
+ bool set_label(Label label) { return upb_fielddef_setlabel(this, label); }
+ void set_offset(uint16_t offset) { upb_fielddef_setoffset(this, offset); }
+ void set_hasbit(int16_t hasbit) { upb_fielddef_sethasbit(this, hasbit); }
+ void set_fval(Value fval) { upb_fielddef_setfval(this, fval); }
+ void set_accessor(struct _upb_accessor_vtbl* vtbl) {
+ upb_fielddef_setaccessor(this, vtbl);
+ }
+ MessageDef* message();
+ const MessageDef* message() const;
- MessageDef* message() { return (MessageDef*)upb_fielddef_msgdef(this); }
- const MessageDef* message() const { return (MessageDef*)upb_fielddef_msgdef(this); }
-
- // Will be added once upb::Def is defined:
- // Def* subdef() { return upb_fielddef_subdef(this); }
- // const Def* subdef() { return upb_fielddef_subdef(this); }
-
- // Returns true if this FieldDef is finalized
- bool IsFinalized() const { return upb_fielddef_finalized(this); }
struct _upb_accessor_vtbl *accessor() const {
return upb_fielddef_accessor(this);
}
- std::string type_name() const {
- return std::string(upb_fielddef_typename(this));
+
+ // "Number" and "name" must be set before the fielddef is added to a msgdef.
+ // For the moment we do not allow these to be set once the fielddef is added
+ // to a msgdef -- this could be relaxed in the future.
+ bool set_number(int32_t number) {
+ return upb_fielddef_setnumber(this, number);
+ }
+ bool set_name(const char *name) { return upb_fielddef_setname(this, name); }
+ bool set_name(const std::string& name) { return set_name(name.c_str()); }
+
+ // Default value. ////////////////////////////////////////////////////////////
+
+ // Returns the default value for this fielddef, which may either be something
+ // the client set explicitly or the "default default" (0 for numbers, empty
+ // for strings). The field's type indicates the type of the returned value,
+ // except for enum fields that are still mutable.
+ //
+ // For enums the default can be set either numerically or symbolically -- the
+ // upb_fielddef_default_is_symbolic() function below will indicate which it
+ // is. For string defaults, the value will be a upb_byteregion which is
+ // invalidated by any other non-const call on this object. Once the fielddef
+ // is finalized, symbolic enum defaults are resolved, so finalized enum
+ // fielddefs always have a default of type int32.
+ Value defaultval() { return upb_fielddef_default(this); }
+
+ // Sets default value for the field. For numeric types, use
+ // upb_fielddef_setdefault(), and "value" must match the type of the field.
+ // For string/bytes types, use upb_fielddef_setdefaultstr(). Enum types may
+ // use either, since the default may be set either numerically or
+ // symbolically.
+ //
+ // NOTE: May only be called for fields whose type has already been set.
+ // Also, will be reset to default if the field's type is set again.
+ void set_default(Value value) { upb_fielddef_setdefault(this, value); }
+ void set_default(const char *str) { upb_fielddef_setdefaultcstr(this, str); }
+ void set_default(const char *str, size_t len) {
+ upb_fielddef_setdefaultstr(this, str, len);
+ }
+ void set_default(const std::string& str) {
+ upb_fielddef_setdefaultstr(this, str.c_str(), str.size());
+ }
+
+ // The results of this function are only meaningful for mutable enum fields,
+ // which can have a default specified either as an integer or as a string.
+ // If this returns true, the default returned from upb_fielddef_default() is
+ // a string, otherwise it is an integer.
+ bool DefaultIsSymbolic() { return upb_fielddef_default_is_symbolic(this); }
+
+ // Subdef. ///////////////////////////////////////////////////////////////////
+
+ // Submessage and enum fields must reference a "subdef", which is the
+ // MessageDef or EnumDef that defines their type. Note that when the
+ // FieldDef is mutable it may not have a subdef *yet*, but this still returns
+ // true to indicate that the field's type requires a subdef.
+ bool HasSubDef() { return upb_hassubdef(this); }
+
+ // Before a FieldDef is finalized, its subdef may be set either directly
+ // (with a Def*) or symbolically. Symbolic refs must be resolved by the
+ // client before the containing msgdef can be finalized.
+ //
+ // Both methods require that HasSubDef() (so the type must be set prior to
+ // calling these methods). Returns false if this is not the case, or if the
+ // given subdef is not of the correct type. The subtype is reset if the
+ // field's type is changed.
+ bool set_subdef(Def* def);
+ bool set_subtype_name(const char *name) {
+ return upb_fielddef_setsubtypename(this, name);
+ }
+ bool set_subtype_name(const std::string& str) {
+ return set_subtype_name(str.c_str());
}
- // Write accessors -- may not be called once the FieldDef is finalized.
+ // Returns the enum or submessage def or symbolic name for this field, if
+ // any. May only be called for fields where HasSubDef() is true. Returns
+ // NULL if the subdef has not been set or if you ask for a subtype name when
+ // the subtype is currently set symbolically (or vice-versa).
+ //
+ // Caller does *not* own a ref on the returned def or string.
+ // subtypename_name() is non-const because only mutable defs can have the
+ // subtype name set symbolically (symbolic references must be resolved before
+ // the MessageDef can be finalized).
+ const Def* subdef() const;
+ const char *subtype_name() { return upb_fielddef_subtypename(this); }
private:
- FieldDef();
- ~FieldDef();
+ UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(FieldDef);
+};
+
+class Def : public upb_def {
+ public:
+ // Converting from C types to C++ wrapper types.
+ static Def* Cast(upb_def *def) { return static_cast<Def*>(def); }
+ static const Def* Cast(const upb_def *def) {
+ return static_cast<const Def*>(def);
+ }
+
+ void Ref(void *owner) const { upb_def_ref(this, owner); }
+ void Unref(void *owner) const { upb_def_unref(this, owner); }
+
+ void set_full_name(const char *name) { upb_def_setfullname(this, name); }
+ void set_full_name(const std::string& name) {
+ upb_def_setfullname(this, name.c_str());
+ }
+
+ const char *full_name() const { return upb_def_fullname(this); }
+
+ // Finalizes the given list of defs (as well as the fielddefs for the given
+ // msgdefs). All defs reachable from any def in this list must either be
+ // already finalized or elsewhere in the list. Any symbolic references to
+ // enums or submessages must already have been resolved. Returns true on
+ // success, otherwise false is returned and status contains details. In the
+ // error case the input defs are unmodified. See the comment at the top of
+ // this file for the semantics of finalized defs.
+ //
+ // n is currently limited to 64k defs, if more are required break them into
+ // batches of 64k (or we could raise this limit, at the cost of a bigger
+ // upb_def structure or complexity in upb_def_finalize()).
+ static bool Finalize(Def*const* defs, int n, Status* status) {
+ return upb_finalize(reinterpret_cast<upb_def*const*>(defs), n, status);
+ }
+ static bool Finalize(const std::vector<Def*>& defs, Status* status) {
+ return Finalize(&defs[0], defs.size(), status);
+ }
};
class MessageDef : public upb_msgdef {
public:
// Converting from C types to C++ wrapper types.
- static MessageDef* Cast(upb_msgdef *md) { return (MessageDef*)md; }
+ static MessageDef* Cast(upb_msgdef *md) {
+ return static_cast<MessageDef*>(md);
+ }
static const MessageDef* Cast(const upb_msgdef *md) {
- return (MessageDef*)md;
+ return static_cast<const MessageDef*>(md);
+ }
+ static MessageDef* DynamicCast(Def* def) {
+ return Cast(upb_dyncast_msgdef(def));
+ }
+ static const MessageDef* DynamicCast(const Def* def) {
+ return Cast(upb_dyncast_msgdef_const(def));
}
- static MessageDef* New() { return Cast(upb_msgdef_new()); }
- MessageDef* Dup() { return Cast(upb_msgdef_dup(this)); }
+ Def* AsDef() { return Def::Cast(UPB_UPCAST(this)); }
+ const Def* AsDef() const { return Def::Cast(UPB_UPCAST(this)); }
+
+ static MessageDef* New(void *owner) { return Cast(upb_msgdef_new(owner)); }
+ MessageDef* Dup(void *owner) const {
+ return Cast(upb_msgdef_dup(this, owner));
+ }
- void Ref() const { upb_msgdef_ref(this); }
- void Unref() const { upb_msgdef_unref(this); }
+ void Ref(void *owner) const { upb_msgdef_ref(this, owner); }
+ void Unref(void *owner) const { upb_msgdef_unref(this, owner); }
// Read accessors -- may be called at any time.
+ const char *full_name() const { return AsDef()->full_name(); }
+
// The total size of in-memory messages created with this MessageDef.
uint16_t instance_size() const { return upb_msgdef_size(this); }
@@ -116,25 +265,32 @@ class MessageDef : public upb_msgdef {
// Write accessors. May only be called before the msgdef is in a symtab.
+ void set_full_name(const char *name) { AsDef()->set_full_name(name); }
+ void set_full_name(const std::string& name) { AsDef()->set_full_name(name); }
+
void set_instance_size(uint16_t size) { upb_msgdef_setsize(this, size); }
void set_hasbit_bytes(uint16_t size) { upb_msgdef_setsize(this, size); }
bool SetExtensionRange(uint32_t start, uint32_t end) {
return upb_msgdef_setextrange(this, start, end);
}
- // Adds a set of fields (upb_fielddef objects) to a msgdef. Caller retains
- // its ref on the fielddef. May only be done before the msgdef is in a
- // symtab (requires upb_def_ismutable(m) for the msgdef). The fielddef's
- // name and number must be set, and the message may not already contain any
- // field with this name or number, and this fielddef may not be part of
- // another message, otherwise false is returned and no action is performed.
- bool AddFields(FieldDef*const * f, int n) {
- return upb_msgdef_addfields(this, (upb_fielddef**)f, n);
+ // Adds a set of fields (FieldDef objects) to a MessageDef. Caller passes a
+ // ref on the FieldDef to the MessageDef in both success and failure cases.
+ // May only be done before the MessageDef is in a SymbolTable (requires
+ // m->IsMutable() for the MessageDef). The FieldDef's name and number must
+ // be set, and the message may not already contain any field with this name
+ // or number, and this FieldDef may not be part of another message, otherwise
+ // false is returned and the MessageDef is unchanged.
+ bool AddField(FieldDef* f, void *owner) { return AddFields(&f, 1, owner); }
+ bool AddFields(FieldDef*const * f, int n, void *owner) {
+ return upb_msgdef_addfields(this, (upb_fielddef*const*)f, n, owner);
}
- bool AddFields(const std::vector<FieldDef*>& fields) {
- return AddFields(&fields[0], fields.size());
+ bool AddFields(const std::vector<FieldDef*>& fields, void *owner) {
+ return AddFields(&fields[0], fields.size(), owner);
}
+ int field_count() const { return upb_msgdef_numfields(this); }
+
// Lookup fields by name or number, returning NULL if no such field exists.
FieldDef* FindFieldByName(const char *name) {
return FieldDef::Cast(upb_msgdef_ntof(this, name));
@@ -156,19 +312,89 @@ class MessageDef : public upb_msgdef {
return FindFieldByNumber(num);
}
- // TODO: iteration over fields.
+ class Iterator : public upb_msg_iter {
+ public:
+ explicit Iterator(MessageDef* md) { upb_msg_begin(this, md); }
+ Iterator() {}
+
+ FieldDef* field() { return FieldDef::Cast(upb_msg_iter_field(this)); }
+ bool Done() { return upb_msg_done(this); }
+ void Next() { return upb_msg_next(this); }
+ };
+
+ class ConstIterator : public upb_msg_iter {
+ public:
+ explicit ConstIterator(const MessageDef* md) { upb_msg_begin(this, md); }
+ ConstIterator() {}
+
+ const FieldDef* field() { return FieldDef::Cast(upb_msg_iter_field(this)); }
+ bool Done() { return upb_msg_done(this); }
+ void Next() { return upb_msg_next(this); }
+ };
private:
- MessageDef();
- ~MessageDef();
+ UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(MessageDef);
+};
+
+class EnumDef : public upb_enumdef {
+ public:
+ // Converting from C types to C++ wrapper types.
+ static EnumDef* Cast(upb_enumdef *e) { return static_cast<EnumDef*>(e); }
+ static const EnumDef* Cast(const upb_enumdef *e) {
+ return static_cast<const EnumDef*>(e);
+ }
+
+ static EnumDef* New(void *owner) { return Cast(upb_enumdef_new(owner)); }
+
+ void Ref(void *owner) { upb_enumdef_ref(this, owner); }
+ void Unref(void *owner) { upb_enumdef_unref(this, owner); }
+ EnumDef* Dup(void *owner) const { return Cast(upb_enumdef_dup(this, owner)); }
+
+ Def* AsDef() { return Def::Cast(UPB_UPCAST(this)); }
+ const Def* AsDef() const { return Def::Cast(UPB_UPCAST(this)); }
+
+ int32_t default_value() const { return upb_enumdef_default(this); }
+
+ // May only be set if IsMutable().
+ void set_full_name(const char *name) { AsDef()->set_full_name(name); }
+ void set_full_name(const std::string& name) { AsDef()->set_full_name(name); }
+ void set_default_value(int32_t val) {
+ return upb_enumdef_setdefault(this, val);
+ }
+
+ // Adds a value to the enumdef. Requires that no existing val has this
+ // name or number (returns false and does not add if there is). May only
+ // be called if IsMutable().
+ bool AddValue(char *name, int32_t num) {
+ return upb_enumdef_addval(this, name, num);
+ }
+ bool AddValue(const std::string& name, int32_t num) {
+ return upb_enumdef_addval(this, name.c_str(), num);
+ }
+
+ // Lookups from name to integer and vice-versa.
+ bool LookupName(const char *name, int32_t* num) const {
+ return upb_enumdef_ntoi(this, name, num);
+ }
+
+ // Lookup from integer to name, returns a NULL-terminated string which
+ // the caller does not own, or NULL if not found.
+ const char *LookupNumber(int32_t num) const {
+ return upb_enumdef_iton(this, num);
+ }
+
+ private:
+ UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(EnumDef);
};
class SymbolTable : public upb_symtab {
public:
// Converting from C types to C++ wrapper types.
- static SymbolTable* Cast(upb_symtab *s) { return (SymbolTable*)s; }
+ static SymbolTable* Cast(upb_symtab *s) {
+ return static_cast<SymbolTable*>(s);
+ }
static const SymbolTable* Cast(const upb_symtab *s) {
- return (SymbolTable*)s;
+ return static_cast<const SymbolTable*>(s);
}
static SymbolTable* New() { return Cast(upb_symtab_new()); }
@@ -176,17 +402,50 @@ class SymbolTable : public upb_symtab {
void Ref() const { upb_symtab_unref(this); }
void Unref() const { upb_symtab_unref(this); }
+ // Adds the given defs to the symtab, resolving all symbols. Only one def
+ // per name may be in the list, but defs can replace existing defs in the
+ // symtab. The entire operation either succeeds or fails. If the operation
+ // fails, the symtab is unchanged, false is returned, and status indicates
+ // the error. The caller passes a ref on the defs in all cases.
+ bool Add(Def *const *defs, int n, void *owner, Status* status) {
+ return upb_symtab_add(this, (upb_def*const*)defs, n, owner, status);
+ }
+ bool Add(const std::vector<Def*>& defs, void *owner, Status* status) {
+ return Add(&defs[0], defs.size(), owner, status);
+ }
+
// If the given name refers to a message in this symbol table, returns a new
// ref to that MessageDef object, otherwise returns NULL.
- const MessageDef* LookupMessage(const char *name) const {
- return MessageDef::Cast(upb_symtab_lookupmsg(this, name));
+ const MessageDef* LookupMessage(const char *name, void *owner) const {
+ return MessageDef::Cast(upb_symtab_lookupmsg(this, name, owner));
}
private:
- SymbolTable();
- ~SymbolTable();
+ UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(SymbolTable);
};
+template <> inline const FieldDef* GetValue<const FieldDef*>(Value v) {
+ return static_cast<const FieldDef*>(upb_value_getfielddef(v));
+}
+
+template <> inline Value MakeValue<FieldDef*>(FieldDef* v) {
+ return upb_value_fielddef(v);
+}
+
+inline MessageDef* FieldDef::message() {
+ return MessageDef::Cast(upb_fielddef_msgdef(this));
+}
+inline const MessageDef* FieldDef::message() const {
+ return MessageDef::Cast(upb_fielddef_msgdef(this));
+}
+
+inline const Def* FieldDef::subdef() const {
+ return Def::Cast(upb_fielddef_subdef(this));
+}
+inline bool FieldDef::set_subdef(Def* def) {
+ return upb_fielddef_setsubdef(this, def);
+}
+
} // namespace upb
#endif
diff --git a/bindings/cpp/upb/handlers.cc b/bindings/cpp/upb/handlers.cc
new file mode 100644
index 0000000..c96a74e
--- /dev/null
+++ b/bindings/cpp/upb/handlers.cc
@@ -0,0 +1,39 @@
+//
+// upb - a minimalist implementation of protocol buffers.
+//
+// Copyright (c) 2011 Google Inc. See LICENSE for details.
+// Author: Josh Haberman <jhaberman@gmail.com>
+
+#include "handlers.hpp"
+
+#include "def.hpp"
+
+namespace upb {
+
+namespace {
+
+void MessageCallbackWrapper(
+ void* closure, upb_mhandlers* mh, const upb_msgdef* m) {
+ Handlers::MessageRegistrationVisitor* visitor =
+ static_cast<Handlers::MessageRegistrationVisitor*>(closure);
+ visitor->OnMessage(static_cast<MessageHandlers*>(mh),
+ static_cast<const MessageDef*>(m));
+}
+
+void FieldCallbackWrapper(
+ void* closure, upb_fhandlers* fh, const upb_fielddef* f) {
+ Handlers::MessageRegistrationVisitor* visitor =
+ static_cast<Handlers::MessageRegistrationVisitor*>(closure);
+ visitor->OnField(static_cast<FieldHandlers*>(fh),
+ static_cast<const FieldDef*>(f));
+}
+} // namepace
+
+MessageHandlers* Handlers::RegisterMessageDef(
+ const MessageDef& m, Handlers::MessageRegistrationVisitor* visitor) {
+ upb_mhandlers* mh = upb_handlers_regmsgdef(
+ this, &m, &MessageCallbackWrapper, &FieldCallbackWrapper, &visitor);
+ return static_cast<MessageHandlers*>(mh);
+}
+
+} // namespace upb
diff --git a/bindings/cpp/upb/handlers.hpp b/bindings/cpp/upb/handlers.hpp
index d356a33..a366c3d 100644
--- a/bindings/cpp/upb/handlers.hpp
+++ b/bindings/cpp/upb/handlers.hpp
@@ -15,11 +15,16 @@
#include "upb/handlers.h"
+#include "upb/upb.hpp"
+
namespace upb {
typedef upb_fieldtype_t FieldType;
typedef upb_flow_t Flow;
+typedef upb_sflow_t SubFlow;
class MessageHandlers;
+class MessageDef;
+class FieldDef;
class FieldHandlers : public upb_fhandlers {
public:
@@ -68,12 +73,11 @@ class FieldHandlers : public upb_fhandlers {
MessageHandlers* GetSubMessageHandlers() const;
// If set to >=0, the given hasbit will be set after the value callback is
// called (offset relative to the current closure).
- int32_t GetValueHasbit() const { return upb_fhandlers_getvaluehasbit(this); }
- void SetValueHasbit(int32_t bit) { upb_fhandlers_setvaluehasbit(this, bit); }
+ int32_t GetHasbit() const { return upb_fhandlers_gethasbit(this); }
+ void SetHasbit(int32_t bit) { upb_fhandlers_sethasbit(this, bit); }
private:
- FieldHandlers(); // Only created by upb::Handlers.
- ~FieldHandlers(); // Only destroyed by refcounting.
+ UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(FieldHandlers);
};
class MessageHandlers : public upb_mhandlers {
@@ -81,6 +85,13 @@ class MessageHandlers : public upb_mhandlers {
typedef upb_startmsg_handler StartMessageHandler;
typedef upb_endmsg_handler EndMessageHandler;
+ static MessageHandlers* Cast(upb_mhandlers* mh) {
+ return static_cast<MessageHandlers*>(mh);
+ }
+ static const MessageHandlers* Cast(const upb_mhandlers* mh) {
+ return static_cast<const MessageHandlers*>(mh);
+ }
+
// The MessageHandlers will live at least as long as the upb::Handlers to
// which it belongs, but can be Ref'd/Unref'd to make it live longer (which
// will prolong the life of the underlying upb::Handlers also).
@@ -89,7 +100,7 @@ class MessageHandlers : public upb_mhandlers {
// Functions to set this message's handlers.
// These return "this" so they can be conveniently chained, eg.
- // handlers->NewMessage()
+ // handlers->NewMessageHandlers()
// ->SetStartMessageHandler(&StartMessage)
// ->SetEndMessageHandler(&EndMessage);
MessageHandlers* SetStartMessageHandler(StartMessageHandler* h) {
@@ -111,13 +122,13 @@ class MessageHandlers : public upb_mhandlers {
FieldHandlers* NewFieldHandlersForSubmessage(uint32_t n, const char *name,
FieldType type, bool repeated,
MessageHandlers* subm) {
+ (void)name;
return static_cast<FieldHandlers*>(
upb_mhandlers_newfhandlers_subm(this, n, type, repeated, subm));
}
private:
- MessageHandlers(); // Only created by upb::Handlers.
- ~MessageHandlers(); // Only destroyed by refcounting.
+ UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(MessageHandlers);
};
class Handlers : public upb_handlers {
@@ -134,17 +145,29 @@ class Handlers : public upb_handlers {
return static_cast<MessageHandlers*>(upb_handlers_newmhandlers(this));
}
+ // Convenience function for registering handlers for all messages and fields
+ // in a MessageDef and all its children. For every registered message,
+ // OnMessage will be called on the visitor with newly-created MessageHandlers
+ // and MessageDef. Likewise with OnField will be called with newly-created
+ // FieldHandlers and FieldDef for each field.
+ class MessageRegistrationVisitor {
+ public:
+ virtual ~MessageRegistrationVisitor() {}
+ virtual void OnMessage(MessageHandlers* mh, const MessageDef* m) = 0;
+ virtual void OnField(FieldHandlers* fh, const FieldDef* f) = 0;
+ };
+ MessageHandlers* RegisterMessageDef(const MessageDef& m,
+ MessageRegistrationVisitor* visitor);
+
private:
- Handlers(); // Only created by Handlers::New().
- ~Handlers(); // Only destroyed by refcounting.
+ UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(Handlers);
};
-
-MessageHandlers* FieldHandlers::GetMessageHandlers() const {
+inline MessageHandlers* FieldHandlers::GetMessageHandlers() const {
return static_cast<MessageHandlers*>(upb_fhandlers_getmsg(this));
}
-MessageHandlers* FieldHandlers::GetSubMessageHandlers() const {
+inline MessageHandlers* FieldHandlers::GetSubMessageHandlers() const {
return static_cast<MessageHandlers*>(upb_fhandlers_getsubmsg(this));
}
diff --git a/bindings/cpp/upb/msg.hpp b/bindings/cpp/upb/msg.hpp
new file mode 100644
index 0000000..c7cf1f2
--- /dev/null
+++ b/bindings/cpp/upb/msg.hpp
@@ -0,0 +1,62 @@
+//
+// upb - a minimalist implementation of protocol buffers.
+//
+// Copyright (c) 2011 Google Inc. See LICENSE for details.
+// Author: Josh Haberman <jhaberman@gmail.com>
+// Routines for reading and writing message data to an in-memory structure,
+// similar to a C struct.
+//
+// upb does not define one single message object that everyone must use.
+// Rather it defines an abstract interface for reading and writing members
+// of a message object, and all of the parsers and serializers use this
+// abstract interface. This allows upb's parsers and serializers to be used
+// regardless of what memory management scheme or synchronization model the
+// application is using.
+//
+// A standard set of accessors is provided for doing simple reads and writes at
+// a known offset into the message. These accessors should be used when
+// possible, because they are specially optimized -- for example, the JIT can
+// recognize them and emit specialized code instead of having to call the
+// function at all. The application can substitute its own accessors when the
+// standard accessors are not suitable.
+
+#ifndef UPB_MSG_HPP
+#define UPB_MSG_HPP
+
+#include "upb/msg.h"
+#include "upb/handlers.hpp"
+
+namespace upb {
+
+typedef upb_accessor_vtbl AccessorVTable;
+
+// Registers handlers for writing into a message of the given type using
+// whatever accessors it has defined.
+inline MessageHandlers* RegisterWriteHandlers(upb::Handlers* handlers,
+ const upb::MessageDef* md) {
+ return MessageHandlers::Cast(
+ upb_accessors_reghandlers(handlers, md));
+}
+
+template <typename T> static FieldHandlers::ValueHandler* GetValueHandler();
+
+// A handy templated function that will retrieve a value handler for a given
+// C++ type.
+#define GET_VALUE_HANDLER(type, ctype) \
+ template <> \
+ FieldHandlers::ValueHandler* GetValueHandler<ctype>() { \
+ return &upb_stdmsg_set ## type; \
+ }
+
+GET_VALUE_HANDLER(double, double);
+GET_VALUE_HANDLER(float, float);
+GET_VALUE_HANDLER(uint64, uint64_t);
+GET_VALUE_HANDLER(uint32, uint32_t);
+GET_VALUE_HANDLER(int64, int64_t);
+GET_VALUE_HANDLER(int32, int32_t);
+GET_VALUE_HANDLER(bool, bool);
+#undef GET_VALUE_HANDLER
+
+} // namespace
+
+#endif
diff --git a/bindings/cpp/upb/pb/glue.hpp b/bindings/cpp/upb/pb/glue.hpp
index be072a7..d43baeb 100644
--- a/bindings/cpp/upb/pb/glue.hpp
+++ b/bindings/cpp/upb/pb/glue.hpp
@@ -13,11 +13,23 @@
namespace upb {
+// All routines that load descriptors expect the descriptor to be a
+// FileDescriptorSet.
bool LoadDescriptorFileIntoSymtab(SymbolTable* s, const char *fname,
Status* status) {
return upb_load_descriptor_file_into_symtab(s, fname, status);
}
+bool LoadDescriptorIntoSymtab(SymbolTable* s, const char* str,
+ size_t len, Status* status) {
+ return upb_load_descriptor_into_symtab(s, str, len, status);
+}
+
+template <typename T>
+bool LoadDescriptorIntoSymtab(SymbolTable* s, const T& desc, Status* status) {
+ return upb_load_descriptor_into_symtab(s, desc.c_str(), desc.size(), status);
+}
+
} // namespace upb
#endif
diff --git a/bindings/cpp/upb/proto2_bridge.cc b/bindings/cpp/upb/proto2_bridge.cc
new file mode 100644
index 0000000..6119295
--- /dev/null
+++ b/bindings/cpp/upb/proto2_bridge.cc
@@ -0,0 +1,892 @@
+//
+// upb - a minimalist implementation of protocol buffers.
+//
+// Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
+// Author: Josh Haberman <jhaberman@gmail.com>
+
+#include <string>
+#include <typeinfo>
+#include "upb/bytestream.hpp"
+#include "upb/def.hpp"
+#include "upb/handlers.hpp"
+#include "upb/msg.hpp"
+#include "upb/proto2_bridge.hpp"
+
+namespace {
+
+static void* GetFieldPointer(void *message, const upb::FieldDef* f) {
+ return static_cast<char*>(message) + f->offset();
+}
+
+} // namespace
+
+#ifdef UPB_GOOGLE3
+
+// TODO(haberman): friend upb so that this isn't required.
+#define protected public
+#include "net/proto2/public/repeated_field.h"
+#undef private
+
+#define private public
+#include "net/proto/proto2_reflection.h"
+#undef private
+
+#include "net/proto2/proto/descriptor.pb.h"
+#include "net/proto2/public/descriptor.h"
+#include "net/proto2/public/generated_message_reflection.h"
+#include "net/proto2/public/lazy_field.h"
+#include "net/proto2/public/message.h"
+#include "net/proto2/public/string_piece_field_support.h"
+#include "net/proto/internal_layout.h"
+#include "strings/cord.h"
+using ::proto2::Descriptor;
+using ::proto2::EnumDescriptor;
+using ::proto2::EnumValueDescriptor;
+using ::proto2::FieldDescriptor;
+using ::proto2::FieldOptions;
+using ::proto2::FileDescriptor;
+using ::proto2::internal::GeneratedMessageReflection;
+using ::proto2::internal::RepeatedPtrFieldBase;
+using ::proto2::internal::StringPieceField;
+using ::proto2::Message;
+using ::proto2::MessageFactory;
+using ::proto2::Reflection;
+using ::proto2::RepeatedField;
+using ::proto2::RepeatedPtrField;
+
+namespace upb {
+
+static const Message* GetPrototypeForField(const Message& m,
+ const FieldDescriptor* f);
+
+namespace proto2_bridge_google3 { class FieldAccessor; }
+
+using ::upb::proto2_bridge_google3::FieldAccessor;
+
+namespace proto2_bridge_google3 {
+
+static void AssignToCord(const 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;
+ }
+}
+
+#else
+
+// TODO(haberman): friend upb so that this isn't required.
+#define protected public
+#include "google/protobuf/repeated_field.h"
+#undef protected
+
+#define private public
+#include "google/protobuf/generated_message_reflection.h"
+#undef private
+
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/message.h"
+using ::google::protobuf::Descriptor;
+using ::google::protobuf::EnumDescriptor;
+using ::google::protobuf::EnumValueDescriptor;
+using ::google::protobuf::FieldDescriptor;
+using ::google::protobuf::FieldOptions;
+using ::google::protobuf::FileDescriptor;
+using ::google::protobuf::internal::GeneratedMessageReflection;
+using ::google::protobuf::internal::RepeatedPtrFieldBase;
+using ::google::protobuf::Message;
+using ::google::protobuf::MessageFactory;
+using ::google::protobuf::Reflection;
+using ::google::protobuf::RepeatedField;
+using ::google::protobuf::RepeatedPtrField;
+
+namespace upb {
+static const Message* GetPrototypeForField(const Message& m,
+ const FieldDescriptor* f);
+
+namespace proto2_bridge_opensource { class FieldAccessor; }
+
+using ::upb::proto2_bridge_opensource::FieldAccessor;
+
+namespace proto2_bridge_opensource {
+
+#endif // ifdef UPB_GOOGLE3
+
+// Have to define this manually since older versions of proto2 didn't define
+// an enum value for STRING.
+#define UPB_CTYPE_STRING 0
+
+// The code in this class depends on the internal representation of the proto2
+// generated classes, which is an internal implementation detail of proto2 and
+// is not a public interface. As a result, this class's implementation may
+// need to be changed if/when proto2 changes its internal representation. It
+// is intended that this class is the only code that depends on these internal,
+// non-public interfaces.
+//
+// This class only works with messages that use GeneratedMessageReflection.
+// Other reflection classes will need other accessor implementations.
+class FieldAccessor {
+ 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 FieldDescriptor* proto2_f,
+ const upb::MessageDef* md,
+ upb::FieldDef* upb_f) {
+ const Message* prototype = static_cast<const Message*>(md->prototype);
+ const Reflection* base_r = prototype->GetReflection();
+ const GeneratedMessageReflection* r =
+ dynamic_cast<const GeneratedMessageReflection*>(base_r);
+ // 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;
+ if (!r) return false;
+ // Extensions not supported yet.
+ if (proto2_f->is_extension()) return false;
+
+ upb_f->set_accessor(GetForFieldDescriptor(proto2_f, ctype));
+ upb_f->set_hasbit(GetHasbit(proto2_f, r));
+ upb_f->set_offset(GetOffset(proto2_f, r));
+ if (upb_f->IsSubmessage()) {
+ upb_f->set_subtype_name(proto2_f->message_type()->full_name());
+ upb_f->prototype = GetPrototypeForField(*prototype, proto2_f);
+ }
+
+ if (upb_f->IsString() && !upb_f->IsSequence() &&
+ ctype == UPB_CTYPE_STRING) {
+ upb_f->prototype = &r->GetStringReference(*prototype, proto2_f, NULL);
+ }
+ return true;
+ }
+
+ static MessageFactory* GetMessageFactory(const Message& m) {
+ const GeneratedMessageReflection* r =
+ dynamic_cast<const GeneratedMessageReflection*>(m.GetReflection());
+ return r ? r->message_factory_ : NULL;
+ }
+
+ private:
+ static int64_t GetHasbit(const FieldDescriptor* f,
+ const GeneratedMessageReflection* r) {
+ if (f->is_repeated()) {
+ // proto2 does not store hasbits for repeated fields.
+ return -1;
+ } else {
+ return (r->has_bits_offset_ * 8) + f->index();
+ }
+ }
+
+ static uint16_t GetOffset(const FieldDescriptor* f,
+ const GeneratedMessageReflection* r) {
+ return r->offsets_[f->index()];
+ }
+
+ static AccessorVTable *GetForFieldDescriptor(const FieldDescriptor* f,
+ int32_t ctype) {
+ switch (f->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_ENUM:
+ // Should handlers validate enum membership to match proto2?
+ case FieldDescriptor::CPPTYPE_INT32: return Get<int32_t>();
+ case FieldDescriptor::CPPTYPE_INT64: return Get<int64_t>();
+ case FieldDescriptor::CPPTYPE_UINT32: return Get<uint32_t>();
+ case FieldDescriptor::CPPTYPE_UINT64: return Get<uint64_t>();
+ case FieldDescriptor::CPPTYPE_DOUBLE: return Get<double>();
+ case FieldDescriptor::CPPTYPE_FLOAT: return Get<float>();
+ case FieldDescriptor::CPPTYPE_BOOL: return Get<bool>();
+ case FieldDescriptor::CPPTYPE_STRING:
+ switch (ctype) {
+#ifdef UPB_GOOGLE3
+ case FieldOptions::STRING:
+ return GetForString<string>();
+ case FieldOptions::CORD:
+ return GetForCord();
+ case FieldOptions::STRING_PIECE:
+ return GetForStringPiece();
+#else
+ case UPB_CTYPE_STRING:
+ return GetForString<std::string>();
+#endif
+ default: return NULL;
+ }
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+#ifdef UPB_GOOGLE3
+ if (f->options().lazy()) {
+ return NULL; // Not yet implemented.
+ } else {
+ return GetForMessage();
+ }
+#else
+ return GetForMessage();
+#endif
+ default: return NULL;
+ }
+ }
+
+ // PushOffset handler (used for StartSequence and others) ///////////////////
+
+ static SubFlow PushOffset(void *m, Value fval) {
+ const FieldDef *f = GetValue<const FieldDef*>(fval);
+ return UPB_CONTINUE_WITH(GetFieldPointer(m, f));
+ }
+
+ // Primitive Value (numeric, enum, bool) /////////////////////////////////////
+
+ template <typename T> static AccessorVTable *Get() {
+ static upb_accessor_vtbl vtbl = {
+ NULL, // StartSubMessage handler
+ GetValueHandler<T>(),
+ &PushOffset, // StartSequence handler
+ NULL, // StartRepeatedSubMessage handler
+ &Append<T>,
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ template <typename T>
+ static Flow Append(void *_r, Value fval, Value val) {
+ (void)fval;
+ RepeatedField<T>* r = static_cast<RepeatedField<T>*>(_r);
+ r->Add(GetValue<T>(val));
+ return UPB_CONTINUE;
+ }
+
+ // String ////////////////////////////////////////////////////////////////////
+
+ template <typename T> static AccessorVTable *GetForString() {
+ static upb_accessor_vtbl vtbl = {
+ NULL, // StartSubMessage handler
+ &SetString<T>,
+ &PushOffset, // StartSequence handler
+ NULL, // StartRepeatedSubMessage handler
+ &AppendString<T>,
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ // This needs to be templated because google3 string is not std::string.
+ template <typename T> static Flow SetString(void *m, Value fval, Value val) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ T **str = static_cast<T**>(GetFieldPointer(m, f));
+ // If it points to the default instance, we must create a new instance.
+ if (*str == f->prototype) *str = new T();
+ GetValue<ByteRegion*>(val)->AssignToString(*str);
+ return UPB_CONTINUE;
+ }
+
+ template <typename T>
+ static Flow AppendString(void *_r, Value fval, Value val) {
+ (void)fval;
+ RepeatedPtrField<T>* r = static_cast<RepeatedPtrField<T>*>(_r);
+ GetValue<ByteRegion*>(val)->AssignToString(r->Add());
+ return UPB_CONTINUE;
+ }
+
+ // SubMessage ////////////////////////////////////////////////////////////////
+
+ static AccessorVTable *GetForMessage() {
+ static upb_accessor_vtbl vtbl = {
+ &StartSubMessage,
+ NULL, // Value handler
+ &PushOffset, // StartSequence handler
+ &StartRepeatedSubMessage,
+ NULL, // Repeated value handler
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ static SubFlow StartSubMessage(void *m, Value fval) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ void **subm = static_cast<void**>(GetFieldPointer(m, f));
+ if (*subm == NULL || *subm == f->prototype) {
+ const Message* prototype = static_cast<const Message*>(f->prototype);
+ *subm = prototype->New();
+ }
+ return UPB_CONTINUE_WITH(*subm);
+ }
+
+ class RepeatedMessageTypeHandler {
+ public:
+ typedef void Type;
+ // 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;
+ assert(false);
+ }
+ };
+
+ // Closure is a RepeatedPtrField<SubMessageType>*, but we access it through
+ // its base class RepeatedPtrFieldBase*.
+ static SubFlow StartRepeatedSubMessage(void* _r, Value fval) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ RepeatedPtrFieldBase *r = static_cast<RepeatedPtrFieldBase*>(_r);
+ void *submsg = r->AddFromCleared<RepeatedMessageTypeHandler>();
+ if (!submsg) {
+ const Message* prototype = static_cast<const Message*>(f->prototype);
+ submsg = prototype->New();
+ r->AddAllocated<RepeatedMessageTypeHandler>(submsg);
+ }
+ return UPB_CONTINUE_WITH(submsg);
+ }
+
+ // TODO(haberman): handle Extensions, Unknown Fields.
+
+#ifdef UPB_GOOGLE3
+ // Handlers for types/features only included in internal proto2 release:
+ // Cord, StringPiece, LazyField, and MessageSet.
+ // TODO(haberman): LazyField, MessageSet.
+
+ // Cord //////////////////////////////////////////////////////////////////////
+
+ static AccessorVTable *GetForCord() {
+ static upb_accessor_vtbl vtbl = {
+ NULL, // StartSubMessage handler
+ &SetCord,
+ &PushOffset, // StartSequence handler
+ NULL, // StartRepeatedSubMessage handler
+ &AppendCord,
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ static Flow SetCord(void *m, Value fval, Value val) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ Cord* field = static_cast<Cord*>(GetFieldPointer(m, f));
+ AssignToCord(GetValue<ByteRegion*>(val), field);
+ return UPB_CONTINUE;
+ }
+
+ static Flow AppendCord(void *_r, Value fval, Value val) {
+ RepeatedField<Cord>* r = static_cast<RepeatedField<Cord>*>(_r);
+ AssignToCord(GetValue<ByteRegion*>(val), r->Add());
+ return UPB_CONTINUE;
+ }
+
+ // StringPiece ///////////////////////////////////////////////////////////////
+
+ static AccessorVTable *GetForStringPiece() {
+ static upb_accessor_vtbl vtbl = {
+ NULL, // StartSubMessage handler
+ &SetStringPiece,
+ &PushOffset, // StartSequence handler
+ NULL, // StartRepeatedSubMessage handler
+ &AppendStringPiece,
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ static void AssignToStringPieceField(const ByteRegion* r,
+ proto2::internal::StringPieceField* f) {
+ // 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.
+ char *data = new char[r->Length()];
+ r->Copy(r->start_ofs(), r->Length(), data);
+ f->CopyFrom(StringPiece(data, r->Length()));
+ delete[] data;
+ }
+
+ static Flow SetStringPiece(void *m, Value fval, Value val) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ StringPieceField* field =
+ static_cast<StringPieceField*>(GetFieldPointer(m, f));
+ AssignToStringPieceField(GetValue<ByteRegion*>(val), field);
+ return UPB_CONTINUE;
+ }
+
+ static Flow AppendStringPiece(void* _r, Value fval, Value val) {
+ RepeatedPtrField<StringPieceField>* r =
+ static_cast<RepeatedPtrField<StringPieceField>*>(_r);
+ AssignToStringPieceField(GetValue<ByteRegion*>(val), r->Add());
+ return UPB_CONTINUE;
+ }
+
+#endif // UPB_GOOGLE3
+};
+
+#ifdef UPB_GOOGLE3
+
+// Proto1 accessor -- only needed inside Google.
+class Proto1FieldAccessor {
+ 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 FieldDescriptor* proto2_f,
+ const upb::MessageDef* md,
+ upb::FieldDef* upb_f) {
+ const Message* m = static_cast<const Message*>(md->prototype);
+ const proto2::Reflection* base_r = m->GetReflection();
+ const _pi::Proto2Reflection* r =
+ dynamic_cast<const _pi::Proto2Reflection*>(base_r);
+ if (!r) return false;
+ // Extensions not supported yet.
+ if (proto2_f->is_extension()) return false;
+
+ const _pi::Field* f = r->GetFieldLayout(proto2_f);
+
+ if (f->crep == _pi::CREP_OPTIONAL_FOREIGN_WEAK) {
+ // Override the BYTES type that proto2 descriptors have for weak fields.
+ upb_f->set_type(UPB_TYPE(MESSAGE));
+ }
+
+ if (upb_f->IsSubmessage()) {
+ const Message* prototype = upb::GetPrototypeForField(*m, proto2_f);
+ upb_f->set_subtype_name(prototype->GetDescriptor()->full_name());
+ upb_f->prototype = prototype;
+ }
+
+ upb_f->set_accessor(GetForCrep(f->crep));
+ upb_f->set_hasbit(GetHasbit(proto2_f, r));
+ upb_f->set_offset(GetOffset(proto2_f, r));
+ return true;
+ }
+
+ private:
+ static int16_t GetHasbit(const FieldDescriptor* f,
+ const _pi::Proto2Reflection* r) {
+ if (f->is_repeated()) {
+ // proto1 does not store hasbits for repeated fields.
+ return -1;
+ } else {
+ return (r->layout_->has_bit_offset * 8) + r->GetFieldLayout(f)->has_index;
+ }
+ }
+
+ static uint16_t GetOffset(const FieldDescriptor* f,
+ const _pi::Proto2Reflection* r) {
+ return r->GetFieldLayout(f)->offset;
+ }
+
+ static AccessorVTable *GetForCrep(int crep) {
+#define PRIMITIVE(name, type_name) \
+ case _pi::CREP_REQUIRED_ ## name: \
+ case _pi::CREP_OPTIONAL_ ## name: \
+ case _pi::CREP_REPEATED_ ## name: return Get<type_name>();
+
+ switch (crep) {
+ 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: return GetForString();
+ case _pi::CREP_OPTIONAL_OUTOFLINE_STRING: return GetForOutOfLineString();
+ case _pi::CREP_REQUIRED_CORD:
+ case _pi::CREP_OPTIONAL_CORD:
+ case _pi::CREP_REPEATED_CORD: return GetForCord();
+ case _pi::CREP_REQUIRED_GROUP:
+ case _pi::CREP_REQUIRED_FOREIGN:
+ case _pi::CREP_REQUIRED_FOREIGN_PROTO2: return GetForRequiredMessage();
+ case _pi::CREP_OPTIONAL_GROUP:
+ case _pi::CREP_REPEATED_GROUP:
+ case _pi::CREP_OPTIONAL_FOREIGN:
+ case _pi::CREP_REPEATED_FOREIGN:
+ case _pi::CREP_OPTIONAL_FOREIGN_PROTO2:
+ case _pi::CREP_REPEATED_FOREIGN_PROTO2: return GetForMessage();
+ case _pi::CREP_OPTIONAL_FOREIGN_WEAK: return GetForWeakMessage();
+ default: assert(false); return NULL;
+ }
+#undef PRIMITIVE
+ }
+
+ // PushOffset handler (used for StartSequence and others) ///////////////////
+
+ // We can find a RepeatedField* or a RepeatedPtrField* at f->offset().
+ static SubFlow PushOffset(void *m, Value fval) {
+ const FieldDef *f = GetValue<const FieldDef*>(fval);
+ return UPB_CONTINUE_WITH(GetFieldPointer(m, f));
+ }
+
+ // Primitive Value (numeric, enum, bool) /////////////////////////////////////
+
+ template <typename T> static AccessorVTable *Get() {
+ static upb_accessor_vtbl vtbl = {
+ NULL, // StartSubMessage handler
+ GetValueHandler<T>(),
+ &PushOffset, // StartSequence handler
+ NULL, // StartRepeatedSubMessage handler
+ &Append<T>,
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ template <typename T>
+ static Flow Append(void *_r, Value fval, Value val) {
+ (void)fval;
+ // Proto1's ProtoArray class derives from RepeatedField.
+ RepeatedField<T>* r = static_cast<RepeatedField<T>*>(_r);
+ r->Add(GetValue<T>(val));
+ return UPB_CONTINUE;
+ }
+
+ // String ////////////////////////////////////////////////////////////////////
+
+ static AccessorVTable *GetForString() {
+ static upb_accessor_vtbl vtbl = {
+ NULL, // StartSubMessage handler
+ &SetString,
+ &PushOffset, // StartSequence handler
+ NULL, // StartRepeatedSubMessage handler
+ &AppendString,
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ static Flow SetString(void *m, Value fval, Value val) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ string *str = static_cast<string*>(GetFieldPointer(m, f));
+ GetValue<ByteRegion*>(val)->AssignToString(str);
+ return UPB_CONTINUE;
+ }
+
+ static Flow AppendString(void *_r, Value fval, Value val) {
+ (void)fval;
+ RepeatedPtrField<string>* r = static_cast<RepeatedPtrField<string>*>(_r);
+ GetValue<ByteRegion*>(val)->AssignToString(r->Add());
+ return UPB_CONTINUE;
+ }
+
+ // Out-of-line string ////////////////////////////////////////////////////////
+
+ static AccessorVTable *GetForOutOfLineString() {
+ static upb_accessor_vtbl vtbl = {
+ NULL, &SetOutOfLineString,
+ // This type is only used for non-repeated string fields.
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ static Flow SetOutOfLineString(void *m, Value fval, Value val) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ string **str = static_cast<string**>(GetFieldPointer(m, f));
+ if (*str == &::ProtocolMessage::___empty_internal_proto_string_)
+ *str = new string();
+ GetValue<ByteRegion*>(val)->AssignToString(*str);
+ return UPB_CONTINUE;
+ }
+
+ // Cord //////////////////////////////////////////////////////////////////////
+
+ static AccessorVTable *GetForCord() {
+ static upb_accessor_vtbl vtbl = {
+ NULL, // StartSubMessage handler
+ &SetCord,
+ &PushOffset, // StartSequence handler
+ NULL, // StartRepeatedSubMessage handler
+ &AppendCord,
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ static Flow SetCord(void *m, Value fval, Value val) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ Cord* field = static_cast<Cord*>(GetFieldPointer(m, f));
+ AssignToCord(GetValue<ByteRegion*>(val), field);
+ return UPB_CONTINUE;
+ }
+
+ static Flow AppendCord(void *_r, Value fval, Value val) {
+ RepeatedField<Cord>* r = static_cast<RepeatedField<Cord>*>(_r);
+ AssignToCord(GetValue<ByteRegion*>(val), r->Add());
+ return UPB_CONTINUE;
+ }
+
+ // SubMessage ////////////////////////////////////////////////////////////////
+
+ static AccessorVTable *GetForRequiredMessage() {
+ static upb_accessor_vtbl vtbl = {
+ &PushOffset, // StartSubMessage handler
+ NULL, // Value handler
+ &PushOffset, // StartSequence handler
+ &StartRepeatedSubMessage,
+ NULL, // Repeated value handler
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ static AccessorVTable *GetForWeakMessage() {
+ static upb_accessor_vtbl vtbl = {
+ &StartWeakSubMessage, // StartSubMessage handler
+ NULL, // Value handler
+ &PushOffset, // StartSequence handler
+ &StartRepeatedSubMessage,
+ NULL, // Repeated value handler
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ static AccessorVTable *GetForMessage() {
+ static upb_accessor_vtbl vtbl = {
+ &StartSubMessage,
+ NULL, // Value handler
+ &PushOffset, // StartSequence handler
+ &StartRepeatedSubMessage,
+ NULL, // Repeated value handler
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+
+ static SubFlow StartSubMessage(void *m, Value fval) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ Message **subm = static_cast<Message**>(GetFieldPointer(m, f));
+ if (*subm == f->prototype) *subm = (*subm)->New();
+ return UPB_CONTINUE_WITH(*subm);
+ }
+
+ static SubFlow StartWeakSubMessage(void *m, Value fval) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ Message **subm = static_cast<Message**>(GetFieldPointer(m, f));
+ if (*subm == NULL) {
+ const Message* prototype = static_cast<const Message*>(f->prototype);
+ *subm = prototype->New();
+ }
+ return UPB_CONTINUE_WITH(*subm);
+ }
+
+ class RepeatedMessageTypeHandler {
+ public:
+ typedef void Type;
+ // 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;
+ assert(false);
+ }
+ };
+
+ // Closure is a RepeatedPtrField<SubMessageType>*, but we access it through
+ // its base class RepeatedPtrFieldBase*.
+ static SubFlow StartRepeatedSubMessage(void* _r, Value fval) {
+ const FieldDef* f = GetValue<const FieldDef*>(fval);
+ RepeatedPtrFieldBase *r = static_cast<RepeatedPtrFieldBase*>(_r);
+ void *submsg = r->AddFromCleared<RepeatedMessageTypeHandler>();
+ if (!submsg) {
+ const Message* prototype = static_cast<const Message*>(f->prototype);
+ submsg = prototype->New();
+ r->AddAllocated<RepeatedMessageTypeHandler>(submsg);
+ }
+ return UPB_CONTINUE_WITH(submsg);
+ }
+};
+
+#endif
+
+} // namespace proto2_bridge_{google3,opensource}
+
+static const Message* GetPrototypeForMessage(const Message& m) {
+ const Message* ret = NULL;
+ MessageFactory* factory = FieldAccessor::GetMessageFactory(m);
+ if (factory) {
+ // proto2 generated message or DynamicMessage.
+ ret = factory->GetPrototype(m.GetDescriptor());
+ assert(ret);
+ } else {
+ // Proto1 message; since proto1 has no dynamic message, it must be
+ // from the generated factory.
+ ret = MessageFactory::generated_factory()->GetPrototype(m.GetDescriptor());
+ assert(ret); // If NULL, then wasn't a proto1 message, can't handle it.
+ }
+ assert(ret->GetReflection() == m.GetReflection());
+ return ret;
+}
+
+static const Message* GetPrototypeForField(const Message& m,
+ const FieldDescriptor* f) {
+#ifdef UPB_GOOGLE3
+ if (f->type() == FieldDescriptor::TYPE_BYTES) {
+ // Proto1 weak field: the proto2 descriptor says their type is BYTES.
+ const _pi::Proto2Reflection* r =
+ dynamic_cast<const _pi::Proto2Reflection*>(m.GetReflection());
+ assert(r);
+ const _pi::Field* field = r->GetFieldLayout(f);
+ assert(field->crep == _pi::CREP_OPTIONAL_FOREIGN_WEAK);
+ return GetPrototypeForMessage(
+ *static_cast<const Message*>(field->weak_layout()->default_instance));
+ } else if (dynamic_cast<const _pi::Proto2Reflection*>(m.GetReflection())) {
+ // Proto1 message; since proto1 has no dynamic message, it must be from
+ // the generated factory.
+ const Message* ret =
+ MessageFactory::generated_factory()->GetPrototype(f->message_type());
+ assert(ret);
+ return ret;
+ }
+#endif
+ assert(f->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
+ // 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().
+ MessageFactory* factory = FieldAccessor::GetMessageFactory(m);
+ assert(factory); // If neither proto1 nor proto2 we can't handle it.
+ const Message* ret = factory->GetPrototype(f->message_type());
+ assert(ret);
+ return ret;
+}
+
+namespace proto2_bridge {
+
+upb::FieldDef* AddFieldDef(const FieldDescriptor* f, upb::MessageDef* md) {
+ upb::FieldDef* upb_f = upb::FieldDef::New(&upb_f);
+ upb_f->set_number(f->number());
+ upb_f->set_name(f->name());
+ upb_f->set_label(static_cast<upb::Label>(f->label()));
+ upb_f->set_type(static_cast<upb::FieldType>(f->type()));
+
+ if (!FieldAccessor::TrySet(f, md, upb_f)
+#ifdef UPB_GOOGLE3
+ && !proto2_bridge_google3::Proto1FieldAccessor::TrySet(f, md, upb_f)
+#endif
+ ) {
+ // Unsupported reflection class.
+ assert(false);
+ }
+
+ if (upb_f->type() == UPB_TYPE(ENUM)) {
+ // We set the enum default symbolically.
+ upb_f->set_default(f->default_value_enum()->name());
+ upb_f->set_subtype_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:
+ upb_f->set_default(MakeValue(f->default_value_int32()));
+ break;
+ case UPB_CTYPE_INT64:
+ upb_f->set_default(
+ MakeValue(static_cast<int64_t>(f->default_value_int64())));
+ break;
+ case UPB_CTYPE_UINT32:
+ upb_f->set_default(MakeValue(f->default_value_uint32()));
+ break;
+ case UPB_CTYPE_UINT64:
+ upb_f->set_default(
+ MakeValue(static_cast<uint64_t>(f->default_value_uint64())));
+ break;
+ case UPB_CTYPE_DOUBLE:
+ upb_f->set_default(MakeValue(f->default_value_double()));
+ break;
+ case UPB_CTYPE_FLOAT:
+ upb_f->set_default(MakeValue(f->default_value_float()));
+ break;
+ case UPB_CTYPE_BOOL:
+ upb_f->set_default(MakeValue(f->default_value_bool()));
+ break;
+ case UPB_CTYPE_BYTEREGION:
+ upb_f->set_default(f->default_value_string());
+ break;
+ }
+ }
+ return md->AddField(upb_f, &upb_f) ? upb_f : NULL;
+}
+
+upb::MessageDef *NewEmptyMessageDef(const Message& m, void *owner) {
+ upb::MessageDef *md = upb::MessageDef::New(owner);
+ md->set_full_name(m.GetDescriptor()->full_name());
+ md->prototype = GetPrototypeForMessage(m);
+ return md;
+}
+
+upb::EnumDef* NewEnumDef(const EnumDescriptor* desc, 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++) {
+ const EnumValueDescriptor* val = desc->value(i);
+ bool success = e->AddValue(val->name(), val->number());
+ assert(success);
+ (void)success;
+ }
+ return e;
+}
+
+void AddAllFields(upb::MessageDef* md) {
+ const Descriptor* d =
+ static_cast<const Message*>(md->prototype)->GetDescriptor();
+ for (int i = 0; i < d->field_count(); i++) {
+#ifdef UPB_GOOGLE3
+ // Skip lazy fields for now since we can't properly handle them.
+ if (d->field(i)->options().lazy()) continue;
+#endif
+ // Extensions not supported yet.
+ if (d->field(i)->is_extension()) continue;
+ AddFieldDef(d->field(i), md);
+ }
+}
+
+upb::MessageDef *NewFullMessageDef(const Message& m, void *owner) {
+ upb::MessageDef* md = NewEmptyMessageDef(m, owner);
+ AddAllFields(md);
+ // TODO(haberman): add unknown field handler and extensions.
+ return md;
+}
+
+typedef std::map<std::string, upb::Def*> SymbolMap;
+
+static upb::MessageDef* NewFinalMessageDefHelper(const Message& m, void *owner,
+ SymbolMap* symbols) {
+ upb::MessageDef* md = NewFullMessageDef(m, owner);
+ // Must do this before processing submessages to prevent infinite recursion.
+ (*symbols)[std::string(md->full_name())] = md->AsDef();
+
+ for (upb::MessageDef::Iterator i(md); !i.Done(); i.Next()) {
+ upb::FieldDef* f = i.field();
+ if (!f->HasSubDef()) continue;
+ SymbolMap::iterator iter = symbols->find(f->subtype_name());
+ upb::Def* subdef;
+ if (iter != symbols->end()) {
+ subdef = iter->second;
+ } else {
+ const FieldDescriptor* proto2_f =
+ m.GetDescriptor()->FindFieldByNumber(f->number());
+ if (f->type() == UPB_TYPE(ENUM)) {
+ subdef = NewEnumDef(proto2_f->enum_type(), owner)->AsDef();
+ (*symbols)[std::string(subdef->full_name())] = subdef;
+ } else {
+ assert(f->IsSubmessage());
+ const Message* prototype = GetPrototypeForField(m, proto2_f);
+ subdef = NewFinalMessageDefHelper(*prototype, owner, symbols)->AsDef();
+ }
+ }
+ f->set_subdef(subdef);
+ }
+ return md;
+}
+
+const upb::MessageDef* NewFinalMessageDef(const Message& m, void *owner) {
+ SymbolMap symbols;
+ upb::MessageDef* ret = NewFinalMessageDefHelper(m, owner, &symbols);
+
+ // Finalize defs.
+ std::vector<upb::Def*> defs;
+ SymbolMap::iterator iter;
+ for (iter = symbols.begin(); iter != symbols.end(); ++iter) {
+ defs.push_back(iter->second);
+ }
+ Status status;
+ bool success = Def::Finalize(defs, &status);
+ assert(success);
+ (void)success;
+
+ // Unref all defs except the top-level one that we are returning.
+ for (int i = 0; i < static_cast<int>(defs.size()); i++) {
+ if (defs[i] != ret->AsDef()) defs[i]->Unref(owner);
+ }
+
+ return ret;
+}
+
+} // namespace proto2_bridge
+} // namespace upb
diff --git a/bindings/cpp/upb/proto2_bridge.hpp b/bindings/cpp/upb/proto2_bridge.hpp
new file mode 100644
index 0000000..ace08ce
--- /dev/null
+++ b/bindings/cpp/upb/proto2_bridge.hpp
@@ -0,0 +1,170 @@
+//
+// upb - a minimalist implementation of protocol buffers.
+//
+// Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
+// Author: Josh Haberman <jhaberman@gmail.com>
+//
+// A bridge between upb and proto2, allows populating proto2 generated
+// classes using upb's parser, translating between descriptors and defs, etc.
+//
+// This is designed to be able to be compiled against either the open-source
+// version of protocol buffers or the Google-internal proto2. The two are
+// the same in most ways, but live in different namespaces (proto2 vs
+// google::protobuf) and have a few other more minor differences.
+//
+// The bridge gives you a lot of control over which fields will be written to
+// the message (fields that are not written will just be skipped), and whether
+// unknown fields are written to the UnknownFieldSet. This can save a lot of
+// work if the client only cares about some subset of the fields.
+//
+// Example usage:
+//
+// // Build a def that will have all fields and parse just like proto2 would.
+// const upb::MessageDef* md = upb::proto2_bridge::NewMessageDef(&MyProto());
+//
+// // 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();
+//
+// // 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::Finalize(md);
+//
+// // Now continue with "JIT the parser" from above.
+//
+// Note that there is currently no support for
+// CodedInputStream::SetExtensionRegistry(), which allows specifying a separate
+// DescriptorPool and MessageFactory for extensions. Since this is a property
+// of the input in proto2, it's difficult to build a plan ahead-of-time that
+// can properly support this. If it's an important use case, the caller should
+// probably build a upb plan explicitly.
+
+#ifndef UPB_PROTO2_BRIDGE
+#define UPB_PROTO2_BRIDGE
+
+#include <vector>
+
+namespace google {
+namespace protobuf {
+class Descriptor;
+class EnumDescriptor;
+class FieldDescriptor;
+class FileDescriptor;
+class Message;
+} // namespace google
+} // namespace protobuf
+
+namespace proto2 {
+class Descriptor;
+class EnumDescriptor;
+class FieldDescriptor;
+class FileDescriptor;
+class Message;
+} // namespace proto2
+
+
+namespace upb {
+
+class Def;
+class FieldDef;
+class MessageDef;
+
+namespace proto2_bridge {
+
+// Unfinalized defs ////////////////////////////////////////////////////////////
+
+// Creating of UNFINALIZED defs. All of these functions return defs that are
+// still mutable and have not been finalized. They must be finalized before
+// using them to parse anything. This is useful if you want more control over
+// the process of constructing defs, eg. to add the specific set of fields you
+// care about.
+
+// Creates a new upb::MessageDef that corresponds to the type in the given
+// prototype message. The MessageDef will not have any fields added to it.
+upb::MessageDef *NewEmptyMessageDef(const proto2::Message& m, void *owner);
+upb::MessageDef *NewEmptyMessageDef(const google::protobuf::Message& desc,
+ void *owner);
+
+// Adds a new upb::FieldDef to the given MessageDef corresponding to the given
+// FieldDescriptor. The FieldDef will be given an accessor and offset so that
+// it can be used to read and write data into the proto2::Message classes.
+// The given MessageDef must have been constructed with NewEmptyDefForMessage()
+// and f->containing_type() must correspond to the message that was used.
+//
+// Any submessage, group, or enum fields will be given symbolic references to
+// the subtype, which must be resolved before the MessageDef can be finalized.
+//
+// On success, returns the FieldDef that was added (caller does not own a ref).
+// If an existing field had the same name or number, returns NULL.
+upb::FieldDef* AddFieldDef(const proto2::FieldDescriptor* f,
+ upb::MessageDef* md);
+upb::FieldDef* AddFieldDef(const google::protobuf::FieldDescriptor* f,
+ upb::MessageDef* md);
+
+// Given a MessageDef that was constructed with NewEmptyDefForMessage(), adds
+// FieldDefs for all fields defined in the original message, but not for any
+// extensions or unknown fields. The given MessageDef must not have any fields
+// that have the same name or number as any of the fields we are adding (the
+// easiest way to guarantee this is to start with an empty MessageDef).
+//
+// Returns true on success or false if any of the fields could not be added.
+void AddAllFields(upb::MessageDef* md);
+
+// TODO(haberman): Add:
+// // Adds a handler that will store unknown fields in the UnknownFieldSet.
+// void AddUnknownFieldHandler(upb::MessageDef* md);
+
+// Returns a new upb::MessageDef that contains handlers for all fields, unknown
+// fields, and any extensions in the descriptor's pool. The resulting
+// def/handlers should be equivalent to the generated code constructed by the
+// protobuf compiler (or the code in DynamicMessage) for the given type.
+// The subdefs for message/enum fields (if any) will be referenced symbolically,
+// and will need to be resolved before being finalized.
+//
+// TODO(haberman): Add missing support (LazyField, MessageSet, and extensions).
+//
+// TODO(haberman): possibly add a similar function that lets you supply a
+// separate DescriptorPool and MessageFactory for extensions, to support
+// proto2's io::CodedInputStream::SetExtensionRegistry().
+upb::MessageDef* NewFullMessageDef(const proto2::Message& m, void *owner);
+upb::MessageDef* NewFullMessageDef(const google::protobuf::Message& m,
+ void *owner);
+
+// Returns a new upb::EnumDef that corresponds to the given EnumDescriptor.
+// Caller owns a ref on the returned EnumDef.
+upb::EnumDef* NewEnumDef(const proto2::EnumDescriptor* desc, void *owner);
+upb::EnumDef* NewEnumDef(const google::protobuf::EnumDescriptor* desc,
+ void *owner);
+
+// Finalized defs //////////////////////////////////////////////////////////////
+
+// These functions return FINALIZED defs, meaning that they are immutable and
+// ready for use. Since they are immutable you cannot make any further changes
+// to eg. the set of fields, but these functions are more convenient if you
+// simply want to parse a message exactly how the built-in proto2 parser would.
+
+// Creates a returns a finalized MessageDef for the give message and its entire
+// type tree that will include all fields and unknown handlers (ie. it will
+// parse just like proto2 would).
+const upb::MessageDef* NewFinalMessageDef(const proto2::Message& m,
+ void *owner);
+const upb::MessageDef* NewFinalMessageDef(const google::protobuf::Message& m,
+ void *owner);
+
+} // namespace proto2_bridge
+} // namespace upb
+
+#endif
diff --git a/bindings/cpp/upb/upb.hpp b/bindings/cpp/upb/upb.hpp
index 226859c..48c2708 100644
--- a/bindings/cpp/upb/upb.hpp
+++ b/bindings/cpp/upb/upb.hpp
@@ -10,6 +10,16 @@
#include "upb/upb.h"
#include <iostream>
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) && !defined(UPB_NO_CXX11)
+#define UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(class_name) \
+ class_name() = delete; \
+ ~class_name() = delete;
+#else
+#define UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(class_name) \
+ class_name(); \
+ ~class_name();
+#endif
+
namespace upb {
typedef upb_success_t Success;
@@ -31,11 +41,35 @@ class Status : public upb_status {
void Clear() { upb_status_clear(this); }
};
-class Value : public upb_value {
- public:
- Value(const upb_value& val) { *this = val; }
- Value() {}
-};
+typedef upb_value Value;
+
+template <typename T> T GetValue(Value v);
+template <typename T> Value MakeValue(T v);
+
+#define UPB_VALUE_ACCESSORS(type, ctype) \
+ template <> inline ctype GetValue<ctype>(Value v) { \
+ return upb_value_get ## type(v); \
+ } \
+ template <> inline Value MakeValue<ctype>(ctype v) { \
+ return upb_value_ ## type(v); \
+ }
+
+UPB_VALUE_ACCESSORS(double, double);
+UPB_VALUE_ACCESSORS(float, float);
+UPB_VALUE_ACCESSORS(int32, int32_t);
+UPB_VALUE_ACCESSORS(int64, int64_t);
+UPB_VALUE_ACCESSORS(uint32, uint32_t);
+UPB_VALUE_ACCESSORS(uint64, uint64_t);
+UPB_VALUE_ACCESSORS(bool, bool);
+
+#undef UPB_VALUE_ACCESSORS
+
+template <typename T> inline T* GetPtrValue(Value v) {
+ return static_cast<T*>(upb_value_getptr(v));
+}
+template <typename T> inline Value MakePtrValue(T* v) {
+ return upb_value_ptr(static_cast<void*>(v));
+}
INLINE std::ostream& operator<<(std::ostream& out, const Status& status) {
out << status.GetString();
diff --git a/bindings/lua/upb.c b/bindings/lua/upb.c
index 56c5be9..4cce4b6 100644
--- a/bindings/lua/upb.c
+++ b/bindings/lua/upb.c
@@ -37,11 +37,15 @@ static uint32_t lupb_touint32(lua_State *L, int narg, const char *name) {
return n;
}
-static void lupb_pushstring(lua_State *L, const upb_byteregion *r) {
- // TODO: could avoid a copy in the case that the string is contiguous.
- char *str = upb_byteregion_strdup(r);
- lua_pushlstring(L, str, upb_byteregion_len(r));
- free(str);
+static void lupb_pushstring(lua_State *L, const upb_strref *ref) {
+ if (ref->ptr) {
+ lua_pushlstring(L, ref->ptr, ref->len);
+ } else {
+ // Lua requires a continguous string; must copy+allocate.
+ char *str = upb_strref_dup(ref);
+ lua_pushlstring(L, str, ref->len);
+ free(str);
+ }
}
static void lupb_pushvalue(lua_State *L, upb_value val, upb_fielddef *f) {
@@ -73,7 +77,7 @@ static void lupb_pushvalue(lua_State *L, upb_value val, upb_fielddef *f) {
// Returns a scalar value (ie. not a submessage) as a upb_value.
static upb_value lupb_getvalue(lua_State *L, int narg, upb_fielddef *f,
- upb_byteregion *ref) {
+ upb_strref *ref) {
assert(!upb_issubmsg(f));
upb_value val;
if (upb_fielddef_type(f) == UPB_TYPE(BOOL)) {
@@ -135,7 +139,7 @@ static upb_value lupb_getvalue(lua_State *L, int narg, upb_fielddef *f,
}
static void lupb_typecheck(lua_State *L, int narg, upb_fielddef *f) {
- upb_byteregion ref;
+ upb_strref ref;
lupb_getvalue(L, narg, f, &ref);
}
@@ -298,8 +302,8 @@ static void lupb_fielddef_set(lua_State *L, upb_fielddef *f,
} else if (streql(field, "default_value")) {
if (!upb_fielddef_type(f))
luaL_error(L, "Must set type before setting default_value");
- upb_byteregion region;
- upb_fielddef_setdefault(f, lupb_getvalue(L, narg, f, &region));
+ upb_strref ref;
+ upb_fielddef_setdefault(f, lupb_getvalue(L, narg, f, &ref));
} else {
luaL_error(L, "Cannot set fielddef member '%s'", field);
}
@@ -778,7 +782,7 @@ static upb_flow_t lupb_msg_string(void *m, upb_value fval, upb_value val,
lua_State *L = *(lua_State**)m;
int offset = array ? lua_rawlen(L, -1) : f->offset;
if (!lua_checkstack(L, 1)) luaL_error(L, "stack full");
- lupb_pushstring(L, upb_value_getbyteregion(val));
+ lupb_pushstring(L, upb_value_getstrref(val));
lua_rawseti(L, -2, offset);
return UPB_CONTINUE;
}
diff --git a/bindings/python/upb.c b/bindings/python/upb.c
index 8f36f70..497074b 100644
--- a/bindings/python/upb.c
+++ b/bindings/python/upb.c
@@ -612,9 +612,8 @@ static upb_sflow_t PyUpb_Message_StartRepeatedSubmessage(void *a, upb_value fval
static upb_flow_t PyUpb_Message_StringValue(void *m, upb_value fval, upb_value val) {
PyObject **str = PyUpb_Accessor_GetPtr(m, fval);
if (*str) { Py_DECREF(*str); }
- upb_byteregion *r = upb_value_getbyteregion(val);
- *str = PyString_FromStringAndSize(NULL, upb_byteregion_len(r));
- upb_byteregion_copyall(r, PyString_AsString(*str));
+ *str = PyString_FromStringAndSize(NULL, upb_value_getstrref(val)->len);
+ upb_strref_read(upb_value_getstrref(val), PyString_AsString(*str));
upb_stdmsg_sethas(m, fval);
return UPB_CONTINUE;
}
@@ -622,9 +621,8 @@ static upb_flow_t PyUpb_Message_StringValue(void *m, upb_value fval, upb_value v
static upb_flow_t PyUpb_Message_AppendStringValue(void *a, upb_value fval, upb_value val) {
(void)fval;
PyObject **elem = upb_stdarray_append(a, sizeof(void*));
- upb_byteregion *r = upb_value_getbyteregion(val);
- *elem = PyString_FromStringAndSize(NULL, upb_byteregion_len(r));
- upb_byteregion_copyall(r, PyString_AsString(*elem));
+ *elem = PyString_FromStringAndSize(NULL, upb_value_getstrref(val)->len);
+ upb_strref_read(upb_value_getstrref(val), PyString_AsString(*elem));
return UPB_CONTINUE;
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback