Changes for PR comments.

pull/13171/head
Josh Haberman 8 years ago
parent 3122535726
commit 949aeee3f1
  1. 12
      tests/bindings/lua/test_upb.lua
  2. 4
      tests/bindings/lua/test_upb.pb.lua
  3. 13
      upb/bindings/lua/msg.c
  4. 105
      upb/msg.c
  5. 10
      upb/msg.h

@ -576,10 +576,10 @@ function test_msg_primitives()
} }
factory = upb.MessageFactory(symtab) factory = upb.MessageFactory(symtab)
TestMessage = factory:get_message_class(symtab:lookup("TestMessage")) TestMessage = factory:get_message_class("TestMessage")
msg = TestMessage() msg = TestMessage()
-- Defaults to nil -- Defaults to zero
assert_equal(0, msg.f) assert_equal(0, msg.f)
msg.f = 0 msg.f = 0
@ -624,7 +624,7 @@ function test_msg_primitives()
} }
factory = upb.MessageFactory(symtab) factory = upb.MessageFactory(symtab)
TestMessage = factory:get_message_class(symtab:lookup("TestMessage")) TestMessage = factory:get_message_class("TestMessage")
msg = TestMessage() msg = TestMessage()
-- Unset member returns default value. -- Unset member returns default value.
@ -673,7 +673,7 @@ function test_msg_array()
} }
factory = upb.MessageFactory(symtab) factory = upb.MessageFactory(symtab)
TestMessage = factory:get_message_class(symtab:lookup("TestMessage")) TestMessage = factory:get_message_class("TestMessage")
msg = TestMessage() msg = TestMessage()
assert_nil(msg.i32_array) assert_nil(msg.i32_array)
@ -711,8 +711,8 @@ function test_msg_submsg()
} }
factory = upb.MessageFactory(symtab) factory = upb.MessageFactory(symtab)
TestMessage = factory:get_message_class(symtab:lookup("TestMessage")) TestMessage = factory:get_message_class("TestMessage")
SubMessage = factory:get_message_class(symtab:lookup("SubMessage")) SubMessage = factory:get_message_class("SubMessage")
msg = TestMessage() msg = TestMessage()
assert_nil(msg.submsg) assert_nil(msg.submsg)

@ -25,7 +25,7 @@ local symtab = upb.SymbolTable{
} }
local factory = upb.MessageFactory(symtab); local factory = upb.MessageFactory(symtab);
local TestMessage = factory:get_message_class(symtab:lookup("TestMessage")) local TestMessage = factory:get_message_class("TestMessage")
function test_decodermethod() function test_decodermethod()
local decoder = pb.MakeStringToMessageDecoder(TestMessage) local decoder = pb.MakeStringToMessageDecoder(TestMessage)
@ -62,7 +62,7 @@ function test_parse_string()
} }
local factory = upb.MessageFactory(symtab); local factory = upb.MessageFactory(symtab);
local TestMessage = factory:get_message_class(symtab:lookup("TestMessage")) local TestMessage = factory:get_message_class("TestMessage")
local binary_pb = "\010\005Hello" local binary_pb = "\010\005Hello"
local decoder = pb.MakeStringToMessageDecoder(TestMessage) local decoder = pb.MakeStringToMessageDecoder(TestMessage)

