Package pygccxml :: Package declarations :: Module container_traits

Source Code for Module pygccxml.declarations.container_traits

  1  # Copyright 2004-2008 Roman Yakovenko.
 
  2  # Distributed under the Boost Software License, Version 1.0. (See
 
  3  # accompanying file LICENSE_1_0.txt or copy at
 
  4  # http://www.boost.org/LICENSE_1_0.txt)
 
  5  
 
  6  """
 
  7  defines few algorithms, that deals with different properties of std containers
 
  8  """ 
  9  
 
 10  import types 
 11  import string 
 12  import calldef 
 13  import cpptypes 
 14  import namespace 
 15  import templates 
 16  import type_traits 
 17  import class_declaration 
 18  
 
 19  std_namespaces = ( 'std', 'stdext', '__gnu_cxx' ) 
20 21 -class defaults_eraser:
22 @staticmethod
23 - def normalize( type_str ):
24 return type_str.replace( ' ', '' )
25 26 @staticmethod
27 - def replace_basic_string( cls_name ):
28 strings = { 29 'std::string' : ( 'std::basic_string<char,std::char_traits<char>,std::allocator<char> >' 30 , 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >' ) 31 , 'std::wstring' : ( 'std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >' 32 , 'std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >' ) } 33 34 new_name = cls_name 35 for short_name, long_names in strings.iteritems(): 36 for lname in long_names: 37 new_name = new_name.replace( lname, short_name ) 38 return new_name
39
40 - class recursive_impl:
41 @staticmethod
42 - def decorated_call_prefix( cls_name, text, doit ):
43 has_text = cls_name.startswith( text ) 44 if has_text: 45 cls_name = cls_name[ len( text ): ] 46 answer = doit( cls_name ) 47 if has_text: 48 answer = text + answer 49 return answer
50 51 @staticmethod
52 - def decorated_call_suffix( cls_name, text, doit ):
53 has_text = cls_name.endswith( text ) 54 if has_text: 55 cls_name = cls_name[: len( text )] 56 answer = doit( cls_name ) 57 if has_text: 58 answer = answer + text 59 return answer
60 61 @staticmethod
62 - def erase_call( cls_name ):
63 global find_container_traits 64 c_traits = find_container_traits( cls_name ) 65 if not c_traits: 66 return cls_name 67 return c_traits.remove_defaults( cls_name )
68 69 @staticmethod
70 - def erase_recursive( cls_name ):
71 ri = defaults_eraser.recursive_impl 72 no_std = lambda cls_name: ri.decorated_call_prefix( cls_name, 'std::', ri.erase_call ) 73 no_stdext = lambda cls_name: ri.decorated_call_prefix( cls_name, 'stdext::', no_std ) 74 no_gnustd = lambda cls_name: ri.decorated_call_prefix( cls_name, '__gnu_cxx::', no_stdext ) 75 no_const = lambda cls_name: ri.decorated_call_prefix( cls_name, 'const ', no_gnustd ) 76 no_end_const = lambda cls_name: ri.decorated_call_suffix( cls_name, ' const', no_const ) 77 return no_end_const( cls_name )
78 79 @staticmethod
80 - def erase_recursive( cls_name ):
82 83 @staticmethod
84 - def erase_allocator( cls_name, default_allocator='std::allocator' ):
85 cls_name = defaults_eraser.replace_basic_string( cls_name ) 86 c_name, c_args = templates.split( cls_name ) 87 if 2 != len( c_args ): 88 return 89 value_type = c_args[0] 90 tmpl = string.Template( "$container< $value_type, $allocator<$value_type> >" ) 91 tmpl = tmpl.substitute( container=c_name, value_type=value_type, allocator=default_allocator ) 92 if defaults_eraser.normalize( cls_name ) == defaults_eraser.normalize( tmpl ): 93 return templates.join( c_name, [defaults_eraser.erase_recursive( value_type )] )
94 95 @staticmethod
96 - def erase_container( cls_name, default_container_name='std::deque' ):
97 cls_name = defaults_eraser.replace_basic_string( cls_name ) 98 c_name, c_args = templates.split( cls_name ) 99 if 2 != len( c_args ): 100 return 101 value_type = c_args[0] 102 dc_no_defaults = defaults_eraser.erase_recursive( c_args[1] ) 103 if defaults_eraser.normalize( dc_no_defaults ) \ 104 != defaults_eraser.normalize( templates.join( default_container_name, [value_type] ) ): 105 return 106 return templates.join( c_name, [defaults_eraser.erase_recursive( value_type )] )
107 108 @staticmethod
109 - def erase_container_compare( cls_name, default_container_name='std::vector', default_compare='std::less' ):
110 cls_name = defaults_eraser.replace_basic_string( cls_name ) 111 c_name, c_args = templates.split( cls_name ) 112 if 3 != len( c_args ): 113 return 114 dc_no_defaults = defaults_eraser.erase_recursive( c_args[1] ) 115 if defaults_eraser.normalize( dc_no_defaults ) \ 116 != defaults_eraser.normalize( templates.join( default_container_name, [c_args[0]] ) ): 117 return 118 dcomp_no_defaults = defaults_eraser.erase_recursive( c_args[2] ) 119 if defaults_eraser.normalize( dcomp_no_defaults ) \ 120 != defaults_eraser.normalize( templates.join( default_compare, [c_args[0]] ) ): 121 return 122 value_type = defaults_eraser.erase_recursive( c_args[0] ) 123 return templates.join( c_name, [value_type] )
124 125 @staticmethod
126 - def erase_compare_allocator( cls_name, default_compare='std::less', default_allocator='std::allocator' ):
127 cls_name = defaults_eraser.replace_basic_string( cls_name ) 128 c_name, c_args = templates.split( cls_name ) 129 if 3 != len( c_args ): 130 return 131 value_type = c_args[0] 132 tmpl = string.Template( "$container< $value_type, $compare<$value_type>, $allocator<$value_type> >" ) 133 tmpl = tmpl.substitute( container=c_name 134 , value_type=value_type 135 , compare=default_compare 136 , allocator=default_allocator ) 137 if defaults_eraser.normalize( cls_name ) == defaults_eraser.normalize( tmpl ): 138 return templates.join( c_name, [defaults_eraser.erase_recursive( value_type )] )
139 140 @staticmethod
141 - def erase_map_compare_allocator( cls_name, default_compare='std::less', default_allocator='std::allocator' ):
142 cls_name = defaults_eraser.replace_basic_string( cls_name ) 143 c_name, c_args = templates.split( cls_name ) 144 if 4 != len( c_args ): 145 return 146 key_type = c_args[0] 147 mapped_type = c_args[1] 148 tmpls = [ 149 string.Template( "$container< $key_type, $mapped_type, $compare<$key_type>, $allocator< std::pair< const $key_type, $mapped_type> > >" ) 150 , string.Template( "$container< $key_type, $mapped_type, $compare<$key_type>, $allocator< std::pair< $key_type const, $mapped_type> > >" ) 151 , string.Template( "$container< $key_type, $mapped_type, $compare<$key_type>, $allocator< std::pair< $key_type, $mapped_type> > >" )] 152 for tmpl in tmpls: 153 tmpl = tmpl.substitute( container=c_name 154 , key_type=key_type 155 , mapped_type=mapped_type 156 , compare=default_compare 157 , allocator=default_allocator ) 158 if defaults_eraser.normalize( cls_name ) == defaults_eraser.normalize( tmpl ): 159 return templates.join( c_name 160 , [ defaults_eraser.erase_recursive( key_type ) 161 , defaults_eraser.erase_recursive( mapped_type )] )
162 163 164 @staticmethod
165 - def erase_hash_allocator( cls_name ):
166 cls_name = defaults_eraser.replace_basic_string( cls_name ) 167 c_name, c_args = templates.split( cls_name ) 168 if len( c_args ) < 3: 169 return 170 171 default_hash=None 172 default_less='std::less' 173 default_equal_to='std::equal_to' 174 default_allocator='std::allocator' 175 176 tmpl = None 177 if 3 == len( c_args ): 178 default_hash='hash_compare' 179 tmpl = "$container< $value_type, $hash<$value_type, $less<$value_type> >, $allocator<$value_type> >" 180 elif 4 == len( c_args ): 181 default_hash='hash' 182 tmpl = "$container< $value_type, $hash<$value_type >, $equal_to<$value_type >, $allocator<$value_type> >" 183 else: 184 return 185 186 value_type = c_args[0] 187 tmpl = string.Template( tmpl ) 188 for ns in std_namespaces: 189 inst = tmpl.substitute( container=c_name 190 , value_type=value_type 191 , hash= ns + '::' + default_hash 192 , less=default_less 193 , equal_to=default_equal_to 194 , allocator=default_allocator ) 195 if defaults_eraser.normalize( cls_name ) == defaults_eraser.normalize( inst ): 196 return templates.join( c_name, [defaults_eraser.erase_recursive( value_type )] )
197 198 199 @staticmethod
200 - def erase_hashmap_compare_allocator( cls_name ):
201 cls_name = defaults_eraser.replace_basic_string( cls_name ) 202 c_name, c_args = templates.split( cls_name ) 203 204 default_hash=None 205 default_less='std::less' 206 default_allocator='std::allocator' 207 default_equal_to = 'std::equal_to' 208 209 tmpl = None 210 key_type = None 211 mapped_type = None 212 if 2 < len( c_args ): 213 key_type = c_args[0] 214 mapped_type = c_args[1] 215 else: 216 return 217 218 if 4 == len( c_args ): 219 default_hash = 'hash_compare' 220 tmpl = string.Template( "$container< $key_type, $mapped_type, $hash<$key_type, $less<$key_type> >, $allocator< std::pair< const $key_type, $mapped_type> > >" ) 221 if key_type.startswith( 'const ' ) or key_type.endswith( ' const' ): 222 tmpl = string.Template( "$container< $key_type, $mapped_type, $hash<$key_type, $less<$key_type> >, $allocator< std::pair< $key_type, $mapped_type> > >" ) 223 elif 5 == len( c_args ): 224 default_hash = 'hash' 225 tmpl = string.Template( "$container< $key_type, $mapped_type, $hash<$key_type >, $equal_to<$key_type>, $allocator< $mapped_type> >" ) 226 if key_type.startswith( 'const ' ) or key_type.endswith( ' const' ): 227 tmpl = string.Template( "$container< $key_type, $mapped_type, $hash<$key_type >, $equal_to<$key_type>, $allocator< $mapped_type > >" ) 228 else: 229 return 230 231 for ns in std_namespaces: 232 inst = tmpl.substitute( container=c_name 233 , key_type=key_type 234 , mapped_type=mapped_type 235 , hash=ns + '::' + default_hash 236 , less=default_less 237 , equal_to = default_equal_to 238 , allocator=default_allocator ) 239 if defaults_eraser.normalize( cls_name ) == defaults_eraser.normalize( inst ): 240 return templates.join( c_name 241 , [ defaults_eraser.erase_recursive( key_type ) 242 , defaults_eraser.erase_recursive( mapped_type )] )
243
244 245 -class container_traits_impl_t:
246 """this class implements the functionality needed for convinient work with 247 STD container classes. 248 249 Implemented functionality: 250 - find out whether a declaration is STD container or not 251 - find out container value( mapped ) type 252 253 This class tries to be useful as much, as possible. For example, for class 254 declaration( and not definition ) it parsers the class name in order to 255 extract all the information. 256 """
257 - def __init__( self 258 , container_name 259 , element_type_index 260 , element_type_typedef 261 , defaults_remover 262 , key_type_index=None 263 , key_type_typedef=None ):
264 """ 265 container_name - std container name 266 element_type_index - position of value\\mapped type within template 267 arguments list 268 element_type_typedef - class typedef to the value\\mapped type 269 key_type_index - position of key type within template arguments list 270 key_type_typedef - class typedef to the key type 271 """ 272 self._name = container_name 273 self.remove_defaults_impl = defaults_remover 274 self.element_type_index = element_type_index 275 self.element_type_typedef = element_type_typedef 276 self.key_type_index = key_type_index 277 self.key_type_typedef = key_type_typedef
278
279 - def name(self):
280 return self._name
281
282 - def get_container_or_none( self, type ):
283 """returns reference to the class declaration or None""" 284 type = type_traits.remove_alias( type ) 285 type = type_traits.remove_cv( type ) 286 287 cls = None 288 if isinstance( type, cpptypes.declarated_t ): 289 cls = type_traits.remove_alias( type.declaration ) 290 elif isinstance( type, class_declaration.class_t ): 291 cls = type 292 elif isinstance( type, class_declaration.class_declaration_t ): 293 cls =