summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--README127
-rw-r--r--benchmarks/parsetoproto2.upb.cc2
-rw-r--r--tests/bindings/lua/LICENSE (renamed from bindings/lua/LICENSE)0
-rw-r--r--tests/bindings/lua/lunit/console.lua (renamed from bindings/lua/lunit/console.lua)0
-rw-r--r--tests/bindings/lua/lunit/lunit.lua (renamed from bindings/lua/lunit/lunit.lua)0
-rw-r--r--tests/bindings/lua/test.lua (renamed from bindings/lua/test.lua)42
-rw-r--r--tests/pb/test_decoder.cc (renamed from tests/test_decoder.cc)11
-rw-r--r--tests/pb/test_decoder_schema.proto (renamed from tests/test_decoder_schema.proto)0
-rw-r--r--tests/pb/test_varint.c (renamed from tests/test_varint.c)2
-rw-r--r--tests/test_cpp.cc448
-rw-r--r--tests/test_def.c4
-rw-r--r--tests/test_vs_proto2.cc6
-rw-r--r--tools/dump_cinit.lua11
-rw-r--r--tools/test_cinit.lua2
-rw-r--r--upb/bindings/README25
-rw-r--r--upb/bindings/googlepb/README20
-rw-r--r--upb/bindings/googlepb/bridge.cc (renamed from upb/google/bridge.cc)58
-rw-r--r--upb/bindings/googlepb/bridge.h (renamed from upb/google/bridge.h)55
-rw-r--r--upb/bindings/googlepb/proto1.cc (renamed from upb/google/proto1.cc)107
-rw-r--r--upb/bindings/googlepb/proto1.h (renamed from upb/google/proto1.h)0
-rw-r--r--upb/bindings/googlepb/proto2.cc (renamed from upb/google/proto2.cc)190
-rw-r--r--upb/bindings/googlepb/proto2.h (renamed from upb/google/proto2.h)0
-rw-r--r--upb/bindings/linux/Makefile (renamed from bindings/linux/Makefile)0
-rw-r--r--upb/bindings/linux/assert.h (renamed from bindings/linux/assert.h)0
-rw-r--r--upb/bindings/linux/errno.h (renamed from bindings/linux/errno.h)0
-rw-r--r--upb/bindings/linux/stdint.h (renamed from bindings/linux/stdint.h)0
-rw-r--r--upb/bindings/linux/stdio.h (renamed from bindings/linux/stdio.h)0
-rw-r--r--upb/bindings/linux/stdlib.h (renamed from bindings/linux/stdlib.h)0
-rw-r--r--upb/bindings/linux/string.h (renamed from bindings/linux/string.h)0
-rw-r--r--upb/bindings/lua/table.c (renamed from bindings/lua/table.c)3
-rw-r--r--upb/bindings/lua/upb.c (renamed from bindings/lua/upb.c)70
-rw-r--r--upb/bindings/lua/upb.h (renamed from bindings/lua/upb.h)0
-rw-r--r--upb/bindings/python/setup.py (renamed from bindings/python/setup.py)0
-rw-r--r--upb/bindings/python/test.py (renamed from bindings/python/test.py)0
-rw-r--r--upb/bindings/python/upb.c (renamed from bindings/python/upb.c)0
-rw-r--r--upb/bindings/python/upb/__init__.py (renamed from bindings/python/upb/__init__.py)0
-rw-r--r--upb/bindings/stdc++/string.h60
-rw-r--r--upb/bindings/stdc/error.c (renamed from upb/stdc/error.c)0
-rw-r--r--upb/bindings/stdc/error.h (renamed from upb/stdc/error.h)0
-rw-r--r--upb/bindings/stdc/io.c (renamed from upb/stdc/io.c)0
-rw-r--r--upb/bindings/stdc/io.h (renamed from upb/stdc/io.h)0
-rw-r--r--upb/def.c85
-rw-r--r--upb/def.h65
-rwxr-xr-xupb/descriptor/descriptor.upb.c146
-rw-r--r--upb/descriptor/reader.c56
-rw-r--r--upb/google/README16
-rw-r--r--upb/handlers-inl.h463
-rw-r--r--upb/handlers.c195
-rw-r--r--upb/handlers.h158
-rw-r--r--upb/pb/compile_decoder_x64.c3
-rw-r--r--upb/pb/compile_decoder_x64.dasc27
-rw-r--r--upb/pb/decoder.c19
-rw-r--r--upb/pb/decoder.h1
-rw-r--r--upb/pb/decoder.int.h4
-rw-r--r--upb/pb/textprinter.c158
-rw-r--r--upb/pb/textprinter.h80
-rw-r--r--upb/shim/shim.c1
-rw-r--r--upb/sink.h52
-rw-r--r--upb/stdc/README15
-rw-r--r--upb/symtab.c92
61 files changed, 2167 insertions, 721 deletions
diff --git a/Makefile b/Makefile
index a6e49d0..440d4f2 100644
--- a/Makefile
+++ b/Makefile
@@ -82,16 +82,14 @@ deps: Makefile $(ALLSRC)
# The core library.
CORE= \
- upb/bytestream.upb.c \
upb/def.c \
upb/descriptor/reader.c \
upb/descriptor/descriptor.upb.c \
- upb/google/bridge.cc \
- upb/google/proto2.cc \
+ upb/bindings/googlepb/bridge.cc \
+ upb/bindings/googlepb/proto2.cc \
upb/handlers.c \
upb/refcounted.c \
upb/shim/shim.c \
- upb/sink.c \
upb/symtab.c \
upb/table.c \
upb/upb.c \
@@ -217,8 +215,7 @@ tests/test.proto.pb: tests/test.proto
SIMPLE_TESTS= \
tests/test_def \
- tests/test_varint \
- tests/test_pipeline \
+ tests/pb/test_varint \
tests/test_handlers
SIMPLE_CXX_TESTS= \
diff --git a/README b/README
index e52f06a..b322e56 100644
--- a/README
+++ b/README
@@ -1,7 +1,8 @@
upb - a small, low-level protocol buffer library
-For API documentation, see the header files.
+BUILDING
+========
To build (the core library is ANSI C99 and has no dependencies):
$ make
@@ -22,100 +23,44 @@ Issue tracking is on Google Code:
A manual is forthcoming, for now see wiki docs at:
https://github.com/haberman/upb/wiki
+API
+===
+
+The public C/C++ API is defined by all of the .h files in upb/ except .int.h
+files (which are internal-only).
+
+The .h files define both C and C++ APIs. Both languages have 100% complete and
+first-class APIs. The C++ API is a wrapper around the C API, but all of the
+wrapping is done in inline methods in .h files, so there is no overhead to this.
+
+For a more detailed description of the scheme we use to provide both C and C++
+APIs, see: https://github.com/haberman/upb/wiki/CAndCPlusPlusAPI
+
+All of the code that is under upb/ but *not* under upb/bindings/ forms the
+namespace of upb's cross-language public API. For example, the code in
+upb/descriptor would be exposed as follows:
+
+ * in C/C++:
+ #include "upb/descriptor/X.h"
+
+ * in Lua:
+ require "upb.descriptor"
+
+ * in Python:
+ import upb.descriptor
+
+ * etc.
+
+STABILITY / STATUS
+==================
+
API and ABI are both subject to change! Please do not distribute as a shared
library for this reason (for now at least).
-TODO
-====
-
-The issue tracker contains small-to-medium tasks that need doing; but here are
-the major things that are broken or not yet implemented yet:
-
-- serialization isn't written yet (only deserialization)
-
-
-C/C++ API
-=========
-
-upb's main interfaces are defined in .h files (like upb/def.h). These header
-files are coded in such a way that they are not only compatible with C and C++
-but provide idiomatic interfaces to both (functions for C, classes for C++).
-
-Here is the general strategy/pattern for this. I'll explain it piece by piece.
-
-// This defines a type called upb::Foo in C++ or upb_foo in C. In both cases
-// there is a typedef for upb_foo, which is important since this is how the
-// C functions are defined (which are exposed to both C and C++).
-
-#ifdef __cplusplus
-namespace upb { class Foo; }
-typedef upb::Foo upb_foo;
-extern "C" {
-#else
-struct upb_foo;
-typedef struct upb_foo upb_foo;
-#endif
-
-// Here is the actual definition of the class/struct. In C++ we get a class
-// called upb::Foo and in C we get a struct called "struct upb_foo", but both
-// have the same members and the C++ version is "standard-layout" according
-// to C++11. This means that the two should be compatible.
-//
-// In addition to being completely accessible from C, it also provides C++
-// niceities like methods (instead of bare functions). We also get
-// encapsulation in C++, even though this is impossible to provide in C. We
-// provide all method documentation in the C++ class, since the class/method
-// syntax is nicer to read than the bare functions of C.
-
-#ifdef __cplusplus
-
-class upb::Foo {
- public:
- // Method documentation for DoBar().
- void DoBar(int32_t x);
-
- // Method documentation for IsSpicy().
- bool IsSpicy();
-
- private:
-
-#else
-struct upb_foo {
-#endif
- int32_t private_member;
-};
-
-// Next follows the C API, which is how the functionality is actually
-// implemented. We omit documentation here because everything was documented
-// in the C++ class, and it's easy to match the functions 1:1 to the C++
-// methods.
-void upb_foo_dobar(upb_foo *f, int32_t x);
-bool upb_foo_isspicy(upb_foo *f);
-
-// Finally we include inline definitions of the C++ methods, which are nothing
-// but this wrappers around the C functions. Since these are inline, the C++
-// API imposes no overhead.
-
-#ifdef __cplusplus
-} // extern "C"
-
-namespace upb {
-inline void Foo::DoBar(int32_t x) { upb_foo_dobar(this, x); }
-inline bool Foo::IsSpicy() { return upb_foo_isspicy(this); }
-}
-#endif
-
-This scheme works pretty nicely. It adds a bit of noise to the header file, but
-gives nice, zero-overhead APIs to both C and C++ without having to duplicate
-the API documentation.
-
-The biggest bummer is that there isn't any good way to use C++ inheritance
-even for types which are trying to express inheritance in C. C++ just doesn't
-give any guarantees about how it will arrange data members in base classes,
-so we can't use C++ inheritance while interoperating with C layouts. The
-biggest effect of this is that we can't get C++'s nice implicit upcasts; all
-upcasts have to be explicit, which is a pain.
+Parsing is becoming stable, but serialization is in very early stages.
+The Python bindings are completely broken and Lua only supports schemas for the
+moment.
CONTACT
=======
diff --git a/benchmarks/parsetoproto2.upb.cc b/benchmarks/parsetoproto2.upb.cc
index 699b521..20b6381 100644
--- a/benchmarks/parsetoproto2.upb.cc
+++ b/benchmarks/parsetoproto2.upb.cc
@@ -8,7 +8,7 @@
#include "upb/def.h"
#include "upb/pb/decoder.h"
#include "upb/pb/glue.h"
-#include "upb/google/bridge.h"
+#include "upb/bindings/google/bridge.h"
#include MESSAGE_HFILE
const char *str;
diff --git a/bindings/lua/LICENSE b/tests/bindings/lua/LICENSE
index fb720fe..fb720fe 100644
--- a/bindings/lua/LICENSE
+++ b/tests/bindings/lua/LICENSE
diff --git a/bindings/lua/lunit/console.lua b/tests/bindings/lua/lunit/console.lua
index 0ff22a4..0ff22a4 100644
--- a/bindings/lua/lunit/console.lua
+++ b/tests/bindings/lua/lunit/console.lua
diff --git a/bindings/lua/lunit/lunit.lua b/tests/bindings/lua/lunit/lunit.lua
index 80f43c1..80f43c1 100644
--- a/bindings/lua/lunit/lunit.lua
+++ b/tests/bindings/lua/lunit/lunit.lua
diff --git a/bindings/lua/test.lua b/tests/bindings/lua/test.lua
index b19da53..99f58f2 100644
--- a/bindings/lua/test.lua
+++ b/tests/bindings/lua/test.lua
@@ -214,6 +214,42 @@ function test_symtab()
assert_equal(msgdef3:field("field5"):subdef(), msgdef2)
end
+function test_symtab_add_extension()
+ -- Adding an extension at the same time as the extendee.
+ local symtab = upb.SymbolTable{
+ upb.MessageDef{full_name = "M1"},
+ upb.FieldDef{name = "extension1", is_extension = true, number = 1,
+ type = upb.TYPE_INT32, containing_type_name = "M1"}
+ }
+
+ local m1 = symtab:lookup("M1")
+ assert_not_nil(m1)
+ assert_equal(1, #m1)
+
+ local f1 = m1:field("extension1")
+ assert_not_nil(f1)
+ assert_true(f1:is_extension())
+ assert_true(f1:is_frozen())
+ assert_equal(1, f1:number())
+
+ -- Adding an extension to an existing extendee.
+ symtab:add{
+ upb.FieldDef{name = "extension2", is_extension = true, number = 2,
+ type = upb.TYPE_INT32, containing_type_name = "M1"}
+ }
+
+ local m1_2 = symtab:lookup("M1")
+ assert_not_nil(m1_2)
+ assert_true(m1 ~= m1_2)
+ assert_equal(2, #m1_2)
+
+ local f2 = m1_2:field("extension2")
+ assert_not_nil(f2)
+ assert_true(f2:is_extension())
+ assert_true(f2:is_frozen())
+ assert_equal(2, f2:number())
+end
+
-- Lua 5.1 and 5.2 have slightly different semantics for how a finalizer
-- can be defined in Lua.
if _VERSION >= 'Lua 5.2' then
@@ -260,4 +296,8 @@ function test_finalizer()
collectgarbage()
end
-lunit.main()
+local stats = lunit.main()
+
+if stats.failed > 0 or stats.errors > 0 then
+ error("One or more errors in test suite")
+end
diff --git a/tests/test_decoder.cc b/tests/pb/test_decoder.cc
index f1ee510..eb95580 100644
--- a/tests/test_decoder.cc
+++ b/tests/pb/test_decoder.cc
@@ -35,12 +35,13 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+
+#include "tests/upb_test.h"
+#include "third_party/upb/tests/pb/test_decoder_schema.upb.h"
#include "upb/handlers.h"
#include "upb/pb/decoder.h"
#include "upb/pb/varint.int.h"
-#include "upb_test.h"
#include "upb/upb.h"
-#include "third_party/upb/tests/test_decoder_schema.upb.h"
#undef PRINT_FAILURE
#define PRINT_FAILURE(expr) \
@@ -59,6 +60,7 @@ double completed;
double total;
double *count;
bool count_only;
+upb::BufferHandle global_handle;
// Copied from decoder.c, since this is not a public interface.
typedef struct {
@@ -235,9 +237,10 @@ int* startstr(int* depth, const uint32_t* num, size_t size_hint) {
}
size_t value_string(int* depth, const uint32_t* num, const char* buf,
- size_t n) {
+ size_t n, const upb::BufferHandle* handle) {
UPB_UNUSED(num);
output.append(buf, n);
+ ASSERT(handle == &global_handle);
return n;
}
@@ -407,7 +410,7 @@ bool parse(upb::BytesSink* s, void* subc, const char* buf, size_t start,
start = UPB_MAX(start, *ofs);
if (start <= end) {
size_t len = end - start;
- size_t parsed = s->PutBuffer(subc, buf + start, len);
+ size_t parsed = s->PutBuffer(subc, buf + start, len, &global_handle);
if (status->ok() != (parsed >= len)) {
fprintf(stderr, "Status: %s, parsed=%zu, len=%zu\n",
status->error_message(), parsed, len);
diff --git a/tests/test_decoder_schema.proto b/tests/pb/test_decoder_schema.proto
index 50bfca9..50bfca9 100644
--- a/tests/test_decoder_schema.proto
+++ b/tests/pb/test_decoder_schema.proto
diff --git a/tests/test_varint.c b/tests/pb/test_varint.c
index fc7eb40..84ff831 100644
--- a/tests/test_varint.c
+++ b/tests/pb/test_varint.c
@@ -6,7 +6,7 @@
#include <stdio.h>
#include "upb/pb/varint.int.h"
-#include "upb_test.h"
+#include "tests/upb_test.h"
// Test that we can round-trip from int->varint->int.
static void test_varint_for_num(upb_decoderet (*decoder)(const char*),
diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc
index 8d06135..c4313e1 100644
--- a/tests/test_cpp.cc
+++ b/tests/test_cpp.cc
@@ -12,7 +12,10 @@
#include <iostream>
#include <set>
+
+#ifdef UPB_CXX11
#include <type_traits>
+#endif
#include "upb/def.h"
#include "upb/descriptor/reader.h"
@@ -231,9 +234,10 @@ class StringBufTesterBase {
upb::Sink sub;
sink->StartMessage();
sink->StartString(start, 0, &sub);
- sub.PutStringBuffer(str, NULL, 5);
+ size_t ret = sub.PutStringBuffer(str, &buf_, 5, &handle_);
ASSERT(seen_);
ASSERT(len_ == 5);
+ ASSERT(ret == 5);
ASSERT(handler_data_val_ == kExpectedHandlerData);
}
@@ -241,115 +245,139 @@ class StringBufTesterBase {
bool seen_;
int handler_data_val_;
size_t len_;
+ char buf_;
+ upb::BufferHandle handle_;
};
-// Test all 8 combinations of:
-// (handler data?) x (function/method) x (returns {void, size_t})
+// Test 8 combinations of:
+// (handler data?) x (buffer handle?) x (function/method)
+//
+// Then we add one test each for this variation: to prevent combinatorial
+// explosion of these tests we don't test the full 16 combinations, but
+// rely on our knowledge that the implementation processes the return wrapping
+// in a second separate and independent stage:
+//
+// (function/method)
-class StringBufTesterVoidFunctionNoHandlerData : public StringBufTesterBase {
+class StringBufTesterVoidMethodNoHandlerDataNoHandle
+ : public StringBufTesterBase {
public:
- typedef StringBufTesterVoidFunctionNoHandlerData ME;
+ typedef StringBufTesterVoidMethodNoHandlerDataNoHandle ME;
void Register(upb::Handlers* h, const upb::FieldDef* f) {
UPB_UNUSED(f);
- ASSERT(h->SetStringHandler(f, UpbMakeHandler(&Handler)));
+ ASSERT(h->SetStringHandler(f, UpbMakeHandler(&ME::Handler)));
handler_data_val_ = kExpectedHandlerData;
}
private:
- static void Handler(ME* t, const char *buf, size_t len) {
- t->seen_ = true;
- t->len_ = len;
+ void Handler(const char *buf, size_t len) {
+ ASSERT(buf == &buf_);
+ seen_ = true;
+ len_ = len;
}
};
-class StringBufTesterSizeTFunctionNoHandlerData : public StringBufTesterBase {
+class StringBufTesterVoidMethodNoHandlerDataWithHandle
+ : public StringBufTesterBase {
public:
- typedef StringBufTesterSizeTFunctionNoHandlerData ME;
+ typedef StringBufTesterVoidMethodNoHandlerDataWithHandle ME;
void Register(upb::Handlers* h, const upb::FieldDef* f) {
UPB_UNUSED(f);
- ASSERT(h->SetStringHandler(f, UpbMakeHandler(&Handler)));
+ ASSERT(h->SetStringHandler(f, UpbMakeHandler(&ME::Handler)));
handler_data_val_ = kExpectedHandlerData;
}
private:
- static size_t Handler(ME* t, const char *buf, size_t len) {
- t->seen_ = true;
- t->len_ = len;
- return len;
+ void Handler(const char *buf, size_t len, const upb::BufferHandle* handle) {
+ ASSERT(buf == &buf_);
+ ASSERT(handle == &handle_);
+ seen_ = true;
+ len_ = len;
}
};
-class StringBufTesterVoidMethodNoHandlerData : public StringBufTesterBase {
+class StringBufTesterVoidMethodWithHandlerDataNoHandle
+ : public StringBufTesterBase {
public:
- typedef StringBufTesterVoidMethodNoHandlerData ME;
+ typedef StringBufTesterVoidMethodWithHandlerDataNoHandle ME;
void Register(upb::Handlers* h, const upb::FieldDef* f) {
UPB_UNUSED(f);
- ASSERT(h->SetStringHandler(f, UpbMakeHandler(&ME::Handler)));
- handler_data_val_ = kExpectedHandlerData;
+ ASSERT(h->SetStringHandler(
+ f, UpbBind(&ME::Handler, new int(kExpectedHandlerData))));
}
private:
- void Handler(const char *buf, size_t len) {
+ void Handler(const int* hd, const char *buf, size_t len) {
+ ASSERT(buf == &buf_);
+ handler_data_val_ = *hd;
seen_ = true;
len_ = len;
}
};
-class StringBufTesterSizeTMethodNoHandlerData : public StringBufTesterBase {
+class StringBufTesterVoidMethodWithHandlerDataWithHandle
+ : public StringBufTesterBase {
public:
- typedef StringBufTesterSizeTMethodNoHandlerData ME;
+ typedef StringBufTesterVoidMethodWithHandlerDataWithHandle ME;
void Register(upb::Handlers* h, const upb::FieldDef* f) {
UPB_UNUSED(f);
- ASSERT(h->SetStringHandler(f, UpbMakeHandler(&ME::Handler)));
- handler_data_val_ = kExpectedHandlerData;
+ ASSERT(h->SetStringHandler(
+ f, UpbBind(&ME::Handler, new int(kExpectedHandlerData))));
}
private:
- size_t Handler(const char *buf, size_t len) {
+ void Handler(const int* hd, const char* buf, size_t len,
+ const upb::BufferHandle* handle) {
+ ASSERT(buf == &buf_);
+ ASSERT(handle == &handle_);
+ handler_data_val_ = *hd;
seen_ = true;
len_ = len;
- return len;
}
};
-class StringBufTesterVoidFunctionWithHandlerData : public StringBufTesterBase {
+class StringBufTesterVoidFunctionNoHandlerDataNoHandle
+ : public StringBufTesterBase {
public:
- typedef StringBufTesterVoidFunctionWithHandlerData ME;
+ typedef StringBufTesterVoidFunctionNoHandlerDataNoHandle ME;
void Register(upb::Handlers* h, const upb::FieldDef* f) {
UPB_UNUSED(f);
- ASSERT(h->SetStringHandler(
- f, UpbBind(&Handler, new int(kExpectedHandlerData))));
+ ASSERT(h->SetStringHandler(f, UpbMakeHandler(&ME::Handler)));
+ handler_data_val_ = kExpectedHandlerData;
}
private:
- static void Handler(ME* t, const int* hd, const char *buf, size_t len) {
- t->handler_data_val_ = *hd;
+ static void Handler(ME* t, const char *buf, size_t len) {
+ ASSERT(buf == &t->buf_);
t->seen_ = true;
t->len_ = len;
}
};
-class StringBufTesterSizeTFunctionWithHandlerData : public StringBufTesterBase {
+class StringBufTesterVoidFunctionNoHandlerDataWithHandle
+ : public StringBufTesterBase {
public:
- typedef StringBufTesterSizeTFunctionWithHandlerData ME;
+ typedef StringBufTesterVoidFunctionNoHandlerDataWithHandle ME;
void Register(upb::Handlers* h, const upb::FieldDef* f) {
UPB_UNUSED(f);
- ASSERT(h->SetStringHandler(
- f, UpbBind(&Handler, new int(kExpectedHandlerData))));
+ ASSERT(h->SetStringHandler(f, UpbMakeHandler(&ME::Handler)));
+ handler_data_val_ = kExpectedHandlerData;
}
private:
- static size_t Handler(ME* t, const int* hd, const char *buf, size_t len) {
- t->handler_data_val_ = *hd;
+ static void Handler(ME* t, const char* buf, size_t len,
+ const upb::BufferHandle* handle) {
+ ASSERT(buf == &t->buf_);
+ ASSERT(handle == &t->handle_);
t->seen_ = true;
t->len_ = len;
- return len;
}
};
-class StringBufTesterVoidMethodWithHandlerData : public StringBufTesterBase {
+class StringBufTesterVoidFunctionWithHandlerDataNoHandle
+ : public StringBufTesterBase {
public:
- typedef StringBufTesterVoidMethodWithHandlerData ME;
+ typedef StringBufTesterVoidFunctionWithHandlerDataNoHandle ME;
void Register(upb::Handlers* h, const upb::FieldDef* f) {
UPB_UNUSED(f);
ASSERT(h->SetStringHandler(
@@ -357,16 +385,18 @@ class StringBufTesterVoidMethodWithHandlerData : public StringBufTesterBase {
}
private:
- void Handler(const int* hd, const char *buf, size_t len) {
- handler_data_val_ = *hd;
- seen_ = true;
- len_ = len;
+ static void Handler(ME* t, const int* hd, const char *buf, size_t len) {
+ ASSERT(buf == &t->buf_);
+ t->handler_data_val_ = *hd;
+ t->seen_ = true;
+ t->len_ = len;
}
};
-class StringBufTesterSizeTMethodWithHandlerData : public StringBufTesterBase {
+class StringBufTesterVoidFunctionWithHandlerDataWithHandle
+ : public StringBufTesterBase {
public:
- typedef StringBufTesterSizeTMethodWithHandlerData ME;
+ typedef StringBufTesterVoidFunctionWithHandlerDataWithHandle ME;
void Register(upb::Handlers* h, const upb::FieldDef* f) {
UPB_UNUSED(f);
ASSERT(h->SetStringHandler(
@@ -374,8 +404,29 @@ class StringBufTesterSizeTMethodWithHandlerData : public StringBufTesterBase {
}
private:
- size_t Handler(const int* hd, const char *buf, size_t len) {
- handler_data_val_ = *hd;
+ static void Handler(ME* t, const int* hd, const char* buf, size_t len,
+ const upb::BufferHandle* handle) {
+ ASSERT(buf == &t->buf_);
+ ASSERT(handle == &t->handle_);
+ t->handler_data_val_ = *hd;
+ t->seen_ = true;
+ t->len_ = len;
+ }
+};
+
+class StringBufTesterSizeTMethodNoHandlerDataNoHandle
+ : public StringBufTesterBase {
+ public:
+ typedef StringBufTesterSizeTMethodNoHandlerDataNoHandle ME;
+ void Register(upb::Handlers* h, const upb::FieldDef* f) {
+ UPB_UNUSED(f);
+ ASSERT(h->SetStringHandler(f, UpbMakeHandler(&ME::Handler)));
+ handler_data_val_ = kExpectedHandlerData;
+ }
+
+ private:
+ size_t Handler(const char *buf, size_t len) {
+ ASSERT(buf == &buf_);
seen_ = true;
len_ = len;
return len;
@@ -712,6 +763,284 @@ void TestHandler() {
tester.CallAndVerify(&sink, f.get());
}
+class T1 {};
+class T2 {};
+
+template <class C>
+void DoNothingHandler(C* closure) {
+ UPB_UNUSED(closure);
+}
+
+template <class C>
+void DoNothingInt32Handler(C* closure, int32_t val) {
+ UPB_UNUSED(closure);
+ UPB_UNUSED(val);
+}
+
+template <class R, class C>
+R* DoNothingStartHandler(C* closure) {
+ UPB_UNUSED(closure);
+ return NULL;
+}
+
+template <class R, class C>
+R* DoNothingStartStringHandler(C* closure, size_t size_len) {
+ UPB_UNUSED(closure);
+ UPB_UNUSED(size_len);
+ return NULL;
+}
+
+template <class C>
+void DoNothingStringBufHandler(C* closure, const char *buf, size_t len) {
+ UPB_UNUSED(closure);
+ UPB_UNUSED(buf);
+ UPB_UNUSED(len);
+}
+
+template <class C>
+void DoNothingEndMessageHandler(C* closure, upb::Status *status) {
+ UPB_UNUSED(closure);
+ UPB_UNUSED(status);
+}
+
+void TestMismatchedTypes() {
+ // First create a schema for our test.
+ upb::reffed_ptr<upb::MessageDef> md(upb::MessageDef::New());
+
+ upb::reffed_ptr<upb::FieldDef> f(upb::FieldDef::New());
+ f->set_type(UPB_TYPE_INT32);
+ ASSERT(f->set_name("i32", NULL));
+ ASSERT(f->set_number(1, NULL));
+ ASSERT(md->AddField(f, NULL));
+ const upb::FieldDef* i32 = f.get();
+
+ f = upb::FieldDef::New();
+ f->set_type(UPB_TYPE_INT32);
+ ASSERT(f->set_name("r_i32", NULL));
+ ASSERT(f->set_number(2, NULL));
+ f->set_label(UPB_LABEL_REPEATED);
+ ASSERT(md->AddField(f, NULL));
+ const upb::FieldDef* r_i32 = f.get();
+
+ f = upb::FieldDef::New();
+ f->set_type(UPB_TYPE_STRING);
+ ASSERT(f->set_name("str", NULL));
+ ASSERT(f->set_number(3, NULL));
+ ASSERT(md->AddField(f, NULL));
+ const upb::FieldDef* str = f.get();
+
+ f = upb::FieldDef::New();
+ f->set_type(UPB_TYPE_STRING);
+ ASSERT(f->set_name("r_str", NULL));
+ ASSERT(f->set_number(4, NULL));
+ f->set_label(UPB_LABEL_REPEATED);
+ ASSERT(md->AddField(f, NULL));
+ const upb::FieldDef* r_str = f.get();
+
+ f = upb::FieldDef::New();
+ f->set_type(UPB_TYPE_MESSAGE);
+ ASSERT(f->set_name("msg", NULL));
+ ASSERT(f->set_number(5, NULL));
+ ASSERT(f->set_message_subdef(md.get(), NULL));
+ ASSERT(md->AddField(f, NULL));
+ const upb::FieldDef* msg = f.get();
+
+ f = upb::FieldDef::New();
+ f->set_type(UPB_TYPE_MESSAGE);
+ ASSERT(f->set_name("r_msg", NULL));
+ ASSERT(f->set_number(6, NULL));
+ ASSERT(f->set_message_subdef(md.get(), NULL));
+ f->set_label(UPB_LABEL_REPEATED);
+ ASSERT(md->AddField(f, NULL));
+ const upb::FieldDef* r_msg = f.get();
+
+ ASSERT(md->Freeze(NULL));
+
+ // Now test the type-checking in handler registration.
+ upb::reffed_ptr<upb::Handlers> h(upb::Handlers::New(md.get()));
+
+ // Establish T1 as the top-level closure type.
+ ASSERT(h->SetInt32Handler(i32, UpbMakeHandler(DoNothingInt32Handler<T1>)));
+
+ // Now any other attempt to set another handler with T2 as the top-level
+ // closure should fail. But setting these same handlers with T1 as the
+ // top-level closure will succeed.
+ ASSERT(!h->SetStartMessageHandler(UpbMakeHandler(DoNothingHandler<T2>)));
+ ASSERT(h->SetStartMessageHandler(UpbMakeHandler(DoNothingHandler<T1>)));
+
+ ASSERT(
+ !h->SetEndMessageHandler(UpbMakeHandler(DoNothingEndMessageHandler<T2>)));
+ ASSERT(
+ h->SetEndMessageHandler(UpbMakeHandler(DoNothingEndMessageHandler<T1>)));
+
+ ASSERT(!h->SetStartStringHandler(
+ str, UpbMakeHandler((DoNothingStartStringHandler<T1, T2>))));
+ ASSERT(h->SetStartStringHandler(
+ str, UpbMakeHandler((DoNothingStartStringHandler<T1, T1>))));
+
+ ASSERT(!h->SetEndStringHandler(str, UpbMakeHandler((DoNothingHandler<T2>))));
+ ASSERT(h->SetEndStringHandler(str, UpbMakeHandler((DoNothingHandler<T1>))));
+
+ ASSERT(!h->SetStartSubMessageHandler(
+ msg, UpbMakeHandler((DoNothingStartHandler<T1, T2>))));
+ ASSERT(h->SetStartSubMessageHandler(
+ msg, UpbMakeHandler((DoNothingStartHandler<T1, T1>))));
+
+ ASSERT(
+ !h->SetEndSubMessageHandler(msg, UpbMakeHandler((DoNothingHandler<T2>))));
+ ASSERT(
+ h->SetEndSubMessageHandler(msg, UpbMakeHandler((DoNothingHandler<T1>))));
+
+ ASSERT(!h->SetStartSequenceHandler(
+ r_i32, UpbMakeHandler((DoNothingStartHandler<T1, T2>))));
+ ASSERT(h->SetStartSequenceHandler(
+ r_i32, UpbMakeHandler((DoNothingStartHandler<T1, T1>))));
+
+ ASSERT(!h->SetEndSequenceHandler(
+ r_i32, UpbMakeHandler((DoNothingHandler<T2>))));
+ ASSERT(h->SetEndSequenceHandler(
+ r_i32, UpbMakeHandler((DoNothingHandler<T1>))));
+
+ ASSERT(!h->SetStartSequenceHandler(
+ r_msg, UpbMakeHandler((DoNothingStartHandler<T1, T2>))));
+ ASSERT(h->SetStartSequenceHandler(
+ r_msg, UpbMakeHandler((DoNothingStartHandler<T1, T1>))));
+
+ ASSERT(!h->SetEndSequenceHandler(
+ r_msg, UpbMakeHandler((DoNothingHandler<T2>))));
+ ASSERT(h->SetEndSequenceHandler(
+ r_msg, UpbMakeHandler((DoNothingHandler<T1>))));
+
+ ASSERT(!h->SetStartSequenceHandler(
+ r_str, UpbMakeHandler((DoNothingStartHandler<T1, T2>))));
+ ASSERT(h->SetStartSequenceHandler(
+ r_str, UpbMakeHandler((DoNothingStartHandler<T1, T1>))));
+
+ ASSERT(!h->SetEndSequenceHandler(
+ r_str, UpbMakeHandler((DoNothingHandler<T2>))));
+ ASSERT(h->SetEndSequenceHandler(
+ r_str, UpbMakeHandler((DoNothingHandler<T1>))));
+
+ // By setting T1 as the return type for the Start* handlers we have
+ // established T1 as the type of the sequence and string frames.
+ // Setting callbacks that use T2 should fail, but T1 should succeed.
+ ASSERT(
+ !h->SetStringHandler(str, UpbMakeHandler(DoNothingStringBufHandler<T2>)));
+ ASSERT(
+ h->SetStringHandler(str, UpbMakeHandler(DoNothingStringBufHandler<T1>)));
+
+ ASSERT(!h->SetInt32Handler(r_i32, UpbMakeHandler(DoNothingInt32Handler<T2>)));
+ ASSERT(h->SetInt32Handler(r_i32, UpbMakeHandler(DoNothingInt32Handler<T1>)));
+
+ ASSERT(!h->SetStartSubMessageHandler(
+ r_msg, UpbMakeHandler((DoNothingStartHandler<T1, T2>))));
+ ASSERT(h->SetStartSubMessageHandler(
+ r_msg, UpbMakeHandler((DoNothingStartHandler<T1, T1>))));
+
+ ASSERT(!h->SetEndSubMessageHandler(r_msg,
+ UpbMakeHandler((DoNothingHandler<T2>))));
+ ASSERT(h->SetEndSubMessageHandler(r_msg,
+ UpbMakeHandler((DoNothingHandler<T1>))));
+
+ ASSERT(!h->SetStartStringHandler(
+ r_str, UpbMakeHandler((DoNothingStartStringHandler<T1, T2>))));
+ ASSERT(h->SetStartStringHandler(
+ r_str, UpbMakeHandler((DoNothingStartStringHandler<T1, T1>))));
+
+ ASSERT(
+ !h->SetEndStringHandler(r_str, UpbMakeHandler((DoNothingHandler<T2>))));
+ ASSERT(h->SetEndStringHandler(r_str, UpbMakeHandler((DoNothingHandler<T1>))));
+
+ ASSERT(!h->SetStringHandler(r_str,
+ UpbMakeHandler(DoNothingStringBufHandler<T2>)));
+ ASSERT(h->SetStringHandler(r_str,
+ UpbMakeHandler(DoNothingStringBufHandler<T1>)));
+
+ h->ClearError();
+ ASSERT(h->Freeze(NULL));
+
+ // For our second test we do the same in reverse. We directly set the type of
+ // the frame and then observe failures at registering a Start* handler that
+ // returns a different type.
+ h = upb::Handlers::New(md.get());
+
+ // First establish the type of a sequence frame directly.
+ ASSERT(h->SetInt32Handler(r_i32, UpbMakeHandler(DoNothingInt32Handler<T1>)));
+
+ // Now setting a StartSequence callback that returns a different type should
+ // fail.
+ ASSERT(!h->SetStartSequenceHandler(
+ r_i32, UpbMakeHandler((DoNothingStartHandler<T2, T1>))));
+ ASSERT(h->SetStartSequenceHandler(
+ r_i32, UpbMakeHandler((DoNothingStartHandler<T1, T1>))));
+
+ // Establish a string frame directly.
+ ASSERT(h->SetStringHandler(r_str,
+ UpbMakeHandler(DoNothingStringBufHandler<T1>)));
+
+ // Fail setting a StartString callback that returns a different type.
+ ASSERT(!h->SetStartStringHandler(
+ r_str, UpbMakeHandler((DoNothingStartStringHandler<T2, T1>))));
+ ASSERT(h->SetStartStringHandler(
+ r_str, UpbMakeHandler((DoNothingStartStringHandler<T1, T1>))));
+
+ // The previous established T1 as the frame for the r_str sequence.
+ ASSERT(!h->SetStartSequenceHandler(
+ r_str, UpbMakeHandler((DoNothingStartHandler<T2, T1>))));
+ ASSERT(h->SetStartSequenceHandler(
+ r_str, UpbMakeHandler((DoNothingStartHandler<T1, T1>))));
+
+ // Now test for this error that is not caught until freeze time:
+ // Change-of-closure-type implies that a StartSequence or StartString handler
+ // should exist to return the closure type of the inner frame but no
+ // StartSequence/StartString handler is registered.
+
+ h = upb::Handlers::New(md.get());
+
+ // Establish T1 as top-level closure type.
+ ASSERT(h->SetInt32Handler(i32, UpbMakeHandler(DoNothingInt32Handler<T1>)));
+
+ // Establish T2 as closure type of sequence frame.
+ ASSERT(
+ h->SetInt32Handler(r_i32, UpbMakeHandler((DoNothingInt32Handler<T2>))));
+
+ // Now attempt to freeze; this should fail because a StartSequence handler
+ // needs to be registered that takes a T1 and returns a T2.
+ ASSERT(!h->Freeze(NULL));
+
+ // Now if we register the necessary StartSequence handler, the freezing should
+ // work.
+ ASSERT(h->SetStartSequenceHandler(
+ r_i32, UpbMakeHandler((DoNothingStartHandler<T2, T1>))));
+ h->ClearError();
+ ASSERT(h->Freeze(NULL));
+
+ // Test for a broken chain that is two deep.
+ h = upb::Handlers::New(md.get());
+
+ // Establish T1 as top-level closure type.
+ ASSERT(h->SetInt32Handler(i32, UpbMakeHandler(DoNothingInt32Handler<T1>)));
+
+ // Establish T2 as the closure type of the string frame inside a sequence
+ // frame.
+ ASSERT(h->SetStringHandler(r_str,
+ UpbMakeHandler(DoNothingStringBufHandler<T2>)));
+
+ // Now attempt to freeze; this should fail because a StartSequence or
+ // StartString handler needs to be registered that takes a T1 and returns a
+ // T2.
+ ASSERT(!h->Freeze(NULL));
+
+ // Now if we register a StartSequence handler it succeeds.
+ ASSERT(h->SetStartSequenceHandler(
+ r_str, UpbMakeHandler((DoNothingStartHandler<T2, T1>))));
+ h->ClearError();
+ ASSERT(h->Freeze(NULL));
+
+ // TODO(haberman): test that closure returned by StartSubMessage does not
+ // match top-level closure of sub-handlers.
+}
+
extern "C" {
int run_tests(int argc, char *argv[]) {
@@ -753,14 +1082,17 @@ int run_tests(int argc, char *argv[]) {
TestHandler<StartMsgTesterVoidMethodWithHandlerData>();
TestHandler<StartMsgTesterBoolMethodWithHandlerData>();
- TestHandler<StringBufTesterVoidFunctionNoHandlerData>();
- TestHandler<StringBufTesterSizeTFunctionNoHandlerData>();
- TestHandler<StringBufTesterVoidMethodNoHandlerData>();
- TestHandler<StringBufTesterSizeTMethodNoHandlerData>();
- TestHandler<StringBufTesterVoidFunctionWithHandlerData>();
- TestHandler<StringBufTesterSizeTFunctionWithHandlerData>();
- TestHandler<StringBufTesterVoidMethodWithHandlerData>();
- TestHandler<StringBufTesterSizeTMethodWithHandlerData>();
+ TestHandler<StringBufTesterVoidMethodNoHandlerDataNoHandle>();
+ TestHandler<StringBufTesterVoidMethodNoHandlerDataWithHandle>();
+ TestHandler<StringBufTesterVoidMethodWithHandlerDataNoHandle>();
+ TestHandler<StringBufTesterVoidMethodWithHandlerDataWithHandle>();
+ TestHandler<StringBufTesterVoidFunctionNoHandlerDataNoHandle>();
+ TestHandler<StringBufTesterVoidFunctionNoHandlerDataWithHandle>();
+ TestHandler<StringBufTesterVoidFunctionWithHandlerDataNoHandle>();
+ TestHandler<StringBufTesterVoidFunctionWithHandlerDataWithHandle>();
+ TestHandler<StringBufTesterSizeTMethodNoHandlerDataNoHandle>();
+
+ TestMismatchedTypes();
#ifdef UPB_CXX11
#define ASSERT_STD_LAYOUT(type) \
diff --git a/tests/test_def.c b/tests/test_def.c
index fb33871..bf45a73 100644
--- a/tests/test_def.c
+++ b/tests/test_def.c
@@ -93,10 +93,10 @@ static void test_fielddef_accessors() {
ASSERT(!upb_fielddef_isfrozen(f2));
ASSERT(upb_fielddef_setname(f2, "f2", NULL));
- ASSERT(upb_fielddef_setnumber(f2, 1572, NULL));
+ ASSERT(upb_fielddef_setnumber(f2, 123456789, NULL));
upb_fielddef_settype(f2, UPB_TYPE_BYTES);
upb_fielddef_setlabel(f2, UPB_LABEL_REPEATED);
- ASSERT(upb_fielddef_number(f2) == 1572);
+ ASSERT(upb_fielddef_number(f2) == 123456789);
upb_fielddef_unref(f1, &f1);
upb_fielddef_unref(f2, &f2);
diff --git a/tests/test_vs_proto2.cc b/tests/test_vs_proto2.cc
index 07946dd..22683c3 100644
--- a/tests/test_vs_proto2.cc
+++ b/tests/test_vs_proto2.cc
@@ -19,8 +19,8 @@
#include <stdio.h>
#include <stdlib.h>
#include "benchmarks/google_messages.pb.h"
+#include "upb/bindings/googlepb/bridge.h"
#include "upb/def.h"
-#include "upb/google/bridge.h"
#include "upb/handlers.h"
#include "upb/pb/decoder.h"
#include "upb/pb/glue.h"
@@ -125,7 +125,7 @@ int run_tests(int argc, char *argv[])
MESSAGE_CIDENT msg1;
MESSAGE_CIDENT msg2;
- upb::reffed_ptr<const upb::Handlers> h(upb::google::NewWriteHandlers(msg1));
+ upb::reffed_ptr<const upb::Handlers> h(upb::googlepb::NewWriteHandlers(msg1));
compare_metadata(msg1.GetDescriptor(), h->message_def());
@@ -142,7 +142,7 @@ int run_tests(int argc, char *argv[])
factory->GetPrototype(msg1.descriptor());
google::protobuf::Message* dyn_msg1 = prototype->New();
google::protobuf::Message* dyn_msg2 = prototype->New();
- h = upb::google::NewWriteHandlers(*dyn_msg1);
+ h = upb::googlepb::NewWriteHandlers(*dyn_msg1);
parse_and_compare(dyn_msg1, dyn_msg2, h.get(), str, len, false);
parse_and_compare(dyn_msg1, dyn_msg2, h.get(), str, len, true);
delete dyn_msg1;
diff --git a/tools/dump_cinit.lua b/tools/dump_cinit.lua
index c83aa04..e23e907 100644
--- a/tools/dump_cinit.lua
+++ b/tools/dump_cinit.lua
@@ -359,13 +359,14 @@ local function dump_defs_c(symtab, basename, append)
else
intfmt = "0"
end
- -- UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, name, num, msgdef,
- -- subdef, selector_base, index, default_value)
- append(' UPB_FIELDDEF_INIT(%s, %s, %s, %s, "%s", %d, %s, %s, %d, %d, ' ..
- '{0},' .. -- TODO: support default value
+ -- UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, name,
+ -- num, msgdef, subdef, selector_base, index,
+ -- default_value)
+ append(' UPB_FIELDDEF_INIT(%s, %s, %s, %s, %s, "%s", %d, %s, %s, %d, ' ..
+ '%d, {0},' .. -- TODO: support default value
'&reftables[%d], &reftables[%d]),\n',
const(f, "label"), const(f, "type"), intfmt,
- boolstr(f:istagdelim()), f:name(),
+ boolstr(f:istagdelim()), boolstr(f:is_extension()), f:name(),
f:number(), linktab:addr(f:containing_type()), subdef,
f:_selector_base(), f:index(),
reftable, reftable + 1
diff --git a/tools/test_cinit.lua b/tools/test_cinit.lua
index 72d8826..3ed77b5 100644
--- a/tools/test_cinit.lua
+++ b/tools/test_cinit.lua
@@ -43,7 +43,7 @@ if arg[1] == "generate" then
local appendh = dump_cinit.file_appender(f_h)
f:write('#include "lua.h"\n')
f:write('#define ELEMENTS(array) (sizeof(array)/sizeof(*array))\n')
- f:write('#include "bindings/lua/upb.h"\n')
+ f:write('#include "upb/bindings/lua/upb.h"\n')
dump_cinit.dump_defs(symtab, "test", appendh, appendc)
f:write([[int luaopen_staticdefs(lua_State *L) {
lua_newtable(L);
diff --git a/upb/bindings/README b/upb/bindings/README
new file mode 100644
index 0000000..e4bf0b8
--- /dev/null
+++ b/upb/bindings/README
@@ -0,0 +1,25 @@
+This directory contains code that interfaces upb with external C/C++
+libraries. For example:
+
+ * upb/bindings/{stdc,stdc++}
+ interfaces between upb and the standard libraries of C and C++ (like C's
+ FILE/stdio, C++'s string/iostream, etc.)
+
+ * upb/bindings/googlepb
+ interfaces between upb and the "protobuf" library distributed by Google.
+
+ * upb/bindings/lua:
+ a Lua extension that exposes upb to Lua programs via the Lua C API.
+
+ * upb/bindings/linux:
+ code and build system for building upb as a Linux kernel module.
+
+The two key characteristics that decide whether code belongs in upb/bindings/
+are:
+
+ * Does the code's public API refer to types from another library?
+ If so it belongs in upb/bindings/. But this doesn't include code that just
+ happens to use another library internally, as an implementation detail.
+
+ * Would this code be useful to someone who is not using this external library
+ in some other way? If so, the code probably doesn't belong in upb/bindings/.
diff --git a/upb/bindings/googlepb/README b/upb/bindings/googlepb/README
new file mode 100644
index 0000000..e3140f4
--- /dev/null
+++ b/upb/bindings/googlepb/README
@@ -0,0 +1,20 @@
+This directory contains code to interoperate with Google's official
+Protocol Buffers release. Since it doesn't really have a name
+besides "protobuf," calling this directory "googlepb" seems like the
+least confusing option, since it lives in the google::protobuf
+namespace.
+
+We support writing into protobuf's generated classes (and hopefully
+reading too, before long). We support both the open source protobuf
+release and the Google-internal version (which is mostly the same
+code, just in a different namespace). A single compile of upb can
+support both (there are no conflicts thanks to function overloading).
+
+The internal version supports some features that are not supported in
+the open-source release. Also, the internal version includes the
+legacy "proto1" classes which we must support; thankfully this is
+mostly relegated to its own separate file.
+
+Our functionality requires the full google::protobuf::Message
+interface; we rely on reflection so we know what fields to read/write
+and where to put them, so we can't support MessageLite.
diff --git a/upb/google/bridge.cc b/upb/bindings/googlepb/bridge.cc
index bb5c631..a125249 100644
--- a/upb/google/bridge.cc
+++ b/upb/bindings/googlepb/bridge.cc
@@ -10,14 +10,14 @@
// without the two conflicting. However we must be careful not to violate the
// ODR.
-#include "upb/google/bridge.h"
+#include "upb/bindings/googlepb/bridge.h"
#include <stdio.h>
#include <map>
#include <string>
#include "upb/def.h"
-#include "upb/google/proto1.h"
-#include "upb/google/proto2.h"
+#include "upb/bindings/googlepb/proto1.h"
+#include "upb/bindings/googlepb/proto2.h"
#include "upb/handlers.h"
#define ASSERT_STATUS(status) do { \
@@ -62,12 +62,12 @@ const goog::Message* GetPrototype(const goog::Message& m,
} // namespace
namespace upb {
-namespace google {
+namespace googlepb {
/* DefBuilder ****************************************************************/
-const EnumDef* DefBuilder::GetOrCreateEnumDef(const goog::EnumDescriptor* ed) {
+const EnumDef* DefBuilder::GetEnumDef(const goog::EnumDescriptor* ed) {
const EnumDef* cached = FindInCache<EnumDef>(ed);
if (cached) return cached;
@@ -87,7 +87,7 @@ const EnumDef* DefBuilder::GetOrCreateEnumDef(const goog::EnumDescriptor* ed) {
return e;
}
-const MessageDef* DefBuilder::GetOrCreateMaybeUnfrozenMessageDef(
+const MessageDef* DefBuilder::GetMaybeUnfrozenMessageDef(
const goog::Descriptor* d, const goog::Message* m) {
const MessageDef* cached = FindInCache<MessageDef>(d);
if (cached) return cached;
@@ -134,9 +134,15 @@ reffed_ptr<FieldDef> DefBuilder::NewFieldDef(const goog::FieldDescriptor* f,
reffed_ptr<FieldDef> upb_f(FieldDef::New());
Status status;
upb_f->set_number(f->number(), &status);
- upb_f->set_name(f->name(), &status);
upb_f->set_label(FieldDef::ConvertLabel(f->label()));
+ if (f->is_extension()) {
+ upb_f->set_name(f->full_name(), &status);
+ upb_f->set_is_extension(true);
+ } else {
+ 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
@@ -169,15 +175,17 @@ reffed_ptr<FieldDef> DefBuilder::NewFieldDef(const goog::FieldDescriptor* f,
case UPB_TYPE_BYTES:
upb_f->set_default_string(f->default_value_string(), &status);
break;
- case UPB_TYPE_MESSAGE:
- upb_f->set_message_subdef(
- GetOrCreateMaybeUnfrozenMessageDef(subm->GetDescriptor(), subm),
- &status);
+ case UPB_TYPE_MESSAGE: {
+ const goog::Descriptor* subd =
+ subm ? subm->GetDescriptor() : f->message_type();
+ upb_f->set_message_subdef(GetMaybeUnfrozenMessageDef(subd, subm),
+ &status);
break;
+ }
case UPB_TYPE_ENUM:
// We set the enum default numerically.
upb_f->set_default_int32(f->default_value_enum()->number());
- upb_f->set_enum_subdef(GetOrCreateEnumDef(f->enum_type()), &status);
+ upb_f->set_enum_subdef(GetEnumDef(f->enum_type()), &status);
break;
}
@@ -192,16 +200,15 @@ void DefBuilder::Freeze() {
to_freeze_.clear();
}
-const MessageDef* DefBuilder::GetOrCreateMessageDef(const goog::Descriptor* d) {
- const MessageDef* ret = GetOrCreateMaybeUnfrozenMessageDef(d, NULL);
+const MessageDef* DefBuilder::GetMessageDef(const goog::Descriptor* d) {
+ const MessageDef* ret = GetMaybeUnfrozenMessageDef(d, NULL);
Freeze();
return ret;
}
-const MessageDef* DefBuilder::GetOrCreateMessageDefExpandWeak(
+const MessageDef* DefBuilder::GetMessageDefExpandWeak(
const goog::Message& m) {
- const MessageDef* ret =
- GetOrCreateMaybeUnfrozenMessageDef(m.GetDescriptor(), &m);
+ const MessageDef* ret = GetMaybeUnfrozenMessageDef(m.GetDescriptor(), &m);
Freeze();
return ret;
}
@@ -209,7 +216,7 @@ const MessageDef* DefBuilder::GetOrCreateMessageDefExpandWeak(
/* CodeCache *****************************************************************/
-const Handlers* CodeCache::GetOrCreateMaybeUnfrozenWriteHandlers(
+const Handlers* CodeCache::GetMaybeUnfrozenWriteHandlers(
const MessageDef* md, const goog::Message& m) {
const Handlers* cached = FindInCache(md);
if (cached) return cached;
@@ -244,8 +251,8 @@ const Handlers* CodeCache::GetOrCreateMaybeUnfrozenWriteHandlers(
if (upb_f->type() == UPB_TYPE_MESSAGE) {
const goog::Message* prototype = GetPrototype(m, proto2_f);
assert(prototype);
- const upb::Handlers* sub_handlers = GetOrCreateMaybeUnfrozenWriteHandlers(
- upb_f->message_subdef(), *prototype);
+ const upb::Handlers* sub_handlers =
+ GetMaybeUnfrozenWriteHandlers(upb_f->message_subdef(), *prototype);
h->SetSubHandlers(upb_f, sub_handlers);
}
}
@@ -253,9 +260,9 @@ const Handlers* CodeCache::GetOrCreateMaybeUnfrozenWriteHandlers(
return h;
}
-const Handlers* CodeCache::GetOrCreateWriteHandlers(const goog::Message& m) {
- const MessageDef* md = def_builder_.GetOrCreateMessageDefExpandWeak(m);
- const Handlers* ret = GetOrCreateMaybeUnfrozenWriteHandlers(md, m);
+const Handlers* CodeCache::GetWriteHandlers(const goog::Message& m) {
+ const MessageDef* md = def_builder_.GetMessageDefExpandWeak(m);
+ const Handlers* ret = GetMaybeUnfrozenWriteHandlers(md, m);
upb::Status status;
upb::Handlers::Freeze(to_freeze_, &status);
ASSERT_STATUS(&status);
@@ -265,9 +272,8 @@ const Handlers* CodeCache::GetOrCreateWriteHandlers(const goog::Message& m) {
upb::reffed_ptr<const upb::Handlers> NewWriteHandlers(const goog::Message& m) {
CodeCache cache;
- return upb::reffed_ptr<const upb::Handlers>(
- cache.GetOrCreateWriteHandlers(m));
+ return upb::reffed_ptr<const upb::Handlers>(cache.GetWriteHandlers(m));
}
-} // namespace google
+} // namespace googlepb
} // namespace upb
diff --git a/upb/google/bridge.h b/upb/bindings/googlepb/bridge.h
index c8bdd47..9eed51b 100644
--- a/upb/google/bridge.h
+++ b/upb/bindings/googlepb/bridge.h
@@ -40,6 +40,7 @@
#include <map>
#include <vector>
+#include "upb/handlers.h"
#include "upb/upb.h"
namespace google {
@@ -60,13 +61,7 @@ class Message;
namespace upb {
-class Def;
-class EnumDef;
-class FieldDef;
-class MessageDef;
-class Handlers;
-
-namespace google {
+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
@@ -89,12 +84,10 @@ class DefBuilder {
// The DefBuilder will retain a ref so it can keep the Def cached, but
// garbage-collection functionality may be added to DefBuilder later that
// could unref the returned pointer.
- const EnumDef* GetOrCreateEnumDef(const proto2::EnumDescriptor* d);
- const EnumDef* GetOrCreateEnumDef(
- const ::google::protobuf::EnumDescriptor* d);
- const MessageDef* GetOrCreateMessageDef(const proto2::Descriptor* d);
- const MessageDef* GetOrCreateMessageDef(
- const ::google::protobuf::Descriptor* d);
+ const EnumDef* GetEnumDef(const proto2::EnumDescriptor* d);
+ const EnumDef* GetEnumDef(const ::google::protobuf::EnumDescriptor* d);
+ const MessageDef* GetMessageDef(const proto2::Descriptor* d);
+ const MessageDef* GetMessageDef(const ::google::protobuf::Descriptor* d);
// Gets or creates a frozen MessageDef, properly expanding weak fields.
//
@@ -102,20 +95,27 @@ class DefBuilder {
// you construct your descriptors in a somewhat complicated way; see
// https://goto.google.com/weak-field-descriptor), but we can get their true
// definitions relatively easily from the proto Message class.
- const MessageDef* GetOrCreateMessageDefExpandWeak(const proto2::Message& m);
- const MessageDef* GetOrCreateMessageDefExpandWeak(
+ const MessageDef* GetMessageDefExpandWeak(const proto2::Message& m);
+ const MessageDef* GetMessageDefExpandWeak(
const ::google::protobuf::Message& m);
+ // Static methods for converting a def without building a DefBuilder.
+ static reffed_ptr<const MessageDef> NewMessageDef(
+ const proto2::Descriptor* d) {
+ DefBuilder builder;
+ return reffed_ptr<const MessageDef>(builder.GetMessageDef(d));
+ }
+
private:
- // Like GetOrCreateMessageDef*(), except the returned def might not be frozen.
+ // Like GetMessageDef*(), except the returned def might not be frozen.
// We need this function because circular graphs of MessageDefs need to all
// be frozen together, to we have to create the graphs of defs in an unfrozen
// state first.
//
// If m is non-NULL, expands weak message fields.
- const MessageDef* GetOrCreateMaybeUnfrozenMessageDef(
- const proto2::Descriptor* d, const proto2::Message* m);
- const MessageDef* GetOrCreateMaybeUnfrozenMessageDef(
+ const MessageDef* GetMaybeUnfrozenMessageDef(const proto2::Descriptor* d,
+ const proto2::Message* m);
+ const MessageDef* GetMaybeUnfrozenMessageDef(
const ::google::protobuf::Descriptor* d,
const ::google::protobuf::Message* m);
@@ -156,7 +156,7 @@ class DefBuilder {
DefCache def_cache_;
// Defs that have not been frozen yet.
- vector<Def*> to_freeze_;
+ std::vector<Def*> to_freeze_;
};
// Builds and caches upb::Handlers for populating proto2 generated classes.
@@ -170,14 +170,13 @@ class CodeCache {
// The CodeCache will retain a ref so it can keep the Def cached, but
// garbage-collection functionality may be added to CodeCache later that could
// unref the returned pointer.
- const Handlers* GetOrCreateWriteHandlers(const proto2::Message& m);
- const Handlers* GetOrCreateWriteHandlers(
- const ::google::protobuf::Message& m);
+ const Handlers* GetWriteHandlers(const proto2::Message& m);
+ const Handlers* GetWriteHandlers(const ::google::protobuf::Message& m);
private:
- const Handlers* GetOrCreateMaybeUnfrozenWriteHandlers(
- const MessageDef* md, const proto2::Message& m);
- const Handlers* GetOrCreateMaybeUnfrozenWriteHandlers(
+ const Handlers* GetMaybeUnfrozenWriteHandlers(const MessageDef* md,
+ const proto2::Message& m);
+ const Handlers* GetMaybeUnfrozenWriteHandlers(
const MessageDef* md, const ::google::protobuf::Message& m);
Handlers* AddToCache(const MessageDef* md, reffed_ptr<Handlers> handlers) {
@@ -197,10 +196,10 @@ class CodeCache {
HandlersCache;
HandlersCache handlers_cache_;
- vector<Handlers*> to_freeze_;
+ std::vector<Handlers*> to_freeze_;
};
-} // namespace google
+} // namespace googlepb
} // namespace upb
#endif // UPB_GOOGLE_BRIDGE_H_
diff --git a/upb/google/proto1.cc b/upb/bindings/googlepb/proto1.cc
index 80a44d8..c317cdf 100644
--- a/upb/google/proto1.cc
+++ b/upb/bindings/googlepb/proto1.cc
@@ -16,7 +16,7 @@
// dynamic_cast<> in this file:
// https://groups.google.com/a/google.com/d/msg/c-style/7Zp_XCX0e7s/I6dpzno4l-MJ
-#include "upb/google/proto1.h"
+#include "upb/bindings/googlepb/proto1.h"
#include <memory>
@@ -28,6 +28,9 @@
#include "upb/shim/shim.h"
#include "upb/sink.h"
+// Unconditionally evaluate, but also assert in debug mode.
+#define CHKRET(x) do { bool ok = (x); UPB_UNUSED(ok); assert(ok); } while (0)
+
template <class T> static T* GetPointer(void* message, size_t offset) {
return reinterpret_cast<T*>(static_cast<char*>(message) + offset);
}
@@ -161,7 +164,7 @@ class P2R_Handlers {
}
}
- template <class T> T* GetFieldPointer(void* message) const {
+ template <class T> T* GetFieldPointer(proto2::Message* message) const {
return GetPointer<T>(message, offset_);
}
@@ -201,16 +204,35 @@ class P2R_Handlers {
// StartSequence /////////////////////////////////////////////////////////////
- static void SetStartSequenceHandler(
+ template <class T>
+ static void SetStartRepeatedField(
+ const proto2::FieldDescriptor* proto2_f, const _pi::Proto2Reflection* r,
+ const upb::FieldDef* f, upb::Handlers* h) {
+ CHKRET(h->SetStartSequenceHandler(
+ f, UpbBindT(PushOffset<proto2::RepeatedField<T> >,
+ new FieldOffset(proto2_f, r))));
+ }
+
+ template <class T>
+ static void SetStartRepeatedPtrField(
const proto2::FieldDescriptor* proto2_f, const _pi::Proto2Reflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
- assert(f->IsSequence());
- h->SetStartSequenceHandler(
- f, UpbBind(PushOffset, new FieldOffset(proto2_f, r)));
+ CHKRET(h->SetStartSequenceHandler(
+ f, UpbBindT(PushOffset<proto2::RepeatedPtrField<T> >,
+ new FieldOffset(proto2_f, r))));
}
- static void* PushOffset(void* m, const FieldOffset* offset) {
- return offset->GetFieldPointer<void>(m);
+ static void SetStartRepeatedSubmessageField(
+ const proto2::FieldDescriptor* proto2_f, const _pi::Proto2Reflection* r,
+ const upb::FieldDef* f, upb::Handlers* h) {
+ CHKRET(h->SetStartSequenceHandler(
+ f, UpbBind(PushOffset<proto2::internal::RepeatedPtrFieldBase>,
+ new FieldOffset(proto2_f, r))));
+ }
+
+ template <class T>
+ static T* PushOffset(proto2::Message* m, const FieldOffset* offset) {
+ return offset->GetFieldPointer<T>(m);
}
// Primitive Value (numeric, enum, bool) /////////////////////////////////////
@@ -220,10 +242,11 @@ class P2R_Handlers {
const _pi::Proto2Reflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetValueHandler<T>(f, UpbMakeHandlerT(Append<T>));
+ SetStartRepeatedField<T>(proto2_f, r, f, h);
+ CHKRET(h->SetValueHandler<T>(f, UpbMakeHandlerT(Append<T>)));
} else {
- upb::Shim::Set(h, f, GetOffset(proto2_f, r), GetHasbit(proto2_f, r));
+ CHKRET(
+ upb::Shim::Set(h, f, GetOffset(proto2_f, r), GetHasbit(proto2_f, r)));
}
}
@@ -240,11 +263,11 @@ class P2R_Handlers {
const upb::FieldDef* f, upb::Handlers* h) {
h->SetStringHandler(f, UpbMakeHandler(OnStringBuf));
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedString));
+ SetStartRepeatedPtrField<string>(proto2_f, r, f, h);
+ CHKRET(h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedString)));
} else {
- h->SetStartStringHandler(
- f, UpbBind(StartString, new FieldOffset(proto2_f, r)));
+ CHKRET(h->SetStartStringHandler(
+ f, UpbBind(StartString, new FieldOffset(proto2_f, r))));
}
}
@@ -257,9 +280,8 @@ class P2R_Handlers {
return str;
}
- static size_t OnStringBuf(string* s, const char* buf, size_t n) {
+ static void OnStringBuf(string* s, const char* buf, size_t n) {
s->append(buf, n);
- return n;
}
static string* StartRepeatedString(proto2::RepeatedPtrField<string>* r,
@@ -276,9 +298,9 @@ class P2R_Handlers {
const upb::FieldDef* f, upb::Handlers* h) {
// This type is only used for non-repeated string fields.
assert(!f->IsSequence());
- h->SetStartStringHandler(
- f, UpbBind(StartOutOfLineString, new FieldOffset(proto2_f, r)));
- h->SetStringHandler(f, UpbMakeHandler(OnStringBuf));
+ CHKRET(h->SetStartStringHandler(
+ f, UpbBind(StartOutOfLineString, new FieldOffset(proto2_f, r))));
+ CHKRET(h->SetStringHandler(f, UpbMakeHandler(OnStringBuf)));
}
static string* StartOutOfLineString(proto2::Message* m,
@@ -299,13 +321,13 @@ class P2R_Handlers {
const _pi::Proto2Reflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedCord));
+ SetStartRepeatedField<Cord>(proto2_f, r, f, h);
+ CHKRET(h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedCord)));
} else {
- h->SetStartStringHandler(
- f, UpbBind(StartCord, new FieldOffset(proto2_f, r)));
+ CHKRET(h->SetStartStringHandler(
+ f, UpbBind(StartCord, new FieldOffset(proto2_f, r))));
}
- h->SetStringHandler(f, UpbMakeHandler(OnCordBuf));
+ CHKRET(h->SetStringHandler(f, UpbMakeHandler(OnCordBuf)));
}
static Cord* StartCord(proto2::Message* m, const FieldOffset* offset,
@@ -350,13 +372,13 @@ class P2R_Handlers {
const _pi::Proto2Reflection* r, const upb::FieldDef* f,
upb::Handlers* h) {
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartSubMessageHandler(
+ SetStartRepeatedSubmessageField(proto2_f, r, f, h);
+ CHKRET(h->SetStartSubMessageHandler(
f, UpbBind(StartRepeatedSubMessage,
- new SubMessageHandlerData(m, proto2_f, r)));
+ new SubMessageHandlerData(m, proto2_f, r))));
} else {
- h->SetStartSubMessageHandler(
- f, UpbBind(StartRequiredSubMessage, new FieldOffset(proto2_f, r)));
+ CHKRET(h->SetStartSubMessageHandler(
+ f, UpbBind(StartRequiredSubMessage, new FieldOffset(proto2_f, r))));
}
}
@@ -373,11 +395,12 @@ class P2R_Handlers {
std::unique_ptr<SubMessageHandlerData> data(
new SubMessageHandlerData(m, proto2_f, r));
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartSubMessageHandler(
- f, UpbBind(StartRepeatedSubMessage, data.release()));
+ SetStartRepeatedSubmessageField(proto2_f, r, f, h);
+ CHKRET(h->SetStartSubMessageHandler(
+ f, UpbBind(StartRepeatedSubMessage, data.release())));
} else {
- h->SetStartSubMessageHandler(f, UpbBind(StartSubMessage, data.release()));
+ CHKRET(h->SetStartSubMessageHandler(
+ f, UpbBind(StartSubMessage, data.release())));
}
}
@@ -388,23 +411,25 @@ class P2R_Handlers {
std::unique_ptr<SubMessageHandlerData> data(
new SubMessageHandlerData(m, proto2_f, r));
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartSubMessageHandler(
- f, UpbBind(StartRepeatedSubMessage, data.release()));
+ SetStartRepeatedSubmessageField(proto2_f, r, f, h);
+ CHKRET(h->SetStartSubMessageHandler(
+ f, UpbBind(StartRepeatedSubMessage, data.release())));
} else {
- h->SetStartSubMessageHandler(
- f, UpbBind(StartWeakSubMessage, data.release()));
+ CHKRET(h->SetStartSubMessageHandler(
+ f, UpbBind(StartWeakSubMessage, data.release())));
}
}
- static void* StartSubMessage(void *m, const SubMessageHandlerData* info) {
+ static void* StartSubMessage(proto2::Message* m,
+ const SubMessageHandlerData* info) {
info->SetHasbit(m);
proto2::Message** subm = info->GetFieldPointer<proto2::Message*>(m);
if (*subm == info->prototype()) *subm = (*subm)->New();
return *subm;
}
- static void* StartWeakSubMessage(void* m, const SubMessageHandlerData* info) {
+ static void* StartWeakSubMessage(proto2::Message* m,
+ const SubMessageHandlerData* info) {
info->SetHasbit(m);
proto2::Message** subm = info->GetFieldPointer<proto2::Message*>(m);
if (*subm == NULL) {
diff --git a/upb/google/proto1.h b/upb/bindings/googlepb/proto1.h
index eb550ac..eb550ac 100644
--- a/upb/google/proto1.h
+++ b/upb/bindings/googlepb/proto1.h
diff --git a/upb/google/proto2.cc b/upb/bindings/googlepb/proto2.cc
index d138123..c0b4907 100644
--- a/upb/google/proto2.cc
+++ b/upb/bindings/googlepb/proto2.cc
@@ -13,14 +13,26 @@
// and protobuf opensource both in a single binary without the two conflicting.
// However we must be careful not to violate the ODR.
-#include "upb/google/proto2.h"
+#include "upb/bindings/googlepb/proto2.h"
#include "upb/def.h"
-#include "upb/google/proto1.h"
+#include "upb/bindings/googlepb/proto1.h"
#include "upb/handlers.h"
#include "upb/shim/shim.h"
#include "upb/sink.h"
+namespace {
+
+template<typename To, typename From> To CheckDownCast(From* f) {
+ assert(f == NULL || dynamic_cast<To>(f) != NULL);
+ return static_cast<To>(f);
+}
+
+}
+
+// Unconditionally evaluate, but also assert in debug mode.
+#define CHKRET(x) do { bool ok = (x); UPB_UNUSED(ok); assert(ok); } while (0)
+
namespace upb {
namespace google_google3 { class GMR_Handlers; }
namespace google_opensource { class GMR_Handlers; }
@@ -230,7 +242,7 @@ case goog::FieldDescriptor::cpptype: \
}
}
- template <class T> T* GetFieldPointer(void* message) const {
+ template <class T> T* GetFieldPointer(goog::Message* message) const {
return GetPointer<T>(message, offset_);
}
@@ -262,7 +274,7 @@ case goog::FieldDescriptor::cpptype: \
int number() const { return number_; }
goog::internal::FieldType type() const { return type_; }
- goog::internal::ExtensionSet* GetExtensionSet(goog::MessageLite* m) const {
+ goog::internal::ExtensionSet* GetExtensionSet(goog::Message* m) const {
return GetPointer<goog::internal::ExtensionSet>(m, offset_);
}
@@ -274,18 +286,38 @@ case goog::FieldDescriptor::cpptype: \
// StartSequence /////////////////////////////////////////////////////////////
- static void SetStartSequenceHandler(
+ template <class T>
+ static void SetStartRepeatedField(
+ const goog::FieldDescriptor* proto2_f,
+ const goog::internal::GeneratedMessageReflection* r,
+ const upb::FieldDef* f, upb::Handlers* h) {
+ CHKRET(h->SetStartSequenceHandler(
+ f, UpbBindT(&PushOffset<goog::RepeatedField<T> >,
+ new FieldOffset(proto2_f, r))));
+ }
+
+ template <class T>
+ static void SetStartRepeatedPtrField(
const goog::FieldDescriptor* proto2_f,
const goog::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
- assert(f->IsSequence());
- h->SetStartSequenceHandler(
- f, UpbBind(PushOffset, new FieldOffset(proto2_f, r)));
+ CHKRET(h->SetStartSequenceHandler(
+ f, UpbBindT(&PushOffset<goog::RepeatedPtrField<T> >,
+ new FieldOffset(proto2_f, r))));
}
- // TODO(haberman): make more type-safe?
- static void* PushOffset(void* message, const FieldOffset* offset) {
- return offset->GetFieldPointer<void>(message);
+ static void SetStartRepeatedSubmessageField(
+ const goog::FieldDescriptor* proto2_f,
+ const goog::internal::GeneratedMessageReflection* r,
+ const upb::FieldDef* f, upb::Handlers* h) {
+ CHKRET(h->SetStartSequenceHandler(
+ f, UpbBind(&PushOffset<goog::internal::RepeatedPtrFieldBase>,
+ new FieldOffset(proto2_f, r))));
+ }
+
+ template <class T>
+ static T* PushOffset(goog::Message* message, const FieldOffset* offset) {
+ return offset->GetFieldPointer<T>(message);
}
// Primitive Value (numeric, bool) ///////////////////////////////////////////
@@ -297,18 +329,19 @@ case goog::FieldDescriptor::cpptype: \
if (proto2_f->is_extension()) {
scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r));
if (f->IsSequence()) {
- h->SetValueHandler<T>(
- f, UpbBindT(AppendPrimitiveExtension<T>, data.release()));
+ CHKRET(h->SetValueHandler<T>(
+ f, UpbBindT(AppendPrimitiveExtension<T>, data.release())));
} else {
- h->SetValueHandler<T>(
- f, UpbBindT(SetPrimitiveExtension<T>, data.release()));
+ CHKRET(h->SetValueHandler<T>(
+ f, UpbBindT(SetPrimitiveExtension<T>, data.release())));
}
} else {
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetValueHandler<T>(f, UpbMakeHandlerT(AppendPrimitive<T>));
+ SetStartRepeatedField<T>(proto2_f, r, f, h);
+ CHKRET(h->SetValueHandler<T>(f, UpbMakeHandlerT(AppendPrimitive<T>)));
} else {
- upb::Shim::Set(h, f, GetOffset(proto2_f, r), GetHasbit(proto2_f, r));
+ CHKRET(upb::Shim::Set(h, f, GetOffset(proto2_f, r),
+ GetHasbit(proto2_f, r)));
}
}
}
@@ -368,9 +401,9 @@ case goog::FieldDescriptor::cpptype: \
assert(!proto2_f->is_extension());
scoped_ptr<EnumHandlerData> data(new EnumHandlerData(proto2_f, r, f));
if (f->IsSequence()) {
- h->SetInt32Handler(f, UpbBind(AppendEnum, data.release()));
+ CHKRET(h->SetInt32Handler(f, UpbBind(AppendEnum, data.release())));
} else {
- h->SetInt32Handler(f, UpbBind(SetEnum, data.release()));
+ CHKRET(h->SetInt32Handler(f, UpbBind(SetEnum, data.release())));
}
}
@@ -408,9 +441,10 @@ case goog::FieldDescriptor::cpptype: \
assert(proto2_f->is_extension());
scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r));
if (f->IsSequence()) {
- h->SetInt32Handler(f, UpbBind(AppendEnumExtension, data.release()));
+ CHKRET(
+ h->SetInt32Handler(f, UpbBind(AppendEnumExtension, data.release())));
} else {
- h->SetInt32Handler(f, UpbBind(SetEnumExtension, data.release()));
+ CHKRET(h->SetInt32Handler(f, UpbBind(SetEnumExtension, data.release())));
}
}
@@ -440,7 +474,7 @@ case goog::FieldDescriptor::cpptype: \
const T* prototype() const { return prototype_; }
- T** GetStringPointer(void* message) const {
+ T** GetStringPointer(goog::Message* message) const {
return GetFieldPointer<T*>(message);
}
@@ -454,13 +488,14 @@ case goog::FieldDescriptor::cpptype: \
const upb::FieldDef* f,
upb::Handlers* h) {
assert(!proto2_f->is_extension());
- h->SetStringHandler(f, UpbMakeHandlerT(&OnStringBuf<T>));
+ CHKRET(h->SetStringHandler(f, UpbMakeHandlerT(&OnStringBuf<T>)));
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartStringHandler(f, UpbMakeHandlerT(StartRepeatedString<T>));
+ SetStartRepeatedPtrField<T>(proto2_f, r, f, h);
+ CHKRET(
+ h->SetStartStringHandler(f, UpbMakeHandlerT(StartRepeatedString<T>)));
} else {
- h->SetStartStringHandler(
- f, UpbBindT(StartString<T>, new StringHandlerData<T>(proto2_f, r)));
+ CHKRET(h->SetStartStringHandler(
+ f, UpbBindT(StartString<T>, new StringHandlerData<T>(proto2_f, r))));
}
}
@@ -479,14 +514,13 @@ case goog::FieldDescriptor::cpptype: \
}
template <typename T>
- static size_t OnStringBuf(T* str, const char* buf, size_t n) {
+ static void OnStringBuf(T* str, const char* buf, size_t n) {
str->append(buf, n);
- return n;
}
template <typename T>
static T* StartRepeatedString(goog::RepeatedPtrField<T>* r,
- size_t size_hint) {
+ size_t size_hint) {
UPB_UNUSED(size_hint);
T* str = r->Add();
str->clear();
@@ -502,14 +536,14 @@ case goog::FieldDescriptor::cpptype: \
const goog::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
assert(proto2_f->is_extension());
- h->SetStringHandler(f, UpbMakeHandlerT(OnStringBuf<T>));
+ CHKRET(h->SetStringHandler(f, UpbMakeHandlerT(OnStringBuf<T>)));
scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r));
if (f->IsSequence()) {
- h->SetStartStringHandler(
- f, UpbBindT(StartRepeatedStringExtension<T>, data.release()));
+ CHKRET(h->SetStartStringHandler(
+ f, UpbBindT(StartRepeatedStringExtension<T>, data.release())));
} else {
- h->SetStartStringHandler(
- f, UpbBindT(StartStringExtension<T>, data.release()));
+ CHKRET(h->SetStartStringHandler(
+ f, UpbBindT(StartStringExtension<T>, data.release())));
}
}
@@ -555,11 +589,12 @@ case goog::FieldDescriptor::cpptype: \
scoped_ptr<SubMessageHandlerData> data(
new SubMessageHandlerData(proto2_f, r, field_prototype));
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartSubMessageHandler(
- f, UpbBind(StartRepeatedSubMessage, data.release()));
+ SetStartRepeatedSubmessageField(proto2_f, r, f, h);
+ CHKRET(h->SetStartSubMessageHandler(
+ f, UpbBind(StartRepeatedSubMessage, data.release())));
} else {
- h->SetStartSubMessageHandler(f, UpbBind(StartSubMessage, data.release()));
+ CHKRET(h->SetStartSubMessageHandler(
+ f, UpbBind(StartSubMessage, data.release())));
}
}
@@ -625,26 +660,32 @@ case goog::FieldDescriptor::cpptype: \
scoped_ptr<SubMessageExtensionHandlerData> data(
new SubMessageExtensionHandlerData(proto2_f, r, field_prototype));
if (f->IsSequence()) {
- h->SetStartSubMessageHandler(
- f, UpbBind(StartRepeatedSubMessageExtension, data.release()));
+ CHKRET(h->SetStartSubMessageHandler(
+ f, UpbBind(StartRepeatedSubMessageExtension, data.release())));
} else {
- h->SetStartSubMessageHandler(
- f, UpbBind(StartSubMessageExtension, data.release()));
+ CHKRET(h->SetStartSubMessageHandler(
+ f, UpbBind(StartSubMessageExtension, data.release())));
}
}
- static goog::MessageLite* StartRepeatedSubMessageExtension(
- goog::MessageLite* m, const SubMessageExtensionHandlerData* data) {
+ static goog::Message* StartRepeatedSubMessageExtension(
+ goog::Message* m, const SubMessageExtensionHandlerData* data) {
goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
- return set->AddMessage(data->number(), data->type(), *data->prototype(),
- NULL);
+ // Because we found this message via a descriptor, we know it has a
+ // descriptor and is therefore a Message and not a MessageLite.
+ // Alternatively we could just use goog::MessageLite everywhere to avoid
+ // this, but since they are in fact goog::Messages, it seems most clear
+ // to refer to them as such.
+ return CheckDownCast<goog::Message*>(set->AddMessage(
+ data->number(), data->type(), *data->prototype(), NULL));
}
- static goog::MessageLite* StartSubMessageExtension(
- goog::MessageLite* m, const SubMessageExtensionHandlerData* data) {
+ static goog::Message* StartSubMessageExtension(
+ goog::Message* m, const SubMessageExtensionHandlerData* data) {
goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
- return set->MutableMessage(data->number(), data->type(), *data->prototype(),
- NULL);
+ // See comment above re: this down cast.
+ return CheckDownCast<goog::Message*>(set->MutableMessage(
+ data->number(), data->type(), *data->prototype(), NULL));
}
// TODO(haberman): handle Unknown Fields.
@@ -661,13 +702,13 @@ case goog::FieldDescriptor::cpptype: \
const proto2::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
assert(!proto2_f->is_extension());
- h->SetStringHandler(f, UpbMakeHandler(&OnCordBuf));
+ CHKRET(h->SetStringHandler(f, UpbMakeHandler(&OnCordBuf)));
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedCord));
+ SetStartRepeatedField<Cord>(proto2_f, r, f, h);
+ CHKRET(h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedCord)));
} else {
- h->SetStartStringHandler(
- f, UpbBind(StartCord, new FieldOffset(proto2_f, r)));
+ CHKRET(h->SetStartStringHandler(
+ f, UpbBind(StartCord, new FieldOffset(proto2_f, r))));
}
}
@@ -680,9 +721,21 @@ case goog::FieldDescriptor::cpptype: \
return field;
}
- static size_t OnCordBuf(Cord* c, const char* buf, size_t n) {
- c->Append(StringPiece(buf, n));
- return n;
+ static void OnCordBuf(Cord* c, const char* buf, size_t n,
+ const upb::BufferHandle* handle) {
+ const Cord* source_cord = handle->GetAttachedObject<Cord>();
+ if (source_cord) {
+ // This TODO is copied from CordReader::CopyToCord():
+ // "We could speed this up by using CordReader internals."
+ Cord piece(*source_cord);
+ piece.RemovePrefix(handle->object_offset() + (buf - handle->buffer()));
+ assert(piece.size() >= n);
+ piece.RemoveSuffix(piece.size() - n);
+
+ c->Append(piece);
+ } else {
+ c->Append(StringPiece(buf, n));
+ }
}
static Cord* StartRepeatedCord(proto2::RepeatedField<Cord>* r,
@@ -698,18 +751,20 @@ case goog::FieldDescriptor::cpptype: \
const proto2::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
assert(!proto2_f->is_extension());
- h->SetStringHandler(f, UpbMakeHandler(OnStringPieceBuf));
+ CHKRET(h->SetStringHandler(f, UpbMakeHandler(OnStringPieceBuf)));
if (f->IsSequence()) {
- SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedStringPiece));
+ SetStartRepeatedPtrField<proto2::internal::StringPieceField>(proto2_f, r,
+ f, h);
+ CHKRET(h->SetStartStringHandler(
+ f, UpbMakeHandler(StartRepeatedStringPiece)));
} else {
- h->SetStartStringHandler(
- f, UpbBind(StartStringPiece, new FieldOffset(proto2_f, r)));
+ CHKRET(h->SetStartStringHandler(
+ f, UpbBind(StartStringPiece, new FieldOffset(proto2_f, r))));
}
}
- static size_t OnStringPieceBuf(proto2::internal::StringPieceField* field,
- const char* buf, size_t len) {
+ static void OnStringPieceBuf(proto2::internal::StringPieceField* field,
+ const char* buf, size_t len) {
// TODO(haberman): alias if possible and enabled on the input stream.
// TODO(haberman): add a method to StringPieceField that lets us avoid
// this copy/malloc/free.
@@ -719,7 +774,6 @@ case goog::FieldDescriptor::cpptype: \
memcpy(data + field->size(), buf, len);
field->CopyFrom(StringPiece(data, new_len));
delete[] data;
- return len;
}
static proto2::internal::StringPieceField* StartStringPiece(
diff --git a/upb/google/proto2.h b/upb/bindings/googlepb/proto2.h
index 516b7fd..516b7fd 100644
--- a/upb/google/proto2.h
+++ b/upb/bindings/googlepb/proto2.h
diff --git a/bindings/linux/Makefile b/upb/bindings/linux/Makefile
index 1736b61..1736b61 100644
--- a/bindings/linux/Makefile
+++ b/upb/bindings/linux/Makefile
diff --git a/bindings/linux/assert.h b/upb/bindings/linux/assert.h
index 26d8ab6..26d8ab6 100644
--- a/bindings/linux/assert.h
+++ b/upb/bindings/linux/assert.h
diff --git a/bindings/linux/errno.h b/upb/bindings/linux/errno.h
index f45d939..f45d939 100644
--- a/bindings/linux/errno.h
+++ b/upb/bindings/linux/errno.h
diff --git a/bindings/linux/stdint.h b/upb/bindings/linux/stdint.h
index 2524b23..2524b23 100644
--- a/bindings/linux/stdint.h
+++ b/upb/bindings/linux/stdint.h
diff --git a/bindings/linux/stdio.h b/upb/bindings/linux/stdio.h
index 72c1b0d..72c1b0d 100644
--- a/bindings/linux/stdio.h
+++ b/upb/bindings/linux/stdio.h
diff --git a/bindings/linux/stdlib.h b/upb/bindings/linux/stdlib.h
index 8381b13..8381b13 100644
--- a/bindings/linux/stdlib.h
+++ b/upb/bindings/linux/stdlib.h
diff --git a/bindings/linux/string.h b/upb/bindings/linux/string.h
index 30ebf8a..30ebf8a 100644
--- a/bindings/linux/string.h
+++ b/upb/bindings/linux/string.h
diff --git a/bindings/lua/table.c b/upb/bindings/lua/table.c
index 4e6aae2..51ba324 100644
--- a/bindings/lua/table.c
+++ b/upb/bindings/lua/table.c
@@ -21,8 +21,9 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
+
#include "lauxlib.h"
-#include "bindings/lua/upb.h"
+#include "upb/bindings/lua/upb.h"
#include "upb/def.h"
static void lupbtable_setnum(lua_State *L, int tab, const char *key,
diff --git a/bindings/lua/upb.c b/upb/bindings/lua/upb.c
index 9eb46f3..1e7540a 100644
--- a/bindings/lua/upb.c
+++ b/upb/bindings/lua/upb.c
@@ -13,7 +13,7 @@
#include <stdlib.h>
#include <string.h>
#include "lauxlib.h"
-#include "bindings/lua/upb.h"
+#include "upb/bindings/lua/upb.h"
#include "upb/handlers.h"
#include "upb/pb/glue.h"
@@ -63,6 +63,13 @@ static const char *chkname(lua_State *L, int narg) {
return name;
}
+static bool chkbool(lua_State *L, int narg, const char *type) {
+ if (!lua_isboolean(L, narg)) {
+ luaL_error(L, "%s must be true or false", type);
+ }
+ return lua_toboolean(L, narg);
+}
+
static bool streql(const char *a, const char *b) { return strcmp(a, b) == 0; }
static uint32_t chkint32(lua_State *L, int narg, const char *name) {
@@ -75,9 +82,7 @@ static uint32_t chkint32(lua_State *L, int narg, const char *name) {
// Sets a fielddef default from the given Lua value.
static void lupb_setdefault(lua_State *L, int narg, upb_fielddef *f) {
if (upb_fielddef_type(f) == UPB_TYPE_BOOL) {
- if (!lua_isboolean(L, narg))
- luaL_error(L, "Must explicitly pass true or false for boolean fields");
- upb_fielddef_setdefaultbool(f, lua_toboolean(L, narg));
+ upb_fielddef_setdefaultbool(f, chkbool(L, narg, "bool default"));
} else {
// Numeric type.
lua_Number num = luaL_checknumber(L, narg);
@@ -309,6 +314,11 @@ static void lupb_fielddef_dosetdefault(lua_State *L, upb_fielddef *f,
}
}
+static void lupb_fielddef_dosetisextension(lua_State *L, upb_fielddef *f,
+ int narg) {
+ CHK(upb_fielddef_setisextension(f, chkbool(L, narg, "is_extension")));
+}
+
static void lupb_fielddef_dosetlabel(lua_State *L, upb_fielddef *f, int narg) {
int label = luaL_checkint(L, narg);
if (!upb_fielddef_checklabel(label))
@@ -339,6 +349,14 @@ static void lupb_fielddef_dosetsubdefname(lua_State *L, upb_fielddef *f,
CHK(upb_fielddef_setsubdefname(f, name, &status));
}
+static void lupb_fielddef_dosetcontainingtypename(lua_State *L, upb_fielddef *f,
+ int narg) {
+ const char *name = NULL;
+ if (!lua_isnil(L, narg))
+ name = chkname(L, narg);
+ CHK(upb_fielddef_setcontainingtypename(f, name, &status));
+}
+
static void lupb_fielddef_dosettype(lua_State *L, upb_fielddef *f, int narg) {
int type = luaL_checkint(L, narg);
if (!upb_fielddef_checktype(type))
@@ -355,21 +373,29 @@ static void lupb_fielddef_dosetintfmt(lua_State *L, upb_fielddef *f, int narg) {
static void lupb_fielddef_dosettagdelim(lua_State *L, upb_fielddef *f,
int narg) {
- if (!lua_isboolean(L, narg))
- luaL_argerror(L, narg, "tagdelim value must be boolean");
- int32_t tagdelim = luaL_checknumber(L, narg);
- if (!upb_fielddef_settagdelim(f, tagdelim))
- luaL_argerror(L, narg, "invalid field tagdelim");
+ CHK(upb_fielddef_settagdelim(f, chkbool(L, narg, "tagdelim")));
}
// Setter API calls. These use the setter functions above.
+static int lupb_fielddef_setcontainingtypename(lua_State *L) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
+ lupb_fielddef_dosetcontainingtypename(L, f, 2);
+ return 0;
+}
+
static int lupb_fielddef_setdefault(lua_State *L) {
upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
lupb_fielddef_dosetdefault(L, f, 2);
return 0;
}
+static int lupb_fielddef_setisextension(lua_State *L) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
+ lupb_fielddef_dosetisextension(L, f, 2);
+ return 0;
+}
+
static int lupb_fielddef_setlabel(lua_State *L) {
upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
lupb_fielddef_dosetlabel(L, f, 2);
@@ -440,9 +466,13 @@ static int lupb_fielddef_new(lua_State *L) {
else if (streql(key, "number")) lupb_fielddef_dosetnumber(L, f, v);
else if (streql(key, "type")) lupb_fielddef_dosettype(L, f, v);
else if (streql(key, "label")) lupb_fielddef_dosetlabel(L, f, v);
- else if (streql(key, "default_value")) ; // Defer to second pass.
- else if (streql(key, "subdef")) ; // Defer to second pass.
- else if (streql(key, "subdef_name")) ; // Defer to second pass.
+ else if (streql(key, "is_extension"))
+ lupb_fielddef_dosetisextension(L, f, v);
+ else if (streql(key, "containing_type_name"))
+ lupb_fielddef_dosetcontainingtypename(L, f, v);
+ else if (streql(key, "default_value")) ; // Defer to second pass.
+ else if (streql(key, "subdef")) ; // Defer to second pass.
+ else if (streql(key, "subdef_name")) ; // Defer to second pass.
else luaL_error(L, "Cannot set fielddef member '%s'", key);
}
@@ -547,6 +577,12 @@ static int lupb_fielddef_containingtype(lua_State *L) {
return 1;
}
+static int lupb_fielddef_containingtypename(lua_State *L) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
+ lua_pushstring(L, upb_fielddef_containingtypename(f));
+ return 1;
+}
+
static int lupb_fielddef_subdef(lua_State *L) {
const upb_fielddef *f = lupb_fielddef_check(L, 1);
if (!upb_fielddef_hassubdef(f))
@@ -585,6 +621,12 @@ static int lupb_fielddef_intfmt(lua_State *L) {
return 1;
}
+static int lupb_fielddef_isextension(lua_State *L) {
+ const upb_fielddef *f = lupb_fielddef_check(L, 1);
+ lua_pushboolean(L, upb_fielddef_isextension(f));
+ return 1;
+}
+
static int lupb_fielddef_istagdelim(lua_State *L) {
const upb_fielddef *f = lupb_fielddef_check(L, 1);
lua_pushboolean(L, upb_fielddef_istagdelim(f));
@@ -602,11 +644,13 @@ static const struct luaL_Reg lupb_fielddef_m[] = {
LUPB_COMMON_DEF_METHODS
{"containing_type", lupb_fielddef_containingtype},
+ {"containing_type_name", lupb_fielddef_containingtypename},
{"default", lupb_fielddef_default},
{"getsel", lupb_fielddef_getsel},
{"has_subdef", lupb_fielddef_hassubdef},
{"index", lupb_fielddef_index},
{"intfmt", lupb_fielddef_intfmt},
+ {"is_extension", lupb_fielddef_isextension},
{"istagdelim", lupb_fielddef_istagdelim},
{"label", lupb_fielddef_label},
{"name", lupb_fielddef_name},
@@ -615,7 +659,9 @@ static const struct luaL_Reg lupb_fielddef_m[] = {
{"subdef_name", lupb_fielddef_subdefname},
{"type", lupb_fielddef_type},
+ {"set_containing_type_name", lupb_fielddef_setcontainingtypename},
{"set_default", lupb_fielddef_setdefault},
+ {"set_is_extension", lupb_fielddef_setisextension},
{"set_label", lupb_fielddef_setlabel},
{"set_name", lupb_fielddef_setname},
{"set_number", lupb_fielddef_setnumber},
diff --git a/bindings/lua/upb.h b/upb/bindings/lua/upb.h
index e6b4f2f..e6b4f2f 100644
--- a/bindings/lua/upb.h
+++ b/upb/bindings/lua/upb.h
diff --git a/bindings/python/setup.py b/upb/bindings/python/setup.py
index 8abaff8..8abaff8 100644
--- a/bindings/python/setup.py
+++ b/upb/bindings/python/setup.py
diff --git a/bindings/python/test.py b/upb/bindings/python/test.py
index 29a6c45..29a6c45 100644
--- a/bindings/python/test.py
+++ b/upb/bindings/python/test.py
diff --git a/bindings/python/upb.c b/upb/bindings/python/upb.c
index 497074b..497074b 100644
--- a/bindings/python/upb.c
+++ b/upb/bindings/python/upb.c
diff --git a/bindings/python/upb/__init__.py b/upb/bindings/python/upb/__init__.py
index e69de29..e69de29 100644
--- a/bindings/python/upb/__init__.py
+++ b/upb/bindings/python/upb/__init__.py
diff --git a/upb/bindings/stdc++/string.h b/upb/bindings/stdc++/string.h
new file mode 100644
index 0000000..668f3e3
--- /dev/null
+++ b/upb/bindings/stdc++/string.h
@@ -0,0 +1,60 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+// Author: haberman@google.com (Josh Haberman)
+//
+// upb - a minimalist implementation of protocol buffers.
+
+#ifndef UPB_STDCPP_H_
+#define UPB_STDCPP_H_
+
+namespace upb {
+
+template <class T>
+class FillStringHandler {
+ public:
+ static void SetHandler(BytesHandler* handler) {
+ upb_byteshandler_setstartstr(handler, &FillStringHandler::StartString,
+ NULL);
+ upb_byteshandler_setstring(handler, &FillStringHandler::StringBuf, NULL);
+ }
+
+ private:
+ // TODO(haberman): add UpbBind/UpbMakeHandler support to BytesHandler so these
+ // can be prettier callbacks.
+ static void* StartString(void *c, const void *hd, size_t size) {
+ T* str = static_cast<T*>(c);
+ str->clear();
+ return c;
+ }
+
+ static size_t StringBuf(void* c, const void* hd, const char* buf, size_t n,
+ const BufferHandle* h) {
+ T* str = static_cast<T*>(c);
+ try {
+ str->append(buf, n);
+ return n;
+ } catch (const std::exception&) {
+ return 0;
+ }
+ }
+};
+
+class StringSink {
+ public:
+ template <class T>
+ explicit StringSink(T* target) {
+ // TODO(haberman): we need to avoid rebuilding a new handler every time,
+ // but with class globals disallowed for google3 C++ this is tricky.
+ FillStringHandler<T>::SetHandler(&handler_);
+ input_.Reset(&handler_, target);
+ }
+
+ BytesSink* input() { return &input_; }
+
+ private:
+ BytesHandler handler_;
+ BytesSink input_;
+};
+
+} // namespace upb
+
+#endif // UPB_STDCPP_H_
diff --git a/upb/stdc/error.c b/upb/bindings/stdc/error.c
index 85c9ca6..85c9ca6 100644
--- a/upb/stdc/error.c
+++ b/upb/bindings/stdc/error.c
diff --git a/upb/stdc/error.h b/upb/bindings/stdc/error.h
index 9802097..9802097 100644
--- a/upb/stdc/error.h
+++ b/upb/bindings/stdc/error.h
diff --git a/upb/stdc/io.c b/upb/bindings/stdc/io.c
index 5d36aa5..5d36aa5 100644
--- a/upb/stdc/io.c
+++ b/upb/bindings/stdc/io.c
diff --git a/upb/stdc/io.h b/upb/bindings/stdc/io.h
index fd19bef..fd19bef 100644
--- a/upb/stdc/io.h
+++ b/upb/bindings/stdc/io.h
diff --git a/upb/def.c b/upb/def.c
index a674a98..805f143 100644
--- a/upb/def.c
+++ b/upb/def.c
@@ -156,17 +156,17 @@ static bool upb_validate_field(upb_fielddef *f, upb_status *s) {
if (subdef == NULL) {
upb_status_seterrf(s,
"field %s.%s is missing required subdef",
- msgdef_name(f->msgdef), upb_fielddef_name(f));
+ msgdef_name(f->msg.def), upb_fielddef_name(f));
return false;
} else if (!upb_def_isfrozen(subdef) && !subdef->came_from_user) {
upb_status_seterrf(s,
"subdef of field %s.%s is not frozen or being frozen",
- msgdef_name(f->msgdef), upb_fielddef_name(f));
+ msgdef_name(f->msg.def), upb_fielddef_name(f));
return false;
} else if (upb_fielddef_default_is_symbolic(f)) {
upb_status_seterrf(s,
"enum field %s.%s has not been resolved",
- msgdef_name(f->msgdef), upb_fielddef_name(f));
+ msgdef_name(f->msg.def), upb_fielddef_name(f));
return false;
}
}
@@ -202,7 +202,7 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
m->submsg_field_count = 0;
for(i = 0, upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j), i++) {
upb_fielddef *f = upb_msg_iter_field(&j);
- assert(f->msgdef == m);
+ assert(f->msg.def == m);
if (!upb_validate_field(f, s)) {
free(fields);
return false;
@@ -428,11 +428,11 @@ static void upb_fielddef_uninit_default(upb_fielddef *f) {
static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit,
void *closure) {
const upb_fielddef *f = (const upb_fielddef*)r;
- if (f->msgdef) {
- visit(r, UPB_UPCAST2(f->msgdef), closure);
+ if (upb_fielddef_containingtype(f)) {
+ visit(r, UPB_UPCAST2(upb_fielddef_containingtype(f)), closure);
}
- if (!f->subdef_is_symbolic && f->sub.def) {
- visit(r, UPB_UPCAST(f->sub.def), closure);
+ if (upb_fielddef_subdef(f)) {
+ visit(r, UPB_UPCAST(upb_fielddef_subdef(f)), closure);
}
}
@@ -453,14 +453,16 @@ upb_fielddef *upb_fielddef_new(const void *owner) {
free(f);
return NULL;
}
- f->msgdef = NULL;
+ f->msg.def = NULL;
f->sub.def = NULL;
f->subdef_is_symbolic = false;
+ f->msg_is_symbolic = false;
f->label_ = UPB_LABEL_OPTIONAL;
f->type_ = UPB_TYPE_INT32;
f->number_ = 0;
f->type_is_set_ = false;
f->tagdelim = false;
+ f->is_extension_ = false;
// For the moment we default this to UPB_INTFMT_VARIABLE, since it will work
// with all integer types and is in some since more "default" since the most
@@ -559,16 +561,43 @@ uint32_t upb_fielddef_number(const upb_fielddef *f) {
return f->number_;
}
+bool upb_fielddef_isextension(const upb_fielddef *f) {
+ return f->is_extension_;
+}
+
const char *upb_fielddef_name(const upb_fielddef *f) {
return upb_def_fullname(UPB_UPCAST(f));
}
const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
- return f->msgdef;
+ return f->msg_is_symbolic ? NULL : f->msg.def;
}
upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) {
- return (upb_msgdef*)f->msgdef;
+ return (upb_msgdef*)upb_fielddef_containingtype(f);
+}
+
+const char *upb_fielddef_containingtypename(upb_fielddef *f) {
+ return f->msg_is_symbolic ? f->msg.name : NULL;
+}
+
+static void release_containingtype(upb_fielddef *f) {
+ if (f->msg_is_symbolic) free(f->msg.name);
+}
+
+bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name,
+ upb_status *s) {
+ assert(!upb_fielddef_isfrozen(f));
+ if (upb_fielddef_containingtype(f)) {
+ upb_status_seterrmsg(s, "field has already been added to a message.");
+ return false;
+ }
+ // TODO: validate name (upb_isident() doesn't quite work atm because this name
+ // may have a leading ".").
+ release_containingtype(f);
+ f->msg.name = upb_strdup(name);
+ f->msg_is_symbolic = true;
+ return true;
}
bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) {
@@ -650,12 +679,7 @@ static void upb_fielddef_init_default(upb_fielddef *f) {
}
const upb_def *upb_fielddef_subdef(const upb_fielddef *f) {
- if (upb_fielddef_hassubdef(f) && upb_fielddef_isfrozen(f)) {
- assert(f->sub.def);
- return f->sub.def;
- } else {
- return f->subdef_is_symbolic ? NULL : f->sub.def;
- }
+ return f->subdef_is_symbolic ? NULL : f->sub.def;
}
const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
@@ -678,7 +702,7 @@ const char *upb_fielddef_subdefname(const upb_fielddef *f) {
}
bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s) {
- if (f->msgdef) {
+ if (upb_fielddef_containingtype(f)) {
upb_status_seterrmsg(
s, "cannot change field number after adding to a message");
return false;
@@ -800,6 +824,12 @@ upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
return 0;
}
+bool upb_fielddef_setisextension(upb_fielddef *f, bool is_extension) {
+ assert(!upb_fielddef_isfrozen(f));
+ f->is_extension_ = is_extension;
+ return true;
+}
+
void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label) {
assert(!upb_fielddef_isfrozen(f));
assert(upb_fielddef_checklabel(label));
@@ -980,6 +1010,8 @@ bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name,
upb_status_seterrmsg(s, "field type does not accept a subdef");
return false;
}
+ // TODO: validate name (upb_isident() doesn't quite work atm because this name
+ // may have a leading ".").
release_subdef(f);
f->sub.name = upb_strdup(name);
f->subdef_is_symbolic = true;
@@ -1104,12 +1136,23 @@ bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname,
bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef *const *fields, int n,
const void *ref_donor, upb_status *s) {
+ // TODO: extensions need to have a separate namespace, because proto2 allows a
+ // top-level extension (ie. one not in any package) to have the same name as a
+ // field from the message.
+ //
+ // This also implies that there needs to be a separate lookup-by-name method
+ // for extensions. It seems desirable for iteration to return both extensions
+ // and non-extensions though.
+ //
+ // We also need to validate that the field number is in an extension range iff
+ // it is an extension.
+
// Check constraints for all fields before performing any action.
for (int i = 0; i < n; i++) {
upb_fielddef *f = fields[i];
// TODO(haberman): handle the case where two fields of the input duplicate
// name or number.
- if (f->msgdef != NULL) {
+ if (upb_fielddef_containingtype(f) != NULL) {
upb_status_seterrmsg(s, "fielddef already belongs to a message");
return false;
} else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
@@ -1125,7 +1168,9 @@ bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef *const *fields, int n,
// Constraint checks ok, perform the action.
for (int i = 0; i < n; i++) {
upb_fielddef *f = fields[i];
- f->msgdef = m;
+ release_containingtype(f);
+ f->msg.def = m;
+ f->msg_is_symbolic = false;
upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f));
upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f));
upb_ref2(f, m);
diff --git a/upb/def.h b/upb/def.h
index 2b7ebba..8951353 100644
--- a/upb/def.h
+++ b/upb/def.h
@@ -272,6 +272,7 @@ class upb::FieldDef /* : public upb::Def */ {
Label label() const; // Defaults to UPB_LABEL_OPTIONAL.
const char* name() const; // NULL if uninitialized.
uint32_t number() const; // Returns 0 if uninitialized.
+ bool is_extension() const;
// An integer that can be used as an index into an array of fields for
// whatever message this field belongs to. Guaranteed to be less than
@@ -279,8 +280,21 @@ class upb::FieldDef /* : public upb::Def */ {
// been finalized.
int index() const;
- // The MessageDef to which this field belongs, or NULL if none.
+ // The MessageDef to which this field belongs.
+ //
+ // If this field has been added to a MessageDef, that message can be retrieved
+ // directly (this is always the case for frozen FieldDefs).
+ //
+ // If the field has not yet been added to a MessageDef, you can set the name
+ // of the containing type symbolically instead. This is mostly useful for
+ // extensions, where the extension is declared separately from the message.
const MessageDef* containing_type() const;
+ const char* containing_type_name();
+
+ // This may only be called if containing_type() == NULL (ie. the field has not
+ // been added to a message yet).
+ bool set_containing_type_name(const char *name, Status* status);
+ bool set_containing_type_name(const std::string& name, Status* status);
// The field's type according to the enum in descriptor.proto. This is not
// the same as UPB_TYPE_*, because it distinguishes between (for example)
@@ -297,6 +311,7 @@ class upb::FieldDef /* : public upb::Def */ {
void set_type(Type type);
void set_label(Label label);
void set_descriptor_type(DescriptorType type);
+ void set_is_extension(bool is_extension);
// "number" and "name" must be set before the FieldDef is added to a
// MessageDef, and may not be set after that.
@@ -395,9 +410,8 @@ class upb::FieldDef /* : public upb::Def */ {
// Before a fielddef is frozen, its subdef may be set either directly (with a
// upb::Def*) or symbolically. Symbolic refs must be resolved before the
- // containing msgdef can be frozen (see upb_resolve() above). The client is
- // responsible for making sure that "subdef" lives until this fielddef is
- // frozen or deleted.
+ // containing msgdef can be frozen (see upb_resolve() above). upb always
+ // guarantees that any def reachable from a live def will also be kept alive.
//
// Both methods require that upb_hassubdef(f) (so the type must be set prior
// to calling these methods). Returns false if this is not the case, or if
@@ -423,14 +437,19 @@ struct upb_fielddef {
float flt;
void *bytes;
} defaultval;
- const upb_msgdef *msgdef;
+ union {
+ const upb_msgdef *def; // If !msg_is_symbolic.
+ char *name; // If msg_is_symbolic.
+ } msg;
union {
const upb_def *def; // If !subdef_is_symbolic.
char *name; // If subdef_is_symbolic.
} sub; // The msgdef or enumdef for this field, if upb_hassubdef(f).
bool subdef_is_symbolic;
+ bool msg_is_symbolic;
bool default_is_string;
bool type_is_set_; // False until type is explicitly set.
+ bool is_extension_;
upb_intfmt_t intfmt;
bool tagdelim;
upb_fieldtype_t type_;
@@ -440,13 +459,14 @@ struct upb_fielddef {
uint32_t index_;
};
-#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, name, num, msgdef, \
- subdef, selector_base, index, defaultval, refs, \
- ref2s) \
- { \
- UPB_DEF_INIT(name, UPB_DEF_FIELD, refs, ref2s), defaultval, msgdef, \
- {subdef}, false, type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, \
- true, intfmt, tagdelim, type, label, num, selector_base, index \
+#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, name, \
+ num, msgdef, subdef, selector_base, index, \
+ defaultval, refs, ref2s) \
+ { \
+ UPB_DEF_INIT(name, UPB_DEF_FIELD, refs, ref2s), defaultval, {msgdef}, \
+ {subdef}, false, false, \
+ type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \
+ intfmt, tagdelim, type, label, num, selector_base, index \
}
// Native C API.
@@ -475,8 +495,10 @@ upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
upb_label_t upb_fielddef_label(const upb_fielddef *f);
uint32_t upb_fielddef_number(const upb_fielddef *f);
const char *upb_fielddef_name(const upb_fielddef *f);
+bool upb_fielddef_isextension(const upb_fielddef *f);
const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f);
+const char *upb_fielddef_containingtypename(upb_fielddef *f);
upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f);
uint32_t upb_fielddef_index(const upb_fielddef *f);
bool upb_fielddef_istagdelim(const upb_fielddef *f);
@@ -504,6 +526,9 @@ void upb_fielddef_setdescriptortype(upb_fielddef *f, int type);
void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label);
bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s);
bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s);
+bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name,
+ upb_status *s);
+bool upb_fielddef_setisextension(upb_fielddef *f, bool is_extension);
bool upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt);
bool upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim);
void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t val);
@@ -1043,9 +1068,15 @@ inline FieldDef::Label FieldDef::label() const {
}
inline uint32_t FieldDef::number() const { return upb_fielddef_number(this); }
inline const char* FieldDef::name() const { return upb_fielddef_name(this); }
+inline bool FieldDef::is_extension() const {
+ return upb_fielddef_isextension(this);
+}
inline const MessageDef* FieldDef::containing_type() const {
return upb_fielddef_containingtype(this);
}
+inline const char* FieldDef::containing_type_name() {
+ return upb_fielddef_containingtypename(this);
+}
inline bool FieldDef::set_number(uint32_t number, Status* s) {
return upb_fielddef_setnumber(this, number, s);
}
@@ -1055,9 +1086,19 @@ inline bool FieldDef::set_name(const char *name, Status* s) {
inline bool FieldDef::set_name(const std::string& name, Status* s) {
return upb_fielddef_setname(this, upb_safecstr(name), s);
}
+inline bool FieldDef::set_containing_type_name(const char *name, Status* s) {
+ return upb_fielddef_setcontainingtypename(this, name, s);
+}
+inline bool FieldDef::set_containing_type_name(const std::string &name,
+ Status *s) {
+ return upb_fielddef_setcontainingtypename(this, upb_safecstr(name), s);
+}
inline void FieldDef::set_type(upb_fieldtype_t type) {
upb_fielddef_settype(this, type);
}
+inline void FieldDef::set_is_extension(bool is_extension) {
+ upb_fielddef_setisextension(this, is_extension);
+}
inline void FieldDef::set_descriptor_type(FieldDef::DescriptorType type) {
upb_fielddef_setdescriptortype(this, type);
}
diff --git a/upb/descriptor/descriptor.upb.c b/upb/descriptor/descriptor.upb.c
index f183285..8046bcd 100755
--- a/upb/descriptor/descriptor.upb.c
+++ b/upb/descriptor/descriptor.upb.c
@@ -39,79 +39,79 @@ const upb_msgdef google_protobuf_msgs[20] = {
};
const upb_fielddef google_protobuf_fields[73] = {
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "aggregate_value", 8, &google_protobuf_msgs[18], NULL, 15, 6, {0},&reftables[40], &reftables[41]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "cc_generic_services", 16, &google_protobuf_msgs[10], NULL, 14, 5, {0},&reftables[42], &reftables[43]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "ctype", 1, &google_protobuf_msgs[7], UPB_UPCAST(&google_protobuf_enums[2]), 6, 1, {0},&reftables[44], &reftables[45]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "default_value", 7, &google_protobuf_msgs[6], NULL, 16, 7, {0},&reftables[46], &reftables[47]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, "dependency", 3, &google_protobuf_msgs[8], NULL, 30, 8, {0},&reftables[48], &reftables[49]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "deprecated", 3, &google_protobuf_msgs[7], NULL, 8, 3, {0},&reftables[50], &reftables[51]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, "double_value", 6, &google_protobuf_msgs[18], NULL, 11, 4, {0},&reftables[52], &reftables[53]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "end", 2, &google_protobuf_msgs[1], NULL, 3, 1, {0},&reftables[54], &reftables[55]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 4, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[2]), 16, 2, {0},&reftables[56], &reftables[57]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 5, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[2]), 13, 1, {0},&reftables[58], &reftables[59]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "experimental_map_key", 9, &google_protobuf_msgs[7], NULL, 9, 4, {0},&reftables[60], &reftables[61]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "extendee", 2, &google_protobuf_msgs[6], NULL, 7, 2, {0},&reftables[62], &reftables[63]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 7, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[6]), 19, 3, {0},&reftables[64], &reftables[65]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 6, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[6]), 22, 4, {0},&reftables[66], &reftables[67]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension_range", 5, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[1]), 19, 3, {0},&reftables[68], &reftables[69]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "field", 2, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[6]), 10, 0, {0},&reftables[70], &reftables[71]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "file", 1, &google_protobuf_msgs[9], UPB_UPCAST(&google_protobuf_msgs[8]), 5, 0, {0},&reftables[72], &reftables[73]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "identifier_value", 3, &google_protobuf_msgs[18], NULL, 6, 1, {0},&reftables[74], &reftables[75]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "input_type", 2, &google_protobuf_msgs[12], NULL, 7, 2, {0},&reftables[76], &reftables[77]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, "is_extension", 2, &google_protobuf_msgs[19], NULL, 5, 1, {0},&reftables[78], &reftables[79]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_generate_equals_and_hash", 20, &google_protobuf_msgs[10], NULL, 17, 8, {0},&reftables[80], &reftables[81]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_generic_services", 17, &google_protobuf_msgs[10], NULL, 15, 6, {0},&reftables[82], &reftables[83]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_multiple_files", 10, &google_protobuf_msgs[10], NULL, 13, 4, {0},&reftables[84], &reftables[85]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_outer_classname", 8, &google_protobuf_msgs[10], NULL, 9, 2, {0},&reftables[86], &reftables[87]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_package", 1, &google_protobuf_msgs[10], NULL, 6, 1, {0},&reftables[88], &reftables[89]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "label", 4, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_enums[0]), 11, 4, {0},&reftables[90], &reftables[91]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "location", 1, &google_protobuf_msgs[16], UPB_UPCAST(&google_protobuf_msgs[17]), 5, 0, {0},&reftables[92], &reftables[93]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "message_set_wire_format", 1, &google_protobuf_msgs[11], NULL, 6, 1, {0},&reftables[94], &reftables[95]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "message_type", 4, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[0]), 10, 0, {0},&reftables[96], &reftables[97]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "method", 2, &google_protobuf_msgs[14], UPB_UPCAST(&google_protobuf_msgs[12]), 6, 0, {0},&reftables[98], &reftables[99]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "name", 2, &google_protobuf_msgs[18], UPB_UPCAST(&google_protobuf_msgs[19]), 5, 0, {0},&reftables[100], &reftables[101]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[8], NULL, 22, 6, {0},&reftables[102], &reftables[103]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[14], NULL, 8, 2, {0},&reftables[104], &reftables[105]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[12], NULL, 4, 1, {0},&reftables[106], &reftables[107]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[6], NULL, 4, 1, {0},&reftables[108], &reftables[109]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[4], NULL, 4, 1, {0},&reftables[110], &reftables[111]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[2], NULL, 8, 2, {0},&reftables[112], &reftables[113]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[0], NULL, 24, 6, {0},&reftables[114], &reftables[115]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, "name_part", 1, &google_protobuf_msgs[19], NULL, 2, 0, {0},&reftables[116], &reftables[117]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, "negative_int_value", 5, &google_protobuf_msgs[18], NULL, 10, 3, {0},&reftables[118], &reftables[119]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "nested_type", 3, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[0]), 13, 1, {0},&reftables[120], &reftables[121]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "no_standard_descriptor_accessor", 2, &google_protobuf_msgs[11], NULL, 7, 2, {0},&reftables[122], &reftables[123]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "number", 2, &google_protobuf_msgs[4], NULL, 7, 2, {0},&reftables[124], &reftables[125]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "number", 3, &google_protobuf_msgs[6], NULL, 10, 3, {0},&reftables[126], &reftables[127]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "optimize_for", 9, &google_protobuf_msgs[10], UPB_UPCAST(&google_protobuf_enums[3]), 12, 3, {0},&reftables[128], &reftables[129]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[2], UPB_UPCAST(&google_protobuf_msgs[3]), 7, 1, {0},&reftables[130], &reftables[131]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[10]), 20, 4, {0},&reftables[132], &reftables[133]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[14], UPB_UPCAST(&google_protobuf_msgs[15]), 7, 1, {0},&reftables[134], &reftables[135]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 7, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[11]), 23, 5, {0},&reftables[136], &reftables[137]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 4, &google_protobuf_msgs[12], UPB_UPCAST(&google_protobuf_msgs[13]), 3, 0, {0},&reftables[138], &reftables[139]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[4], UPB_UPCAST(&google_protobuf_msgs[5]), 3, 0, {0},&reftables[140], &reftables[141]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_msgs[7]), 3, 0, {0},&reftables[142], &reftables[143]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "output_type", 3, &google_protobuf_msgs[12], NULL, 10, 3, {0},&reftables[144], &reftables[145]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "package", 2, &google_protobuf_msgs[8], NULL, 25, 7, {0},&reftables[146], &reftables[147]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "packed", 2, &google_protobuf_msgs[7], NULL, 7, 2, {0},&reftables[148], &reftables[149]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "path", 1, &google_protobuf_msgs[17], NULL, 4, 0, {0},&reftables[150], &reftables[151]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, "positive_int_value", 4, &google_protobuf_msgs[18], NULL, 9, 2, {0},&reftables[152], &reftables[153]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "py_generic_services", 18, &google_protobuf_msgs[10], NULL, 16, 7, {0},&reftables[154], &reftables[155]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "service", 6, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[14]), 16, 2, {0},&reftables[156], &reftables[157]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "source_code_info", 9, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[16]), 21, 5, {0},&reftables[158], &reftables[159]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "span", 2, &google_protobuf_msgs[17], NULL, 7, 1, {0},&reftables[160], &reftables[161]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "start", 1, &google_protobuf_msgs[1], NULL, 2, 0, {0},&reftables[162], &reftables[163]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, "string_value", 7, &google_protobuf_msgs[18], NULL, 12, 5, {0},&reftables[164], &reftables[165]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "type", 5, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_enums[1]), 12, 5, {0},&reftables[166], &reftables[167]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "type_name", 6, &google_protobuf_msgs[6], NULL, 13, 6, {0},&reftables[168], &reftables[169]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[3], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[170], &reftables[171]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[15], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[172], &reftables[173]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[11], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[174], &reftables[175]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[10], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[176], &reftables[177]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[7], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[178], &reftables[179]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[13], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[180], &reftables[181]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[5], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[182], &reftables[183]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "value", 2, &google_protobuf_msgs[2], UPB_UPCAST(&google_protobuf_msgs[4]), 6, 0, {0},&reftables[184], &reftables[185]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "aggregate_value", 8, &google_protobuf_msgs[18], NULL, 15, 6, {0},&reftables[40], &reftables[41]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, "cc_generic_services", 16, &google_protobuf_msgs[10], NULL, 14, 5, {0},&reftables[42], &reftables[43]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, "ctype", 1, &google_protobuf_msgs[7], UPB_UPCAST(&google_protobuf_enums[2]), 6, 1, {0},&reftables[44], &reftables[45]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "default_value", 7, &google_protobuf_msgs[6], NULL, 16, 7, {0},&reftables[46], &reftables[47]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, "dependency", 3, &google_protobuf_msgs[8], NULL, 30, 8, {0},&reftables[48], &reftables[49]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, "deprecated", 3, &google_protobuf_msgs[7], NULL, 8, 3, {0},&reftables[50], &reftables[51]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, "double_value", 6, &google_protobuf_msgs[18], NULL, 11, 4, {0},&reftables[52], &reftables[53]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, "end", 2, &google_protobuf_msgs[1], NULL, 3, 1, {0},&reftables[54], &reftables[55]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "enum_type", 4, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[2]), 16, 2, {0},&reftables[56], &reftables[57]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "enum_type", 5, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[2]), 13, 1, {0},&reftables[58], &reftables[59]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "experimental_map_key", 9, &google_protobuf_msgs[7], NULL, 9, 4, {0},&reftables[60], &reftables[61]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "extendee", 2, &google_protobuf_msgs[6], NULL, 7, 2, {0},&reftables[62], &reftables[63]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "extension", 7, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[6]), 19, 3, {0},&reftables[64], &reftables[65]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "extension", 6, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[6]), 22, 4, {0},&reftables[66], &reftables[67]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "extension_range", 5, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[1]), 19, 3, {0},&reftables[68], &reftables[69]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "field", 2, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[6]), 10, 0, {0},&reftables[70], &reftables[71]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "file", 1, &google_protobuf_msgs[9], UPB_UPCAST(&google_protobuf_msgs[8]), 5, 0, {0},&reftables[72], &reftables[73]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "identifier_value", 3, &google_protobuf_msgs[18], NULL, 6, 1, {0},&reftables[74], &reftables[75]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "input_type", 2, &google_protobuf_msgs[12], NULL, 7, 2, {0},&reftables[76], &reftables[77]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, "is_extension", 2, &google_protobuf_msgs[19], NULL, 5, 1, {0},&reftables[78], &reftables[79]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, "java_generate_equals_and_hash", 20, &google_protobuf_msgs[10], NULL, 17, 8, {0},&reftables[80], &reftables[81]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, "java_generic_services", 17, &google_protobuf_msgs[10], NULL, 15, 6, {0},&reftables[82], &reftables[83]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, "java_multiple_files", 10, &google_protobuf_msgs[10], NULL, 13, 4, {0},&reftables[84], &reftables[85]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "java_outer_classname", 8, &google_protobuf_msgs[10], NULL, 9, 2, {0},&reftables[86], &reftables[87]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "java_package", 1, &google_protobuf_msgs[10], NULL, 6, 1, {0},&reftables[88], &reftables[89]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, "label", 4, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_enums[0]), 11, 4, {0},&reftables[90], &reftables[91]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "location", 1, &google_protobuf_msgs[16], UPB_UPCAST(&google_protobuf_msgs[17]), 5, 0, {0},&reftables[92], &reftables[93]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, "message_set_wire_format", 1, &google_protobuf_msgs[11], NULL, 6, 1, {0},&reftables[94], &reftables[95]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "message_type", 4, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[0]), 10, 0, {0},&reftables[96], &reftables[97]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "method", 2, &google_protobuf_msgs[14], UPB_UPCAST(&google_protobuf_msgs[12]), 6, 0, {0},&reftables[98], &reftables[99]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "name", 2, &google_protobuf_msgs[18], UPB_UPCAST(&google_protobuf_msgs[19]), 5, 0, {0},&reftables[100], &reftables[101]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "name", 1, &google_protobuf_msgs[8], NULL, 22, 6, {0},&reftables[102], &reftables[103]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "name", 1, &google_protobuf_msgs[14], NULL, 8, 2, {0},&reftables[104], &reftables[105]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "name", 1, &google_protobuf_msgs[12], NULL, 4, 1, {0},&reftables[106], &reftables[107]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "name", 1, &google_protobuf_msgs[6], NULL, 4, 1, {0},&reftables[108], &reftables[109]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "name", 1, &google_protobuf_msgs[4], NULL, 4, 1, {0},&reftables[110], &reftables[111]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "name", 1, &google_protobuf_msgs[2], NULL, 8, 2, {0},&reftables[112], &reftables[113]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "name", 1, &google_protobuf_msgs[0], NULL, 24, 6, {0},&reftables[114], &reftables[115]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, "name_part", 1, &google_protobuf_msgs[19], NULL, 2, 0, {0},&reftables[116], &reftables[117]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, "negative_int_value", 5, &google_protobuf_msgs[18], NULL, 10, 3, {0},&reftables[118], &reftables[119]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "nested_type", 3, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[0]), 13, 1, {0},&reftables[120], &reftables[121]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, "no_standard_descriptor_accessor", 2, &google_protobuf_msgs[11], NULL, 7, 2, {0},&reftables[122], &reftables[123]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, "number", 2, &google_protobuf_msgs[4], NULL, 7, 2, {0},&reftables[124], &reftables[125]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, "number", 3, &google_protobuf_msgs[6], NULL, 10, 3, {0},&reftables[126], &reftables[127]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, "optimize_for", 9, &google_protobuf_msgs[10], UPB_UPCAST(&google_protobuf_enums[3]), 12, 3, {0},&reftables[128], &reftables[129]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, "options", 3, &google_protobuf_msgs[2], UPB_UPCAST(&google_protobuf_msgs[3]), 7, 1, {0},&reftables[130], &reftables[131]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, "options", 8, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[10]), 20, 4, {0},&reftables[132], &reftables[133]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, "options", 3, &google_protobuf_msgs[14], UPB_UPCAST(&google_protobuf_msgs[15]), 7, 1, {0},&reftables[134], &reftables[135]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, "options", 7, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[11]), 23, 5, {0},&reftables[136], &reftables[137]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, "options", 4, &google_protobuf_msgs[12], UPB_UPCAST(&google_protobuf_msgs[13]), 3, 0, {0},&reftables[138], &reftables[139]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, "options", 3, &google_protobuf_msgs[4], UPB_UPCAST(&google_protobuf_msgs[5]), 3, 0, {0},&reftables[140], &reftables[141]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, "options", 8, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_msgs[7]), 3, 0, {0},&reftables[142], &reftables[143]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "output_type", 3, &google_protobuf_msgs[12], NULL, 10, 3, {0},&reftables[144], &reftables[145]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "package", 2, &google_protobuf_msgs[8], NULL, 25, 7, {0},&reftables[146], &reftables[147]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, "packed", 2, &google_protobuf_msgs[7], NULL, 7, 2, {0},&reftables[148], &reftables[149]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, "path", 1, &google_protobuf_msgs[17], NULL, 4, 0, {0},&reftables[150], &reftables[151]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, "positive_int_value", 4, &google_protobuf_msgs[18], NULL, 9, 2, {0},&reftables[152], &reftables[153]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, "py_generic_services", 18, &google_protobuf_msgs[10], NULL, 16, 7, {0},&reftables[154], &reftables[155]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "service", 6, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[14]), 16, 2, {0},&reftables[156], &reftables[157]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, "source_code_info", 9, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[16]), 21, 5, {0},&reftables[158], &reftables[159]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, "span", 2, &google_protobuf_msgs[17], NULL, 7, 1, {0},&reftables[160], &reftables[161]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, "start", 1, &google_protobuf_msgs[1], NULL, 2, 0, {0},&reftables[162], &reftables[163]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, "string_value", 7, &google_protobuf_msgs[18], NULL, 12, 5, {0},&reftables[164], &reftables[165]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, "type", 5, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_enums[1]), 12, 5, {0},&reftables[166], &reftables[167]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, "type_name", 6, &google_protobuf_msgs[6], NULL, 13, 6, {0},&reftables[168], &reftables[169]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[3], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[170], &reftables[171]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[15], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[172], &reftables[173]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[11], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[174], &reftables[175]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[10], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[176], &reftables[177]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[7], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[178], &reftables[179]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[13], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[180], &reftables[181]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[5], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[182], &reftables[183]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, "value", 2, &google_protobuf_msgs[2], UPB_UPCAST(&google_protobuf_msgs[4]), 6, 0, {0},&reftables[184], &reftables[185]),
};
const upb_enumdef google_protobuf_enums[4] = {
diff --git a/upb/descriptor/reader.c b/upb/descriptor/reader.c
index 9dff6e9..eea6ce7 100644
--- a/upb/descriptor/reader.c
+++ b/upb/descriptor/reader.c
@@ -101,6 +101,7 @@ static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) {
void upb_descreader_init(upb_descreader *r, const upb_handlers *handlers,
upb_status *status) {
+ UPB_UNUSED(status);
upb_deflist_init(&r->defs);
upb_sink_reset(upb_descreader_input(r), handlers, r);
r->stack_len = 0;
@@ -176,8 +177,9 @@ static bool file_endmsg(void *closure, const void *hd, upb_status *status) {
}
static size_t file_onpackage(void *closure, const void *hd, const char *buf,
- size_t n) {
+ size_t n, const upb_bufhandle *handle) {
UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
upb_descreader *r = closure;
// XXX: see comment at the top of the file.
upb_descreader_setscopename(r, upb_strndup(buf, n));
@@ -194,8 +196,9 @@ static bool enumval_startmsg(void *closure, const void *hd) {
}
static size_t enumval_onname(void *closure, const void *hd, const char *buf,
- size_t n) {
+ size_t n, const upb_bufhandle *handle) {
UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
upb_descreader *r = closure;
// XXX: see comment at the top of the file.
free(r->name);
@@ -256,8 +259,9 @@ static bool enum_endmsg(void *closure, const void *hd, upb_status *status) {
}
static size_t enum_onname(void *closure, const void *hd, const char *buf,
- size_t n) {
+ size_t n, const upb_bufhandle *handle) {
UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
upb_descreader *r = closure;
// XXX: see comment at the top of the file.
char *fullname = upb_strndup(buf, n);
@@ -349,7 +353,8 @@ static bool field_endmsg(void *closure, const void *hd, upb_status *status) {
upb_descreader *r = closure;
upb_fielddef *f = r->f;
// TODO: verify that all required fields were present.
- assert(upb_fielddef_number(f) != 0 && upb_fielddef_name(f) != NULL);
+ assert(upb_fielddef_number(f) != 0);
+ assert(upb_fielddef_name(f) != NULL);
assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f));
if (r->default_string) {
@@ -388,13 +393,15 @@ static bool field_onlabel(void *closure, const void *hd, int32_t val) {
static bool field_onnumber(void *closure, const void *hd, int32_t val) {
UPB_UNUSED(hd);
upb_descreader *r = closure;
- upb_fielddef_setnumber(r->f, val, NULL);
+ bool ok = upb_fielddef_setnumber(r->f, val, NULL);
+ UPB_ASSERT_VAR(ok, ok);
return true;
}
static size_t field_onname(void *closure, const void *hd, const char *buf,
- size_t n) {
+ size_t n, const upb_bufhandle *handle) {
UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
upb_descreader *r = closure;
// XXX: see comment at the top of the file.
char *name = upb_strndup(buf, n);
@@ -404,8 +411,9 @@ static size_t field_onname(void *closure, const void *hd, const char *buf,
}
static size_t field_ontypename(void *closure, const void *hd, const char *buf,
- size_t n) {
+ size_t n, const upb_bufhandle *handle) {
UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
upb_descreader *r = closure;
// XXX: see comment at the top of the file.
char *name = upb_strndup(buf, n);
@@ -414,9 +422,22 @@ static size_t field_ontypename(void *closure, const void *hd, const char *buf,
return n;
}
-static size_t field_ondefaultval(void *closure, const void *hd,
- const char *buf, size_t n) {
+static size_t field_onextendee(void *closure, const void *hd, const char *buf,
+ size_t n, const upb_bufhandle *handle) {
+ UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
+ upb_descreader *r = closure;
+ // XXX: see comment at the top of the file.
+ char *name = upb_strndup(buf, n);
+ upb_fielddef_setcontainingtypename(r->f, name, NULL);
+ free(name);
+ return n;
+}
+
+static size_t field_ondefaultval(void *closure, const void *hd, const char *buf,
+ size_t n, const upb_bufhandle *handle) {
UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
upb_descreader *r = closure;
// Have to convert from string to the correct type, but we might not know the
// type yet, so we save it as a string until the end of the field.
@@ -448,8 +469,9 @@ static bool msg_endmsg(void *closure, const void *hd, upb_status *status) {
}
static size_t msg_onname(void *closure, const void *hd, const char *buf,
- size_t n) {
+ size_t n, const upb_bufhandle *handle) {
UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
upb_descreader *r = closure;
upb_msgdef *m = upb_descreader_top(r);
// XXX: see comment at the top of the file.
@@ -468,11 +490,12 @@ static bool msg_onendfield(void *closure, const void *hd) {
return true;
}
-static bool discardfield(void *closure, const void *hd) {
+static bool pushextension(void *closure, const void *hd) {
UPB_UNUSED(hd);
upb_descreader *r = closure;
- // Discard extension field so we don't leak it.
- upb_fielddef_unref(r->f, &r->defs);
+ assert(upb_fielddef_containingtypename(r->f));
+ upb_fielddef_setisextension(r->f, true);
+ upb_deflist_push(&r->defs, UPB_UPCAST(r->f));
r->f = NULL;
return true;
}
@@ -492,14 +515,12 @@ static void reghandlers(void *closure, upb_handlers *h) {
upb_handlers_setendmsg(h, &msg_endmsg, NULL);
upb_handlers_setstring(h, f(h, "name"), &msg_onname, NULL);
upb_handlers_setendsubmsg(h, f(h, "field"), &msg_onendfield, NULL);
- // TODO: support extensions
- upb_handlers_setendsubmsg(h, f(h, "extension"), &discardfield, NULL);
+ upb_handlers_setendsubmsg(h, f(h, "extension"), &pushextension, NULL);
} else if (m == GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO) {
upb_handlers_setstartmsg(h, &file_startmsg, NULL);
upb_handlers_setendmsg(h, &file_endmsg, NULL);
upb_handlers_setstring(h, f(h, "package"), &file_onpackage, NULL);
- // TODO: support extensions
- upb_handlers_setendsubmsg(h, f(h, "extension"), &discardfield, NULL);
+ upb_handlers_setendsubmsg(h, f(h, "extension"), &pushextension, NULL);
} else if (m == GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO) {
upb_handlers_setstartmsg(h, &enumval_startmsg, NULL);
upb_handlers_setendmsg(h, &enumval_endmsg, NULL);
@@ -517,6 +538,7 @@ static void reghandlers(void *closure, upb_handlers *h) {
upb_handlers_setint32(h, f(h, "number"), &field_onnumber, NULL);
upb_handlers_setstring(h, f(h, "name"), &field_onname, NULL);
upb_handlers_setstring(h, f(h, "type_name"), &field_ontypename, NULL);
+ upb_handlers_setstring(h, f(h, "extendee"), &field_onextendee, NULL);
upb_handlers_setstring(h, f(h, "default_value"), &field_ondefaultval, NULL);
}
}
diff --git a/upb/google/README b/upb/google/README
deleted file mode 100644
index a237583..0000000
--- a/upb/google/README
+++ /dev/null
@@ -1,16 +0,0 @@
-This directory contains code to interoperate with Google's official
-Protocol Buffers release. Since it doesn't really have a name
-besides "protobuf," calling this directory "google" seems like the
-least confusing option.
-
-We support writing into protobuf's generated classes (and hopefully
-reading too, before long). We support both the open source protobuf
-release and the Google-internal version of the same code. The two
-live in different namespaces, and the internal version supports some
-features that are not supported in the open-source release. Also, the
-internal version includes the legacy "proto1" classes which we must
-support; thankfully this is mostly relegated to its own separate file.
-
-Our functionality requires the full google::protobuf::Message
-interface; we rely on reflection so we know what fields to read/write
-and where to put them, so we can't support MessageLite.
diff --git a/upb/handlers-inl.h b/upb/handlers-inl.h
index a101da6..0bee5a2 100644
--- a/upb/handlers-inl.h
+++ b/upb/handlers-inl.h
@@ -91,6 +91,39 @@
#undef UPB_LONG_IS_64BITS
#undef UPB_LLONG_IS_64BITS
+// C inline methods.
+
+// upb_bufhandle
+UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h) {
+ h->obj_ = NULL;
+ h->objtype_ = NULL;
+ h->buf_ = NULL;
+ h->objofs_ = 0;
+}
+UPB_INLINE void upb_bufhandle_uninit(upb_bufhandle *h) {
+ UPB_UNUSED(h);
+}
+UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj,
+ const void *type) {
+ h->obj_ = obj;
+ h->objtype_ = type;
+}
+UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf,
+ size_t ofs) {
+ h->buf_ = buf;
+ h->objofs_ = ofs;
+}
+UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h) {
+ return h->obj_;
+}
+UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h) {
+ return h->objtype_;
+}
+UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h) {
+ return h->buf_;
+}
+
+
#ifdef __cplusplus
namespace upb {
@@ -122,8 +155,8 @@ typedef void CleanupFunc(void *ptr);
// We define a nonsense default because otherwise it will fail to instantiate as
// a function parameter type even in cases where we don't expect any caller to
// actually match the overload.
-class NonsenseType {};
-template <class T> struct remove_constptr { typedef NonsenseType type; };
+class CouldntRemoveConst {};
+template <class T> struct remove_constptr { typedef CouldntRemoveConst type; };
template <class T> struct remove_constptr<const T *> { typedef T *type; };
// Template that we use below to remove a template specialization from
@@ -133,6 +166,44 @@ template <class T> struct disable_if_same<T, T> {};
template <class T> void DeletePointer(void *p) { delete static_cast<T *>(p); }
+template <class T1, class T2>
+struct FirstUnlessVoid {
+ typedef T1 value;
+};
+
+template <class T2>
+struct FirstUnlessVoid<void, T2> {
+ typedef T2 value;
+};
+
+template<class T, class U>
+struct is_same {
+ static bool value;
+};
+
+template<class T>
+struct is_same<T, T> {
+ static bool value;
+};
+
+template<class T, class U>
+bool is_same<T, U>::value = false;
+
+template<class T>
+bool is_same<T, T>::value = true;
+
+// FuncInfo ////////////////////////////////////////////////////////////////////
+
+// Info about the user's original, pre-wrapped function.
+template <class C, class R = void>
+struct FuncInfo {
+ // The type of the closure that the function takes (its first param).
+ typedef C Closure;
+
+ // The return type.
+ typedef R Return;
+};
+
// Func ////////////////////////////////////////////////////////////////////////
// Func1, Func2, Func3: Template classes representing a function and its
@@ -147,30 +218,45 @@ struct UnboundFunc {
void *GetData() { return NULL; }
};
-template <class R, class P1, R F(P1)>
+template <class R, class P1, R F(P1), class I>
struct Func1 : public UnboundFunc {
typedef R Return;
+ typedef I FuncInfo;
static R Call(P1 p1) { return F(p1); }
};
-template <class R, class P1, class P2, R F(P1, P2)>
+template <class R, class P1, class P2, R F(P1, P2), class I>
struct Func2 : public UnboundFunc {
typedef R Return;
+ typedef I FuncInfo;
static R Call(P1 p1, P2 p2) { return F(p1, p2); }
};
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
struct Func3 : public UnboundFunc {
typedef R Return;
+ typedef I FuncInfo;
static R Call(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); }
};
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
+ class I>
struct Func4 : public UnboundFunc {
typedef R Return;
+ typedef I FuncInfo;
static R Call(P1 p1, P2 p2, P3 p3, P4 p4) { return F(p1, p2, p3, p4); }
};
+template <class R, class P1, class P2, class P3, class P4, class P5,
+ R F(P1, P2, P3, P4, P5), class I>
+struct Func5 : public UnboundFunc {
+ typedef R Return;
+ typedef I FuncInfo;
+ static R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+ return F(p1, p2, p3, p4, p5);
+ }
+};
+
// BoundFunc ///////////////////////////////////////////////////////////////////
// BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that
@@ -187,24 +273,36 @@ struct BoundFunc {
MutableP2 data;
};
-template <class R, class P1, class P2, R F(P1, P2)>
+template <class R, class P1, class P2, R F(P1, P2), class I>
struct BoundFunc2 : public BoundFunc<P2> {
typedef BoundFunc<P2> Base;
+ typedef I FuncInfo;
explicit BoundFunc2(typename Base::MutableP2 arg) : Base(arg) {}
};
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
struct BoundFunc3 : public BoundFunc<P2> {
typedef BoundFunc<P2> Base;
+ typedef I FuncInfo;
explicit BoundFunc3(typename Base::MutableP2 arg) : Base(arg) {}
};
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
+ class I>
struct BoundFunc4 : public BoundFunc<P2> {
typedef BoundFunc<P2> Base;
+ typedef I FuncInfo;
explicit BoundFunc4(typename Base::MutableP2 arg) : Base(arg) {}
};
+template <class R, class P1, class P2, class P3, class P4, class P5,
+ R F(P1, P2, P3, P4, P5), class I>
+struct BoundFunc5 : public BoundFunc<P2> {
+ typedef BoundFunc<P2> Base;
+ typedef I FuncInfo;
+ explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {}
+};
+
// FuncSig /////////////////////////////////////////////////////////////////////
// FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
@@ -215,49 +313,64 @@ struct BoundFunc4 : public BoundFunc<P2> {
template <class R, class P1>
struct FuncSig1 {
template <R F(P1)>
- Func1<R, P1, F> GetFunc() {
- return Func1<R, P1, F>();
+ Func1<R, P1, F, FuncInfo<P1, R> > GetFunc() {
+ return Func1<R, P1, F, FuncInfo<P1, R> >();
}
};
template <class R, class P1, class P2>
struct FuncSig2 {
template <R F(P1, P2)>
- Func2<R, P1, P2, F> GetFunc() {
- return Func2<R, P1, P2, F>();
+ Func2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc() {
+ return Func2<R, P1, P2, F, FuncInfo<P1, R> >();
}
template <R F(P1, P2)>
- BoundFunc2<R, P1, P2, F> GetFunc(typename remove_constptr<P2>::type param2) {
- return BoundFunc2<R, P1, P2, F>(param2);
+ BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc(
+ typename remove_constptr<P2>::type param2) {
+ return BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> >(param2);
}
};
template <class R, class P1, class P2, class P3>
struct FuncSig3 {
template <R F(P1, P2, P3)>
- Func3<R, P1, P2, P3, F> GetFunc() {
- return Func3<R, P1, P2, P3, F>();
+ Func3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc() {
+ return Func3<R, P1, P2, P3, F, FuncInfo<P1, R> >();
}
template <R F(P1, P2, P3)>
- BoundFunc3<R, P1, P2, P3, F> GetFunc(
+ BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc(
typename remove_constptr<P2>::type param2) {
- return BoundFunc3<R, P1, P2, P3, F>(param2);
+ return BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> >(param2);
}
};
template <class R, class P1, class P2, class P3, class P4>
struct FuncSig4 {
template <R F(P1, P2, P3, P4)>
- Func4<R, P1, P2, P3, P4, F> GetFunc() {
- return Func4<R, P1, P2, P3, P4, F>();
+ Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc() {
+ return Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >();
}
template <R F(P1, P2, P3, P4)>
- BoundFunc4<R, P1, P2, P3, P4, F> GetFunc(
+ BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc(
+ typename remove_constptr<P2>::type param2) {
+ return BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >(param2);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5>
+struct FuncSig5 {
+ template <R F(P1, P2, P3, P4, P5)>
+ Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc() {
+ return Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >();
+ }
+
+ template <R F(P1, P2, P3, P4, P5)>
+ BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc(
typename remove_constptr<P2>::type param2) {
- return BoundFunc4<R, P1, P2, P3, P4, F>(param2);
+ return BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >(param2);
}
};
@@ -287,6 +400,12 @@ inline FuncSig4<R, P1, P2, P3, P4> MatchFunc(R (*f)(P1, P2, P3, P4)) {
return FuncSig4<R, P1, P2, P3, P4>();
}
+template <class R, class P1, class P2, class P3, class P4, class P5>
+inline FuncSig5<R, P1, P2, P3, P4, P5> MatchFunc(R (*f)(P1, P2, P3, P4, P5)) {
+ UPB_UNUSED(f); // Only used for template parameter deduction.
+ return FuncSig5<R, P1, P2, P3, P4, P5>();
+}
+
// MethodSig ///////////////////////////////////////////////////////////////////
// CallMethod*: a function template that calls a given method.
@@ -310,6 +429,12 @@ R CallMethod3(C *obj, P1 arg1, P2 arg2, P3 arg3) {
return ((*obj).*F)(arg1, arg2, arg3);
}
+template <class R, class C, class P1, class P2, class P3, class P4,
+ R (C::*F)(P1, P2, P3, P4)>
+R CallMethod4(C *obj, P1 arg1, P2 arg2, P3 arg3, P4 arg4) {
+ return ((*obj).*F)(arg1, arg2, arg3, arg4);
+}
+
// MethodSig: like FuncSig, but for member functions.
//
// GetFunc() returns a normal FuncN object, so after calling GetFunc() no
@@ -317,50 +442,77 @@ R CallMethod3(C *obj, P1 arg1, P2 arg2, P3 arg3) {
template <class R, class C>
struct MethodSig0 {
template <R (C::*F)()>
- Func1<R, C *, CallMethod0<R, C, F> > GetFunc() {
- return Func1<R, C *, CallMethod0<R, C, F> >();
+ Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> > GetFunc() {
+ return Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> >();
}
};
template <class R, class C, class P1>
struct MethodSig1 {
template <R (C::*F)(P1)>
- Func2<R, C *, P1, CallMethod1<R, C, P1, F> > GetFunc() {
- return Func2<R, C *, P1, CallMethod1<R, C, P1, F> >();
+ Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc() {
+ return Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >();
}
template <R (C::*F)(P1)>
- BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F> > GetFunc(
+ BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc(
typename remove_constptr<P1>::type param1) {
- return BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F> >(param1);
+ return BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >(
+ param1);
}
};
template <class R, class C, class P1, class P2>
struct MethodSig2 {
template <R (C::*F)(P1, P2)>
- Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F> > GetFunc() {
- return Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F> >();
+ Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
+ GetFunc() {
+ return Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
+ FuncInfo<C *, R> >();
}
template <R (C::*F)(P1, P2)>
- BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F> > GetFunc(
- typename remove_constptr<P1>::type param1) {
- return BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F> >(param1);
+ BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
+ GetFunc(typename remove_constptr<P1>::type param1) {
+ return BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
+ FuncInfo<C *, R> >(param1);
}
};
template <class R, class C, class P1, class P2, class P3>
struct MethodSig3 {
template <R (C::*F)(P1, P2, P3)>
- Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F> > GetFunc() {
- return Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F> >();
+ Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>, FuncInfo<C *, R> >
+ GetFunc() {
+ return Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
+ FuncInfo<C *, R> >();
}
template <R (C::*F)(P1, P2, P3)>
- BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F> > GetFunc(
- typename remove_constptr<P1>::type param1) {
- return BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F> >(
+ BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
+ FuncInfo<C *, R> >
+ GetFunc(typename remove_constptr<P1>::type param1) {
+ return BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
+ FuncInfo<C *, R> >(param1);
+ }
+};
+
+template <class R, class C, class P1, class P2, class P3, class P4>
+struct MethodSig4 {
+ template <R (C::*F)(P1, P2, P3, P4)>
+ Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
+ FuncInfo<C *, R> >
+ GetFunc() {
+ return Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
+ FuncInfo<C *, R> >();
+ }
+
+ template <R (C::*F)(P1, P2, P3, P4)>
+ BoundFunc5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
+ FuncInfo<C *, R> >
+ GetFunc(typename remove_constptr<P1>::type param1) {
+ return BoundFunc5<R, C *, P1, P2, P3, P4,
+ CallMethod4<R, C, P1, P2, P3, P4, F>, FuncInfo<C *, R> >(
param1);
}
};
@@ -389,6 +541,12 @@ inline MethodSig3<R, C, P1, P2, P3> MatchFunc(R (C::*f)(P1, P2, P3)) {
return MethodSig3<R, C, P1, P2, P3>();
}
+template <class R, class C, class P1, class P2, class P3, class P4>
+inline MethodSig4<R, C, P1, P2, P3, P4> MatchFunc(R (C::*f)(P1, P2, P3, P4)) {
+ UPB_UNUSED(f); // Only used for template parameter deduction.
+ return MethodSig4<R, C, P1, P2, P3, P4>();
+}
+
// MaybeWrapReturn /////////////////////////////////////////////////////////////
// Template class that attempts to wrap the return value of the function so it
@@ -448,58 +606,62 @@ void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) {
return F(p1, p2, p3);
}
-// For the string callback, which takes four params, returns the last param
-// which is the size of the entire string.
-template <class P1, class P2, class P3, void F(P1, P2, P3, size_t)>
-size_t ReturnStringLen(P1 p1, P2 p2, P3 p3, size_t p4) {
- F(p1, p2, p3, p4);
+// For the string callback, which takes five params, returns the size param.
+template <class P1, class P2,
+ void F(P1, P2, const char *, size_t, const BufferHandle *)>
+size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4,
+ const BufferHandle *p5) {
+ F(p1, p2, p3, p4, p5);
return p4;
}
// If we have a function returning void but want a function returning bool, wrap
// it in a function that returns true.
-template <class P1, class P2, void F(P1, P2)>
-struct MaybeWrapReturn<Func2<void, P1, P2, F>, bool> {
- typedef Func2<bool, P1, P2, ReturnTrue2<P1, P2, F> > Func;
+template <class P1, class P2, void F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, bool> {
+ typedef Func2<bool, P1, P2, ReturnTrue2<P1, P2, F>, I> Func;
};
-template <class P1, class P2, class P3, void F(P1, P2, P3)>
-struct MaybeWrapReturn<Func3<void, P1, P2, P3, F>, bool> {
- typedef Func3<bool, P1, P2, P3, ReturnTrue3<P1, P2, P3, F> > Func;
+template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, bool> {
+ typedef Func3<bool, P1, P2, P3, ReturnTrue3<P1, P2, P3, F>, I> Func;
};
// If our function returns void but we want one returning void*, wrap it in a
// function that returns the first argument.
-template <class P1, class P2, void F(P1, P2)>
-struct MaybeWrapReturn<Func2<void, P1, P2, F>, void *> {
- typedef Func2<void *, P1, P2, ReturnClosure2<P1, P2, F> > Func;
+template <class P1, class P2, void F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, void *> {
+ typedef Func2<void *, P1, P2, ReturnClosure2<P1, P2, F>, I> Func;
};
-template <class P1, class P2, class P3, void F(P1, P2, P3)>
-struct MaybeWrapReturn<Func3<void, P1, P2, P3, F>, void *> {
- typedef Func3<void *, P1, P2, P3, ReturnClosure3<P1, P2, P3, F> > Func;
+template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, void *> {
+ typedef Func3<void *, P1, P2, P3, ReturnClosure3<P1, P2, P3, F>, I> Func;
};
// If our function returns void but we want one returning size_t, wrap it in a
-// function that returns the last argument.
-template <class P1, class P2, class P3, void F(P1, P2, P3, size_t)>
-struct MaybeWrapReturn<Func4<void, P1, P2, P3, size_t, F>, size_t> {
- typedef Func4<size_t, P1, P2, P3, size_t, ReturnStringLen<P1, P2, P3, F> >
- Func;
+// function that returns the size argument.
+template <class P1, class P2,
+ void F(P1, P2, const char *, size_t, const BufferHandle *), class I>
+struct MaybeWrapReturn<
+ Func5<void, P1, P2, const char *, size_t, const BufferHandle *, F, I>,
+ size_t> {
+ typedef Func5<size_t, P1, P2, const char *, size_t, const BufferHandle *,
+ ReturnStringLen<P1, P2, F>, I> Func;
};
// If our function returns R* but we want one returning void*, wrap it in a
// function that casts to void*.
-template <class R, class P1, class P2, R *F(P1, P2)>
-struct MaybeWrapReturn<Func2<R *, P1, P2, F>, void *,
+template <class R, class P1, class P2, R *F(P1, P2), class I>
+struct MaybeWrapReturn<Func2<R *, P1, P2, F, I>, void *,
typename disable_if_same<R *, void *>::Type> {
- typedef Func2<void *, P1, P2, CastReturnToVoidPtr2<R *, P1, P2, F> > Func;
+ typedef Func2<void *, P1, P2, CastReturnToVoidPtr2<R *, P1, P2, F>, I> Func;
};
-template <class R, class P1, class P2, class P3, R *F(P1, P2, P3)>
-struct MaybeWrapReturn<Func3<R *, P1, P2, P3, F>, void *,
+template <class R, class P1, class P2, class P3, R *F(P1, P2, P3), class I>
+struct MaybeWrapReturn<Func3<R *, P1, P2, P3, F, I>, void *,
typename disable_if_same<R *, void *>::Type> {
- typedef Func3<void *, P1, P2, P3, CastReturnToVoidPtr3<R *, P1, P2, P3, F> >
+ typedef Func3<void *, P1, P2, P3, CastReturnToVoidPtr3<R *, P1, P2, P3, F>, I>
Func;
};
@@ -532,6 +694,20 @@ R IgnoreHandlerData4(void *p1, const void *hd, P2 p2, P3 p3) {
return F(static_cast<P1>(p1), p2, p3);
}
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
+R IgnoreHandlerData5(void *p1, const void *hd, P2 p2, P3 p3, P4 p4) {
+ UPB_UNUSED(hd);
+ return F(static_cast<P1>(p1), p2, p3, p4);
+}
+
+template <class R, class P1, R F(P1, const char*, size_t)>
+R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2,
+ size_t p3, const BufferHandle *handle) {
+ UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
+ return F(static_cast<P1>(p1), p2, p3);
+}
+
// Function that casts the handler data parameter.
template <class R, class P1, class P2, R F(P1, P2)>
R CastHandlerData2(void *c, const void *hd) {
@@ -544,47 +720,75 @@ R CastHandlerData3(void *c, const void *hd, P3Wrapper p3) {
return F(static_cast<P1>(c), static_cast<P2>(hd), p3);
}
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
-R CastHandlerData4(void *c, const void *hd, P3 p3, P4 p4) {
+template <class R, class P1, class P2, class P3, class P4, class P5,
+ R F(P1, P2, P3, P4, P5)>
+R CastHandlerData5(void *c, const void *hd, P3 p3, P4 p4, P5 p5) {
+ return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4, p5);
+}
+
+template <class R, class P1, class P2, R F(P1, P2, const char *, size_t)>
+R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3,
+ size_t p4, const BufferHandle *handle) {
+ UPB_UNUSED(handle);
return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4);
}
// For unbound functions, ignore the handler data.
-template <class R, class P1, R F(P1)>
-struct ConvertParams<Func1<R, P1, F> > {
- typedef Func2<R, void *, const void *, IgnoreHandlerData2<R, P1, F> > Func;
+template <class R, class P1, R F(P1), class I>
+struct ConvertParams<Func1<R, P1, F, I> > {
+ typedef Func2<R, void *, const void *, IgnoreHandlerData2<R, P1, F>, I> Func;
};
-template <class R, class P1, class P2, R F(P1, P2)>
-struct ConvertParams<Func2<R, P1, P2, F> > {
+template <class R, class P1, class P2, R F(P1, P2), class I>
+struct ConvertParams<Func2<R, P1, P2, F, I> > {
typedef typename CanonicalType<P2>::Type CanonicalP2;
typedef Func3<R, void *, const void *, CanonicalP2,
- IgnoreHandlerData3<R, P1, CanonicalP2, P2, F> > Func;
+ IgnoreHandlerData3<R, P1, CanonicalP2, P2, F>, I> Func;
};
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
-struct ConvertParams<Func3<R, P1, P2, P3, F> > {
- typedef Func4<R, void *, const void *, P2, P3,
- IgnoreHandlerData4<R, P1, P2, P3, F> > Func;
+// For StringBuffer only; this ignores both the handler data and the
+// BufferHandle.
+template <class R, class P1, R F(P1, const char *, size_t), class I>
+struct ConvertParams<Func3<R, P1, const char *, size_t, F, I> > {
+ typedef Func5<R, void *, const void *, const char *, size_t,
+ const BufferHandle *, IgnoreHandlerDataIgnoreHandle<R, P1, F>,
+ I> Func;
+};
+
+template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4), class I>
+struct ConvertParams<Func4<R, P1, P2, P3, P4, F, I> > {
+ typedef Func5<R, void *, const void *, P2, P3, P4,
+ IgnoreHandlerData5<R, P1, P2, P3, P4, F>, I> Func;
};
// For bound functions, cast the handler data.
-template <class R, class P1, class P2, R F(P1, P2)>
-struct ConvertParams<BoundFunc2<R, P1, P2, F> > {
- typedef Func2<R, void *, const void *, CastHandlerData2<R, P1, P2, F> > Func;
+template <class R, class P1, class P2, R F(P1, P2), class I>
+struct ConvertParams<BoundFunc2<R, P1, P2, F, I> > {
+ typedef Func2<R, void *, const void *, CastHandlerData2<R, P1, P2, F>, I>
+ Func;
};
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
-struct ConvertParams<BoundFunc3<R, P1, P2, P3, F> > {
+template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
+struct ConvertParams<BoundFunc3<R, P1, P2, P3, F, I> > {
typedef typename CanonicalType<P3>::Type CanonicalP3;
typedef Func3<R, void *, const void *, CanonicalP3,
- CastHandlerData3<R, P1, P2, CanonicalP3, P3, F> > Func;
+ CastHandlerData3<R, P1, P2, CanonicalP3, P3, F>, I> Func;
};
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
-struct ConvertParams<BoundFunc4<R, P1, P2, P3, P4, F> > {
- typedef Func4<R, void *, const void *, P3, P4,
- CastHandlerData4<R, P1, P2, P3, P4, F> > Func;
+// For StringBuffer only; this ignores the BufferHandle.
+template <class R, class P1, class P2, R F(P1, P2, const char *, size_t),
+ class I>
+struct ConvertParams<BoundFunc4<R, P1, P2, const char *, size_t, F, I> > {
+ typedef Func5<R, void *, const void *, const char *, size_t,
+ const BufferHandle *, CastHandlerDataIgnoreHandle<R, P1, P2, F>,
+ I> Func;
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5,
+ R F(P1, P2, P3, P4, P5), class I>
+struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I> > {
+ typedef Func5<R, void *, const void *, P3, P4, P5,
+ CastHandlerData5<R, P1, P2, P3, P4, P5, F>, I> Func;
};
// utype/ltype are upper/lower-case, ctype is canonical C type, vtype is
@@ -659,6 +863,16 @@ struct ReturnOf<R (*)(P1, P2, P3, P4)> {
typedef R Return;
};
+template <class R, class P1, class P2, class P3, class P4, class P5>
+struct ReturnOf<R (*)(P1, P2, P3, P4, P5)> {
+ typedef R Return;
+};
+
+template<class T> const void *UniquePtrForType() {
+ static const char ch = 0;
+ return &ch;
+}
+
template <class T>
template <class F>
inline Handler<T>::Handler(F func)
@@ -669,6 +883,25 @@ inline Handler<T>::Handler(F func)
typedef typename MaybeWrapReturn<ConvertedParamsFunc, Return>::Func
ReturnWrappedFunc;
handler_ = ReturnWrappedFunc().Call;
+
+ // Set attributes based on what templates can statically tell us about the
+ // user's function.
+
+ // If the original function returns void, then we know that we wrapped it to
+ // always return ok.
+ bool always_ok = is_same<typename F::FuncInfo::Return, void>::value;
+ attr_.SetAlwaysOk(always_ok);
+
+ // Closure parameter and return type.
+ attr_.SetClosureType(UniquePtrForType<typename F::FuncInfo::Closure>());
+
+ // We use the closure type (from the first parameter) if the return type is
+ // void. This is all nonsense for non START* handlers, but it doesn't matter
+ // because in that case the value will be ignored.
+ typedef typename FirstUnlessVoid<typename F::FuncInfo::Return,
+ typename F::FuncInfo::Closure>::value
+ EffectiveReturn;
+ attr_.SetReturnClosureType(UniquePtrForType<EffectiveReturn>());
}
template <class T>
@@ -682,6 +915,49 @@ inline bool HandlerAttributes::SetHandlerData(void *hd,
upb_handlerfree *cleanup) {
return upb_handlerattr_sethandlerdata(this, hd, cleanup);
}
+inline const void* HandlerAttributes::handler_data() const {
+ return upb_handlerattr_handlerdata(this);
+}
+inline bool HandlerAttributes::SetClosureType(const void *type) {
+ return upb_handlerattr_setclosuretype(this, type);
+}
+inline const void* HandlerAttributes::closure_type() const {
+ return upb_handlerattr_closuretype(this);
+}
+inline bool HandlerAttributes::SetReturnClosureType(const void *type) {
+ return upb_handlerattr_setreturnclosuretype(this, type);
+}
+inline const void* HandlerAttributes::return_closure_type() const {
+ return upb_handlerattr_returnclosuretype(this);
+}
+inline bool HandlerAttributes::SetAlwaysOk(bool always_ok) {
+ return upb_handlerattr_setalwaysok(this, always_ok);
+}
+inline bool HandlerAttributes::always_ok() const {
+ return upb_handlerattr_alwaysok(this);
+}
+
+inline BufferHandle::BufferHandle() { upb_bufhandle_init(this); }
+inline BufferHandle::~BufferHandle() { upb_bufhandle_uninit(this); }
+inline const char* BufferHandle::buffer() const {
+ return upb_bufhandle_buf(this);
+}
+inline size_t BufferHandle::object_offset() const {
+ return upb_bufhandle_objofs(this);
+}
+inline void BufferHandle::SetBuffer(const char* buf, size_t ofs) {
+ upb_bufhandle_setbuf(this, buf, ofs);
+}
+template <class T>
+void BufferHandle::SetAttachedObject(const T* obj) {
+ upb_bufhandle_setobj(this, obj, UniquePtrForType<T>());
+}
+template <class T>
+const T* BufferHandle::GetAttachedObject() const {
+ return upb_bufhandle_objtype(this) == UniquePtrForType<T>()
+ ? static_cast<const T *>(upb_bufhandle_obj(this))
+ : NULL;
+}
inline reffed_ptr<Handlers> Handlers::New(const MessageDef *m) {
upb_handlers *h = upb_handlers_new(m, &h);
@@ -803,10 +1079,19 @@ inline const void *Handlers::GetHandlerData(Handlers::Selector selector) {
return upb_handlers_gethandlerdata(this, selector);
}
+inline BytesHandler::BytesHandler() {
+ upb_byteshandler_init(this);
+}
+
+inline BytesHandler::~BytesHandler() {
+ upb_byteshandler_uninit(this);
+}
+
} // namespace upb
#endif // __cplusplus
+
#undef UPB_TWO_32BIT_TYPES
#undef UPB_TWO_64BIT_TYPES
#undef UPB_INT32_T
diff --git a/upb/handlers.c b/upb/handlers.c
index baa3e06..006ff83 100644
--- a/upb/handlers.c
+++ b/upb/handlers.c
@@ -92,8 +92,8 @@ oom:
// The selector for a submessage field is the field index.
#define SUBH_F(h, f) SUBH(h, f->index_)
-static int32_t getsel(upb_handlers *h, const upb_fielddef *f,
- upb_handlertype_t type) {
+static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
+ upb_handlertype_t type) {
upb_selector_t sel;
assert(!upb_handlers_isfrozen(h));
if (upb_handlers_msgdef(h) != upb_fielddef_containingtype(f)) {
@@ -112,7 +112,20 @@ static int32_t getsel(upb_handlers *h, const upb_fielddef *f,
return sel;
}
-static bool doset(upb_handlers *h, int32_t sel, upb_func *func,
+static upb_selector_t getsel(upb_handlers *h, const upb_fielddef *f,
+ upb_handlertype_t type) {
+ int32_t sel = trygetsel(h, f, type);
+ assert(sel >= 0);
+ return sel;
+}
+
+static const void **returntype(upb_handlers *h, const upb_fielddef *f,
+ upb_handlertype_t type) {
+ return &h->table[getsel(h, f, type)].attr.return_closure_type_;
+}
+
+static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
+ upb_handlertype_t type, upb_func *func,
upb_handlerattr *attr) {
assert(!upb_handlers_isfrozen(h));
@@ -133,11 +146,103 @@ static bool doset(upb_handlers *h, int32_t sel, upb_func *func,
set_attr = *attr;
}
+ // Check that the given closure type matches the closure type that has been
+ // established for this context (if any).
+ const void *closure_type = upb_handlerattr_closuretype(&set_attr);
+ const void **context_closure_type;
+
+ if (type == UPB_HANDLER_STRING) {
+ context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR);
+ } else if (f && upb_fielddef_isseq(f) &&
+ type != UPB_HANDLER_STARTSEQ &&
+ type != UPB_HANDLER_ENDSEQ) {
+ context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ);
+ } else {
+ context_closure_type = &h->top_closure_type;
+ }
+
+ if (closure_type && *context_closure_type &&
+ closure_type != *context_closure_type) {
+ // TODO(haberman): better message for debugging.
+ upb_status_seterrmsg(&h->status_, "closure type does not match");
+ return false;
+ }
+
+ if (closure_type)
+ *context_closure_type = closure_type;
+
+ // If this is a STARTSEQ or STARTSTR handler, check that the returned pointer
+ // matches any pre-existing expectations about what type is expected.
+ if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) {
+ const void *return_type = upb_handlerattr_returnclosuretype(&set_attr);
+ const void *table_return_type =
+ upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+ if (return_type && table_return_type && return_type != table_return_type) {
+ upb_status_seterrmsg(&h->status_, "closure return type does not match");
+ return false;
+ }
+
+ if (table_return_type && !return_type)
+ upb_handlerattr_setreturnclosuretype(&set_attr, table_return_type);
+ }
+
h->table[sel].func = (upb_func*)func;
h->table[sel].attr = set_attr;
return true;
}
+// Returns the effective closure type for this handler (which will propagate
+// from outer frames if this frame has no START* handler). Not implemented for
+// UPB_HANDLER_STRING at the moment since this is not needed. Returns NULL is
+// the effective closure type is unspecified (either no handler was registered
+// to specify it or the handler that was registered did not specify the closure
+// type).
+const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
+ upb_handlertype_t type) {
+ assert(type != UPB_HANDLER_STRING);
+ const void *ret = h->top_closure_type;
+ upb_selector_t sel;
+ if (upb_fielddef_isseq(f) &&
+ type != UPB_HANDLER_STARTSEQ &&
+ type != UPB_HANDLER_ENDSEQ &&
+ h->table[sel = getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
+ ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+ }
+
+ if (type == UPB_HANDLER_STRING &&
+ h->table[sel = getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
+ ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+ }
+
+ // The effective type of the submessage; not used yet.
+ // if (type == SUBMESSAGE &&
+ // h->table[sel = getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
+ // ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
+ // }
+
+ return ret;
+}
+
+// Checks whether the START* handler specified by f & type is missing even
+// though it is required to convert the established type of an outer frame
+// ("closure_type") into the established type of an inner frame (represented in
+// the return closure type of this handler's attr.
+bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type,
+ upb_status *status) {
+ upb_selector_t sel = getsel(h, f, type);
+ if (h->table[sel].func) return true;
+ const void *closure_type = effective_closure_type(h, f, type);
+ const upb_handlerattr *attr = &h->table[sel].attr;
+ const void *return_closure_type = upb_handlerattr_returnclosuretype(attr);
+ if (closure_type && return_closure_type &&
+ closure_type != return_closure_type) {
+ upb_status_seterrf(status,
+ "expected start handler to return sub type for field %f",
+ upb_fielddef_name(f));
+ return false;
+ }
+ return true;
+}
/* Public interface ***********************************************************/
@@ -218,8 +323,8 @@ void upb_handlers_clearerr(upb_handlers *h) {
#define SETTER(name, handlerctype, handlertype) \
bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \
handlerctype func, upb_handlerattr *attr) { \
- int32_t sel = getsel(h, f, handlertype); \
- return doset(h, sel, (upb_func*)func, attr); \
+ int32_t sel = trygetsel(h, f, handlertype); \
+ return doset(h, sel, f, handlertype, (upb_func*)func, attr); \
}
SETTER(int32, upb_int32_handlerfunc*, UPB_HANDLER_INT32);
@@ -241,13 +346,15 @@ SETTER(endseq, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSEQ);
bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
upb_handlerattr *attr) {
- return doset(h, UPB_STARTMSG_SELECTOR, (upb_func*)func, attr);
+ return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
+ (upb_func *)func, attr);
}
bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
upb_handlerattr *attr) {
assert(!upb_handlers_isfrozen(h));
- return doset(h, UPB_ENDMSG_SELECTOR, (upb_func*)func, attr);
+ return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
+ (upb_func *)func, attr);
}
bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
@@ -270,6 +377,14 @@ const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
return SUBH_F(h, f);
}
+bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel,
+ upb_handlerattr *attr) {
+ if (!upb_handlers_gethandler(h, sel))
+ return false;
+ *attr = h->table[sel].attr;
+ return true;
+}
+
const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
upb_selector_t sel) {
// STARTSUBMSG selector in sel is the field's selector base.
@@ -284,12 +399,37 @@ const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) {
// TODO: verify we have a transitive closure.
for (int i = 0; i < n; i++) {
- if (!upb_ok(&handlers[i]->status_)) {
+ upb_handlers *h = handlers[i];
+
+ if (!upb_ok(&h->status_)) {
upb_status_seterrf(s, "handlers for message %s had error status: %s",
- upb_msgdef_fullname(upb_handlers_msgdef(handlers[i])),
- upb_status_errmsg(&handlers[i]->status_));
+ upb_msgdef_fullname(upb_handlers_msgdef(h)),
+ upb_status_errmsg(&h->status_));
return false;
}
+
+ // Check that there are no closure mismatches due to missing Start* handlers
+ // or subhandlers with different type-level types.
+ upb_msg_iter j;
+ for(upb_msg_begin(&j, h->msg); !upb_msg_done(&j); upb_msg_next(&j)) {
+
+ const upb_fielddef *f = upb_msg_iter_field(&j);
+ if (upb_fielddef_isseq(f)) {
+ if (!checkstart(h, f, UPB_HANDLER_STARTSEQ, s))
+ return false;
+ }
+
+ if (upb_fielddef_isstring(f)) {
+ if (!checkstart(h, f, UPB_HANDLER_STARTSTR, s))
+ return false;
+ }
+
+ if (upb_fielddef_issubmsg(f)) {
+ // TODO(haberman): check type of submessage.
+ // This is slightly tricky; also consider whether we should check that
+ // they match at setsubhandlers time.
+ }
+ }
}
if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s,
@@ -394,13 +534,44 @@ void upb_handlerattr_uninit(upb_handlerattr *attr) {
bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, void *hd,
upb_handlerfree *cleanup) {
- if (attr->handler_data_)
- return false;
attr->handler_data_ = hd;
attr->cleanup = cleanup;
return true;
}
+bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type) {
+ attr->closure_type_ = type;
+ return true;
+}
+
+const void *upb_handlerattr_closuretype(const upb_handlerattr *attr) {
+ return attr->closure_type_;
+}
+
+bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr,
+ const void *type) {
+ attr->return_closure_type_ = type;
+ return true;
+}
+
+const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr) {
+ return attr->return_closure_type_;
+}
+
+bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok) {
+ attr->alwaysok_ = alwaysok;
+ return true;
+}
+
+bool upb_handlerattr_alwaysok(const upb_handlerattr *attr) {
+ return attr->alwaysok_;
+}
+
+/* upb_bufhandle **************************************************************/
+
+size_t upb_bufhandle_objofs(const upb_bufhandle *h) {
+ return h->objofs_;
+}
/* upb_byteshandler ***********************************************************/
diff --git a/upb/handlers.h b/upb/handlers.h
index ceb559f..a03c99e 100644
--- a/upb/handlers.h
+++ b/upb/handlers.h
@@ -27,18 +27,26 @@
#ifdef __cplusplus
namespace upb {
+class BufferHandle;
+class BytesHandler;
class HandlerAttributes;
class Handlers;
template <class T> class Handler;
template <class T> struct CanonicalType;
} // namespace upb
+typedef upb::BufferHandle upb_bufhandle;
+typedef upb::BytesHandler upb_byteshandler;
typedef upb::HandlerAttributes upb_handlerattr;
typedef upb::Handlers upb_handlers;
#else
+struct upb_bufhandle;
+struct upb_byteshandler;
struct upb_handlerattr;
struct upb_handlers;
struct upb_sinkframe;
+typedef struct upb_bufhandle upb_bufhandle;
+typedef struct upb_byteshandler upb_byteshandler;
typedef struct upb_handlerattr upb_handlerattr;
typedef struct upb_handlers upb_handlers;
typedef struct upb_sinkframe upb_sinkframe;
@@ -89,12 +97,23 @@ typedef void upb_func();
extern "C" {
#endif
+// Forward-declares for C inline accessors. We need to declare these here
+// so we can "friend" them in the class declarations in C++.
UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h,
upb_selector_t s);
UPB_INLINE const void *upb_handlerattr_handlerdata(const upb_handlerattr *attr);
UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h,
upb_selector_t s);
+UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h);
+UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj,
+ const void *type);
+UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf,
+ size_t ofs);
+UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h);
+UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h);
+UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h);
+
#ifdef __cplusplus
}
#endif
@@ -114,6 +133,7 @@ typedef void upb_handlerfree(void *d);
#ifdef __cplusplus
+// A set of attributes that accompanies a handler's function pointer.
class upb::HandlerAttributes {
public:
HandlerAttributes();
@@ -126,7 +146,27 @@ class upb::HandlerAttributes {
// cleanup handler will be called once for each handler it was successfully
// set on.
bool SetHandlerData(void *handler_data, upb_handlerfree *cleanup);
- void *handler_data() const;
+ const void* handler_data() const;
+
+ // Use this to specify the type of the closure. This will be checked against
+ // all other closure types for handler that use the same closure.
+ // Registration will fail if this does not match all other non-NULL closure
+ // types.
+ bool SetClosureType(const void *closure_type);
+ const void* closure_type() const;
+
+ // Use this to specify the type of the returned closure. Only used for
+ // Start*{String,SubMessage,Sequence} handlers. This must match the closure
+ // type of any handlers that use it (for example, the StringBuf handler must
+ // match the closure returned from StartString).
+ bool SetReturnClosureType(const void *return_closure_type);
+ const void* return_closure_type() const;
+
+ // Set to indicate that the handler always returns "ok" (either "true" or a
+ // non-NULL closure). This is a hint that can allow code generators to
+ // generate more efficient code.
+ bool SetAlwaysOk(bool always_ok);
+ bool always_ok() const;
private:
friend UPB_INLINE const void * ::upb_handlerattr_handlerdata(
@@ -137,15 +177,81 @@ struct upb_handlerattr {
#endif
void *handler_data_;
upb_handlerfree *cleanup;
+ const void *closure_type_;
+ const void *return_closure_type_;
+ bool alwaysok_;
};
+#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, NULL, false}
+
typedef struct {
upb_func *func;
+ // It is wasteful to include the entire attributes here:
+ //
+ // * Some of the information is redundant (like storing the closure type
+ // separately for each handler that must match).
+ // * Some of the info is only needed prior to freeze() (like closure types).
+ // * alignment padding wastes a lot of space for alwaysok_.
+ //
+ // If/when the size and locality of handlers is an issue, we can optimize this
+ // not to store the entire attr like this. We do not expose the table's
+ // layout to allow this optimization in the future.
upb_handlerattr attr;
} upb_handlers_tabent;
#ifdef __cplusplus
+// Extra information about a buffer that is passed to a StringBuf handler.
+// TODO(haberman): allow the handle to be pinned so that it will outlive
+// the handler invocation.
+class upb::BufferHandle {
+ public:
+ BufferHandle();
+ ~BufferHandle();
+
+ // The beginning of the buffer. This may be different than the pointer
+ // passed to a StringBuf handler because the handler may receive data
+ // that is from the middle or end of a larger buffer.
+ const char* buffer() const;
+
+ // The offset within the attached object where this buffer begins. Only
+ // meaningful if there is an attached object.
+ size_t object_offset() const;
+
+ // Note that object_offset is the offset of "buf" within the attached object.
+ void SetBuffer(const char* buf, size_t object_offset);
+
+ // The BufferHandle can have an "attached object", which can be used to
+ // tunnel through a pointer to the buffer's underlying representation.
+ template <class T>
+ void SetAttachedObject(const T* obj);
+
+ // Returns NULL if the attached object is not of this type.
+ template <class T>
+ const T* GetAttachedObject() const;
+
+ private:
+ friend UPB_INLINE void ::upb_bufhandle_init(upb_bufhandle *h);
+ friend UPB_INLINE void ::upb_bufhandle_setobj(upb_bufhandle *h,
+ const void *obj,
+ const void *type);
+ friend UPB_INLINE void ::upb_bufhandle_setbuf(upb_bufhandle *h,
+ const char *buf, size_t ofs);
+ friend UPB_INLINE const void* ::upb_bufhandle_obj(const upb_bufhandle *h);
+ friend UPB_INLINE const void* ::upb_bufhandle_objtype(
+ const upb_bufhandle *h);
+ friend UPB_INLINE const char* ::upb_bufhandle_buf(const upb_bufhandle *h);
+#else
+struct upb_bufhandle {
+#endif
+ const char *buf_;
+ const void *obj_;
+ const void *objtype_;
+ size_t objofs_;
+};
+
+#ifdef __cplusplus
+
// A upb::Handlers object represents the set of handlers associated with a
// message in the graph of messages. You can think of it as a big virtual
// table with functions corresponding to all the events that can fire while
@@ -167,8 +273,8 @@ class upb::Handlers {
typedef Handler<bool (*)(void *, const void *)> StartMessageHandler;
typedef Handler<bool (*)(void *, const void *, Status*)> EndMessageHandler;
typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler;
- typedef Handler<size_t(*)(void *, const void *, const char *, size_t)>
- StringHandler;
+ typedef Handler<size_t (*)(void *, const void *, const char *, size_t,
+ const BufferHandle *)> StringHandler;
template <class T> struct ValueHandler {
typedef Handler<bool(*)(void *, const void *, T)> H;
@@ -224,7 +330,7 @@ class upb::Handlers {
// Freezes the given set of handlers. You may not freeze a handler without
// also freezing any handlers they point to.
static bool Freeze(Handlers*const* handlers, int n, Status* s);
- static bool Freeze(const vector<Handlers*>& handlers, Status* s);
+ static bool Freeze(const std::vector<Handlers*>& handlers, Status* s);
// Returns the msgdef associated with this handlers object.
const MessageDef* message_def() const;
@@ -401,6 +507,9 @@ class upb::Handlers {
// responsibility to cast to the correct function type before calling it.
GenericFunction* GetHandler(Selector selector);
+ // Sets the given attributes to the attributes for this selector.
+ bool GetAttributes(Selector selector, HandlerAttributes* attr);
+
// Returns the handler data that was registered with this handler.
const void* GetHandlerData(Selector selector);
@@ -424,6 +533,7 @@ struct upb_handlers {
upb_refcounted base;
const upb_msgdef *msg;
const upb_handlers **sub;
+ const void *top_closure_type;
upb_status status_; // Used only when mutable.
upb_handlers_tabent table[1]; // Dynamically-sized field handler array.
};
@@ -538,31 +648,38 @@ typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val);
typedef void *upb_startstr_handlerfunc(void *c, const void *hd,
size_t size_hint);
typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf,
- size_t n);
-// upb_handlerattr
-#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL}
+ size_t n, const upb_bufhandle* handle);
+// upb_bufhandle
+size_t upb_bufhandle_objofs(const upb_bufhandle *h);
+
+// upb_handlerattr
void upb_handlerattr_init(upb_handlerattr *attr);
void upb_handlerattr_uninit(upb_handlerattr *attr);
bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, void *hd,
upb_handlerfree *cleanup);
+bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type);
+const void *upb_handlerattr_closuretype(const upb_handlerattr *attr);
+bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr,
+ const void *type);
+const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr);
+bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok);
+bool upb_handlerattr_alwaysok(const upb_handlerattr *attr);
+
UPB_INLINE const void *upb_handlerattr_handlerdata(
const upb_handlerattr *attr) {
return attr->handler_data_;
}
-typedef void upb_handlers_callback(void *closure, upb_handlers *h);
-
// upb_handlers
+typedef void upb_handlers_callback(void *closure, upb_handlers *h);
upb_handlers *upb_handlers_new(const upb_msgdef *m,
const void *owner);
const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
const void *owner,
upb_handlers_callback *callback,
void *closure);
-
-// From upb_refcounted.
bool upb_handlers_isfrozen(const upb_handlers *h);
void upb_handlers_ref(const upb_handlers *h, const void *owner);
void upb_handlers_unref(const upb_handlers *h, const void *owner);
@@ -630,17 +747,32 @@ UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h,
return (upb_func *)h->table[s].func;
}
+bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s,
+ upb_handlerattr *attr);
+
UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h,
upb_selector_t s) {
return upb_handlerattr_handlerdata(&h->table[s].attr);
}
+#ifdef __cplusplus
+
// Handler types for single fields.
// Right now we only have one for TYPE_BYTES but ones for other types
// should follow.
//
// These follow the same handlers protocol for fields of a message.
-typedef struct { upb_handlers_tabent table[3]; } upb_byteshandler;
+class upb::BytesHandler {
+ public:
+ BytesHandler();
+ ~BytesHandler();
+
+ // TODO(haberman): make private and figure out what to friend.
+#else
+struct upb_byteshandler {
+#endif
+ upb_handlers_tabent table[3];
+};
void upb_byteshandler_init(upb_byteshandler *h);
void upb_byteshandler_uninit(upb_byteshandler *h);
@@ -659,7 +791,7 @@ bool upb_byteshandler_setendstr(upb_byteshandler *h,
#ifdef __cplusplus
namespace upb {
-typedef upb_byteshandler BytesHandler;
+typedef upb_byteshandler BytesHandler;
}
#endif
diff --git a/upb/pb/compile_decoder_x64.c b/upb/pb/compile_decoder_x64.c
index 429f690..44331b8 100644
--- a/upb/pb/compile_decoder_x64.c
+++ b/upb/pb/compile_decoder_x64.c
@@ -56,8 +56,6 @@ typedef struct {
// Used by DynASM to store globals.
void **globals;
-
- bool chkret;
} jitcompiler;
// Functions called by codegen.
@@ -72,7 +70,6 @@ static int pcofs(jitcompiler* jc);
static jitcompiler *newjitcompiler(mgroup *group) {
jitcompiler *jc = malloc(sizeof(jitcompiler));
- jc->chkret = false;
jc->group = group;
jc->pclabel_count = 0;
jc->lastlabelofs = -1;
diff --git a/upb/pb/compile_decoder_x64.dasc b/upb/pb/compile_decoder_x64.dasc
index fec822a..571aa9b 100644
--- a/upb/pb/compile_decoder_x64.dasc
+++ b/upb/pb/compile_decoder_x64.dasc
@@ -23,6 +23,7 @@
|.define ARG3_32, edx
|.define ARG3_64, rdx
|.define ARG4_64, rcx
+|.define ARG5_64, r8
|.define XMMARG1, xmm0
|
|// Register allocation / type map.
@@ -159,6 +160,16 @@ static upb_func *gethandler(const upb_handlers *h, upb_selector_t sel) {
return h ? upb_handlers_gethandler(h, sel) : NULL;
}
+// Should only be called when the associated handler is known to exist.
+static bool alwaysok(const upb_handlers *h, upb_selector_t sel) {
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+ bool ok = upb_handlers_getattr(h, sel, &attr);
+ UPB_ASSERT_VAR(ok, ok);
+ bool ret = upb_handlerattr_alwaysok(&attr);
+ upb_handlerattr_uninit(&attr);
+ return ret;
+}
+
// Emit static assembly routines; code that does not vary based on the message
// schema. Since it's not input-dependent, we only need one single copy of it.
// For the moment we generate a single copy per generated handlers. Eventually
@@ -623,9 +634,9 @@ static void jitprimitive(jitcompiler *jc, opcode op,
| mov ARG1_64, CLOSURE
| load_handler_data h, sel
| callp handler
- if (jc->chkret) {
+ if (!alwaysok(h, sel)) {
| test al, al
- | jz >5
+ | jnz >5
| call ->suspend
| jmp <1
|5:
@@ -887,10 +898,11 @@ static void jitbytecode(jitcompiler *jc) {
| mov ARG1_64, CLOSURE
| load_handler_data h, UPB_STARTMSG_SELECTOR
| callp startmsg
- if (jc->chkret) {
+ if (!alwaysok(h, UPB_STARTMSG_SELECTOR)) {
| test al, al
- | jnz <2
+ | jnz >2
| call ->suspend
+ | jmp <1
|2:
}
}
@@ -960,7 +972,7 @@ static void jitbytecode(jitcompiler *jc) {
| sub ARG3_64, PTR
}
| callp start
- if (jc->chkret) {
+ if (!alwaysok(h, arg)) {
| test rax, rax
| jnz >2
| call ->suspend
@@ -986,7 +998,7 @@ static void jitbytecode(jitcompiler *jc) {
| mov ARG1_64, CLOSURE
| load_handler_data h, arg
| callp end
- if (jc->chkret) {
+ if (!alwaysok(h, arg)) {
| test al, al
| jnz >2
| call ->suspend
@@ -1016,9 +1028,10 @@ static void jitbytecode(jitcompiler *jc) {
| mov ARG3_64, PTR
| mov ARG4_64, DATAEND
| sub ARG4_64, PTR
+ | mov ARG5_64, qword DECODER->handle
| callp str
| add PTR, rax
- if (jc->chkret) {
+ if (!alwaysok(h, arg)) {
| cmp PTR, DATAEND
| je >3
| call ->strret_fallback
diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c
index 6fd6576..c5fae0e 100644
--- a/upb/pb/decoder.c
+++ b/upb/pb/decoder.c
@@ -148,10 +148,11 @@ static void checkpoint(upb_pbdecoder *d) {
// Resumes the decoder from an initial state or from a previous suspend.
void *upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
- size_t size) {
+ size_t size, const upb_bufhandle *handle) {
UPB_UNUSED(p); // Useless; just for the benefit of the JIT.
d->buf_param = buf;
d->size_param = size;
+ d->handle = handle;
d->skip = 0;
if (d->residual_end > d->residual) {
// We have residual bytes from the last buffer.
@@ -488,11 +489,11 @@ upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) {
/* The main decoding loop *****************************************************/
size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf,
- size_t size) {
+ size_t size, const upb_bufhandle *handle) {
upb_pbdecoder *d = closure;
const mgroup *group = hd;
assert(buf);
- upb_pbdecoder_resume(d, NULL, buf, size);
+ upb_pbdecoder_resume(d, NULL, buf, size, handle);
UPB_UNUSED(group);
#define VMCASE(op, code) \
@@ -578,7 +579,8 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf,
)
VMCASE(OP_STRING,
uint32_t len = curbufleft(d);
- CHECK_SUSPEND(upb_sink_putstring(&d->top->sink, arg, ptr(d), len));
+ CHECK_SUSPEND(
+ upb_sink_putstring(&d->top->sink, arg, ptr(d), len, handle));
advance(d, len);
if (d->delim_end == NULL) { // String extends beyond this buf?
d->pc--;
@@ -683,6 +685,7 @@ void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) {
void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint) {
UPB_UNUSED(hd);
+ UPB_UNUSED(size_hint);
upb_pbdecoder *d = closure;
d->call_len = 0;
return d;
@@ -712,7 +715,7 @@ bool upb_pbdecoder_end(void *closure, const void *handler_data) {
if (group->jit_code) {
if (d->top != d->stack)
d->stack->end_ofs = 0;
- group->jit_code(closure, method->code_base.ptr, &dummy, 0);
+ group->jit_code(closure, method->code_base.ptr, &dummy, 0, NULL);
} else {
#endif
d->stack->end_ofs = end;
@@ -726,7 +729,7 @@ bool upb_pbdecoder_end(void *closure, const void *handler_data) {
getop(*d->pc) == OP_TAGN);
d->pc = p;
}
- upb_pbdecoder_decode(closure, handler_data, &dummy, 0);
+ upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL);
#ifdef UPB_USE_JIT_X64
}
#endif
@@ -762,7 +765,9 @@ void upb_pbdecoder_reset(upb_pbdecoder *d) {
// Not currently required, but to support outgrowing the static stack we need
// this.
-void upb_pbdecoder_uninit(upb_pbdecoder *d) {}
+void upb_pbdecoder_uninit(upb_pbdecoder *d) {
+ UPB_UNUSED(d);
+}
const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) {
return d->method_;
diff --git a/upb/pb/decoder.h b/upb/pb/decoder.h
index 4529324..4313bb3 100644
--- a/upb/pb/decoder.h
+++ b/upb/pb/decoder.h
@@ -234,6 +234,7 @@ struct upb_pbdecoder {
// Stores the user buffer passed to our decode function.
const char *buf_param;
size_t size_param;
+ const upb_bufhandle *handle;
#ifdef UPB_USE_JIT_X64
// Used momentarily by the generated code to store a value while a user
diff --git a/upb/pb/decoder.int.h b/upb/pb/decoder.int.h
index 1c10eb3..20afa68 100644
--- a/upb/pb/decoder.int.h
+++ b/upb/pb/decoder.int.h
@@ -108,12 +108,12 @@ typedef struct {
void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint);
void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint);
size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf,
- size_t size);
+ size_t size, const upb_bufhandle *handle);
bool upb_pbdecoder_end(void *closure, const void *handler_data);
// Decoder-internal functions that the JIT calls to handle fallback paths.
void *upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
- size_t size);
+ size_t size, const upb_bufhandle *handle);
size_t upb_pbdecoder_suspend(upb_pbdecoder *d);
int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, uint32_t fieldnum,
uint8_t wire_type);
diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c
index 0c12571..8a49c73 100644
--- a/upb/pb/textprinter.c
+++ b/upb/pb/textprinter.c
@@ -3,6 +3,9 @@
*
* Copyright (c) 2009 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
+ *
+ * OPT: This is not optimized at all. It uses printf() which parses the format
+ * string every time, and it allocates memory for every put.
*/
#include "upb/pb/textprinter.h"
@@ -16,29 +19,29 @@
#include "upb/sink.h"
-struct _upb_textprinter {
- int indent_depth;
- bool single_line;
- upb_status status;
-};
-
#define CHECK(x) if ((x) < 0) goto err;
+static const char *shortname(const char *longname) {
+ const char *last = strrchr(longname, '.');
+ return last ? last + 1 : longname;
+}
+
static int indent(upb_textprinter *p) {
int i;
- if (!p->single_line)
- for (i = 0; i < p->indent_depth * 2; i++)
- putchar(' ');
+ if (!p->single_line_)
+ for (i = 0; i < p->indent_depth_; i++)
+ upb_bytessink_putbuf(p->output_, p->subc, " ", 2, NULL);
return 0;
- return -1;
}
static int endfield(upb_textprinter *p) {
- putchar(p->single_line ? ' ' : '\n');
+ const char ch = (p->single_line_ ? ' ' : '\n');
+ upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL);
return 0;
}
-static int putescaped(const char* buf, size_t len, bool preserve_utf8) {
+static int putescaped(upb_textprinter *p, const char *buf, size_t len,
+ bool preserve_utf8) {
// Based on CEscapeInternal() from Google's protobuf release.
char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
const char *end = buf + len;
@@ -50,7 +53,7 @@ static int putescaped(const char* buf, size_t len, bool preserve_utf8) {
for (; buf < end; buf++) {
if (dstend - dst < 4) {
- fwrite(dstbuf, dst - dstbuf, 1, stdout);
+ upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
dst = dstbuf;
}
@@ -78,18 +81,57 @@ static int putescaped(const char* buf, size_t len, bool preserve_utf8) {
last_hex_escape = is_hex_escape;
}
// Flush remaining data.
- fwrite(dst, dst - dstbuf, 1, stdout);
+ upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
return 0;
}
+bool putf(upb_textprinter *p, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+
+ // Run once to get the length of the string.
+ va_list args_copy;
+ va_copy(args_copy, args);
+ int len = vsnprintf(NULL, 0, fmt, args_copy);
+ va_end(args_copy);
+
+ // + 1 for NULL terminator (vsnprintf() requires it even if we don't).
+ char *str = malloc(len + 1);
+ if (!str) return false;
+ int written = vsnprintf(str, len + 1, fmt, args);
+ va_end(args);
+ UPB_ASSERT_VAR(written, written == len);
+
+ bool ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
+ free(str);
+ return ok;
+}
+
+
+/* handlers *******************************************************************/
+
+static bool startmsg(void *c, const void *hd) {
+ upb_textprinter *p = c;
+ if (p->indent_depth_ == 0) {
+ upb_bytessink_start(p->output_, 0, &p->subc);
+ }
+ return true;
+}
+
+static bool endmsg(void *c, const void *hd, upb_status *s) {
+ upb_textprinter *p = c;
+ if (p->indent_depth_ == 0) {
+ upb_bytessink_end(p->output_);
+ }
+ return true;
+}
+
#define TYPE(name, ctype, fmt) \
static bool put ## name(void *closure, const void *handler_data, ctype val) {\
upb_textprinter *p = closure; \
const upb_fielddef *f = handler_data; \
CHECK(indent(p)); \
- puts(upb_fielddef_name(f)); \
- puts(": "); \
- printf(fmt, val); \
+ putf(p, "%s: " fmt, upb_fielddef_name(f), val); \
CHECK(endfield(p)); \
return true; \
err: \
@@ -100,9 +142,7 @@ static bool putbool(void *closure, const void *handler_data, bool val) {
upb_textprinter *p = closure;
const upb_fielddef *f = handler_data;
CHECK(indent(p));
- puts(upb_fielddef_name(f));
- puts(": ");
- puts(val ? "true" : "false");
+ putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false");
CHECK(endfield(p));
return true;
err:
@@ -121,11 +161,14 @@ TYPE(double, double, "%." STRINGIFY_MACROVAL(DBL_DIG) "g")
// Output a symbolic value from the enum if found, else just print as int32.
static bool putenum(void *closure, const void *handler_data, int32_t val) {
+ upb_textprinter *p = closure;
const upb_fielddef *f = handler_data;
const upb_enumdef *enum_def = upb_downcast_enumdef(upb_fielddef_subdef(f));
const char *label = upb_enumdef_iton(enum_def, val);
if (label) {
- puts(label);
+ indent(p);
+ putf(p, "%s: %s", upb_fielddef_name(f), label);
+ endfield(p);
} else {
CHECK(putint32(closure, handler_data, val));
}
@@ -136,25 +179,27 @@ err:
static void *startstr(void *closure, const void *handler_data,
size_t size_hint) {
- UPB_UNUSED(handler_data);
+ const upb_fielddef *f = handler_data;
UPB_UNUSED(size_hint);
upb_textprinter *p = closure;
- putchar('"');
+ putf(p, "%s: \"", upb_fielddef_name(f));
return p;
}
static bool endstr(void *closure, const void *handler_data) {
- UPB_UNUSED(closure);
UPB_UNUSED(handler_data);
- putchar('"');
+ upb_textprinter *p = closure;
+ putf(p, "\"");
+ endfield(p);
return true;
}
static size_t putstr(void *closure, const void *hd, const char *buf,
- size_t len) {
- UPB_UNUSED(closure);
+ size_t len, const upb_bufhandle *handle) {
+ UPB_UNUSED(handle);
+ upb_textprinter *p = closure;
const upb_fielddef *f = hd;
- CHECK(putescaped(buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
+ CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
return len;
err:
return 0;
@@ -162,12 +207,10 @@ err:
static void *startsubmsg(void *closure, const void *handler_data) {
upb_textprinter *p = closure;
- const upb_fielddef *f = handler_data;
+ const char *name = handler_data;
CHECK(indent(p));
- printf("%s {", upb_fielddef_name(f));
- if (!p->single_line)
- putchar('\n');
- p->indent_depth++;
+ putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n');
+ p->indent_depth_++;
return p;
err:
return UPB_BREAK;
@@ -176,30 +219,36 @@ err:
static bool endsubmsg(void *closure, const void *handler_data) {
UPB_UNUSED(handler_data);
upb_textprinter *p = closure;
- p->indent_depth--;
+ p->indent_depth_--;
CHECK(indent(p));
- putchar('}');
+ upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL);
CHECK(endfield(p));
return true;
err:
return false;
}
-upb_textprinter *upb_textprinter_new() {
- upb_textprinter *p = malloc(sizeof(*p));
- return p;
+
+/* Public API *****************************************************************/
+
+void upb_textprinter_init(upb_textprinter *p, const upb_handlers *h) {
+ p->single_line_ = false;
+ p->indent_depth_ = 0;
+ upb_sink_reset(&p->input_, h, p);
}
-void upb_textprinter_free(upb_textprinter *p) { free(p); }
+void upb_textprinter_uninit(upb_textprinter *p) {}
void upb_textprinter_reset(upb_textprinter *p, bool single_line) {
- p->single_line = single_line;
- p->indent_depth = 0;
+ p->single_line_ = single_line;
+ p->indent_depth_ = 0;
}
static void onmreg(void *c, upb_handlers *h) {
(void)c;
const upb_msgdef *m = upb_handlers_msgdef(h);
+ upb_handlers_setstartmsg(h, startmsg, NULL);
+ upb_handlers_setendmsg(h, endmsg, NULL);
upb_msg_iter i;
for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
upb_fielddef *f = upb_msg_iter_field(&i);
@@ -233,20 +282,37 @@ static void onmreg(void *c, upb_handlers *h) {
upb_handlers_setstring(h, f, putstr, &attr);
upb_handlers_setendstr(h, f, endstr, &attr);
break;
- case UPB_TYPE_MESSAGE:
+ case UPB_TYPE_MESSAGE: {
+ const char *name =
+ upb_fielddef_istagdelim(f)
+ ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f)))
+ : upb_fielddef_name(f);
+ // TODO(haberman): add "setconsthandlerdata"? If we pass NULL for
+ // cleanup then we don't need a non-const pointer.
+ upb_handlerattr_sethandlerdata(&attr, (void*)name, NULL);
upb_handlers_setstartsubmsg(h, f, startsubmsg, &attr);
upb_handlers_setendsubmsg(h, f, endsubmsg, &attr);
break;
+ }
case UPB_TYPE_ENUM:
upb_handlers_setint32(h, f, putenum, &attr);
- default:
- assert(false);
break;
}
}
}
-const upb_handlers *upb_textprinter_newhandlers(const void *owner,
- const upb_msgdef *m) {
+const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m,
+ const void *owner) {
return upb_handlers_newfrozen(m, owner, &onmreg, NULL);
}
+
+upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; }
+
+bool upb_textprinter_resetoutput(upb_textprinter *p, upb_bytessink *output) {
+ p->output_ = output;
+ return true;
+}
+
+void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
+ p->single_line_ = single_line;
+}
diff --git a/upb/pb/textprinter.h b/upb/pb/textprinter.h
index 7b653e7..eb3e132 100644
--- a/upb/pb/textprinter.h
+++ b/upb/pb/textprinter.h
@@ -8,23 +8,87 @@
#ifndef UPB_TEXT_H_
#define UPB_TEXT_H_
-#include "upb/handlers.h"
+#include "upb/sink.h"
+
+#ifdef __cplusplus
+namespace upb {
+namespace pb {
+class TextPrinter;
+} // namespace pb
+} // namespace upb
+
+typedef upb::pb::TextPrinter upb_textprinter;
+#else
+struct upb_textprinter;
+typedef struct upb_textprinter upb_textprinter;
+#endif
+
+#ifdef __cplusplus
+class upb::pb::TextPrinter {
+ public:
+ // The given handlers must have come from NewHandlers(). It must outlive the
+ // TextPrinter.
+ explicit TextPrinter(const upb::Handlers* handlers);
+
+ void SetSingleLineMode(bool single_line);
+
+ bool ResetOutput(BytesSink* output);
+ Sink* input();
+
+ // If handler caching becomes a requirement we can add a code cache as in
+ // decoder.h
+ static reffed_ptr<const Handlers> NewHandlers(const MessageDef* md);
+
+ private:
+#else
+struct upb_textprinter {
+#endif
+ upb_sink input_;
+ upb_bytessink *output_;
+ int indent_depth_;
+ bool single_line_;
+ void *subc;
+};
#ifdef __cplusplus
extern "C" {
#endif
-struct _upb_textprinter;
-typedef struct _upb_textprinter upb_textprinter;
+// C API.
+void upb_textprinter_init(upb_textprinter *p, const upb_handlers *h);
+void upb_textprinter_uninit(upb_textprinter *p);
+bool upb_textprinter_resetoutput(upb_textprinter *p, upb_bytessink *output);
+void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line);
+upb_sink *upb_textprinter_input(upb_textprinter *p);
-upb_textprinter *upb_textprinter_new();
-void upb_textprinter_free(upb_textprinter *p);
-void upb_textprinter_reset(upb_textprinter *p, bool single_line);
-const upb_handlers *upb_textprinter_newhandlers(const void *owner,
- const upb_msgdef *m);
+const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m,
+ const void *owner);
#ifdef __cplusplus
} /* extern "C" */
+
+namespace upb {
+namespace pb {
+inline TextPrinter::TextPrinter(const upb::Handlers* handlers) {
+ upb_textprinter_init(this, handlers);
+}
+inline void TextPrinter::SetSingleLineMode(bool single_line) {
+ upb_textprinter_setsingleline(this, single_line);
+}
+inline bool TextPrinter::ResetOutput(BytesSink* output) {
+ return upb_textprinter_resetoutput(this, output);
+}
+inline Sink* TextPrinter::input() {
+ return upb_textprinter_input(this);
+}
+inline reffed_ptr<const Handlers> TextPrinter::NewHandlers(
+ const MessageDef *md) {
+ const Handlers* h = upb_textprinter_newhandlers(md, &h);
+ return reffed_ptr<const Handlers>(h, &h);
+}
+} // namespace pb
+} // namespace upb
+
#endif
#endif /* UPB_TEXT_H_ */
diff --git a/upb/shim/shim.c b/upb/shim/shim.c
index 5c3e026..797a2d1 100644
--- a/upb/shim/shim.c
+++ b/upb/shim/shim.c
@@ -38,6 +38,7 @@ bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
upb_handlerattr_sethandlerdata(&attr, d, free);
+ upb_handlerattr_setalwaysok(&attr, true);
#define TYPE(u, l) \
case UPB_TYPE_##u: \
diff --git a/upb/sink.h b/upb/sink.h
index dd2b9f1..d8322e1 100644
--- a/upb/sink.h
+++ b/upb/sink.h
@@ -120,7 +120,8 @@ class upb::Sink {
// For StartString(), the function will write a sink for the string to "sub."
// The sub-sink must be used for any/all PutStringBuffer() calls.
bool StartString(Handlers::Selector s, size_t size_hint, Sink* sub);
- size_t PutStringBuffer(Handlers::Selector s, const char *buf, size_t len);
+ size_t PutStringBuffer(Handlers::Selector s, const char *buf, size_t len,
+ const BufferHandle *handle);
bool EndString(Handlers::Selector s);
// For submessage fields.
@@ -160,13 +161,14 @@ class upb::BytesSink {
//
// TODO(haberman): once the Handlers know the expected closure type, verify
// that T matches it.
- template <class T> BytesSink(const Handlers* handlers, T* closure);
+ template <class T> BytesSink(const BytesHandler* handler, T* closure);
// Resets the value of the sink.
- template <class T> void Reset(const Handlers* handlers, T* closure);
+ template <class T> void Reset(const BytesHandler* handler, T* closure);
bool Start(size_t size_hint, void **subc);
- size_t PutBuffer(void *subc, const char *buf, size_t len);
+ size_t PutBuffer(void *subc, const char *buf, size_t len,
+ const BufferHandle *handle);
bool End();
#else
@@ -219,6 +221,7 @@ UPB_INLINE void upb_bytessink_reset(upb_bytessink *s, const upb_byteshandler *h,
UPB_INLINE bool upb_bytessink_start(upb_bytessink *s, size_t size_hint,
void **subc) {
+ *subc = NULL;
if (!s->handler) return true;
upb_startstr_handlerfunc *start =
(upb_startstr_handlerfunc *)s->handler->table[UPB_STARTSTR_SELECTOR].func;
@@ -231,7 +234,8 @@ UPB_INLINE bool upb_bytessink_start(upb_bytessink *s, size_t size_hint,
}
UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink *s, void *subc,
- const char *buf, size_t size) {
+ const char *buf, size_t size,
+ const upb_bufhandle* handle) {
if (!s->handler) return true;
upb_string_handlerfunc *putbuf =
(upb_string_handlerfunc *)s->handler->table[UPB_STRING_SELECTOR].func;
@@ -239,7 +243,7 @@ UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink *s, void *subc,
if (!putbuf) return true;
return putbuf(subc, upb_handlerattr_handlerdata(
&s->handler->table[UPB_STRING_SELECTOR].attr),
- buf, size);
+ buf, size, handle);
}
UPB_INLINE bool upb_bytessink_end(upb_bytessink *s) {
@@ -256,10 +260,18 @@ UPB_INLINE bool upb_bytessink_end(upb_bytessink *s) {
UPB_INLINE bool upb_bufsrc_putbuf(const char *buf, size_t len,
upb_bytessink *sink) {
void *subc;
- return
- upb_bytessink_start(sink, len, &subc) &&
- (len == 0 || upb_bytessink_putbuf(sink, subc, buf, len) == len) &&
- upb_bytessink_end(sink);
+ upb_bufhandle handle;
+ upb_bufhandle_init(&handle);
+ upb_bufhandle_setbuf(&handle, buf, 0);
+ bool ret = upb_bytessink_start(sink, len, &subc);
+ if (ret && len != 0) {
+ ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) == len);
+ }
+ if (ret) {
+ ret = upb_bytessink_end(sink);
+ }
+ upb_bufhandle_uninit(&handle);
+ return ret;
}
#define PUTVAL(type, ctype) \
@@ -287,15 +299,16 @@ UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) {
s->closure = c;
}
-UPB_INLINE size_t
-upb_sink_putstring(upb_sink *s, upb_selector_t sel, const char *buf, size_t n) {
+UPB_INLINE size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel,
+ const char *buf, size_t n,
+ const upb_bufhandle *handle) {
if (!s->handlers) return n;
upb_string_handlerfunc *handler =
(upb_string_handlerfunc *)upb_handlers_gethandler(s->handlers, sel);
if (!handler) return n;
const void *hd = upb_handlers_gethandlerdata(s->handlers, sel);
- return handler(s->closure, hd, buf, n);
+ return handler(s->closure, hd, buf, n, handle);
}
UPB_INLINE bool upb_sink_startmsg(upb_sink *s) {
@@ -443,8 +456,8 @@ inline bool Sink::StartString(Handlers::Selector sel, size_t size_hint,
return upb_sink_startstr(this, sel, size_hint, sub);
}
inline size_t Sink::PutStringBuffer(Handlers::Selector sel, const char *buf,
- size_t len) {
- return upb_sink_putstring(this, sel, buf, len);
+ size_t len, const BufferHandle* handle) {
+ return upb_sink_putstring(this, sel, buf, len, handle);
}
inline bool Sink::EndString(Handlers::Selector sel) {
return upb_sink_endstr(this, sel);
@@ -462,11 +475,16 @@ inline bool Sink::EndSequence(Handlers::Selector sel) {
return upb_sink_endseq(this, sel);
}
+template <class T>
+void BytesSink::Reset(const BytesHandler *handler, T *closure) {
+ upb_bytessink_reset(this, handler, closure);
+}
inline bool BytesSink::Start(size_t size_hint, void **subc) {
return upb_bytessink_start(this, size_hint, subc);
}
-inline size_t BytesSink::PutBuffer(void *subc, const char *buf, size_t len) {
- return upb_bytessink_putbuf(this, subc, buf, len);
+inline size_t BytesSink::PutBuffer(void *subc, const char *buf, size_t len,
+ const BufferHandle *handle) {
+ return upb_bytessink_putbuf(this, subc, buf, len, handle);
}
inline bool BytesSink::End() {
return upb_bytessink_end(this);
diff --git a/upb/stdc/README b/upb/stdc/README
deleted file mode 100644
index 1815af4..0000000
--- a/upb/stdc/README
+++ /dev/null
@@ -1,15 +0,0 @@
-This directory contains code that is ANSI C but uses parts of the
-standard library that are not available to very limited environments
-like Linux Kernel modules. The standard calls environments like this
-"freestanding implementations."
-
-This does *not* imply that the upb core can be compiled directly on a
-freestanding implementation. Even the core uses library functions
-that are not directly available on freestanding implementations
-(notably malloc()/free(), vsnprintf(), and assert()). So compiling on
-freestanding implementations may require implementing compatibility
-versions of functions like malloc().
-
-Also, Linux is not technically a freestanding implementation either,
-since it does not accept functions that return float or double on
-x86-64 (these use SSE registers which are disabled in kernel mode).
diff --git a/upb/symtab.c b/upb/symtab.c
index a3acd16..099aa8d 100644
--- a/upb/symtab.c
+++ b/upb/symtab.c
@@ -146,10 +146,10 @@ static bool upb_resolve_dfs(const upb_def *def, upb_strtable *addtab,
if (def->type == UPB_DEF_FIELD) continue;
upb_value v;
if (upb_strtable_lookup(addtab, upb_def_fullname(def), &v)) {
- // Because we memoize we should not visit a node after we have dup'd it.
- assert(((upb_def*)upb_value_getptr(v))->came_from_user);
need_dup = true;
}
+
+ // For messages, continue the recursion by visiting all subdefs.
const upb_msgdef *m = upb_dyncast_msgdef(def);
if (m) {
upb_msg_iter i;
@@ -188,6 +188,8 @@ oom:
return false;
}
+// TODO(haberman): we need a lot more testing of error conditions.
+// The came_from_user stuff in particular is not tested.
bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
upb_status *status) {
upb_def **add_defs = NULL;
@@ -197,7 +199,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
return false;
}
- // Add new defs to table.
+ // Add new defs to our "add" set.
for (int i = 0; i < n; i++) {
upb_def *def = defs[i];
if (upb_def_isfrozen(def)) {
@@ -211,20 +213,79 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
status, "Anonymous defs cannot be added to a symtab");
goto err;
}
- if (upb_strtable_lookup(&addtab, fullname, NULL)) {
- upb_status_seterrf(status, "Conflicting defs named '%s'", fullname);
+
+ upb_fielddef *f = upb_dyncast_fielddef_mutable(def);
+
+ if (f) {
+ if (!upb_fielddef_containingtypename(f)) {
+ upb_status_seterrmsg(status,
+ "Standalone fielddefs must have a containing type "
+ "(extendee) name set");
+ goto err;
+ }
+ } else {
+ if (upb_strtable_lookup(&addtab, fullname, NULL)) {
+ upb_status_seterrf(status, "Conflicting defs named '%s'", fullname);
+ goto err;
+ }
+ // We need this to back out properly, because if there is a failure we
+ // need to donate the ref back to the caller.
+ def->came_from_user = true;
+ upb_def_donateref(def, ref_donor, s);
+ if (!upb_strtable_insert(&addtab, fullname, upb_value_ptr(def)))
+ goto oom_err;
+ }
+ }
+
+ // Add standalone fielddefs (ie. extensions) to the appropriate messages.
+ // If the appropriate message only exists in the existing symtab, duplicate
+ // it so we have a mutable copy we can add the fields to.
+ for (int i = 0; i < n; i++) {
+ upb_def *def = defs[i];
+ upb_fielddef *f = upb_dyncast_fielddef_mutable(def);
+ if (!f) continue;
+ const char *msgname = upb_fielddef_containingtypename(f);
+ // We validated this earlier in this function.
+ assert(msgname);
+
+ // If the extendee name is absolutely qualified, move past the initial ".".
+ // TODO(haberman): it is not obvious what it would mean if this was not
+ // absolutely qualified.
+ if (msgname[0] == '.') {
+ msgname++;
+ }
+
+ upb_value v;
+ upb_msgdef *m;
+ if (upb_strtable_lookup(&addtab, msgname, &v)) {
+ // Extendee is in the set of defs the user asked us to add.
+ m = upb_value_getptr(v);
+ } else {
+ // Need to find and dup the extendee from the existing symtab.
+ const upb_msgdef *frozen_m = upb_symtab_lookupmsg(s, msgname, &frozen_m);
+ if (!frozen_m) {
+ upb_status_seterrf(status,
+ "Tried to extend message %s that does not exist "
+ "in this SymbolTable.",
+ msgname);
+ goto err;
+ }
+ m = upb_msgdef_dup(frozen_m, s);
+ upb_msgdef_unref(frozen_m, &frozen_m);
+ if (!m) goto oom_err;
+ if (!upb_strtable_insert(&addtab, msgname, upb_value_ptr(m))) {
+ upb_msgdef_unref(m, s);
+ goto oom_err;
+ }
+ }
+
+ if (!upb_msgdef_addfield(m, f, ref_donor, status)) {
goto err;
}
- // We need this to back out properly, because if there is a failure we need
- // to donate the ref back to the caller.
- def->came_from_user = true;
- upb_def_donateref(def, ref_donor, s);
- if (!upb_strtable_insert(&addtab, fullname, upb_value_ptr(def)))
- goto oom_err;
}
// Add dups of any existing def that can reach a def with the same name as
- // one of "defs."
+ // anything in our "add" set.
upb_inttable seen;
if (!upb_inttable_init(&seen, UPB_CTYPE_BOOL)) goto oom_err;
upb_strtable_iter i;
@@ -236,7 +297,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
}
upb_inttable_uninit(&seen);
- // Now using the table, resolve symbolic references.
+ // Now using the table, resolve symbolic references for subdefs.
upb_strtable_begin(&i, &addtab);
for (; !upb_strtable_done(&i); upb_strtable_next(&i)) {
upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i));
@@ -305,12 +366,13 @@ err: {
upb_strtable_begin(&i, &addtab);
for (; !upb_strtable_done(&i); upb_strtable_next(&i)) {
upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i));
- if (def->came_from_user) {
+ bool came_from_user = def->came_from_user;
+ def->came_from_user = false;
+ if (came_from_user) {
upb_def_donateref(def, s, ref_donor);
} else {
upb_def_unref(def, s);
}
- def->came_from_user = false;
}
}
upb_strtable_uninit(&addtab);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback