syndilights/open-lighting-architecture/ola-0.8.4/include/ola/gen_callbacks.py

308 lines
11 KiB
Python
Executable File

#!/usr/bin/python
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# gen_callbacks.py
# Copyright (C) 2010 Simon Newton
import textwrap
def Header():
print textwrap.dedent("""\
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Callback.h
* Callback classes, these are similar to closures but can take arguments at
* exec time.
* Copyright (C) 2005-2010 Simon Newton
*
* THIS FILE IS AUTOGENERATED!
* Please run edit & run gen_callbacks.py if you need to add more types.
*/
#ifndef INCLUDE_OLA_CALLBACK_H_
#define INCLUDE_OLA_CALLBACK_H_
namespace ola {
""")
def Footer():
print textwrap.dedent("""\
} // ola
#endif // INCLUDE_OLA_CALLBACK_H_""")
def GenerateBase(number_of_args):
"""Generate the base Callback classes."""
typenames = ', '.join('typename Arg%d' % i for i in xrange(number_of_args))
arg_list = ', '.join('Arg%d arg%d' % (i, i) for i in xrange(number_of_args))
args = ', '.join('arg%d' % i for i in xrange(number_of_args))
arg_types = ', '.join('Arg%d' % i for i in xrange(number_of_args))
# generate the base callback class
print '// %d argument callbacks' % number_of_args
print 'template <typename ReturnType, %s>' % typenames
print 'class BaseCallback%d {' % number_of_args
print ' public:'
print ' virtual ~BaseCallback%d() {}' % number_of_args
print ' virtual ReturnType Run(%s) = 0;' % arg_list
print ' virtual ReturnType DoRun(%s) = 0;' % arg_list
print '};'
print ''
print ''
# generate the multi-use version of the callback
print '// A callback, this can be called multiple times'
print 'template <typename ReturnType, %s>' % typenames
print ('class Callback%d: public BaseCallback%d<ReturnType, %s> {' %
(number_of_args, number_of_args, arg_types))
print ' public:'
print ' virtual ~Callback%d() {}' % number_of_args
print (' ReturnType Run(%s) { return DoRun(%s); }' %
(arg_list, args))
print '};'
print ''
print ''
# generate the single-use version of the callback
print "// A single use callback, this deletes itself after it's run."
print 'template <typename ReturnType, %s>' % typenames
print ('class SingleUseCallback%d: public BaseCallback%d<ReturnType, %s> {' %
(number_of_args, number_of_args, arg_types))
print ' public:'
print ' virtual ~SingleUseCallback%d() {}' % number_of_args
print ' ReturnType Run(%s) {' % arg_list
print ' ReturnType ret = DoRun(%s);' % args
print ' delete this;'
print ' return ret;'
print ' }'
print '};'
print ''
print ''
# the void specialization
print "// A single use callback returning void."
print 'template <%s>' % typenames
print ('class SingleUseCallback%d<void, %s>: public BaseCallback%d<void, %s> {' %
(number_of_args, arg_types, number_of_args, arg_types))
print ' public:'
print ' virtual ~SingleUseCallback%d() {}' % number_of_args
print ' void Run(%s) {' % arg_list
print ' DoRun(%s);' % args
print ' delete this;'
print ' }'
print '};'
print ''
print ''
def GenerateHelperFunction(bind_count,
exec_count,
function_name,
parent_class,
is_method=True):
"""Generate the helper functions which create callbacks.
Args:
bind_count the number of args supplied at create time.
exec_count the number of args supplied at exec time.
function_name what to call the helper function
parent_class the parent class to use
is_method True if this is a method callback, False if this is a function
callback.
"""
typenames = (['typename A%d' % i for i in xrange(bind_count)] +
['typename Arg%d' % i for i in xrange(exec_count)])
bind_types = ['A%d' % i for i in xrange(bind_count)]
exec_types = ['Arg%d' % i for i in xrange(exec_count)]
method_types = ', '.join(bind_types + exec_types)
optional_class, ptr_name, signature = '', 'callback', '*callback'
if is_method:
optional_class, ptr_name, signature = (
'typename Class, ', 'method', 'Class::*method')
# The single use helper function
print '// Helper method to create a new %s.' % parent_class
print ('template <%stypename ReturnType, %s>' %
(optional_class, ', '.join(typenames)))
print ('inline %s%d<ReturnType, %s>* %s(' %
(parent_class, exec_count, ', '.join(exec_types), function_name))
if is_method:
print ' Class* object,'
if bind_count:
print ' ReturnType (%s)(%s),' % (signature, method_types)
for i in xrange(bind_count):
suffix = ','
if i == bind_count - 1:
suffix = ') {'
print ' A%d a%d%s' % (i, i, suffix)
else:
print ' ReturnType (%s)(%s)) {' % (signature, method_types)
if is_method:
print ' return new MethodCallback%d_%d<Class,' % (bind_count, exec_count)
else:
print ' return new FunctionCallback%d_%d<' % (bind_count, exec_count)
print (' %s%d<ReturnType, %s>,'
% (parent_class, exec_count, ', '.join(exec_types)))
print ' ReturnType,'
for i in xrange(bind_count):
print ' A%d,' % i
for i in xrange(exec_count):
suffix = ','
if i == exec_count - 1:
suffix = '>('
print ' Arg%d%s' % (i, suffix)
if is_method:
print ' object,'
if bind_count:
print ' %s,' % ptr_name
else:
print ' %s);' % ptr_name
for i in xrange(bind_count):
suffix = ','
if i == bind_count - 1:
suffix = ');'
print ' a%d%s' % (i, suffix)
print '}'
print ''
print ''
def GenerateMethodCallback(bind_count,
exec_count,
is_method=True):
"""Generate the specific function callback & helper methods.
bind_count the number of args supplied at create time.
exec_count the number of args supplied at exec time.
is_method True if this is a method callback, False if this is a function
callback.
"""
typenames = (['typename A%d' % i for i in xrange(bind_count)] +
['typename Arg%d' % i for i in xrange(exec_count)])
bind_types = ['A%d' % i for i in xrange(bind_count)]
exec_types = ['Arg%d' % i for i in xrange(exec_count)]
method_types = ', '.join(bind_types + exec_types)
method_args = (['m_a%d' % i for i in xrange(bind_count)] +
['arg%d' % i for i in xrange(exec_count)])
exec_args = ', '.join(['Arg%d arg%d' % (i, i) for i in xrange(exec_count)])
bind_args = ', '.join(['A%d a%d' % (i, i) for i in xrange(bind_count)])
optional_class, method_or_function, class_name = (
'', 'Function', 'FunctionCallback')
class_param, signature = '', '*callback';
if is_method:
optional_class, method_or_function, class_name = (
'typename Class, ', 'Method', 'MethodCallback')
class_param, signature = 'Class *object, ', 'Class::*Method'
print ('// A %s callback with %d create-time args and %d exec time '
'args' % (method_or_function, bind_count, exec_count))
print ('template <%stypename Parent, typename ReturnType, %s>' %
(optional_class, ', '.join(typenames)))
print 'class %s%d_%d: public Parent {' % (class_name, bind_count, exec_count)
print ' public:'
if is_method:
print ' typedef ReturnType (%s)(%s);' % (signature, method_types)
else:
print ' typedef ReturnType (*Function)(%s);' % (method_types)
if bind_count:
print (' %s%d_%d(%s%s callback, %s):' %
(class_name, bind_count, exec_count, class_param,
method_or_function, bind_args))
else:
print (' %s%d_%d(%s%s callback):' %
(class_name, bind_count, exec_count, class_param,
method_or_function))
print ' Parent(),'
if is_method:
print ' m_object(object),'
if bind_count:
print ' m_callback(callback),'
for i in xrange(bind_count):
suffix = ','
if i == bind_count - 1:
suffix = ' {}'
print ' m_a%d(a%d)%s' % (i, i, suffix)
else:
print ' m_callback(callback) {}'
print ' ReturnType DoRun(%s) {' % exec_args
if is_method:
print ' return (m_object->*m_callback)(%s);' % ', '.join(method_args)
else:
print ' return m_callback(%s);' % ', '.join(method_args)
print ' }'
print ' private:'
if is_method:
print ' Class *m_object;'
print ' %s m_callback;' % method_or_function
for i in xrange(bind_count):
print ' A%d m_a%d;' % (i, i)
print '};'
print ''
print ''
# generate the helper methods
GenerateHelperFunction(bind_count,
exec_count,
'NewSingleCallback',
'SingleUseCallback',
is_method)
GenerateHelperFunction(bind_count,
exec_count,
'NewCallback',
'Callback',
is_method)
def main():
Header()
# exec_time : [bind time args]
calback_types = {1: [0, 1, 2, 3],
2: [0, 1, 2, 3, 4],
3: [0, 1, 2, 3],
4: [0, 1, 2, 3],
}
for exec_time in sorted(calback_types):
GenerateBase(exec_time)
for bind_time in calback_types[exec_time]:
GenerateMethodCallback(bind_time, exec_time, is_method=False);
GenerateMethodCallback(bind_time, exec_time)
Footer()
main()