Skip to content

Commit 1d3797d

Browse files
author
roman_yakovenko
committed
add key_type functionality for container_traits
add element_type and key_type caching
1 parent 548802e commit 1d3797d

File tree

4 files changed

+172
-57
lines changed

4 files changed

+172
-57
lines changed

pygccxml/declarations/algorithms_cache.py

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ def __init__( self ):
1717
self._access_type = None
1818
self._demangled_name = None
1919
self._declaration_path = None
20-
self._partial_declaration_path = None
20+
self._partial_declaration_path = None
21+
self._container_key_type = None
22+
self._container_element_type = None
2123

2224
def disable( self ):
2325
self._enabled = False
@@ -31,27 +33,22 @@ def enabled( self ):
3133

3234
def _get_full_name( self ):
3335
return self._full_name
34-
3536
def _set_full_name( self, fname ):
3637
if not self.enabled:
3738
fname = None
38-
self._full_name = fname
39-
39+
self._full_name = fname
4040
full_name = property( _get_full_name, _set_full_name )
4141

4242
def _get_full_partial_name( self ):
4343
return self._full_partial_name
44-
4544
def _set_full_partial_name( self, fname ):
4645
if not self.enabled:
4746
fname = None
48-
self._full_partial_name = fname
49-
47+
self._full_partial_name = fname
5048
full_partial_name = property( _get_full_partial_name, _set_full_partial_name )
5149

5250
def _get_access_type( self ):
5351
return self._access_type
54-
5552
def _set_access_type( self, access_type ):
5653
if not self.enabled:
5754
access_type = None
@@ -60,49 +57,63 @@ def _set_access_type( self, access_type ):
6057

6158
def _get_demangled_name( self ):
6259
return self._demangled_name
63-
6460
def _set_demangled_name( self, demangled_name ):
6561
if not self.enabled:
6662
demangled_name = None
67-
self._demangled_name = demangled_name
68-
63+
self._demangled_name = demangled_name
6964
demangled_name = property( _get_demangled_name, _set_demangled_name )
7065

7166
def _get_declaration_path( self ):
7267
return self._declaration_path
73-
7468
def _set_declaration_path( self, declaration_path ):
7569
if not self.enabled:
7670
declaration_path = None
7771
self._declaration_path = declaration_path
78-
7972
declaration_path = property( _get_declaration_path, _set_declaration_path )
8073

8174
def _get_partial_declaration_path( self ):
8275
return self._partial_declaration_path
83-
8476
def _set_partial_declaration_path( self, partial_declaration_path ):
8577
if not self.enabled:
8678
partial_declaration_path = None
8779
self._partial_declaration_path = partial_declaration_path
88-
8980
partial_declaration_path = property( _get_partial_declaration_path
9081
, _set_partial_declaration_path )
9182

83+
def _get_container_element_type( self ):
84+
return self._container_element_type
85+
def _set_container_element_type( self, etype ):
86+
if not self.enabled:
87+
etype = None
88+
self._container_element_type = etype
89+
container_element_type = property( _get_container_element_type, _set_container_element_type )
90+
91+
def _get_container_key_type( self ):
92+
return self._container_key_type
93+
def _set_container_key_type( self, ktype ):
94+
if not self.enabled:
95+
ktype = None
96+
self._container_key_type = ktype
97+
container_key_type = property( _get_container_key_type, _set_container_key_type )
98+
9299
def reset( self ):
93100
self.full_name = None
94101
self.full_partial_name = None
95102
self.access_type = None
96103
self.demangled_name = None
97104
self.declaration_path = None
98105
self.partial_declaration_path = None
106+
self.container_key_type = None
107+
self.container_element_type = None
99108

100109
def reset_name_based( self ):
101110
self.full_name = None
102111
self.full_partial_name = None
103112
self.demangled_name = None
104113
self.declaration_path = None
105114
self.partial_declaration_path = None
115+
self.container_key_type = None
116+
self.container_element_type = None
106117

107118
def reset_access_type( self ):
108119
self.access_type = None
@@ -124,7 +135,6 @@ def __init__( self ):
124135

125136
def _get_remove_alias( self ):
126137
return self._remove_alias
127-
128138
def _set_remove_alias( self, remove_alias ):
129139
if not type_algs_cache_t.enabled:
130140
remove_alias = None
@@ -134,4 +144,4 @@ def _set_remove_alias( self, remove_alias ):
134144