@ -256,10 +256,19 @@ static int lupb_msgfactory_new(lua_State *L) {
* lupb_msgfactory_getmsgclass() * lupb_msgfactory_getmsgclass()
* *
* Handles: * Handles:
* MessageClass = factory.get_message_class(msgdef) * MessageClass = factory.get_message_class(message_name)
*/ */
static int lupb_msgfactory_getmsgclass(lua_State *L) { static int lupb_msgfactory_getmsgclass(lua_State *L) {
lupb_msgfactory_pushmsgclass(L, 1, lupb_msgdef_check(L, 2)); lupb_msgfactory *lfactory = lupb_msgfactory_check(L, 1);
const upb_symtab *symtab = upb_msgfactory_symtab(lfactory->factory);
const upb_msgdef *m = upb_symtab_lookupmsg(symtab, luaL_checkstring(L, 2));
if (!m) {
luaL_error(L, "No such message type: %s\n", lua_tostring(L, 2));
}
lupb_msgfactory_pushmsgclass(L, 1, m);
return 1; return 1;
} }

@ -24,6 +24,7 @@ bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) {
void *upb_array_pack(const upb_array *arr, void *p, size_t *ofs, size_t size); void *upb_array_pack(const upb_array *arr, void *p, size_t *ofs, size_t size);
void *upb_map_pack(const upb_map *map, void *p, size_t *ofs, size_t size); void *upb_map_pack(const upb_map *map, void *p, size_t *ofs, size_t size);
#define CHARPTR_AT(msg, ofs) ((char*)msg + ofs)
/** upb_msgval ****************************************************************/ /** upb_msgval ****************************************************************/
@ -158,13 +159,11 @@ struct upb_msglayout {
uint8_t align; uint8_t align;
}; };
static void upb_msg_check(const upb_msglayout *l, const upb_fielddef *f) { static void upb_msg_checkfield(const upb_msglayout *l, const upb_fielddef *f) {
UPB_ASSERT(l->msgdef == upb_fielddef_containingtype(f)); UPB_ASSERT(l->msgdef == upb_fielddef_containingtype(f));
} }
static void upb_msglayout_free(upb_msglayout *l) { static void upb_msglayout_free(upb_msglayout *l) {
upb_gfree(l->offsets);
upb_gfree(l->hasbits);
upb_gfree(l->default_msg); upb_gfree(l->default_msg);
upb_gfree(l); upb_gfree(l);
} }
@ -193,27 +192,59 @@ static uint32_t upb_msglayout_hasbit(const upb_msglayout *l,
return l->hasbits[upb_fielddef_index(f)]; return l->hasbits[upb_fielddef_index(f)];
} }
static bool upb_msglayout_initdefault(upb_msglayout *l) {
const upb_msgdef *m = l->msgdef;
upb_msg_field_iter it;
if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2 && l->size) {
/* Allocate default message and set default values in it. */
l->default_msg = upb_gmalloc(l->size);
if (!l->default_msg) {
return false;
}
memset(l->default_msg, 0, l->size);
for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
upb_msg_field_next(&it)) {
const upb_fielddef* f = upb_msg_iter_field(&it);
if (upb_fielddef_containingoneof(f)) {
continue;
}
if (!upb_fielddef_isstring(f) &&
!upb_fielddef_issubmsg(f) &&
!upb_fielddef_isseq(f)) {
upb_msg_set(l->default_msg, f, upb_msgval_fromdefault(f), l);
}
}
}
return true;
}
static upb_msglayout *upb_msglayout_new(const upb_msgdef *m) { static upb_msglayout *upb_msglayout_new(const upb_msgdef *m) {
upb_msg_field_iter it; upb_msg_field_iter it;
upb_msg_oneof_iter oit; upb_msg_oneof_iter oit;
upb_msglayout *l; upb_msglayout *l;
size_t hasbit; size_t hasbit;
size_t array_size = upb_msgdef_numfields(m) + upb_msgdef_numoneofs(m);
if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2) {
array_size += upb_msgdef_numfields(m); /* hasbits. */
}
l = upb_gmalloc(sizeof(*l)); l = upb_gmalloc(sizeof(*l) + (sizeof(uint32_t) * array_size));
if (!l) return NULL; if (!l) return NULL;
memset(l, 0, sizeof(*l)); memset(l, 0, sizeof(*l));
l->msgdef = m; l->msgdef = m;
if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2) {
l->hasbits = upb_gmalloc(sizeof(*l->hasbits) * upb_msgdef_numfields(m));
}
l->offsets = upb_gmalloc(sizeof(*l->offsets) * upb_msgdef_numfields(m));
l->case_offsets =
upb_gmalloc(sizeof(*l->case_offsets) * upb_msgdef_numoneofs(m));
l->align = 1; l->align = 1;
l->offsets = (uint32_t*)CHARPTR_AT(l, sizeof(*l));
l->case_offsets = l->offsets + upb_msgdef_numfields(m);
l->hasbits = l->case_offsets + upb_msgdef_numoneofs(m);
/* Allocate data offsets in three stages: /* Allocate data offsets in three stages:
* *
@ -289,36 +320,12 @@ static upb_msglayout *upb_msglayout_new(const upb_msgdef *m) {
* alignment. */ * alignment. */
l->size = align_up(l->size, l->align); l->size = align_up(l->size, l->align);
if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2 && l->size) { if (upb_msglayout_initdefault(l)) {
/* Allocate default message and set default values in it. */
l->default_msg = upb_gmalloc(l->size);
if (!l->default_msg) {
goto err;
}
memset(l->default_msg, 0, l->size);
for (upb_msg_field_begin(&it, m), hasbit = 0; !upb_msg_field_done(&it);
upb_msg_field_next(&it)) {
const upb_fielddef* f = upb_msg_iter_field(&it);
if (upb_fielddef_containingoneof(f)) {
continue;
}
if (!upb_fielddef_isstring(f) &&
!upb_fielddef_issubmsg(f) &&
!upb_fielddef_isseq(f)) {
upb_msg_set(l->default_msg, f, upb_msgval_fromdefault(f), l);
}
}
}
return l; return l;
} else {
err:
upb_msglayout_free(l); upb_msglayout_free(l);
return NULL; return NULL;
}
} }
@ -361,13 +368,17 @@ void upb_msgfactory_free(upb_msgfactory *f) {
upb_gfree(f); upb_gfree(f);
} }
const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f) {
return f->symtab;
}
/* Requires: /* Requires:
* - m is in upb_msgfactory_symtab(f) * - m is in upb_msgfactory_symtab(f)
* - upb_msgdef_mapentry(m) == false (since map messages can't have layouts). * - upb_msgdef_mapentry(m) == false (since map messages can't have layouts).
* *
* The returned layout will live for as long as the msgfactory does. * The returned layout will live for as long as the msgfactory does.
*/ */
const upb_msglayout *upb_msgfactory_getlayout(const upb_msgfactory *f, const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f,
const upb_msgdef *m) { const upb_msgdef *m) {
upb_value v; upb_value v;
UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m); UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m);
@ -377,7 +388,6 @@ const upb_msglayout *upb_msgfactory_getlayout(const upb_msgfactory *f,
UPB_ASSERT(upb_value_getptr(v)); UPB_ASSERT(upb_value_getptr(v));
return upb_value_getptr(v); return upb_value_getptr(v);
} else { } else {
/* This method should be made thread-safe so the "const" is accurate. */
upb_msgfactory *mutable_f = (void*)f; upb_msgfactory *mutable_f = (void*)f;
upb_msglayout *l = upb_msglayout_new(m); upb_msglayout *l = upb_msglayout_new(m);
upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l)); upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l));
@ -430,7 +440,7 @@ size_t upb_msg_str(void *msg, const void *hd, const char *ptr, size_t size,
} }
static void callback(const void *closure, upb_handlers *h) { static void callback(const void *closure, upb_handlers *h) {
const upb_msgfactory *factory = closure; upb_msgfactory *factory = (upb_msgfactory*)closure;
const upb_msgdef *md = upb_handlers_msgdef(h); const upb_msgdef *md = upb_handlers_msgdef(h);
const upb_msglayout* layout = upb_msgfactory_getlayout(factory, md); const upb_msglayout* layout = upb_msgfactory_getlayout(factory, md);
upb_msg_field_iter i; upb_msg_field_iter i;
@ -455,9 +465,8 @@ static void callback(const void *closure, upb_handlers *h) {
} }
} }
const upb_handlers *upb_msgfactory_getmergehandlers(const upb_msgfactory *f, const upb_handlers *upb_msgfactory_getmergehandlers(upb_msgfactory *f,
const upb_msgdef *m) { const upb_msgdef *m) {
/* This method should be made thread-safe so the "const" is accurate. */
upb_msgfactory *mutable_f = (void*)f; upb_msgfactory *mutable_f = (void*)f;
/* TODO(haberman): properly cache these. */ /* TODO(haberman): properly cache these. */
@ -473,7 +482,6 @@ const upb_handlers *upb_msgfactory_getmergehandlers(const upb_msgfactory *f,
/* If we always read/write as a consistent type to each address, this shouldn't /* If we always read/write as a consistent type to each address, this shouldn't
* violate aliasing. * violate aliasing.
*/ */
#define CHARPTR_AT(msg, ofs) ((char*)msg + ofs)
#define DEREF(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs) #define DEREF(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs)
static upb_inttable *upb_msg_trygetextdict(const upb_msg *msg, static upb_inttable *upb_msg_trygetextdict(const upb_msg *msg,
@ -575,7 +583,7 @@ bool upb_msg_has(const upb_msg *msg,
const upb_fielddef *f, const upb_fielddef *f,
const upb_msglayout *l) { const upb_msglayout *l) {
const upb_oneofdef *o; const upb_oneofdef *o;
upb_msg_check(l, f); upb_msg_checkfield(l, f);
UPB_ASSERT(upb_fielddef_haspresence(f)); UPB_ASSERT(upb_fielddef_haspresence(f));
if (upb_fielddef_isextension(f)) { if (upb_fielddef_isextension(f)) {
@ -596,7 +604,7 @@ bool upb_msg_has(const upb_msg *msg,
upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f, upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f,
const upb_msglayout *l) { const upb_msglayout *l) {
upb_msg_check(l, f); upb_msg_checkfield(l, f);
if (upb_fielddef_isextension(f)) { if (upb_fielddef_isextension(f)) {
upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l); upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l);
@ -627,7 +635,7 @@ bool upb_msg_set(upb_msg *msg,
upb_msgval val, upb_msgval val,
const upb_msglayout *l) { const upb_msglayout *l) {
upb_alloc *a = upb_msg_alloc(msg, l); upb_alloc *a = upb_msg_alloc(msg, l);
upb_msg_check(l, f); upb_msg_checkfield(l, f);
if (upb_fielddef_isextension(f)) { if (upb_fielddef_isextension(f)) {
/* TODO(haberman): introduce table API that can do this in one call. */ /* TODO(haberman): introduce table API that can do this in one call. */
@ -882,6 +890,7 @@ bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
upb_map_tokey(map->key_type, &key, &key_str, &key_len); upb_map_tokey(map->key_type, &key, &key_str, &key_len);
/* TODO(haberman): add overwrite operation to minimize number of lookups. */
if (upb_strtable_lookup2(&map->strtab, key_str, key_len, NULL)) { if (upb_strtable_lookup2(&map->strtab, key_str, key_len, NULL)) {
upb_strtable_remove3(&map->strtab, key_str, key_len, &removedtabval, a); upb_strtable_remove3(&map->strtab, key_str, key_len, &removedtabval, a);
memcpy(&removed, &removedtabval, sizeof(removed)); memcpy(&removed, &removedtabval, sizeof(removed));

@ -101,6 +101,8 @@ bool upb_visitor_visitmsg(upb_visitor *v, const void *msg);
upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab); upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab);
void upb_msgfactory_free(upb_msgfactory *f); void upb_msgfactory_free(upb_msgfactory *f);
const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f);
/* The functions to get cached objects, lazily creating them on demand. These /* The functions to get cached objects, lazily creating them on demand. These
* all require: * all require:
* *
@ -108,11 +110,11 @@ void upb_msgfactory_free(upb_msgfactory *f);
* - upb_msgdef_mapentry(m) == false (since map messages can't have layouts). * - upb_msgdef_mapentry(m) == false (since map messages can't have layouts).
* *
* The returned objects will live for as long as the msgfactory does. */ * The returned objects will live for as long as the msgfactory does. */
const upb_msglayout *upb_msgfactory_getlayout(const upb_msgfactory *f, const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f,
const upb_msgdef *m); const upb_msgdef *m);
const upb_handlers *upb_msgfactory_getmergehandlers(const upb_msgfactory *f, const upb_handlers *upb_msgfactory_getmergehandlers(upb_msgfactory *f,
const upb_msgdef *m); const upb_msgdef *m);
const upb_visitorplan *upb_visitorplan_new(const upb_msgfactory *f, const upb_visitorplan *upb_msgfactory_getvisitorplan(const upb_msgfactory *f,
const upb_msgdef *m); const upb_msgdef *m);
@ -354,8 +356,6 @@ void upb_mapiter_free(upb_mapiter *i, upb_alloc *a);
void upb_mapiter_next(upb_mapiter *i); void upb_mapiter_next(upb_mapiter *i);
bool upb_mapiter_done(const upb_mapiter *i); bool upb_mapiter_done(const upb_mapiter *i);
/* For string keys, the value will be in upb_msgval_strkey(), *not*
* upb_msgval_str(). */
upb_msgval upb_mapiter_key(const upb_mapiter *i); upb_msgval upb_mapiter_key(const upb_mapiter *i);
upb_msgval upb_mapiter_value(const upb_mapiter *i); upb_msgval upb_mapiter_value(const upb_mapiter *i);
void upb_mapiter_setdone(upb_mapiter *i); void upb_mapiter_setdone(upb_mapiter *i);

Loading…
Cancel
Save