From 4b0c4ca7fb0aa9207af3398e04534b23fbb88f27 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Fri, 9 Sep 2016 14:03:25 -0700 Subject: New upb_msg code and Lua bindings around it. There are still some things that are unfinished, but we are at parity with what Lua had before. --- upb/bindings/lua/upb.h | 64 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 21 deletions(-) (limited to 'upb/bindings/lua/upb.h') diff --git a/upb/bindings/lua/upb.h b/upb/bindings/lua/upb.h index f37ed9a..30fc59d 100644 --- a/upb/bindings/lua/upb.h +++ b/upb/bindings/lua/upb.h @@ -8,6 +8,7 @@ #include "lauxlib.h" #include "upb/def.h" #include "upb/handlers.h" +#include "upb/msg.h" #include "upb/symtab.h" /* Lua 5.1/5.2 compatibility code. */ @@ -23,10 +24,14 @@ void *luaL_testudata(lua_State *L, int ud, const char *tname); +#define lupb_setfuncs(L, l) luaL_register(L, NULL, l) + #elif LUA_VERSION_NUM == 502 int luaL_typerror(lua_State *L, int narg, const char *tname); +#define lupb_setfuncs(L, l) luaL_setfuncs(L, l, 0) + #else #error Only Lua 5.1 and 5.2 are supported #endif @@ -69,6 +74,7 @@ uint32_t lupb_checkuint32(lua_State *L, int narg); double lupb_checkdouble(lua_State *L, int narg); float lupb_checkfloat(lua_State *L, int narg); bool lupb_checkbool(lua_State *L, int narg); +const char *lupb_checkstring(lua_State *L, int narg, size_t *len); const char *lupb_checkname(lua_State *L, int narg); void lupb_pushint64(lua_State *L, int64_t val); @@ -77,10 +83,30 @@ void lupb_pushuint64(lua_State *L, uint64_t val); void lupb_pushuint32(lua_State *L, uint32_t val); void lupb_pushdouble(lua_State *L, double val); void lupb_pushfloat(lua_State *L, float val); -void lupb_pushbool(lua_State *L, bool val); -/* Functions for getting/pushing wrappers to various types defined in the - * core library. */ +/* Builds and returns a handlers object for populating a lupb_msg described by + * the MessageDef at "narg". + * + * TODO(haberman): factor this so it doesn't have to take a lua_State. We + * should be able to generate message handlers for a upb_msgdef that can be used + * across many Lua states, so we can shared JIT code across lua_States. */ +const upb_handlers *lupb_msg_newwritehandlers(lua_State *L, int narg, + const void *owner); + +/* Registers a type with the given name, methods, and metamethods. + * If "refcount_gc" is true, adds a __gc metamethod that does an unref. + * Refcounted types must be allocated with lupb_refcounted_push[new]wrapper. */ +void lupb_register_type(lua_State *L, const char *name, const luaL_Reg *m, + const luaL_Reg *mm); + +/* Checks the given upb_status and throws a Lua error if it is not ok. */ +void lupb_checkstatus(lua_State *L, upb_status *s); + + +/** From def.c. ***************************************************************/ + +upb_fieldtype_t lupb_checkfieldtype(lua_State *L, int narg); + void *lupb_refcounted_check(lua_State *L, int narg, const char *type); const upb_msgdef *lupb_msg_checkdef(lua_State *L, int narg); const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg); @@ -101,26 +127,22 @@ void lupb_symtab_pushwrapper(lua_State *L, const upb_symtab *s, void lupb_symtab_pushnewrapper(lua_State *L, const upb_symtab *s, const void *ref_donor); -/* For constructing a new message. narg is the Lua value for the MessageDef - * object. */ -void lupb_msg_pushnew(lua_State *L, int narg); +void lupb_def_registertypes(lua_State *L); -/* Builds and returns a handlers object for populating a lupb_msg described by - * the MessageDef at "narg". - * - * TODO(haberman): factor this so it doesn't have to take a lua_State. We - * should be able to generate message handlers for a upb_msgdef that can be used - * across many Lua states, so we can shared JIT code across lua_States. */ -const upb_handlers *lupb_msg_newwritehandlers(lua_State *L, int narg, - const void *owner); +int lupb_refcounted_gc(lua_State *L); -/* Registers a type with the given name, methods, and metamethods. - * If "refcount_gc" is true, adds a __gc metamethod that does an unref. - * Refcounted types must be allocated with lupb_refcounted_push[new]wrapper. */ -void lupb_register_type(lua_State *L, const char *name, const luaL_Reg *m, - const luaL_Reg *mm, bool refcount_gc); -/* Checks the given upb_status and throws a Lua error if it is not ok. */ -void lupb_checkstatus(lua_State *L, upb_status *s); +/** From msg.c. ***************************************************************/ + +struct lupb_msgclass; +typedef struct lupb_msgclass lupb_msgclass; + +upb_arena *lupb_arena_check(lua_State *L, int narg); +int lupb_arena_new(lua_State *L); +int lupb_msg_pushref(lua_State *L, int msgclass, void *msg); + +const upb_msglayout *lupb_msgclass_getlayout(lua_State *L, int narg); +const upb_handlers *lupb_msgclass_getmergehandlers(lua_State *L, int narg); +void lupb_msg_registertypes(lua_State *L); #endif /* UPB_LUA_UPB_H_ */ -- cgit v1.2.3 From 31225357260d26e203a5f61d910cd405ab819e3b Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Mon, 5 Dec 2016 05:51:58 +0000 Subject: Fleshed out comments and removed some dead code. --- upb/bindings/lua/upb.h | 9 ------ upb/msg.h | 86 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 30 deletions(-) (limited to 'upb/bindings/lua/upb.h') diff --git a/upb/bindings/lua/upb.h b/upb/bindings/lua/upb.h index 30fc59d..109113c 100644 --- a/upb/bindings/lua/upb.h +++ b/upb/bindings/lua/upb.h @@ -84,15 +84,6 @@ void lupb_pushuint32(lua_State *L, uint32_t val); void lupb_pushdouble(lua_State *L, double val); void lupb_pushfloat(lua_State *L, float val); -/* Builds and returns a handlers object for populating a lupb_msg described by - * the MessageDef at "narg". - * - * TODO(haberman): factor this so it doesn't have to take a lua_State. We - * should be able to generate message handlers for a upb_msgdef that can be used - * across many Lua states, so we can shared JIT code across lua_States. */ -const upb_handlers *lupb_msg_newwritehandlers(lua_State *L, int narg, - const void *owner); - /* Registers a type with the given name, methods, and metamethods. * If "refcount_gc" is true, adds a __gc metamethod that does an unref. * Refcounted types must be allocated with lupb_refcounted_push[new]wrapper. */ diff --git a/upb/msg.h b/upb/msg.h index 2d1a261..92c9817 100644 --- a/upb/msg.h +++ b/upb/msg.h @@ -3,7 +3,9 @@ ** ** However it differs from other common representations like ** google::protobuf::Message in one key way: it does not prescribe any -** ownership semantics, and it does not perform any memory management. +** ownership between messages and submessages, and it relies on the +** client to delete each message/submessage/array/map at the appropriate +** time. ** ** A client can access a upb::Message without knowing anything about ** ownership semantics, but to create or mutate a message a user needs @@ -58,10 +60,12 @@ UPB_BEGIN_EXTERN_C /** upb_msglayout *************************************************************/ -/* Please note that map_entry messages (upb_msgdef_mapentry(m) == true) cannot - * have layouts. They can only be represented as upb_map, not as a message. */ +/* upb_msglayout represents the memory layout of a given upb_msgdef. You get + * instances of this from a upb_msgfactory, and the factory always owns the + * msglayout. */ -/* Requires that upb_fielddef_issubmsg(upb_msglayout_msgdef(l)) == true. +/* Get the msglayout for a submessage. This requires that this field is a + * submessage, ie. upb_fielddef_issubmsg(upb_msglayout_msgdef(l)) == true. * * Since map entry messages don't have layouts, if upb_fielddef_ismap(f) == true * then this function will return the layout for the map's value. It requires @@ -69,36 +73,48 @@ UPB_BEGIN_EXTERN_C const upb_msglayout *upb_msglayout_sublayout(const upb_msglayout *l, const upb_fielddef *f); +/* Returns the msgdef for this msglayout. */ const upb_msgdef *upb_msglayout_msgdef(const upb_msglayout *l); +/** upb_visitor ***************************************************************/ + +/* upb_visitor will visit all the fields of a message and its submessages. It + * uses a upb_visitorplan which you can obtain from a upb_msgfactory. */ + +upb_visitor *upb_visitor_create(upb_env *e, const upb_visitorplan *vp, + upb_sink *output); +bool upb_visitor_visitmsg(upb_visitor *v, const void *msg); + + /** upb_msgfactory ************************************************************/ +/* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and + * upb_visitorplan objects. These are the objects necessary to represent, + * populate, and and visit upb_msg objects. + * + * These caches are all populated by upb_msgdef, and lazily created on demand. + */ + +/* Creates and destroys a msgfactory, respectively. The messages for this + * msgfactory must come from |symtab| (which should outlive the msgfactory). */ upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab); void upb_msgfactory_free(upb_msgfactory *f); -/* Requires: +/* The functions to get cached objects, lazily creating them on demand. These + * all require: + * * - m is in upb_msgfactory_symtab(f) * - 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 objects will live for as long as the msgfactory does. */ const upb_msglayout *upb_msgfactory_getlayout(const upb_msgfactory *f, const upb_msgdef *m); - -/* Returns handlers for populating a message with the given msgdef. */ const upb_handlers *upb_msgfactory_getmergehandlers(const upb_msgfactory *f, const upb_msgdef *m); - -/* Returns a plan for visiting the data and submessages of the given msgdef. */ const upb_visitorplan *upb_visitorplan_new(const upb_msgfactory *f, const upb_msgdef *m); -/* For actually visiting a message and its submessages. */ -upb_visitor *upb_visitor_create(upb_env *e, const upb_visitorplan *vp, - upb_sink *output); -bool upb_visitor_visitmsg(upb_visitor *v, const void *msg); - /** upb_msgval ****************************************************************/ @@ -162,13 +178,37 @@ UPB_INLINE upb_msgval upb_msgval_str(const char *ptr, size_t len) { /** upb_msg *******************************************************************/ +/* A upb_msg represents a protobuf message. It always corresponds to a specific + * upb_msglayout, which describes how it is laid out in memory. + * + * The message will have a fixed size, as returned by upb_msg_sizeof(), which + * will be used to store fixed-length fields. The upb_msg may also allocate + * dynamic memory internally to store data such as: + * + * - extensions + * - unknown fields + */ + +/* Returns the size of a message given this layout. */ size_t upb_msg_sizeof(const upb_msglayout *l); + +/* upb_msg_init() / upb_msg_uninit() allow the user to use a pre-allocated + * block of memory as a message. The block's size should be upb_msg_sizeof(). + * upb_msg_uninit() must be called to release internally-allocated memory + * unless the allocator is an arena that does not require freeing. + * + * Please note that upb_msg_uninit() does *not* free any submessages, maps, + * or arrays referred to by this message's fields. You must free them manually + * yourself. */ void upb_msg_init(upb_msg *msg, const upb_msglayout *l, upb_alloc *a); void upb_msg_uninit(upb_msg *msg, const upb_msglayout *l); +/* Like upb_msg_init() / upb_msg_uninit(), except the message's memory is + * allocated / freed from the given upb_alloc. */ upb_msg *upb_msg_new(const upb_msglayout *l, upb_alloc *a); void upb_msg_free(upb_msg *msg, const upb_msglayout *l); +/* Returns the upb_alloc for the given message. */ upb_alloc *upb_msg_alloc(const upb_msg *msg, const upb_msglayout *l); /* Packs the tree of messages rooted at "msg" into a single hunk of memory, @@ -240,6 +280,10 @@ bool upb_msg_clearoneof(upb_msg *msg, /** upb_array *****************************************************************/ +/* A upb_array stores data for a repeated field. The memory management + * semantics are the same as upb_msg. A upb_array allocates dynamic + * memory internally for the array elements. */ + size_t upb_array_sizeof(upb_fieldtype_t type); void upb_array_init(upb_array *arr, upb_fieldtype_t type, upb_alloc *a); void upb_array_uninit(upb_array *arr); @@ -260,11 +304,11 @@ bool upb_array_set(upb_array *arr, size_t i, upb_msgval val); /** upb_map *******************************************************************/ -/* Stores data for a map field. The map will internally allocate (and free, if - * desired) all the internal storage used for the hash table or tree, using the - * given allocator. It will also copy and internally store the data for string - * keys, but *not* for string or message *values*. So the caller must ensure - * that any string or message values outlive the map. */ +/* A upb_map stores data for a map field. The memory management semantics are + * the same as upb_msg, with one notable exception. upb_map will internally + * store a copy of all string keys, but *not* any string values or submessages. + * So you must ensure that any string or message values outlive the map, and you + * must delete them manually when they are no longer required. */ size_t upb_map_sizeof(upb_fieldtype_t ktype, upb_fieldtype_t vtype); bool upb_map_init(upb_map *map, upb_fieldtype_t ktype, upb_fieldtype_t vtype, -- cgit v1.2.3