135145
def reset(self):
136146
self.remove_alias = None
137-
147+

pygccxml/declarations/container_traits.py

Lines changed: 124 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -312,21 +312,54 @@ def class_declaration( self, type ):
312312
raise TypeError( 'Type "%s" is not instantiation of std::%s' % ( type.decl_string, self.name() ) )
313313
return cls
314314

315+
def is_sequence( self, type ):
316+
#raise exception if type is not container
317+
unused = self.class_declaration( type )
318+
return self.key_type_index is None
319+
320+
def is_mapping( self, type ):
321+
return not self.is_sequence( type )
322+
323+
def __find_xxx_type( self, type, xxx_index, xxx_typedef, cache_property_name ):
324+
cls = self.class_declaration( type )
325+
result = getattr( cls.cache, cache_property_name )
326+
if not result:
327+
if isinstance( cls, class_declaration.class_t ):
328+
xxx_type = cls.typedef( xxx_typedef, recursive=False ).type
329+
result = type_traits.remove_declarated( xxx_type )
330+
else:
331+
xxx_type_str = templates.args( cls.name )[xxx_index]
332+
result = type_traits.impl_details.find_value_type( cls.top_parent, xxx_type_str )
333+
if None is result:
334+
raise RuntimeError( "Unable to find out %s '%s' key\\value type."
335+
% ( self.name(), cls.decl_string ) )
336+
setattr( cls.cache, cache_property_name, result )
337+
return result
338+
315339
def element_type( self, type ):
316340
"""returns reference to the class value\\mapped type declaration"""
317-
cls = self.class_declaration( type )
318-
if isinstance( cls, class_declaration.class_t ):
319-
value_type = cls.typedef( self.element_type_typedef, recursive=False ).type
320-
return type_traits.remove_declarated( value_type )
321-
else:
322-
value_type_str = templates.args( cls.name )[self.element_type_index]
323-
ref = type_traits.impl_details.find_value_type( cls.top_parent, value_type_str )
324-
if None is ref:
325-
raise RuntimeError( "Unable to find out %s '%s' value type."
326-
% ( self.name(), cls.decl_string ) )
327-
return ref
341+
return self.__find_xxx_type( type
342+
, self.element_type_index
343+
, self.element_type_typedef
344+
, 'container_element_type')
345+
346+
def key_type( self, type ):
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' )
328354

