Created
April 21, 2013 12:52
-
-
Save urasandesu/5429490 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#ifndef URASANDESU_SWATHE_METADATA_BASECLASSPIMPL_BASETYPEMETADATAPIMPL_HPP | |
#define URASANDESU_SWATHE_METADATA_BASECLASSPIMPL_BASETYPEMETADATAPIMPL_HPP | |
#ifndef URASANDESU_SWATHE_METADATA_BASECLASSPIMPL_BASETYPEMETADATAPIMPL_H | |
#include <Urasandesu/Swathe/Metadata/BaseClassPimpl/BaseTypeMetadataPimpl.h> | |
#endif | |
namespace Urasandesu { namespace Swathe { namespace Metadata { namespace BaseClassPimpl { | |
template<class ApiHolder> | |
BaseTypeMetadataPimpl<ApiHolder>::BaseTypeMetadataPimpl(type_metadata_label_type *pClass) : | |
m_pClass(pClass), | |
m_mdt(mdTokenNil), | |
m_genericArgsInit(false), | |
m_filled(false) | |
{ } | |
#define SWATHE_DECLARE_BASE_TYPE_METADATA_PIMPL_ADDITIONAL_INSTANTIATION \ | |
template<class ApiHolder> | |
mdToken BaseTypeMetadataPimpl<ApiHolder>::GetToken() const | |
{ | |
using Urasandesu::CppAnonym::CppAnonymCOMException; | |
if (m_mdt == mdTokenNil) | |
{ | |
if (auto const *pDeclaringType = m_pClass->MapFirstAncestor<type_metadata_label_type>()) | |
{ | |
m_mdt = pDeclaringType->GetToken(); | |
} | |
else | |
{ | |
_ASSERTE(!m_fullName.empty()); | |
auto *pAsmMeta = m_pClass->MapFirst<assembly_metadata_label_type>(); | |
auto &comMetaImp = pAsmMeta->GetCOMMetaDataImport(); | |
auto hr = comMetaImp.FindTypeDefByName(m_fullName.c_str(), NULL, &m_mdt); | |
if (FAILED(hr)) | |
BOOST_THROW_EXCEPTION(CppAnonymCOMException(hr)); | |
} | |
} | |
return m_mdt; | |
} | |
template<class ApiHolder> | |
wstring const &BaseTypeMetadataPimpl<ApiHolder>::GetFullName() const | |
{ | |
if (m_fullName.empty()) | |
FillPropertiesIfNecessary(); | |
return m_fullName; | |
} | |
template<class ApiHolder> | |
bool BaseTypeMetadataPimpl<ApiHolder>::IsGenericParameter() const | |
{ | |
return TypeFromToken(GetToken()) == mdtGenericParam; | |
} | |
template<class ApiHolder> | |
bool BaseTypeMetadataPimpl<ApiHolder>::IsGenericType() const | |
{ | |
return !GetGenericArguments().empty(); | |
} | |
template<class ApiHolder> | |
bool BaseTypeMetadataPimpl<ApiHolder>::IsGenericTypeDefinition() const | |
{ | |
if (!IsGenericType()) | |
{ | |
return false; | |
} | |
else | |
{ | |
auto const *pDeclaringType = m_pClass->MapFirstAncestor<type_metadata_label_type>(); | |
return !pDeclaringType; | |
} | |
} | |
template<class ApiHolder> | |
TempPtrVector<IType const> const &BaseTypeMetadataPimpl<ApiHolder>::GetGenericArguments() const | |
{ | |
using boost::array; | |
using Urasandesu::CppAnonym::CppAnonymCOMException; | |
if (!m_genericArgsInit) | |
{ | |
auto *pAsm = m_pClass->MapFirst<assembly_metadata_label_type>(); | |
auto &comMetaImp = pAsm->GetCOMMetaDataImport(); | |
auto hEnum = static_cast<HCORENUM>(nullptr); | |
BOOST_SCOPE_EXIT((&hEnum)(&comMetaImp)) | |
{ | |
if (hEnum) | |
comMetaImp.CloseEnum(hEnum); | |
} | |
BOOST_SCOPE_EXIT_END | |
auto mdgps = array<mdGenericParam, 16>(); | |
auto count = 0ul; | |
auto hr = E_FAIL; | |
auto mdtTarget = GetToken(); | |
do | |
{ | |
hr = comMetaImp.EnumGenericParams(&hEnum, mdtTarget, mdgps.c_array(), mdgps.size(), &count); | |
if (FAILED(hr)) | |
BOOST_THROW_EXCEPTION(CppAnonymCOMException(hr)); | |
m_genericArgs.reserve(m_genericArgs.size() + count); | |
for (auto i = 0u; i < count; ++i) | |
{ | |
auto pGenericArg = NewGenericArgument(mdgps[i]); | |
m_genericArgs.push_back(pGenericArg); | |
} | |
} while (0 < count); | |
m_genericArgsInit = true; | |
} | |
return m_genericArgs; | |
} | |
template<class ApiHolder> | |
void BaseTypeMetadataPimpl<ApiHolder>::Register(type_metadata_label_type const &type, SIZE_T index) | |
{ | |
m_typeToIndex[&type] = index; | |
} | |
template<class ApiHolder> | |
void BaseTypeMetadataPimpl<ApiHolder>::SetToken(mdToken mdt) | |
{ | |
_ASSERTE(!IsNilToken(mdt)); | |
_ASSERTE(IsNilToken(m_mdt)); | |
m_mdt = mdt; | |
} | |
template<class ApiHolder> | |
void BaseTypeMetadataPimpl<ApiHolder>::SetFullName(wstring const &fullName) | |
{ | |
_ASSERTE(!fullName.empty()); | |
_ASSERTE(m_fullName.empty()); | |
m_fullName = fullName; | |
} | |
template<class ApiHolder> | |
TempPtr<typename BaseTypeMetadataPimpl<ApiHolder>::type_metadata_label_type> BaseTypeMetadataPimpl<ApiHolder>::NewGenericArgument(mdGenericParam mdgp) const | |
{ | |
auto pType = NewTypeCore(); | |
pType->SetToken(mdgp); | |
return pType; | |
} | |
template<class ApiHolder> | |
TempPtr<typename BaseTypeMetadataPimpl<ApiHolder>::type_metadata_label_type> BaseTypeMetadataPimpl<ApiHolder>::NewTypeCore() const | |
{ | |
auto const *pDisp = m_pClass->MapFirst<metadata_dispenser_label_type>(); | |
auto &provider = pDisp->FirstProviderOf<type_metadata_label_type>(); | |
auto &chain = m_pClass->ChainFrom<type_metadata_label_type>(); | |
auto pType = chain.NewObject<type_metadata_label_type>(provider); | |
auto handler = type_metadata_persisted_handler_label_type(); | |
provider.AddPersistedHandler(pType, handler); | |
return pType; | |
} | |
template<class ApiHolder> | |
void BaseTypeMetadataPimpl<ApiHolder>::FillPropertiesIfNecessary() const | |
{ | |
using boost::array; | |
using Urasandesu::CppAnonym::CppAnonymCOMException; | |
if (m_filled) | |
return; | |
auto *pMod = m_pClass->MapFirst<module_metadata_label_type>(); | |
auto *pAsm = pMod->MapFirst<assembly_metadata_label_type>(); | |
auto &comMetaImp = pAsm->GetCOMMetaDataImport(); | |
auto mdtTarget = GetToken(); | |
if (TypeFromToken(mdtTarget) == mdtTypeRef) | |
{ | |
BOOST_THROW_EXCEPTION(Urasandesu::CppAnonym::CppAnonymNotImplementedException()); | |
} | |
else if (TypeFromToken(mdtTarget) == mdtTypeDef) | |
{ | |
BOOST_THROW_EXCEPTION(Urasandesu::CppAnonym::CppAnonymNotImplementedException()); | |
//WCHAR name[MAX_SYM_NAME] = { 0 }; | |
//ULONG nameSize = sizeof(name); | |
//DWORD attr = 0; | |
//mdToken mdtExt = mdTokenNil; | |
//HRESULT hr = comMetaImp.GetTypeDefProps(mdtTarget, name, nameSize, | |
// &nameSize, &attr, &mdtExt); | |
//if (FAILED(hr)) | |
// BOOST_THROW_EXCEPTION(SwatheCOMException(hr)); | |
//m_name = name; | |
//if (!IsNilToken(mdtExt) && | |
// (TypeFromToken(mdtExt) == mdtTypeDef || | |
// TypeFromToken(mdtExt) == mdtTypeRef)) | |
//{ | |
// m_pBaseType = pMod->NewType(mdtExt); | |
//} | |
//else if (!IsNilToken(mdtExt)) | |
//{ | |
// BOOST_THROW_EXCEPTION(SwatheNotImplementedException()); | |
//} | |
} | |
else if (TypeFromToken(mdtTarget) == mdtGenericParam) | |
{ | |
auto paramIndex = 0ul; | |
auto paramFlags = 0ul; | |
auto mdtOwner = mdTokenNil; | |
auto reserved = 0ul; | |
auto name = array<WCHAR, MAX_SYM_NAME>(); | |
auto length = 0ul; | |
auto hr = comMetaImp.GetGenericParamProps(mdtTarget, ¶mIndex, | |
¶mFlags, &mdtOwner, | |
&reserved, name.c_array(), name.size(), | |
&length); | |
if (FAILED(hr)) | |
BOOST_THROW_EXCEPTION(CppAnonymCOMException(hr)); | |
m_fullName = name.data(); | |
} | |
else | |
{ | |
BOOST_THROW_EXCEPTION(Urasandesu::CppAnonym::CppAnonymNotImplementedException()); | |
} | |
m_filled = true; | |
} | |
}}}} // namespace Urasandesu { namespace Swathe { namespace Metadata { namespace BaseClassPimpl { | |
#endif // URASANDESU_SWATHE_METADATA_BASECLASSPIMPL_BASETYPEMETADATAPIMPL_HPP | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment