blob: 6935abe2592776a59744d69f51489ed993490e96 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include <precomp.h>
#include "c_reposypart.hxx"
// NOT FULLY DECLARED SERVICES
#include <ary/getncast.hxx>
#include <ary/namesort.hxx>
#include <ary/cpp/c_builtintype.hxx>
#include <ary/cpp/c_class.hxx>
#include <ary/cpp/c_cppentity.hxx>
#include <ary/cpp/c_define.hxx>
#include <ary/cpp/c_enum.hxx>
#include <ary/cpp/c_enuval.hxx>
#include <ary/cpp/c_funct.hxx>
#include <ary/cpp/c_macro.hxx>
#include <ary/cpp/c_namesp.hxx>
#include <ary/cpp/c_tydef.hxx>
#include <ary/cpp/c_type.hxx>
#include <ary/cpp/usedtype.hxx>
#include <ary/cpp/c_vari.hxx>
#include <ary/loc/locp_le.hxx>
#include <ary/getncast.hxx>
#include <loc_internalgate.hxx>
#include <reposy.hxx>
#include "ca_ce.hxx"
#include "ca_def.hxx"
#include "ca_type.hxx"
#include "cs_ce.hxx"
#include "cs_def.hxx"
#include "cs_type.hxx"
namespace
{
using ::ary::GlobalId;
using ::ary::Rid;
using namespace ::ary::cpp;
inline bool
IsDefine( const GlobalId & i_id )
{
return i_id.Class() == Define::class_id
OR
i_id.Class() == Macro::class_id;
}
/// Find Ces
class TypeConnector
{
public:
TypeConnector(
Gate & i_gate )
: pGate(&i_gate) {}
~TypeConnector() {}
void operator()(
Type & io_rType ) const;
private:
// DATA
Gate * pGate;
};
/// Find Ces only known from base class name scope.
class TypeConnector2ndTry
{
public:
TypeConnector2ndTry(
Gate & i_gate )
: pGate(&i_gate) {}
~TypeConnector2ndTry() {}
void operator()(
Type & io_rType ) const;
private:
// DATA
Gate * pGate;
};
/// Reconnect (in both directions) base-derived relations of classes.
class HierarchyLinker
{
public:
HierarchyLinker(
Gate & i_gate )
: pGate(&i_gate) {}
~HierarchyLinker() {}
void operator()(
Class & io_rCe ) const;
private:
// DATA
Gate * pGate;
};
/// Helper functor for ->RepositoryPartition::Get_AlphabeticalList().
template <class TRAITS>
struct MakeGlobalId
{
GlobalId operator()(
typename TRAITS::id_type
i_id ) const
{
return GlobalId( TRAITS::EntityOf_(i_id).AryClass(),
i_id.Value() );
}
};
/** Compare two {->GlobalId}s.
@todo Move this up to the definition of GlobalId<>.
*/
struct LesserGlobal
{
LesserGlobal(
const Ce_Storage & i_ces,
const Def_Storage & i_des )
: rCes(i_ces), rDes(i_des) {}
bool operator()(
GlobalId i_1,
GlobalId i_2 ) const;
private:
const String & NameOf(
GlobalId i_id ) const;
// DATA
const Ce_Storage & rCes;
const Def_Storage & rDes;
::ary::LesserName aLess;
};
bool
LesserGlobal::operator()( GlobalId i_1,
GlobalId i_2 ) const
{
String s1 = NameOf(i_1);
String s2 = NameOf(i_2);
if (s1 != s2)
return aLess(s1, s2);
if ( IsDefine(i_1) != IsDefine(i_2) )
{
return NOT IsDefine(i_2);
}
else if (IsDefine(i_1))
{
return i_1.Class() < i_2.Class();
}
return Ce_GlobalCompare::Lesser_(
rCes[i_1.Id()],
rCes[i_2.Id()] );
}
} // namespace anonymous
namespace ary
{
namespace cpp
{
DYN InternalGate &
InternalGate::Create_Partition_(RepositoryCenter & i_center)
{
return *new RepositoryPartition(i_center);
}
RepositoryPartition::RepositoryPartition(RepositoryCenter & i_center)
: pRepositoryCenter(&i_center),
pCes(0),
pTypes(0),
pDefs(0),
pLocations(& loc::InternalGate::Create_Locations_())
{
pCes = new CeAdmin(*this);
pTypes = new TypeAdmin(*this);
pDefs = new DefAdmin(*this);
pCes->Set_Related(*pTypes);
}
RepositoryPartition::~RepositoryPartition()
{
}
void
RepositoryPartition::Calculate_AllSecondaryInformation()
// const ::autodoc::Options & )
{
// KORR_FUTURE
// Forward the options from here.
Connect_AllTypes_2_TheirRelated_CodeEntites();
}
const String &
RepositoryPartition::RepositoryTitle() const
{
return static_cast< ary::Repository* >(pRepositoryCenter)->Title();
}
const CodeEntity *
RepositoryPartition::Search_RelatedCe(Type_id i_type) const
{
if (NOT i_type.IsValid())
return 0;
Ce_id
ce_id = pTypes->Find_Type(i_type).RelatedCe();
return ce_id.IsValid()
? & pCes->Find_Ce(ce_id)
: (CodeEntity*)(0);
}
const ::ary::cpp::CppEntity *
RepositoryPartition::Search_Entity(GlobalId i_id) const
{
if (i_id.Id() == 0)
return 0;
if ( NOT IsDefine(i_id) )
{
// Shall make sure this is a C++ CodeEntity:
csv_assert( i_id.Class() >= Namespace::class_id
AND
i_id.Class() < BuiltInType::class_id
&& "Unexpected entity type in cpp::RepositoryPartition"
"::Search_Entity()." );
return & Ces().Find_Ce( Ce_id(i_id.Id()) );
}
else
{
return & Defs().Find_Def( De_id(i_id.Id()) );
}
}
const CePilot &
RepositoryPartition::Ces() const
{
csv_assert(pCes != 0);
return *pCes;
}
const DefPilot &
RepositoryPartition::Defs() const
{
csv_assert(pDefs != 0);
return *pDefs;
}
const TypePilot &
RepositoryPartition::Types() const
{
csv_assert(pTypes != 0);
return *pTypes;
}
const loc::LocationPilot &
RepositoryPartition::Locations() const
{
csv_assert(pLocations != 0);
return *pLocations;
}
CePilot &
RepositoryPartition::Ces()
{
csv_assert(pCes != 0);
return *pCes;
}
DefPilot &
RepositoryPartition::Defs()
{
csv_assert(pDefs != 0);
return *pDefs;
}
TypePilot &
RepositoryPartition::Types()
{
csv_assert(pTypes != 0);
return *pTypes;
}
loc::LocationPilot &
RepositoryPartition::Locations()
{
csv_assert(pLocations != 0);
return *pLocations;
}
void
RepositoryPartition::Connect_AllTypes_2_TheirRelated_CodeEntites()
{
TypeConnector
aConnector(*this);
std::for_each( pTypes->Storage().BeginUnreserved(),
pTypes->Storage().End(),
aConnector );
typedef ::ary::stg::filter_iterator<CodeEntity,Class>
filter_class_iter;
HierarchyLinker
aHierarchyLinker(*this);
filter_class_iter itEnd( pCes->Storage().End() );
for ( filter_class_iter it( pCes->Storage().BeginUnreserved() );
it != itEnd;
++it )
{
if (NOT it.IsValid())
continue;
if (is_type<Class>(*it))
aHierarchyLinker(ary_cast<Class>(*it));
}
TypeConnector2ndTry
aConnector2ndTry(*this);
std::for_each( pTypes->Storage().BeginUnreserved(),
pTypes->Storage().End(),
aConnector2ndTry );
}
template <class COMPARE>
void Add2Result(
List_GlobalIds & o_result,
const SortedIds<COMPARE> &
i_data,
const char * i_begin,
const char * i_end );
template <class COMPARE>
void
Add2Result( List_GlobalIds & o_result,
const SortedIds<COMPARE> & i_data,
const char * i_begin,
const char * i_end )
{
const size_t
previous_size = o_result.size();
typename std::vector<typename COMPARE::id_type>::const_iterator
it_beg = i_data.LowerBound(i_begin);
typename std::vector<typename COMPARE::id_type>::const_iterator
it_end = i_data.LowerBound(i_end);
size_t
count_added = static_cast<size_t>( std::distance(it_beg,it_end) );
o_result.insert( o_result.end(),
count_added,
GlobalId() );
List_GlobalIds::iterator
it_out = o_result.begin() + previous_size;
std::transform( it_beg, it_end,
it_out,
MakeGlobalId<COMPARE>() );
}
uintt
RepositoryPartition::Get_AlphabeticalList( List_GlobalIds & o_result,
const char * i_begin,
const char * i_end ) const
{
size_t
ret = o_result.size();
const Ce_Storage &
ce_storage = pCes->Storage();
const Def_Storage &
def_storage = pDefs->Storage();
Add2Result( o_result,
ce_storage.TypeIndex(),
i_begin, i_end );
Add2Result( o_result,
ce_storage.OperationIndex(),
i_begin, i_end );
Add2Result( o_result,
ce_storage.DataIndex(),
i_begin, i_end );
Add2Result( o_result,
def_storage.DefineIndex(),
i_begin, i_end );
Add2Result( o_result,
def_storage.MacroIndex(),
i_begin, i_end );
LesserGlobal
aLess(ce_storage, def_storage);
std::sort(o_result.begin(), o_result.end(), aLess);
return o_result.size() - ret;
}
} // namespace cpp
} // namespace ary
namespace
{
void
TypeConnector::operator()( Type & io_rType ) const
{
csv_assert(pGate != 0);
UsedType *
pt = ::ary::ary_cast<UsedType>(&io_rType);
if (pt != 0)
pt->Connect2Ce(pGate->Ces());
}
void
TypeConnector2ndTry::operator()( Type & io_rType ) const
{
csv_assert(pGate != 0);
UsedType *
pt = ::ary::ary_cast<UsedType>(&io_rType);
if (pt != 0)
pt->Connect2CeOnlyKnownViaBaseClass(*pGate);
}
void
HierarchyLinker::operator()( Class & io_rCe ) const
{
csv_assert( ::ary::is_type<Class>(io_rCe) );
Class &
rClass = io_rCe;
for ( List_Bases::const_iterator it = rClass.BaseClasses().begin();
it != rClass.BaseClasses().end();
++it )
{
const CodeEntity *
pCe = 0;
Type_id
nTid = (*it).nId;
for ( pCe = pGate->Search_RelatedCe(nTid);
ary::ary_cast<Typedef>(pCe) != 0;
pCe = pGate->Search_RelatedCe(nTid) )
{
nTid = static_cast< const Typedef* >(pCe)->DescribingType();
}
const Class *
pClass = ary::ary_cast<Class>(pCe);
if (pClass == 0)
return;
// KORR_FUTURE: we need a non const Find_Class()
const_cast< Class* >(pClass)->Add_KnownDerivative( io_rCe.CeId() );
}
}
const String &
LesserGlobal::NameOf(GlobalId i_id) const
{
if ( NOT IsDefine(i_id) )
{
return rCes[i_id.Id()].LocalName();
}
else
{
return rDes[i_id.Id()].LocalName();
}
}
} // namespace anonymous