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 ()__anonda3f86150111::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__anonda3f86150111::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