def add_overriding_functions(data, scope, classname): if data.small_buffer_optimization: if data.copy_on_write: virtual_clone_into = 'std :: shared_ptr < HandleBase < ' + data.interface_type + ' , Buffer > > clone_into ( Buffer & buffer ) const override ' virtual_clone_into += '{ if ( HeapAllocated ) return std :: make_shared < ' + classname + ' > ( value_ ) ; ' \ 'new ( & buffer ) ' + classname + ' ( value_ ) ; ' \ 'return std :: shared_ptr < ' + classname + ' > ( std :: shared_ptr < ' + classname + ' > ( ) , ' \ 'static_cast < ' + classname + ' * >( static_cast < void * > ( &buffer ) ) ) ; }' scope.add( cpp_file_parser.get_function_from_text(classname, 'clone_into', 'return ', virtual_clone_into)) else: clone_into = 'HandleBase < ' + data.interface_type + ' , Buffer > * clone_into ( Buffer & buffer ) const override { return ' \ 'type_erasure_detail :: clone_into < HandleBase < ' + data.interface_type + ' , ' \ ' Buffer > , Handle < T , ' + data.interface_type + ' , Buffer , false > , ' \ 'Handle < T , ' + data.interface_type + ' , Buffer , true > > ( value_ , buffer ) ; }' scope.add( cpp_file_parser.get_function_from_text(classname, 'clone_into', 'return ', clone_into)) destroy = 'void destroy ( ) noexcept override { if ( HeapAllocated ) delete this ; ' \ 'else this -> ~ ' + classname + ' ( ) ; }' scope.add( cpp_file_parser.get_function_from_text(classname, 'destroy', '', destroy)) else: clone = code.get_handle_return_type(data, classname) + 'clone ( ) const override { ' \ 'return ' + code.get_generator(data, classname) + '( value_ ) ; }' scope.add( cpp_file_parser.get_function_from_text(classname, 'clone', 'return ', clone))
def add_private_section(data, scope, detail_namespace, classname): scope.add(cpp.private_access) if data.copy_on_write: if data.copy_on_write and data.small_buffer_optimization: return_type = data.handle_base_typename else: return_type = data.handle_base_typename + ' < ' + classname if data.small_buffer_optimization: return_type += ' , Buffer ' return_type += ' > ' return_type += ' & ' if not data.small_buffer_optimization: return_type = return_type.replace(data.handle_base_typename, detail_namespace + ' :: ' + data.handle_base_typename) const_return_type = 'const ' + return_type scope.add(cpp_file_parser.get_function_from_text(classname, 'read', 'return ', code.get_read_function(data, const_return_type, data.impl_member))) scope.add(cpp_file_parser.get_function_from_text(classname, 'write', 'return ', code.get_write_function(data, return_type))) if data.small_buffer_optimization and not data.copy_on_write: reset = 'void reset ( ) noexcept { if ( ' + data.impl_member + ' ) ' + data.impl_member + ' -> destroy ( ) ; }' scope.add(cpp_file_parser.get_function_from_text(classname, 'reset', '', reset)) scope.add(cpp.Variable(data.get_impl_type(detail_namespace, classname) + ' ' + data.impl_member + ' = nullptr;')) if data.small_buffer_optimization: scope.add(cpp.Variable('Buffer buffer_ ;'))
def add_operators(data, scope, classname, detail_namespace): # assignment operators scope.add( cpp_file_parser.get_function_from_text( classname, 'operator=', 'return ', code.get_assignment_from_value(data, classname, detail_namespace), cpp.FUNCTION_TEMPLATE)) if not data.copy_on_write: if not data.non_copyable: scope.add( cpp_file_parser.get_function_from_text( classname, 'operator=', 'return ', code.get_copy_operator(data, classname))) scope.add( cpp_file_parser.get_function_from_text( classname, 'operator=', 'return ', code.get_move_operator(data, classname))) # operator bool function = cpp_file_parser.get_function_from_text( classname, 'operator bool', 'return ', code.get_operator_bool_for_member_ptr(data.impl_member)) comment = code.get_operator_bool_comment(function.get_declaration()) scope.add(cpp.Comment(comment)) scope.add(function)
def add_handle_constructors(scope): # add templated constructors # constructor for values and rvalues constructor = 'template < class U , ' + code.get_static_value_check('T','U') + ' > ' constructor += 'explicit Handle ( U && value ) ' + code.noexcept_if_nothrow_constructible constructor += ': value_ ( std :: forward < U > ( value ) ) { }' scope.add( cpp_file_parser.get_function_from_text('Handle', 'Handle', '', constructor, 'constructor') ) # constructor for references constructor = 'template < class U , ' + code.static_reference_check + ' > ' constructor += 'explicit Handle ( U && value ) noexcept : value_ ( value ) { }' scope.add( cpp_file_parser.get_function_from_text('Handle', 'Handle', '', constructor, 'constructor') )
def add_pure_virtual_functions_for_small_buffer_optimization( data, scope, classname): clone_into = 'virtual ' + code.get_handle_return_type( data, classname) + 'clone_into ( Buffer & ) const = 0 ;' scope.add( cpp_file_parser.get_function_from_text(classname, 'clone_into', 'return ', clone_into)) if not data.copy_on_write: destroy = 'virtual void destroy ( ) noexcept = 0 ;' scope.add( cpp_file_parser.get_function_from_text(classname, 'destroy', '', destroy))
def add_casts(data, scope, classname, detail_namespace): function = cpp_file_parser.get_function_from_text(classname, 'target', 'return ', code.get_cast(data, classname, detail_namespace, ''), cpp.FUNCTION_TEMPLATE) comment = code.get_handle_cast_comment(function.get_declaration()) scope.add(cpp.Comment(comment)) scope.add(function) function = cpp_file_parser.get_function_from_text(classname, 'target', 'return ', code.get_cast(data, classname, detail_namespace, 'const'), cpp.FUNCTION_TEMPLATE) comment = code.get_handle_cast_comment(function.get_declaration(), 'const') scope.add(cpp.Comment(comment)) scope.add(function)
def visit_function(self, function_): function = copy.deepcopy(function_) tokens = function.tokens[:cpp.get_declaration_end_index( function.name, function.tokens)] index, offset = cpp.find_function_name(function.name, tokens) cpp_file_parser.replace_in_tokens(function.classname, self.data.interface_type, tokens[:index]) function_name = cpp_file_parser.get_function_name_for_type_erasure( function) code = util.concat(tokens[:index], ' ') + function_name + ' ( ' cpp_file_parser.replace_in_tokens(function.classname, 'HandleBase', tokens[index:]) code += cpp_file_parser.const_specifier( function) + self.data.interface_type + ' & ' for arg in cpp.get_function_arguments(function): code += ' , ' + arg.in_declaration() code += util.concat( tokens[cpp.get_arguments_end_index(function.name, tokens):cpp. get_declaration_end_index(function.name, tokens)], ' ') if not code.startswith('virtual '): code = 'virtual ' + code if not code.endswith('= 0'): code += ' = 0' code += ' ;' self.scope.add( cpp_file_parser.get_function_from_text(function.classname, function_name, function.return_str, code))
def visit_function(self,function): index, offset = cpp.find_function_name(function.name, function.tokens) # returns_self = cpp.contains_sequence(function.tokens[:index], [cpp.SimpleToken(function.classname), cpp.SimpleToken('&')]) returns_self_by_reference = cpp.contains_sequence(function.tokens[:index], [cpp.SimpleToken(function.classname), cpp.SimpleToken('&')]) member = self.data.impl_const_access if cpp.is_const(function) else self.data.impl_access if self.in_private_section: return code = function.get_declaration() code += '{ assert ( ' + self.data.impl_member + ' ) ; ' code += function.return_str + self.data.function_table_member + ' . ' + cpp_file_parser.get_function_name_for_type_erasure(function) code += ' ( ' if returns_self_by_reference: code += '* this , ' code += member + ' ' arguments = cpp.get_function_arguments(function) for arg in arguments: code += ' , ' if cpp_file_parser.contains(function.classname, arg.tokens): code += arg.name() + ' . ' + self.data.impl_raw_member else: code += arg.in_single_function_call() code += ' ) ; }' self.scope.add(cpp_file_parser.get_function_from_text(self.classname,function.name,function.return_str, code))
def visit_function(self,function): if self.in_private_section: return code = util.concat(function.tokens[:cpp.get_declaration_end_index(function.name, function.tokens)], ' ') code += ' { assert ( ' + self.data.impl_member + ' ) ; ' + function.return_str if self.data.copy_on_write: if cpp.is_const(function): code += 'read ( ) . ' else: code += 'write ( ) . ' else: code += self.data.impl_member + ' -> ' code += cpp_file_parser.get_function_name_for_type_erasure(function) + ' ( * this ' arguments = cpp.get_function_arguments(function) for arg in arguments: code += ' , ' if self.scope.get_open_scope().name + ' &' in arg.type(): code += ' * ' + arg.in_single_function_call() + ' . ' + self.data.impl_member + ' ' elif self.scope.get_open_scope().name + ' *' in arg.type(): code += arg.in_single_function_call() + ' -> ' + self.data.impl_member else: code += arg.in_single_function_call() code += ' ) ; }' self.scope.add(cpp_file_parser.get_function_from_text(function.classname, function.name, function.return_str, code))
def visit_function(self, function): if self.in_private_section: return code = util.concat( function.tokens[:cpp.get_declaration_end_index( function.name, function.tokens)], ' ') code += ' { assert ( ' + self.data.impl_member + ' ) ; ' + function.return_str if self.data.copy_on_write: if cpp.is_const(function): code += 'read ( ) . ' else: code += 'write ( ) . ' else: code += self.data.impl_member + ' -> ' code += cpp_file_parser.get_function_name_for_type_erasure( function) + ' ( * this ' arguments = cpp.get_function_arguments(function) for arg in arguments: code += ' , ' if self.scope.get_open_scope().name + ' &' in arg.type(): code += ' * ' + arg.in_single_function_call( ) + ' . ' + self.data.impl_member + ' ' elif self.scope.get_open_scope().name + ' *' in arg.type(): code += arg.in_single_function_call( ) + ' -> ' + self.data.impl_member else: code += arg.in_single_function_call() code += ' ) ; }' self.scope.add( cpp_file_parser.get_function_from_text(function.classname, function.name, function.return_str, code))
def add_handle_constructors(scope): # add templated constructors # constructor for values and rvalues constructor = 'template < class U , ' + code.get_static_value_check( 'T', 'U') + ' > ' constructor += 'explicit Handle ( U && value ) ' + code.noexcept_if_nothrow_constructible constructor += ': value_ ( std :: forward < U > ( value ) ) { }' scope.add( cpp_file_parser.get_function_from_text('Handle', 'Handle', '', constructor, 'constructor')) # constructor for references constructor = 'template < class U , ' + code.static_reference_check + ' > ' constructor += 'explicit Handle ( U && value ) noexcept : value_ ( value ) { }' scope.add( cpp_file_parser.get_function_from_text('Handle', 'Handle', '', constructor, 'constructor'))
def add_constructors(data, scope, class_scope, detail_namespace): classname = class_scope.get_name() constexpr = '' if data.small_buffer_optimization else 'constexpr' constructor = code.get_default_default_constructor(classname,'noexcept',constexpr) scope.add( cpp_file_parser.get_function_from_text(classname, classname, '', constructor, cpp.CONSTRUCTOR) ) scope.add(cpp_file_parser.get_function_from_text(classname, classname, '', code.get_handle_constructor(data, classname, detail_namespace), cpp.CONSTRUCTOR_TEMPLATE)) if not data.copy_on_write: if not data.non_copyable: scope.add(cpp_file_parser.get_function_from_text(classname, classname, '', code.get_copy_constructor(data, classname), cpp.CONSTRUCTOR)) scope.add( cpp_file_parser.get_function_from_text(classname, classname, '', code.get_move_constructor(data, classname), cpp.CONSTRUCTOR) )
def add_operators(data, scope, classname, detail_namespace): # assignment operators scope.add(cpp_file_parser.get_function_from_text(classname, 'operator=', 'return ', code.get_assignment_from_value(data, classname, detail_namespace), cpp.FUNCTION_TEMPLATE)) if not data.copy_on_write or data.small_buffer_optimization: if not data.non_copyable: scope.add(cpp_file_parser.get_function_from_text(classname, 'operator=', 'return ', code.get_copy_operator(data, classname))) scope.add(cpp_file_parser.get_function_from_text(classname, 'operator=', 'return ', code.get_move_operator(data, classname))) # operator bool function = cpp_file_parser.get_function_from_text(classname, 'operator bool', 'return ', code.get_operator_bool_for_member_ptr(data.impl_member)) comment = code.get_operator_bool_comment(function.get_declaration()) scope.add(cpp.Comment(comment)) scope.add(function)
def add_private_section(data, scope, detail_namespace, classname): scope.add(cpp.private_access) if data.copy_on_write: if data.copy_on_write and data.small_buffer_optimization: return_type = data.handle_base_typename else: return_type = data.handle_base_typename + ' < ' + classname if data.small_buffer_optimization: return_type += ' , Buffer ' return_type += ' > ' return_type += ' & ' if not data.small_buffer_optimization: return_type = return_type.replace( data.handle_base_typename, detail_namespace + ' :: ' + data.handle_base_typename) const_return_type = 'const ' + return_type scope.add( cpp_file_parser.get_function_from_text( classname, 'read', 'return ', code.get_read_function(data, const_return_type, data.impl_member))) scope.add( cpp_file_parser.get_function_from_text( classname, 'write', 'return ', code.get_write_function(data, return_type))) if data.small_buffer_optimization and not data.copy_on_write: reset = 'void reset ( ) noexcept { if ( ' + data.impl_member + ' ) ' + data.impl_member + ' -> destroy ( ) ; }' scope.add( cpp_file_parser.get_function_from_text(classname, 'reset', '', reset)) scope.add( cpp.Variable( data.get_impl_type(detail_namespace, classname) + ' ' + data.impl_member + ' = nullptr;')) if data.small_buffer_optimization: scope.add(cpp.Variable('Buffer buffer_ ;'))
def add_private_section(data, scope, detail_namespace, classname): scope.add(cpp.private_access) if data.copy_on_write: return_type = 'void *' const_return_type = return_type scope.add(cpp_file_parser.get_function_from_text(classname, 'read', 'return ', code.get_read_function(data, const_return_type, data.impl_member))) scope.add(cpp_file_parser.get_function_from_text(classname, 'write', 'return ', code.get_write_function(data, return_type))) function_table_var = detail_namespace + '::' + data.function_table_type + '<' + classname if data.small_buffer_optimization: function_table_var += ', Buffer' function_table_var += '>' + data.function_table_member + ';' scope.add(cpp.Variable(function_table_var)) if not data.no_rtti: scope.add(cpp.Variable('std::size_t type_id_;')) if data.copy_on_write: scope.add(cpp.Variable('std::shared_ptr<void> ' + data.impl_member + ' = nullptr;')) else: scope.add(cpp.Variable('void* ' + data.impl_member + ' = nullptr;')) if not data.copy_on_write: reset = 'void reset ( ) noexcept { if ( ' + data.impl_member + ' ' if data.small_buffer_optimization: reset += ' && type_erasure_table_detail :: is_heap_allocated ( ' + data.impl_raw_member + ' , buffer_ ) ' reset += ') ' + data.function_table_member + ' . del ( ' + data.impl_raw_member + ' ) ; }' scope.add(cpp_file_parser.get_function_from_text(classname, 'reset', '', reset)) if not data.non_copyable and data.small_buffer_optimization: clone_into = 'void * clone_into ( Buffer & buffer ) const { if ( ! ' + data.impl_member + ' ) return nullptr ; ' clone_into += 'if ( type_erasure_table_detail :: is_heap_allocated ( ' + data.impl_raw_member + ' , buffer_ ) ) ' clone_into += 'return ' + data.function_table_member + ' . clone ( ' + data.impl_member + ' ) ; else ' clone_into += 'return ' + data.function_table_member + ' . clone_into ( ' + data.impl_member + ' , buffer ) ; }' scope.add(cpp_file_parser.get_function_from_text(classname, 'clone_into', 'return ', clone_into)) if data.small_buffer_optimization: scope.add(cpp.Variable('Buffer buffer_ ;'))
def add_constructors(data, scope, class_scope, detail_namespace): classname = class_scope.get_name() constructor = classname + ' ( ) noexcept : ' + data.impl_member + ' ( nullptr ) { }' scope.add( cpp_file_parser.get_function_from_text(classname, classname, '', constructor, cpp.CONSTRUCTOR) ) table_constructor_extractor = TableConstructorExtractor(data, class_scope.get_name(), detail_namespace) class_scope.visit(table_constructor_extractor) constructor = table_constructor_extractor.constructor + table_constructor_extractor.constructor_end scope.add(cpp_file_parser.get_function_from_text(class_scope.get_name(), class_scope.get_name(), '', constructor, cpp.CONSTRUCTOR_TEMPLATE)) if not data.copy_on_write or data.small_buffer_optimization: if not data.non_copyable: scope.add(cpp_file_parser.get_function_from_text(classname, classname, '', code.get_copy_constructor(data, classname), cpp.CONSTRUCTOR)) scope.add( cpp_file_parser.get_function_from_text(classname, classname, '', code.get_move_constructor(data, classname), cpp.CONSTRUCTOR) )
def add_default_interface(data, scope, class_scope, detail_namespace): classname = class_scope.get_name() scope.add( cpp.private_access ) add_aliases(data, scope, detail_namespace) scope.add( cpp.public_access ) add_constructors(data, scope, class_scope, detail_namespace) if not data.copy_on_write: destructor = '~ ' + classname + ' ( ) { reset ( ) ; }' scope.add( cpp_file_parser.get_function_from_text(classname, '~'+classname, '', destructor, 'destructor')) add_operators(data, scope, classname, detail_namespace)
def add_overriding_functions(data, scope, classname): if data.small_buffer_optimization: if data.copy_on_write: virtual_clone_into = 'std :: shared_ptr < HandleBase < ' + data.interface_type + ' , Buffer > > clone_into ( Buffer & buffer ) const override ' virtual_clone_into += '{ if ( HeapAllocated ) return std :: make_shared < ' + classname + ' > ( value_ ) ; ' \ 'new ( & buffer ) ' + classname + ' ( value_ ) ; ' \ 'return std :: shared_ptr < ' + classname + ' > ( std :: shared_ptr < ' + classname + ' > ( ) , ' \ 'static_cast < ' + classname + ' * >( static_cast < void * > ( &buffer ) ) ) ; }' scope.add(cpp_file_parser.get_function_from_text(classname, 'clone_into', 'return ', virtual_clone_into)) else: clone_into = 'HandleBase < ' + data.interface_type + ' , Buffer > * clone_into ( Buffer & buffer ) const override { return ' \ 'type_erasure_detail :: clone_into < HandleBase < ' + data.interface_type + ' , ' \ ' Buffer > , Handle < T , ' + data.interface_type + ' , Buffer , false > , ' \ 'Handle < T , ' + data.interface_type + ' , Buffer , true > > ( value_ , buffer ) ; }' scope.add(cpp_file_parser.get_function_from_text(classname, 'clone_into', 'return ', clone_into)) destroy = 'void destroy ( ) noexcept override { if ( HeapAllocated ) delete this ; ' \ 'else this -> ~ ' + classname + ' ( ) ; }' scope.add(cpp_file_parser.get_function_from_text(classname, 'destroy', '', destroy)) else: clone = code.get_handle_return_type(data, classname) + 'clone ( ) const override { ' \ 'return ' + code.get_generator(data, classname) + '( value_ ) ; }' scope.add(cpp_file_parser.get_function_from_text(classname, 'clone', 'return ', clone))
def add_constructors(data, scope, class_scope, detail_namespace): classname = class_scope.get_name() constexpr = '' if data.small_buffer_optimization else 'constexpr' constructor = code.get_default_default_constructor(classname, 'noexcept', constexpr) scope.add( cpp_file_parser.get_function_from_text(classname, classname, '', constructor, cpp.CONSTRUCTOR)) scope.add( cpp_file_parser.get_function_from_text( classname, classname, '', code.get_handle_constructor(data, classname, detail_namespace), cpp.CONSTRUCTOR_TEMPLATE)) if not data.copy_on_write: if not data.non_copyable: scope.add( cpp_file_parser.get_function_from_text( classname, classname, '', code.get_copy_constructor(data, classname), cpp.CONSTRUCTOR)) scope.add( cpp_file_parser.get_function_from_text( classname, classname, '', code.get_move_constructor(data, classname), cpp.CONSTRUCTOR))
def visit_function(self,function_): function = copy.deepcopy(function_) tokens = function.tokens[:cpp.get_declaration_end_index(function.name, function.tokens)] index, offset = cpp.find_function_name(function.name, function.tokens) cpp_file_parser.replace_in_tokens(function.classname, self.data.interface_type, tokens[:index]) function_name = cpp_file_parser.get_function_name_for_type_erasure(function) code = util.concat(tokens[:index], ' ') + function_name + ' ( ' cpp_file_parser.replace_in_tokens(function.classname, 'HandleBase', tokens[index:]) code += cpp_file_parser.const_specifier(function) + self.data.interface_type + ' & ' + self.data.interface_variable + ' ' for arg in cpp.get_function_arguments(function): if 'HandleBase' in arg.type(): cpp_file_parser.replace_in_tokens('HandleBase', self.data.handle_base_type, arg.tokens) code += ' , ' + arg.in_declaration() code += util.concat(tokens[cpp.get_arguments_end_index(function.name, tokens): cpp.get_declaration_end_index(function.name, tokens)], ' ') if code.startswith('virtual '): code = code[len('virtual '):] if code.endswith(' = 0'): code = code[:-len(' = 0')] code += 'override { ' contains_class_ref = util.concat(tokens[:index], ' ') in ['const ' + self.data.interface_type + ' & ', self.data.interface_type + ' & '] if not contains_class_ref: code += function.return_str code += 'value_ . ' + function.name + ' ( ' arguments = cpp.get_function_arguments(function) for arg in arguments: if arg.type() == 'const HandleBase & ': code += 'static_cast < ' + 'const ' + self.data.handle_type + ' & > ( ' code += arg.name() + ' ) . value_ ' elif arg.type() == 'HandleBase & ': code += 'static_cast < ' + self.data.handle_type + ' & > ( ' code += arg.name() + ' ) . value_ ' else: code += arg.in_single_function_call() if arg is not arguments[-1]: code += ' , ' code += ' ) ; ' if contains_class_ref: code += 'return ' + self.data.interface_variable + ' ;' code += ' }' self.scope.add(cpp_file_parser.get_function_from_text(function.classname, function_name, function.return_str, code))
def visit_class(self, class_object): if class_object.get_name() != self.data.classname: return class_object.content.append( cpp_file_parser.AccessSpecifier(cpp_file_parser.PUBLIC)) default_constructor = self.data.classname + ' ( ) ' if self.data.implicit_default_constructor: default_constructor += ': pimpl_( new ' + self.data.private_classname + ' ( ) ) { }' else: default_constructor += '{ }' class_object.content.append( cpp_file_parser.get_function_from_text( self.data.classname, self.data.classname, '', default_constructor, cpp_file_parser.CONSTRUCTOR)) destructor = '~ ' + self.data.classname + ' ( ) { } ' class_object.content.append( cpp_file_parser.get_function_from_text(self.data.classname, '~' + self.data.classname, '', destructor, cpp_file_parser.DESTRUCTOR)) if not self.data.non_copyable: copy_assignment = code.get_pimpl_copy_assignment( self.data, self.data.classname, self.data.private_classname, 'pimpl_') class_object.content.append( cpp_file_parser.get_function_from_text( self.data.classname, 'operator=', '', copy_assignment, cpp_file_parser.ASSIGNMENT_OPERATOR)) copy_constructor = code.get_pimpl_copy_constructor( self.data, self.data.classname, self.data.private_classname, 'pimpl_') class_object.content.append( cpp_file_parser.get_function_from_text( self.data.classname, self.data.classname, '', copy_constructor, cpp_file_parser.CONSTRUCTOR)) if not self.data.non_moveable: move_assignment = code.get_pimpl_move_assignment( self.data, self.data.classname, 'pimpl_') class_object.content.append( cpp_file_parser.get_function_from_text( self.data.classname, 'operator=', '', move_assignment, cpp_file_parser.ASSIGNMENT_OPERATOR)) move_constructor = code.get_pimpl_move_constructor( self.data, self.data.classname, 'pimpl_') class_object.content.append( cpp_file_parser.get_function_from_text( self.data.classname, self.data.classname, '', move_constructor, cpp_file_parser.CONSTRUCTOR))
def add_handle_base(data, scope, class_scope): classname = 'HandleBase' handle_base = 'template < class ' + data.interface_type if data.small_buffer_optimization: handle_base += ', class Buffer ' handle_base += '> struct HandleBase' scope.add(cpp.get_template_struct_from_text(classname, handle_base)) destructor = 'virtual ~ ' + classname + ' ( ) = default ;' scope.add( cpp_file_parser.get_function_from_text(classname, '~' + classname, '', destructor, 'destructor') ) if data.small_buffer_optimization: add_pure_virtual_functions_for_small_buffer_optimization(data, scope, classname) else: add_pure_virtual_clone_function(data, scope, classname) class_scope.visit(PureVirtualFunctionExtractor(data, scope)) scope.close()
def visit_function(self,function_): function = copy.deepcopy(function_) tokens = function.tokens[:cpp.get_declaration_end_index(function.name, function.tokens)] index, offset = cpp.find_function_name(function.name, tokens) cpp_file_parser.replace_in_tokens(function.classname, self.data.interface_type, tokens[:index]) function_name = cpp_file_parser.get_function_name_for_type_erasure(function) code = util.concat(tokens[:index], ' ') + function_name + ' ( ' cpp_file_parser.replace_in_tokens(function.classname, 'HandleBase', tokens[index:]) code += cpp_file_parser.const_specifier(function) + self.data.interface_type + ' & ' for arg in cpp.get_function_arguments(function): code += ' , ' + arg.in_declaration() code += util.concat(tokens[cpp.get_arguments_end_index(function.name, tokens): cpp.get_declaration_end_index(function.name, tokens)], ' ') if not code.startswith('virtual '): code = 'virtual ' + code if not code.endswith('= 0'): code += ' = 0' code += ' ;' self.scope.add(cpp_file_parser.get_function_from_text(function.classname, function_name, function.return_str, code))
def add_handle_base(data, scope, class_scope): classname = 'HandleBase' handle_base = 'template < class ' + data.interface_type if data.small_buffer_optimization: handle_base += ', class Buffer ' handle_base += '> struct HandleBase' scope.add(cpp.get_template_struct_from_text(classname, handle_base)) destructor = 'virtual ~ ' + classname + ' ( ) = default ;' scope.add( cpp_file_parser.get_function_from_text(classname, '~' + classname, '', destructor, 'destructor')) if data.small_buffer_optimization: add_pure_virtual_functions_for_small_buffer_optimization( data, scope, classname) else: add_pure_virtual_clone_function(data, scope, classname) class_scope.visit(PureVirtualFunctionExtractor(data, scope)) scope.close()
def visit_class(self,class_object): if class_object.get_name() != self.data.classname: return class_object.content.append(cpp_file_parser.AccessSpecifier(cpp_file_parser.PUBLIC)) default_constructor = self.data.classname + ' ( ) ' if self.data.implicit_default_constructor: default_constructor += ': pimpl_( new ' + self.data.private_classname + ' ( ) ) { }' else: default_constructor += '{ }' class_object.content.append(cpp_file_parser.get_function_from_text(self.data.classname, self.data.classname, '', default_constructor, cpp_file_parser.CONSTRUCTOR)) destructor = '~ ' + self.data.classname + ' ( ) { } ' class_object.content.append(cpp_file_parser.get_function_from_text(self.data.classname, '~' + self.data.classname, '', destructor, cpp_file_parser.DESTRUCTOR)) if not self.data.non_copyable: copy_assignment = code.get_pimpl_copy_assignment(self.data, self.data.classname, self.data.private_classname, 'pimpl_') class_object.content.append(cpp_file_parser.get_function_from_text(self.data.classname, 'operator=', '', copy_assignment, cpp_file_parser.ASSIGNMENT_OPERATOR)) copy_constructor = code.get_pimpl_copy_constructor(self.data, self.data.classname, self.data.private_classname, 'pimpl_') class_object.content.append(cpp_file_parser.get_function_from_text(self.data.classname, self.data.classname, '', copy_constructor, cpp_file_parser.CONSTRUCTOR)) if not self.data.non_moveable: move_assignment = code.get_pimpl_move_assignment(self.data, self.data.classname, 'pimpl_') class_object.content.append(cpp_file_parser.get_function_from_text(self.data.classname, 'operator=', '', move_assignment, cpp_file_parser.ASSIGNMENT_OPERATOR)) move_constructor = code.get_pimpl_move_constructor(self.data, self.data.classname, 'pimpl_') class_object.content.append(cpp_file_parser.get_function_from_text(self.data.classname, self.data.classname, '', move_constructor, cpp_file_parser.CONSTRUCTOR))
def add_pure_virtual_clone_function(data, scope, classname): clone = 'virtual ' + code.get_handle_return_type(data, classname) + 'clone ( ) const = 0 ;' scope.add( cpp_file_parser.get_function_from_text(classname, 'clone', 'return ', clone) )
def add_pure_virtual_clone_function(data, scope, classname): clone = 'virtual ' + code.get_handle_return_type( data, classname) + 'clone ( ) const = 0 ;' scope.add( cpp_file_parser.get_function_from_text(classname, 'clone', 'return ', clone))
def visit_function(self,function_): function = copy.deepcopy(function_) name = cpp_file_parser.get_function_name_for_type_erasure(function) index, offset = cpp.find_function_name(function.name, function.tokens) returns_self = util.contains(function.tokens[:index], function.classname) returns_self_by_reference = cpp.contains_sequence(function.tokens[:index], [cpp.SimpleToken(function.classname), cpp.SimpleToken('&')]) if returns_self: cpp_file_parser.replace_in_tokens(function.classname, self.data.interface_type, function.tokens[:index]) arguments = copy.deepcopy(cpp.get_function_arguments(function)) wrapper = 'static ' + util.concat(function.tokens[:index], ' ') wrapper += name + ' ( ' if returns_self_by_reference: wrapper += cpp_file_parser.const_specifier(function) + self.data.interface_type + ' & ' + self.data.interface_variable + ' , ' wrapper += ' void * impl ' for arg in arguments: if cpp_file_parser.contains(function.classname, arg.tokens): wrapper += ' , void * ' + arg.tokens[-1].spelling else: wrapper += ' , ' + arg.in_declaration() wrapper += ' ) ' if 'noexcept' in function.tokens[cpp.get_arguments_end_index(function.name, function.tokens): cpp.get_declaration_end_index(function.name, function.tokens)]: wrapper += 'noexcept ' wrapper += '{ ' returns_class_ref = cpp.returns_class_ref(self.data.interface_type, function) if not returns_class_ref: wrapper += function.return_str + ' ' wrapper += 'static_cast ' const = 'const ' if cpp.is_const(function) else '' if self.for_reference_wrapper: wrapper += '< std :: reference_wrapper < Impl > * > ( impl ) -> get ( ) . ' else: wrapper += '< ' + const + ' Impl * > ( impl ) -> ' wrapper += function.name + ' ( ' for arg in arguments: if cpp_file_parser.contains(function.classname, arg.tokens): typename = util.concat(arg.tokens[:-1], ' ') typename = typename.replace(' ' + function.classname + ' ', ' Impl ') if self.for_reference_wrapper: if typename.endswith('* '): wrapper += '& ' wrapper += 'static_cast < std :: reference_wrapper < Impl > * > ( ' + arg.in_single_function_call() wrapper += ' ) -> get ( )' else: if typename.endswith('& '): wrapper += '* ' wrapper += 'static_cast< ' + ('const ' if cpp.is_const(function) else '') wrapper += 'Impl * > ( ' + arg.in_single_function_call() + ' )' else: wrapper += arg.in_single_function_call() if arg is not arguments[-1]: wrapper += ' , ' wrapper += ' ) ; ' if returns_class_ref: wrapper += 'return interface ; ' wrapper += '}' self.scope.add(cpp_file_parser.get_function_from_text('execution_wrapper', name, function.return_str, wrapper))
def visit_function(self, function_): function = copy.deepcopy(function_) tokens = function.tokens[:cpp.get_declaration_end_index( function.name, function.tokens)] index, offset = cpp.find_function_name(function.name, function.tokens) cpp_file_parser.replace_in_tokens(function.classname, self.data.interface_type, tokens[:index]) function_name = cpp_file_parser.get_function_name_for_type_erasure( function) code = util.concat(tokens[:index], ' ') + function_name + ' ( ' cpp_file_parser.replace_in_tokens(function.classname, 'HandleBase', tokens[index:]) code += cpp_file_parser.const_specifier( function ) + self.data.interface_type + ' & ' + self.data.interface_variable + ' ' for arg in cpp.get_function_arguments(function): if 'HandleBase' in arg.type(): cpp_file_parser.replace_in_tokens('HandleBase', self.data.handle_base_type, arg.tokens) code += ' , ' + arg.in_declaration() code += util.concat( tokens[cpp.get_arguments_end_index(function.name, tokens):cpp. get_declaration_end_index(function.name, tokens)], ' ') if code.startswith('virtual '): code = code[len('virtual '):] if code.endswith(' = 0'): code = code[:-len(' = 0')] code += 'override { ' contains_class_ref = util.concat(tokens[:index], ' ') in [ 'const ' + self.data.interface_type + ' & ', self.data.interface_type + ' & ' ] if not contains_class_ref: code += function.return_str code += 'value_ . ' + function.name + ' ( ' arguments = cpp.get_function_arguments(function) for arg in arguments: if arg.type() == 'const HandleBase & ': code += 'static_cast < ' + 'const ' + self.data.handle_type + ' & > ( ' code += arg.name() + ' ) . value_ ' elif arg.type() == 'HandleBase & ': code += 'static_cast < ' + self.data.handle_type + ' & > ( ' code += arg.name() + ' ) . value_ ' else: code += arg.in_single_function_call() if arg is not arguments[-1]: code += ' , ' code += ' ) ; ' if contains_class_ref: code += 'return ' + self.data.interface_variable + ' ;' code += ' }' self.scope.add( cpp_file_parser.get_function_from_text(function.classname, function_name, function.return_str, code))
def add_pure_virtual_functions_for_small_buffer_optimization(data, scope, classname): clone_into = 'virtual ' + code.get_handle_return_type(data, classname) + 'clone_into ( Buffer & ) const = 0 ;' scope.add(cpp_file_parser.get_function_from_text(classname, 'clone_into', 'return ', clone_into)) if not data.copy_on_write: destroy = 'virtual void destroy ( ) noexcept = 0 ;' scope.add(cpp_file_parser.get_function_from_text(classname, 'destroy', '', destroy))