From 5e550e88f8f1ac58fd00e4b25b1278d8ea557d31 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 9 Jan 2021 15:45:44 -0800 Subject: [PATCH] Added API for getting fielddef default as a upb_msgval. --- BUILD | 1 + cmake/CMakeLists.txt | 3 ++- tests/test_cpp.cc | 12 ++++++++++++ tests/test_cpp.proto | 4 ++-- tests/test_generated_code.c | 35 +++++++++++++++++++++++++++++++++++ upb/def.c | 20 ++++++++++++++++++++ upb/def.h | 1 + upb/def.hpp | 5 +++++ upb/handlers.h | 4 ++-- upb/reflection.h | 10 ++++++++++ upb/reflection.hpp | 13 +++++++++++++ 11 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 upb/reflection.hpp diff --git a/BUILD b/BUILD index 2e133263a7..c0b6655a0b 100644 --- a/BUILD +++ b/BUILD @@ -149,6 +149,7 @@ cc_library( "upb/def.h", "upb/def.hpp", "upb/reflection.h", + "upb/reflection.hpp", ], copts = UPB_DEFAULT_COPTS, visibility = ["//visibility:public"], diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index d4cbcc91fc..2b1d457423 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -99,7 +99,8 @@ add_library(reflection ../upb/reflection.c ../upb/def.h ../upb/def.hpp - ../upb/reflection.h) + ../upb/reflection.h + ../upb/reflection.hpp) target_link_libraries(reflection descriptor_upb_proto port diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc index 9d3f64acb3..15fa4b5aad 100644 --- a/tests/test_cpp.cc +++ b/tests/test_cpp.cc @@ -977,6 +977,17 @@ void TestInlinedArena() { ASSERT(n == 0); } +void TestDefault() { + upb::SymbolTable symtab; + upb::MessageDefPtr md(upb_test_TestMessage_getmsgdef(symtab.ptr())); + upb::FieldDefPtr i32_f = md.FindFieldByName("i32"); + upb::FieldDefPtr str_f = md.FindFieldByName("str"); + ASSERT(i32_f && str_f); + ASSERT(i32_f.default_value().int32_val == 5); + ASSERT(strcmp(str_f.default_value().str_val.data, "abc") == 0); + ASSERT(str_f.default_value().str_val.size == 3); +} + extern "C" { int run_tests() { @@ -1014,6 +1025,7 @@ int run_tests() { TestHandlerDataDestruction(); TestIteration(); TestArena(); + TestDefault(); return 0; } diff --git a/tests/test_cpp.proto b/tests/test_cpp.proto index f890350ece..4992b8c55c 100644 --- a/tests/test_cpp.proto +++ b/tests/test_cpp.proto @@ -3,9 +3,9 @@ syntax = "proto2"; package upb.test; message TestMessage { - optional int32 i32 = 1; + optional int32 i32 = 1 [default = 5]; repeated int32 r_i32 = 2; - optional string str = 3; + optional string str = 3 [default = "abc"]; repeated string r_str = 4; optional TestMessage msg = 5; repeated TestMessage r_msg = 6; diff --git a/tests/test_generated_code.c b/tests/test_generated_code.c index bd1066b233..63ac4babab 100644 --- a/tests/test_generated_code.c +++ b/tests/test_generated_code.c @@ -410,6 +410,40 @@ void test_status_truncation(void) { } } +void decrement_int(void *ptr) { + int* iptr = ptr; + (*iptr)--; +} + +void test_arena(void) { + int i1 = 5; + int i2 = 5; + int i3 = 5; + int i4 = 5; + + upb_arena *arena1 = upb_arena_new(); + upb_arena *arena2 = upb_arena_new(); + + upb_arena_addcleanup(arena1, &i1, decrement_int); + upb_arena_addcleanup(arena2, &i2, decrement_int); + + upb_arena_fuse(arena1, arena2); + + upb_arena_addcleanup(arena1, &i3, decrement_int); + upb_arena_addcleanup(arena2, &i4, decrement_int); + + upb_arena_free(arena1); + ASSERT(i1 == 5); + ASSERT(i2 == 5); + ASSERT(i3 == 5); + ASSERT(i4 == 5); + upb_arena_free(arena2); + ASSERT(i1 == 4); + ASSERT(i2 == 4); + ASSERT(i3 == 4); + ASSERT(i4 == 4); +} + int run_tests(int argc, char *argv[]) { test_scalars(); test_utf8(); @@ -419,5 +453,6 @@ int run_tests(int argc, char *argv[]) { test_repeated(); test_null_decode_buf(); test_status_truncation(); + test_arena(); return 0; } diff --git a/upb/def.c b/upb/def.c index 4ba553a69c..cdb5a5e5bd 100644 --- a/upb/def.c +++ b/upb/def.c @@ -8,6 +8,9 @@ #include #include "google/protobuf/descriptor.upb.h" +#include "upb/reflection.h" + +/* Must be last. */ #include "upb/port_def.inc" typedef struct { @@ -407,6 +410,23 @@ const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) { return f->oneof; } +upb_msgval upb_fielddef_default(const upb_fielddef *f) { + UPB_ASSERT(!upb_fielddef_issubmsg(f)); + upb_msgval ret; + if (upb_fielddef_isstring(f)) { + str_t *str = f->defaultval.str; + if (str) { + ret.str_val.data = str->str; + ret.str_val.size = str->len; + } else { + ret.str_val.size = 0; + } + } else { + memcpy(&ret, &f->defaultval, 8); + } + return ret; +} + static void chkdefaulttype(const upb_fielddef *f, int ctype) { UPB_UNUSED(f); UPB_UNUSED(ctype); diff --git a/upb/def.h b/upb/def.h index 7206ec0d3e..ec61fcb091 100644 --- a/upb/def.h +++ b/upb/def.h @@ -18,6 +18,7 @@ #include "upb/table.int.h" #include "google/protobuf/descriptor.upb.h" +/* Must be last. */ #include "upb/port_def.inc" #ifdef __cplusplus diff --git a/upb/def.hpp b/upb/def.hpp index e32da2a1ee..579a3baeb5 100644 --- a/upb/def.hpp +++ b/upb/def.hpp @@ -8,10 +8,13 @@ #include #include "upb/def.h" +#include "upb/reflection.h" #include "upb/upb.hpp" namespace upb { +typedef upb_msgval MessageValue; + class EnumDefPtr; class MessageDefPtr; class OneofDefPtr; @@ -106,6 +109,8 @@ class FieldDefPtr { float default_float() const { return upb_fielddef_defaultfloat(ptr_); } double default_double() const { return upb_fielddef_defaultdouble(ptr_); } + MessageValue default_value() const { return upb_fielddef_default(ptr_); } + // The resulting string is always NULL-terminated. If non-NULL, the length // will be stored in *len. const char* default_string(size_t* len) const { diff --git a/upb/handlers.h b/upb/handlers.h index 53904b6022..3ec212225a 100644 --- a/upb/handlers.h +++ b/upb/handlers.h @@ -22,8 +22,6 @@ #include "upb/def.h" #include "upb/table.int.h" -#include "upb/port_def.inc" - #ifdef __cplusplus #include "upb/def.hpp" namespace upb { @@ -34,6 +32,8 @@ template struct CanonicalType; } /* namespace upb */ #endif +/* Must be last. */ +#include "upb/port_def.inc" /* The maximum depth that the handler graph can have. This is a resource limit * for the C stack since we sometimes need to recursively traverse the graph. diff --git a/upb/reflection.h b/upb/reflection.h index 0133630c58..70e6ec2dc2 100644 --- a/upb/reflection.h +++ b/upb/reflection.h @@ -8,6 +8,10 @@ #include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + typedef union { bool bool_val; float float_val; @@ -28,6 +32,8 @@ typedef union { upb_array* array; } upb_mutmsgval; +upb_msgval upb_fielddef_default(const upb_fielddef *f); + /** upb_msg *******************************************************************/ /* Creates a new message of the given type in the given arena. */ @@ -163,6 +169,10 @@ upb_msgval upb_mapiter_value(const upb_map *map, size_t iter); * iterator must not have been initialized const. */ void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); +#ifdef __cplusplus +} /* extern "C" */ +#endif + #include "upb/port_undef.inc" #endif /* UPB_REFLECTION_H_ */ diff --git a/upb/reflection.hpp b/upb/reflection.hpp new file mode 100644 index 0000000000..05150bd305 --- /dev/null +++ b/upb/reflection.hpp @@ -0,0 +1,13 @@ + +#ifndef UPB_REFLECTION_HPP_ +#define UPB_REFLECTION_HPP_ + +#include "upb/reflection.h" + +namespace upb { + +typedef upb_msgval MessageValue; + +} // namespace upb + +#endif // UPB_REFLECTION_HPP_