1   
  2   
  3   
  4   
  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' ) 
 22      @staticmethod 
 24          return type_str.replace( ' ', '' ) 
  25   
 26      @staticmethod 
 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   
 41          @staticmethod 
 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 
 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 
 68   
 69          @staticmethod 
 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 
 82   
 83      @staticmethod 
 94   
 95      @staticmethod 
107   
108      @staticmethod 
124   
125      @staticmethod 
139   
140      @staticmethod 
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 
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 
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   
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   
281   
303   
307   
309          """returns reference to the class declaration""" 
310          cls = self.get_container_or_none( type ) 
311          if not cls: 
312              raise TypeError( 'Type "%s" is not instantiation of std::%s' % ( type.decl_string, self.name() ) ) 
313          return cls 
 314   
319           
322   
323 -    def __find_xxx_type( self, type, xxx_index, xxx_typedef, cache_property_name ): 
 338   
340          """returns reference to the class value\\mapped type declaration""" 
341          return self.__find_xxx_type( type 
342                                       , self.element_type_index 
343                                       , self.element_type_typedef 
344                                       , 'container_element_type') 
 345   
347          """returns reference to the class key type declaration"""         
348          if not self.is_mapping( type ): 
349              raise TypeError( 'Type "%s" is not "mapping" container' % str( type ) ) 
350          return self.__find_xxx_type( type 
351                                       , self.key_type_index 
352                                       , self.key_type_typedef 
353                                       , 'container_key_type' ) 
 354   
356          """remove template defaults from a template class instantiation 
357           
358          For example: 
359              std::vector< int, std::allocator< int > >  
360          will become 
361              std::vector< int >  
362          """ 
363          name = type_or_string 
364          if not isinstance( type_or_string, types.StringTypes ): 
365              name = self.class_declaration( type_or_string ).name 
366          if not self.remove_defaults_impl: 
367              return name 
368          no_defaults = self.remove_defaults_impl( name ) 
369          if not no_defaults: 
370              return name 
371          else: 
372              return no_defaults 
  373   
374  create_traits = container_traits_impl_t 
375  list_traits = create_traits( 'list' 
376                               , 0 
377                               , 'value_type' 
378                               , defaults_eraser.erase_allocator ) 
379   
380  deque_traits = create_traits( 'deque' 
381                                , 0 
382                                , 'value_type' 
383                                , defaults_eraser.erase_allocator ) 
384   
385  queue_traits = create_traits( 'queue' 
386                                , 0 
387                                , 'value_type' 
388                                , defaults_eraser.erase_container ) 
389   
390  priority_queue_traits = create_traits( 'priority_queue' 
391                                         , 0 
392                                         , 'value_type' 
393                                         , defaults_eraser.erase_container_compare ) 
394   
395  vector_traits = create_traits( 'vector' 
396                                 , 0 
397                                 , 'value_type' 
398                                 , defaults_eraser.erase_allocator ) 
399   
400  stack_traits = create_traits( 'stack' 
401                                , 0 
402                                , 'value_type' 
403                                , defaults_eraser.erase_container ) 
404   
405  map_traits = create_traits( 'map' 
406                              , 1 
407                              , 'mapped_type' 
408                              , defaults_eraser.erase_map_compare_allocator 
409                              , key_type_index=0 
410                              , key_type_typedef='key_type') 
411                               
412  multimap_traits = create_traits( 'multimap' 
413                                   , 1 
414                                   , 'mapped_type' 
415                                   , defaults_eraser.erase_map_compare_allocator  
416                                   , key_type_index=0 
417                                   , key_type_typedef='key_type') 
418   
419   
420  hash_map_traits = create_traits( 'hash_map' 
421                                   , 1 
422                                   , 'mapped_type' 
423                                   , defaults_eraser.erase_hashmap_compare_allocator  
424                                   , key_type_index=0 
425                                   , key_type_typedef='key_type') 
426                                    
427                                    
428  hash_multimap_traits = create_traits( 'hash_multimap' 
429                                        , 1 
430                                        , 'mapped_type' 
431                                        , defaults_eraser.erase_hashmap_compare_allocator  
432                                        , key_type_index=0 
433                                        , key_type_typedef='key_type') 
434   
435  set_traits = create_traits( 'set' 
436                              , 0 
437                              , 'value_type' 
438                              , defaults_eraser.erase_compare_allocator) 
439                               
440  multiset_traits = create_traits( 'multiset' 
441                                   , 0 
442                                   , 'value_type' 
443                                   , defaults_eraser.erase_compare_allocator ) 
444   
445  hash_set_traits = create_traits( 'hash_set' 
446                                   , 0 
447                                   , 'value_type' 
448                                   , defaults_eraser.erase_hash_allocator ) 
449                                    
450  hash_multiset_traits = create_traits( 'hash_multiset' 
451                                        , 0 
452                                        , 'value_type' 
453                                        , defaults_eraser.erase_hash_allocator ) 
454   
455  container_traits = ( 
456        list_traits 
457      , deque_traits 
458      , queue_traits 
459      , priority_queue_traits 
460      , vector_traits 
461      , stack_traits 
462      , map_traits 
463      , multimap_traits 
464      , hash_map_traits 
465      , hash_multimap_traits 
466      , set_traits 
467      , hash_set_traits 
468      , multiset_traits 
469      , hash_multiset_traits ) 
470  """tuple of all STD container traits classes""" 
486