308 lines
11 KiB
Python
Executable File
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()
|