1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 #include <precomp.h>
23 #include "c_reposypart.hxx"
24
25
26 // NOT FULLY DECLARED SERVICES
27 #include <ary/getncast.hxx>
28 #include <ary/namesort.hxx>
29 #include <ary/cpp/c_builtintype.hxx>
30 #include <ary/cpp/c_class.hxx>
31 #include <ary/cpp/c_cppentity.hxx>
32 #include <ary/cpp/c_define.hxx>
33 #include <ary/cpp/c_enum.hxx>
34 #include <ary/cpp/c_enuval.hxx>
35 #include <ary/cpp/c_funct.hxx>
36 #include <ary/cpp/c_macro.hxx>
37 #include <ary/cpp/c_namesp.hxx>
38 #include <ary/cpp/c_tydef.hxx>
39 #include <ary/cpp/c_type.hxx>
40 #include <ary/cpp/usedtype.hxx>
41 #include <ary/cpp/c_vari.hxx>
42 #include <ary/loc/locp_le.hxx>
43 #include <ary/getncast.hxx>
44 #include <loc_internalgate.hxx>
45 #include <reposy.hxx>
46 #include "ca_ce.hxx"
47 #include "ca_def.hxx"
48 #include "ca_type.hxx"
49 #include "cs_ce.hxx"
50 #include "cs_def.hxx"
51 #include "cs_type.hxx"
52
53
54
55 namespace
56 {
57
58 using ::ary::GlobalId;
59 using ::ary::Rid;
60 using namespace ::ary::cpp;
61
62
63 inline bool
IsDefine(const GlobalId & i_id)64 IsDefine( const GlobalId & i_id )
65 {
66 return i_id.Class() == Define::class_id
67 OR
68 i_id.Class() == Macro::class_id;
69 }
70
71
72 /// Find Ces
73 class TypeConnector
74 {
75 public:
TypeConnector(Gate & i_gate)76 TypeConnector(
77 Gate & i_gate )
78 : pGate(&i_gate) {}
~TypeConnector()79 ~TypeConnector() {}
80
81 void operator()(
82 Type & io_rType ) const;
83 private:
84 // DATA
85 Gate * pGate;
86 };
87
88 /// Find Ces only known from base class name scope.
89 class TypeConnector2ndTry
90 {
91 public:
TypeConnector2ndTry(Gate & i_gate)92 TypeConnector2ndTry(
93 Gate & i_gate )
94 : pGate(&i_gate) {}
~TypeConnector2ndTry()95 ~TypeConnector2ndTry() {}
96
97 void operator()(
98 Type & io_rType ) const;
99 private:
100 // DATA
101 Gate * pGate;
102 };
103
104 /// Reconnect (in both directions) base-derived relations of classes.
105 class HierarchyLinker
106 {
107 public:
HierarchyLinker(Gate & i_gate)108 HierarchyLinker(
109 Gate & i_gate )
110 : pGate(&i_gate) {}
111
~HierarchyLinker()112 ~HierarchyLinker() {}
113
114 void operator()(
115 Class & io_rCe ) const;
116 private:
117 // DATA
118 Gate * pGate;
119 };
120
121
122
123 /// Helper functor for ->RepositoryPartition::Get_AlphabeticalList().
124 template <class TRAITS>
125 struct MakeGlobalId
126 {
operator ()__anon799c54be0111::MakeGlobalId127 GlobalId operator()(
128 typename TRAITS::id_type
129 i_id ) const
130 {
131 return GlobalId( TRAITS::EntityOf_(i_id).AryClass(),
132 i_id.Value() );
133 }
134 };
135
136
137
138
139 /** Compare two {->GlobalId}s.
140
141
142 @todo Move this up to the definition of GlobalId<>.
143 */
144 struct LesserGlobal
145 {
LesserGlobal__anon799c54be0111::LesserGlobal146 LesserGlobal(
147 const Ce_Storage & i_ces,
148 const Def_Storage & i_des )
149 : rCes(i_ces), rDes(i_des) {}
150
151 bool operator()(
152 GlobalId i_1,
153 GlobalId i_2 ) const;
154
155 private:
156 const String & NameOf(
157 GlobalId i_id ) const;
158 // DATA
159 const Ce_Storage & rCes;
160 const Def_Storage & rDes;
161 ::ary::LesserName aLess;
162 };
163
164
165 bool
operator ()(GlobalId i_1,GlobalId i_2) const166 LesserGlobal::operator()( GlobalId i_1,
167 GlobalId i_2 ) const
168 {
169 String s1 = NameOf(i_1);
170 String s2 = NameOf(i_2);
171
172 if (s1 != s2)
173 return aLess(s1, s2);
174
175 if ( IsDefine(i_1) != IsDefine(i_2) )
176 {
177 return NOT IsDefine(i_2);
178 }
179 else if (IsDefine(i_1))
180 {
181 return i_1.Class() < i_2.Class();
182 }
183
184 return Ce_GlobalCompare::Lesser_(
185 rCes[i_1.Id()],
186 rCes[i_2.Id()] );
187 }
188
189
190 } // namespace anonymous
191
192
193
194
195
196
197 namespace ary
198 {
199 namespace cpp
200 {
201
202 DYN InternalGate &
Create_Partition_(RepositoryCenter & i_center)203 InternalGate::Create_Partition_(RepositoryCenter & i_center)
204 {
205 return *new RepositoryPartition(i_center);
206 }
207
208
RepositoryPartition(RepositoryCenter & i_center)209 RepositoryPartition::RepositoryPartition(RepositoryCenter & i_center)
210 : pRepositoryCenter(&i_center),
211 pCes(0),
212 pTypes(0),
213 pDefs(0),
214 pLocations(& loc::InternalGate::Create_Locations_())
215 {
216 pCes = new CeAdmin(*this);
217 pTypes = new TypeAdmin(*this);
218 pDefs = new DefAdmin(*this);
219 pCes->Set_Related(*pTypes);
220 }
221
~RepositoryPartition()222 RepositoryPartition::~RepositoryPartition()
223 {
224 }
225
226 void
Calculate_AllSecondaryInformation()227 RepositoryPartition::Calculate_AllSecondaryInformation()
228 // const ::autodoc::Options & )
229 {
230 // KORR_FUTURE
231 // Forward the options from here.
232
233 Connect_AllTypes_2_TheirRelated_CodeEntites();
234 }
235
236 const String &
RepositoryTitle() const237 RepositoryPartition::RepositoryTitle() const
238 {
239 return static_cast< ary::Repository* >(pRepositoryCenter)->Title();
240 }
241
242 const CodeEntity *
Search_RelatedCe(Type_id i_type) const243 RepositoryPartition::Search_RelatedCe(Type_id i_type) const
244 {
245 if (NOT i_type.IsValid())
246 return 0;
247
248 Ce_id
249 ce_id = pTypes->Find_Type(i_type).RelatedCe();
250 return ce_id.IsValid()
251 ? & pCes->Find_Ce(ce_id)
252 : (CodeEntity*)(0);
253 }
254
255 const ::ary::cpp::CppEntity *
Search_Entity(GlobalId i_id) const256 RepositoryPartition::Search_Entity(GlobalId i_id) const
257 {
258 if (i_id.Id() == 0)
259 return 0;
260
261 if ( NOT IsDefine(i_id) )
262 {
263 // Shall make sure this is a C++ CodeEntity:
264 csv_assert( i_id.Class() >= Namespace::class_id
265 AND
266 i_id.Class() < BuiltInType::class_id
267 && "Unexpected entity type in cpp::RepositoryPartition"
268 "::Search_Entity()." );
269 return & Ces().Find_Ce( Ce_id(i_id.Id()) );
270 }
271 else
272 {
273 return & Defs().Find_Def( De_id(i_id.Id()) );
274 }
275 }
276
277
278 const CePilot &
Ces() const279 RepositoryPartition::Ces() const
280 {
281 csv_assert(pCes != 0);
282 return *pCes;
283 }
284
285 const DefPilot &
Defs() const286 RepositoryPartition::Defs() const
287 {
288 csv_assert(pDefs != 0);
289 return *pDefs;
290 }
291
292 const TypePilot &
Types() const293 RepositoryPartition::Types() const
294 {
295 csv_assert(pTypes != 0);
296 return *pTypes;
297 }
298
299 const loc::LocationPilot &
Locations() const300 RepositoryPartition::Locations() const
301 {
302 csv_assert(pLocations != 0);
303 return *pLocations;
304 }
305
306 CePilot &
Ces()307 RepositoryPartition::Ces()
308 {
309 csv_assert(pCes != 0);
310 return *pCes;
311 }
312
313 DefPilot &
Defs()314 RepositoryPartition::Defs()
315 {
316 csv_assert(pDefs != 0);
317 return *pDefs;
318 }
319
320 TypePilot &
Types()321 RepositoryPartition::Types()
322 {
323 csv_assert(pTypes != 0);
324 return *pTypes;
325 }
326
327 loc::LocationPilot &
Locations()328 RepositoryPartition::Locations()
329 {
330 csv_assert(pLocations != 0);
331 return *pLocations;
332 }
333
334
335 void
Connect_AllTypes_2_TheirRelated_CodeEntites()336 RepositoryPartition::Connect_AllTypes_2_TheirRelated_CodeEntites()
337 {
338 TypeConnector
339 aConnector(*this);
340 std::for_each( pTypes->Storage().BeginUnreserved(),
341 pTypes->Storage().End(),
342 aConnector );
343
344 typedef ::ary::stg::filter_iterator<CodeEntity,Class>
345 filter_class_iter;
346
347 HierarchyLinker
348 aHierarchyLinker(*this);
349 filter_class_iter itEnd( pCes->Storage().End() );
350 for ( filter_class_iter it( pCes->Storage().BeginUnreserved() );
351 it != itEnd;
352 ++it )
353 {
354 if (NOT it.IsValid())
355 continue;
356
357 if (is_type<Class>(*it))
358 aHierarchyLinker(ary_cast<Class>(*it));
359 }
360
361 TypeConnector2ndTry
362 aConnector2ndTry(*this);
363 std::for_each( pTypes->Storage().BeginUnreserved(),
364 pTypes->Storage().End(),
365 aConnector2ndTry );
366 }
367
368 template <class COMPARE>
369 void Add2Result(
370 List_GlobalIds & o_result,
371 const SortedIds<COMPARE> &
372 i_data,
373 const char * i_begin,
374 const char * i_end );
375 template <class COMPARE>
376 void
Add2Result(List_GlobalIds & o_result,const SortedIds<COMPARE> & i_data,const char * i_begin,const char * i_end)377 Add2Result( List_GlobalIds & o_result,
378 const SortedIds<COMPARE> & i_data,
379 const char * i_begin,
380 const char * i_end )
381 {
382 const size_t
383 previous_size = o_result.size();
384 typename std::vector<typename COMPARE::id_type>::const_iterator
385 it_beg = i_data.LowerBound(i_begin);
386 typename std::vector<typename COMPARE::id_type>::const_iterator
387 it_end = i_data.LowerBound(i_end);
388 size_t
389 count_added = static_cast<size_t>( std::distance(it_beg,it_end) );
390 o_result.insert( o_result.end(),
391 count_added,
392 GlobalId() );
393 List_GlobalIds::iterator
394 it_out = o_result.begin() + previous_size;
395 std::transform( it_beg, it_end,
396 it_out,
397 MakeGlobalId<COMPARE>() );
398 }
399
400
401 uintt
Get_AlphabeticalList(List_GlobalIds & o_result,const char * i_begin,const char * i_end) const402 RepositoryPartition::Get_AlphabeticalList( List_GlobalIds & o_result,
403 const char * i_begin,
404 const char * i_end ) const
405 {
406 size_t
407 ret = o_result.size();
408
409 const Ce_Storage &
410 ce_storage = pCes->Storage();
411 const Def_Storage &
412 def_storage = pDefs->Storage();
413
414 Add2Result( o_result,
415 ce_storage.TypeIndex(),
416 i_begin, i_end );
417 Add2Result( o_result,
418 ce_storage.OperationIndex(),
419 i_begin, i_end );
420 Add2Result( o_result,
421 ce_storage.DataIndex(),
422 i_begin, i_end );
423 Add2Result( o_result,
424 def_storage.DefineIndex(),
425 i_begin, i_end );
426 Add2Result( o_result,
427 def_storage.MacroIndex(),
428 i_begin, i_end );
429
430 LesserGlobal
431 aLess(ce_storage, def_storage);
432
433 std::sort(o_result.begin(), o_result.end(), aLess);
434
435 return o_result.size() - ret;
436 }
437
438
439
440
441 } // namespace cpp
442 } // namespace ary
443
444
445
446
447
448 namespace
449 {
450
451
452 void
operator ()(Type & io_rType) const453 TypeConnector::operator()( Type & io_rType ) const
454 {
455 csv_assert(pGate != 0);
456 UsedType *
457 pt = ::ary::ary_cast<UsedType>(&io_rType);
458 if (pt != 0)
459 pt->Connect2Ce(pGate->Ces());
460 }
461
462 void
operator ()(Type & io_rType) const463 TypeConnector2ndTry::operator()( Type & io_rType ) const
464 {
465 csv_assert(pGate != 0);
466 UsedType *
467 pt = ::ary::ary_cast<UsedType>(&io_rType);
468 if (pt != 0)
469 pt->Connect2CeOnlyKnownViaBaseClass(*pGate);
470 }
471
472 void
operator ()(Class & io_rCe) const473 HierarchyLinker::operator()( Class & io_rCe ) const
474 {
475 csv_assert( ::ary::is_type<Class>(io_rCe) );
476 Class &
477 rClass = io_rCe;
478
479 for ( List_Bases::const_iterator it = rClass.BaseClasses().begin();
480 it != rClass.BaseClasses().end();
481 ++it )
482 {
483 const CodeEntity *
484 pCe = 0;
485 Type_id
486 nTid = (*it).nId;
487 for ( pCe = pGate->Search_RelatedCe(nTid);
488 ary::ary_cast<Typedef>(pCe) != 0;
489 pCe = pGate->Search_RelatedCe(nTid) )
490 {
491 nTid = static_cast< const Typedef* >(pCe)->DescribingType();
492 }
493 const Class *
494 pClass = ary::ary_cast<Class>(pCe);
495 if (pClass == 0)
496 return;
497 // KORR_FUTURE: we need a non const Find_Class()
498 const_cast< Class* >(pClass)->Add_KnownDerivative( io_rCe.CeId() );
499 }
500 }
501
502 const String &
NameOf(GlobalId i_id) const503 LesserGlobal::NameOf(GlobalId i_id) const
504 {
505 if ( NOT IsDefine(i_id) )
506 {
507 return rCes[i_id.Id()].LocalName();
508 }
509 else
510 {
511 return rDes[i_id.Id()].LocalName();
512 }
513 }
514
515
516
517 } // namespace anonymous
518