Browse files

compatible with recent protocol buffer

  • Loading branch information...
1 parent 77e887e commit ae6de1a3cd3e3f6176a867113e1b0f5004170ae4 @yihuang committed Dec 2, 2012
Showing with 56 additions and 45 deletions.
  1. +50 −41 lua_protobuf/generator.py
  2. +6 −4 protoc-gen-lua
View
91 lua_protobuf/generator.py
@@ -13,7 +13,7 @@
# limitations under the License.
from google.protobuf.descriptor import FieldDescriptor
-import re
+import re, os
RE_BARE_BEGIN_BRACKET = re.compile(r'^\s*{\s*$')
RE_BEGIN_BRACKET = re.compile(r'{\s*$')
@@ -46,6 +46,16 @@
FieldDescriptor.TYPE_SINT64: 'sint64',
}
+def basename(filename):
+ return os.path.splitext(filename)[0]
+
+def remove_namespace(type_name):
+ parts = type_name.split('.', 2)
+ if len(parts)>2:
+ return parts[2]
+ else:
+ return '.'.join(parts)
+
def lua_protobuf_header():
'''Returns common header included by all produced files'''
return '''
@@ -120,7 +130,7 @@ def lua_protobuf_source():
'''
-def c_header_header(filename, package):
+def c_header_header(filename, package, namespace):
return [
'// Generated by the lua-protobuf compiler.',
'// You shouldn\'t be editing this file manually',
@@ -131,7 +141,8 @@ def c_header_header(filename, package):
'#define LUA_PROTOBUF_%s_H' % package.replace('.', '_'),
'',
'#include "lua-protobuf.h"',
- '#include "%s.pb.h"' % package.replace('.', '/'),
+ '#include <%s.pb.h>' % package.replace('.', '/'),
+ 'using namespace %s;' % namespace,
'',
'#ifdef __cplusplus',
'extern "C" {',
@@ -144,7 +155,7 @@ def c_header_header(filename, package):
'',
]
-def source_header(filename, package):
+def source_header(filename, package, dependencies):
'''Returns lines that begin a source file'''
return [
'// Generated by the lua-protobuf compiler',
@@ -153,6 +164,7 @@ def source_header(filename, package):
'// source proto file: %s' % filename,
'',
'#include "%s.pb-lua.h"' % package.replace('.', '/'),
+ ]+['#include "%s.pb-lua.h"'%basename(dep) for dep in dependencies]+[
'',
'#ifdef __cplusplus',
'extern "C" { // make sure functions treated with C naming',
@@ -181,7 +193,7 @@ def package_function_prefix(package):
return 'lua_protobuf_%s_' % package.replace('.', '_')
def message_function_prefix(package, message):
- return '%s%s_' % (package_function_prefix(package), message)
+ return 'lua_protobuf_%s_' % message
def message_open_function_name(package, message):
'''Returns function name that registers the Lua library for a message type'''
@@ -194,7 +206,7 @@ def cpp_class(package, message = None):
if not message:
return package.replace('.', '::')
- return '::%s::%s' % ( package.replace('.', '::'), message )
+ return '%s' % message
def field_function_name(package, message, prefix, field):
'''Obtain the function name of a field accessor/mutator function'''
@@ -272,7 +284,7 @@ def add_body(package, message, field, type_name):
# since the message is allocated out of the containing message, Lua
# does not need to do GC
- 'lua_protobuf%s_pushreference(L, msg_new, NULL, NULL);' % type_name.replace('.', '_'),
+ '%spushreference(L, msg_new, NULL, NULL);' % message_function_prefix(package, type_name),
'return 1;',
])
@@ -283,7 +295,7 @@ def field_get(package, message, field_descriptor):
name = field_descriptor.name.lower()
type = field_descriptor.type
- type_name = field_descriptor.type_name
+ type_name = remove_namespace(field_descriptor.type_name)
label = field_descriptor.label
repeated = label == FieldDescriptor.LABEL_REPEATED
@@ -338,8 +350,8 @@ def field_get(package, message, field_descriptor):
elif type == FieldDescriptor.TYPE_MESSAGE:
lines.extend([
- '%s * got_msg = m->mutable_%s(index-1);' % ( type_name.replace('.', '::'), name ),
- 'lua_protobuf%s_pushreference(L, got_msg, NULL, NULL);' % type_name.replace('.', '_'),
+ '%s * got_msg = m->mutable_%s(index-1);' % ( cpp_class(type_name), name ),
+ '%spushreference(L, got_msg, NULL, NULL);' % message_function_prefix(package, type_name),
])
else:
@@ -377,8 +389,8 @@ def field_get(package, message, field_descriptor):
# we push the message as userdata
# since the message is allocated out of the parent message, we
# don't need to do garbage collection
- '%s * got_msg = m->mutable_%s();' % ( type_name.replace('.', '::'), name ),
- 'lua_protobuf%s_pushreference(L, got_msg, NULL, NULL);' % type_name.replace('.', '_'),
+ '%s * got_msg = m->mutable_%s();' % ( cpp_class(type_name), name ),
+ '%spushreference(L, got_msg, NULL, NULL);' % message_function_prefix(package, type_name),
])
else:
@@ -405,7 +417,7 @@ def field_set(package, message, field_descriptor):
name = field_descriptor.name.lower()
type = field_descriptor.type
- type_name = field_descriptor.type_name
+ type_name = remove_namespace(field_descriptor.type_name)
label = field_descriptor.label
repeated = label == FieldDescriptor.LABEL_REPEATED
@@ -466,7 +478,7 @@ def field_set(package, message, field_descriptor):
elif type == FieldDescriptor.TYPE_ENUM:
lines.append('lua_Integer i = lua_tointeger(L, 3);')
- lines.extend(field_set_assignment(name, '(%s)i' % type_name.replace('.', '::')))
+ lines.extend(field_set_assignment(name, '(%s)i' % cpp_class(type_name)))
elif type == FieldDescriptor.TYPE_MESSAGE:
lines.append('return luaL_error(L, "to manipulate embedded messages, fetch the embedded message and modify it");')
@@ -534,7 +546,7 @@ def field_set(package, message, field_descriptor):
elif type == FieldDescriptor.TYPE_ENUM:
lines.extend([
'lua_Integer i = luaL_checkinteger(L, 2);',
- 'm->set_%s((%s)i);' % ( name, type_name.replace('.', '::') ),
+ 'm->set_%s((%s)i);' % ( name, cpp_class(type_name) ),
'return 0;',
])
@@ -793,7 +805,6 @@ def message_header(package, message_descriptor):
lines = []
lines.append('// Message %s' % message_name)
- function_prefix = 'lua_protobuf_' + package.replace('.', '_') + '_'
c = cpp_class(package, message_name)
lines.extend([
@@ -803,7 +814,7 @@ def message_header(package, message_descriptor):
'// push a copy of the message to the Lua stack',
'// caller is free to use original message however she wants, but changes will not',
'// be reflected in Lua and vice-verse',
- 'LUA_PROTOBUF_EXPORT bool %s%s_pushcopy(lua_State *L, const %s &msg);' % ( function_prefix, message_name, c),
+ 'LUA_PROTOBUF_EXPORT bool %spushcopy(lua_State *L, const %s &msg);' % ( message_function_prefix(package, message_name), c),
'',
'// push a reference of the message to the Lua stack',
'// the 3rd and 4th arguments define a callback that can be invoked just before Lua',
@@ -812,27 +823,27 @@ def message_header(package, message_descriptor):
'// Lua garbage collects the object. The function is sent a pointer to the message being',
'// collected and the 4th argument to this function. If the function returns true,',
'// Lua will free the memory. If false (0), Lua will not free the memory.',
- 'LUA_PROTOBUF_EXPORT bool %s%s_pushreference(lua_State *L, %s *msg, lua_protobuf_gc_callback callback, void *data);' % ( function_prefix, message_name, c ),
+ 'LUA_PROTOBUF_EXPORT bool %spushreference(lua_State *L, %s *msg, lua_protobuf_gc_callback callback, void *data);' % ( message_function_prefix(package, message_name), c ),
'',
'',
'// The following functions are called by Lua. Many people will not need them,',
'// but they are exported for those that do.',
'',
'',
'// constructor called from Lua',
- 'LUA_PROTOBUF_EXPORT int %s%s_new(lua_State *L);' % ( function_prefix, message_name ),
+ 'LUA_PROTOBUF_EXPORT int %snew(lua_State *L);' % message_function_prefix( package, message_name ),
'',
'// obtain instance from a serialized string',
- 'LUA_PROTOBUF_EXPORT int %s%s_parsefromstring(lua_State *L);' % ( function_prefix, message_name ),
+ 'LUA_PROTOBUF_EXPORT int %sparsefromstring(lua_State *L);' % message_function_prefix( package, message_name ),
'',
'// garbage collects message instance in Lua',
- 'LUA_PROTOBUF_EXPORT int %s%s_gc(lua_State *L);' % ( function_prefix, message_name ),
+ 'LUA_PROTOBUF_EXPORT int %sgc(lua_State *L);' % message_function_prefix( package, message_name ),
'',
'// obtain serialized representation of instance',
- 'LUA_PROTOBUF_EXPORT int %s%s_serialized(lua_State *L);' % ( function_prefix, message_name ),
+ 'LUA_PROTOBUF_EXPORT int %sserialized(lua_State *L);' % message_function_prefix( package, message_name ),
'',
'// clear all fields in the message',
- 'LUA_PROTOBUF_EXPORT int %s%s_clear(lua_State *L);' % ( function_prefix, message_name ),
+ 'LUA_PROTOBUF_EXPORT int %sclear(lua_State *L);' % message_function_prefix( package, message_name ),
'',
])
@@ -855,20 +866,20 @@ def message_header(package, message_descriptor):
field_type_s = FIELD_TYPE_MAP[field_type]
lines.append('// %s %s %s = %d' % (field_label_s, field_type_s, field_name, field_number))
- lines.append('LUA_PROTOBUF_EXPORT int %s%s_clear_%s(lua_State *L);' % (function_prefix, message_name, field_name))
- lines.append('LUA_PROTOBUF_EXPORT int %s%s_get_%s(lua_State *L);' % (function_prefix, message_name, field_name))
+ lines.append('LUA_PROTOBUF_EXPORT int %sclear_%s(lua_State *L);' % (message_function_prefix( package, message_name ), field_name))
+ lines.append('LUA_PROTOBUF_EXPORT int %sget_%s(lua_State *L);' % (message_function_prefix( package, message_name ), field_name))
# TODO I think we can get rid of this for message types
- lines.append('LUA_PROTOBUF_EXPORT int %s%s_set_%s(lua_State *L);' % (function_prefix, message_name, field_name))
+ lines.append('LUA_PROTOBUF_EXPORT int %sset_%s(lua_State *L);' % (message_function_prefix( package, message_name ), field_name))
if field_label in [ FieldDescriptor.LABEL_REQUIRED, FieldDescriptor.LABEL_OPTIONAL ]:
- lines.append('LUA_PROTOBUF_EXPORT int %s%s_has_%s(lua_State *L);' % (function_prefix, message_name, field_name))
+ lines.append('LUA_PROTOBUF_EXPORT int %shas_%s(lua_State *L);' % (message_function_prefix( package, message_name ), field_name))
if field_label == FieldDescriptor.LABEL_REPEATED:
- lines.append('LUA_PROTOBUF_EXPORT int %s%s_size_%s(lua_State *L);' % (function_prefix, message_name, field_name))
+ lines.append('LUA_PROTOBUF_EXPORT int %ssize_%s(lua_State *L);' % (message_function_prefix( package, message_name ), field_name))
if field_type == FieldDescriptor.TYPE_MESSAGE:
- lines.append('LUA_PROTOBUF_EXPORT int %s%s_add_%s(lua_State *L);' % ( function_prefix, message_name, field_name))
+ lines.append('LUA_PROTOBUF_EXPORT int %sadd_%s(lua_State *L);' % ( message_function_prefix( package, message_name ), field_name))
lines.append('')
@@ -896,6 +907,7 @@ def message_source(package, message_descriptor):
for descriptor in message_descriptor.field:
name = descriptor.name.lower()
+ type_name = remove_namespace(descriptor.type_name)
# clear() is in all label types
lines.extend(field_function_start(package, message, 'clear', name))
@@ -919,7 +931,7 @@ def message_source(package, message_descriptor):
if descriptor.type == FieldDescriptor.TYPE_MESSAGE:
lines.extend(field_function_start(package, message, 'add', name))
- lines.extend(add_body(package, message, name, descriptor.type_name))
+ lines.extend(add_body(package, message, name, type_name))
lines.append('}\n')
@@ -992,11 +1004,12 @@ def enum_source(descriptor):
def file_header(file_descriptor):
filename = file_descriptor.name
- package = file_descriptor.package
+ package = basename(filename)
+ namespace = file_descriptor.package
lines = []
- lines.extend(c_header_header(filename, package))
+ lines.extend(c_header_header(filename, package, namespace))
for descriptor in file_descriptor.message_type:
lines.extend(message_header(package, descriptor))
@@ -1013,11 +1026,13 @@ def file_source(file_descriptor):
'''Obtains the source code for a FileDescriptor instance'''
filename = file_descriptor.name
- package = file_descriptor.package
+ package = basename(filename)
+ namespace = file_descriptor.package
lines = []
- lines.extend(source_header(filename, package))
+ lines.extend(source_header(filename, package, file_descriptor.dependency))
lines.append('using ::std::string;\n')
+ lines.append('using namespace %s;\n' % namespace)
lines.append('''
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502
static const char *luaL_findtable (lua_State *L, int idx,
@@ -1047,12 +1062,6 @@ def file_source(file_descriptor):
}
#endif''')
- lines.append('''
-#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
-extern "C" int luaopen_lib%s (lua_State* tolua_S) {
- return %sopen(tolua_S);
-};
-#endif'''%(package.replace('.', '_'), package_function_prefix(package)))
lines.extend([
'int %sopen(lua_State *L)' % package_function_prefix(package),
'{',
@@ -1073,7 +1082,7 @@ def file_source(file_descriptor):
'lua_pushglobaltable(L);',
'const char *table = luaL_findtable(L, 0, "protobuf.%s", 1);' % package,
'#else',
- 'const char *table = luaL_findtable(L, LUA_GLOBALSINDEX, "protobuf.user", 1);',
+ 'const char *table = luaL_findtable(L, LUA_GLOBALSINDEX, "protobuf.%s", 1);' % package,
'#endif',
'if (table) {',
'return luaL_error(L, "could not create parent Lua tables");',
View
10 protoc-gen-lua
@@ -42,11 +42,13 @@ response = CodeGeneratorResponse()
# each input file to the compiler
for i in range(0, len(request.proto_file)):
file_descriptor = request.proto_file[i]
- package = file_descriptor.package
- basename = package.replace('.', '/') if package else os.path.basename(file_descriptor.name)
+ basename = os.path.splitext(file_descriptor.name)[0]
- cpp_header = '%s.pb.h' % basename
- cpp_namespace = '::%s' % package.replace('.', '::') if package else ''
+ # for now, we require package, which is bad
+ # TODO fix this
+ if not file_descriptor.package:
+ response.error = 'file seen without package. lua-protobuf currently requires a package on every proto file: %s' % file_descriptor.name
+ break
f = response.file.add()
f.name = '%s.pb-lua.h' % basename

0 comments on commit ae6de1a

Please sign in to comment.