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