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 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: 76 TypeConnector( 77 Gate & i_gate ) 78 : pGate(&i_gate) {} 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: 92 TypeConnector2ndTry( 93 Gate & i_gate ) 94 : pGate(&i_gate) {} 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: 108 HierarchyLinker( 109 Gate & i_gate ) 110 : pGate(&i_gate) {} 111 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 { 127 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 { 146 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 166 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 & 203 InternalGate::Create_Partition_(RepositoryCenter & i_center) 204 { 205 return *new RepositoryPartition(i_center); 206 } 207 208 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 222 RepositoryPartition::~RepositoryPartition() 223 { 224 } 225 226 void 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 & 237 RepositoryPartition::RepositoryTitle() const 238 { 239 return static_cast< ary::Repository* >(pRepositoryCenter)->Title(); 240 } 241 242 const CodeEntity * 243 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 * 256 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 & 279 RepositoryPartition::Ces() const 280 { 281 csv_assert(pCes != 0); 282 return *pCes; 283 } 284 285 const DefPilot & 286 RepositoryPartition::Defs() const 287 { 288 csv_assert(pDefs != 0); 289 return *pDefs; 290 } 291 292 const TypePilot & 293 RepositoryPartition::Types() const 294 { 295 csv_assert(pTypes != 0); 296 return *pTypes; 297 } 298 299 const loc::LocationPilot & 300 RepositoryPartition::Locations() const 301 { 302 csv_assert(pLocations != 0); 303 return *pLocations; 304 } 305 306 CePilot & 307 RepositoryPartition::Ces() 308 { 309 csv_assert(pCes != 0); 310 return *pCes; 311 } 312 313 DefPilot & 314 RepositoryPartition::Defs() 315 { 316 csv_assert(pDefs != 0); 317 return *pDefs; 318 } 319 320 TypePilot & 321 RepositoryPartition::Types() 322 { 323 csv_assert(pTypes != 0); 324 return *pTypes; 325 } 326 327 loc::LocationPilot & 328 RepositoryPartition::Locations() 329 { 330 csv_assert(pLocations != 0); 331 return *pLocations; 332 } 333 334 335 void 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 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 402 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 453 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 463 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 473 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 & 503 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