329355
def remove_defaults( self, type_or_string ):
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+
"""
330363
name = type_or_string
331364
if not isinstance( type_or_string, types.StringTypes ):
332365
name = self.class_declaration( type_or_string ).name
@@ -338,29 +371,86 @@ def remove_defaults( self, type_or_string ):
338371
else:
339372
return no_defaults
340373

341-
list_traits = container_traits_impl_t( 'list', 0, 'value_type', defaults_eraser.erase_allocator )
342-
343-
deque_traits = container_traits_impl_t( 'deque', 0, 'value_type', defaults_eraser.erase_allocator )
344-
345-
queue_traits = container_traits_impl_t( 'queue', 0, 'value_type', defaults_eraser.erase_container )
346-
347-
priority_queue_traits = container_traits_impl_t( 'priority_queue', 0, 'value_type', defaults_eraser.erase_container_compare )
348-
349-
vector_traits = container_traits_impl_t( 'vector', 0, 'value_type', defaults_eraser.erase_allocator )
350-
351-
stack_traits = container_traits_impl_t( 'stack', 0, 'value_type', defaults_eraser.erase_container )
352-
353-
map_traits = container_traits_impl_t( 'map', 1, 'mapped_type', defaults_eraser.erase_map_compare_allocator )
354-
multimap_traits = container_traits_impl_t( 'multimap', 1, 'mapped_type', defaults_eraser.erase_map_compare_allocator )
355-
356-
hash_map_traits = container_traits_impl_t( 'hash_map', 1, 'mapped_type', defaults_eraser.erase_hashmap_compare_allocator )
357-
hash_multimap_traits = container_traits_impl_t( 'hash_multimap', 1, 'mapped_type', defaults_eraser.erase_hashmap_compare_allocator )
358-
359-
set_traits = container_traits_impl_t( 'set', 0, 'value_type', defaults_eraser.erase_compare_allocator)
360-
multiset_traits = container_traits_impl_t( 'multiset', 0, 'value_type', defaults_eraser.erase_compare_allocator )
361-
362-
hash_set_traits = container_traits_impl_t( 'hash_set', 0, 'value_type', defaults_eraser.erase_hash_allocator )
363-
hash_multiset_traits = container_traits_impl_t( 'hash_multiset', 0, 'value_type', defaults_eraser.erase_hash_allocator )
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 )
364454

365455
container_traits = (
366456
list_traits

unittests/find_container_traits_tester.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def setUp(self):
2323
tester_t.global_ns = declarations.get_global_namespace( decls )
2424
tester_t.global_ns.init_optimizer()
2525

26-
def __cmp_traits( self, typedef, expected, partial_name):
26+
def __cmp_traits( self, typedef, expected, partial_name, key_type=None):
2727
if isinstance( typedef, str ):
2828
typedef = self.global_ns.typedef( typedef )
2929
traits = declarations.find_container_traits( typedef )
@@ -34,7 +34,21 @@ def __cmp_traits( self, typedef, expected, partial_name):
3434
cls = declarations.remove_declarated( typedef )
3535
self.failUnless( cls.container_traits is expected )
3636
self.failUnless( cls.partial_name == partial_name )
37-
37+
cls = traits.class_declaration( cls )
38+
39+
self.failUnless( traits.element_type( typedef ) )
40+
self.failUnless( cls.cache.container_element_type, "For some reason cache was not updated" )
41+
42+
if key_type:
43+
self.failUnless( traits.is_mapping( typedef ) )
44+
real_key_type = traits.key_type( typedef )
45+
self.failUnless( real_key_type.decl_string == key_type
46+
, 'Error extracting key type. Expected type "%s", got "%s"'
47+
% ( key_type, real_key_type.decl_string ) )
48+
self.failUnless( cls.cache.container_key_type, "For some reason cache was not updated" )
49+
else:
50+
self.failUnless( traits.is_sequence( typedef ) )
51+
3852
def test_find_traits( self ):
3953
self.__cmp_traits( 'v_int', declarations.vector_traits, "vector< int >" )
4054
self.__cmp_traits( 'l_int', declarations.list_traits, "list< int >" )
@@ -43,12 +57,12 @@ def test_find_traits( self ):
4357
self.__cmp_traits( 'pq_int', declarations.priority_queue_traits, "priority_queue< int >")
4458
self.__cmp_traits( 's_v_int', declarations.set_traits, "set< std::vector< int > >")
4559
self.__cmp_traits( 'ms_v_int', declarations.multiset_traits, "multiset< std::vector< int > >")
46-
self.__cmp_traits( 'm_i2d', declarations.map_traits, "map< int, double >" )
47-
self.__cmp_traits( 'mm_i2d', declarations.multimap_traits, "multimap< int, double >" )
60+
self.__cmp_traits( 'm_i2d', declarations.map_traits, "map< int, double >", 'int' )
61+
self.__cmp_traits( 'mm_i2d', declarations.multimap_traits, "multimap< int, double >", 'int' )
4862
self.__cmp_traits( 'hs_v_int', declarations.hash_set_traits, "hash_set< std::vector< int > >" )
4963
self.__cmp_traits( 'mhs_v_int', declarations.hash_multiset_traits, "hash_multiset< std::vector< int > >" )
50-
self.__cmp_traits( 'hm_i2d', declarations.hash_map_traits, "hash_map< int, double >" )
51-
self.__cmp_traits( 'hmm_i2d', declarations.hash_multimap_traits, "hash_multimap< int, double >" )
64+
self.__cmp_traits( 'hm_i2d', declarations.hash_map_traits, "hash_map< int, double >", 'int' )
65+
self.__cmp_traits( 'hmm_i2d', declarations.hash_multimap_traits, "hash_multimap< int, double >", 'int' )
5266

5367
def test_multimap( self ):
5468
mm = self.global_ns.classes( lambda decl: decl.name.startswith( 'multimap' ) )

unittests/vector_traits_tester.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def validate_yes( self, value_type, container ):
2929
traits = declarations.vector_traits
3030
self.failUnless( traits.is_my_case( container ) )
3131
self.failUnless( declarations.is_same( value_type, traits.element_type( container ) ) )
32+
self.failUnless( traits.is_sequence( container ) )
3233

3334
def test_global_ns( self ):
3435
value_type = self.global_ns.class_( '_0_' )

0 commit comments

Comments
 (0)