Skip to content

Instantly share code, notes, and snippets.

@urasandesu
Last active December 17, 2015 05:48
Show Gist options
  • Save urasandesu/5560100 to your computer and use it in GitHub Desktop.
Save urasandesu/5560100 to your computer and use it in GitHub Desktop.
#include "stdafx.h"
#ifndef URASANDESU_SWATHE_METADATA_SIGNATURE_H
#include <Urasandesu/Swathe/Metadata/Signature.h>
#endif
#ifndef URASANDESU_SWATHE_METADATA_IMETHOD_H
#include <Urasandesu/Swathe/Metadata/IMethod.h>
#endif
#ifndef URASANDESU_SWATHE_METADATA_ITYPE_H
#include <Urasandesu/Swathe/Metadata/IType.h>
#endif
namespace Urasandesu { namespace Swathe { namespace Metadata {
namespace SignatureDetail {
using boost::mpl::and_;
typedef boost::mpl::bool_<false> False;
template<class SignatureHolder, class HasGetSignature>
struct PutImplForSpecializedGetter
{
static void Put(SimpleBlob &sb, SignatureHolder const &sigHolder)
{
sb.Put<COR_SIGNATURE>(SignatureHolder::GetSignature(sigHolder));
}
};
template<class T>
struct PutImplForSpecializedGetter<T, False>
{
static void Put(SimpleBlob &sb, T const &v)
{
sb.Put<COR_SIGNATURE>(v);
}
};
template<class SignatureHolder, class IsSequence>
struct PutImplForSequenceDispensing
{
static void Put(SimpleBlob &sb, SignatureHolder const &sigs)
{
typedef PutImplForPointerDispensing<typename SignatureHolder::value_type> Impl;
for (auto i = sigs.begin(), i_end = sigs.end(); i != i_end; ++i)
Impl::Put(sb, *i);
}
};
template<class SignatureHolder>
struct PutImplForSequenceDispensing<SignatureHolder, False>
{
CPP_ANONYM_DECLARE_HAS_STATIC_MEMBER_FUNCTION(GetSignature, GetSignature, COR_SIGNATURE, (SignatureHolder const &v));
static void Put(SimpleBlob &sb, SignatureHolder const &sigHolder)
{
typedef CPP_ANONYM_HAS_STATIC_MEMBER_FUNCTION(GetSignature, SignatureHolder)::type HasGetSignature;
typedef PutImplForSpecializedGetter<SignatureHolder, HasGetSignature> Impl;
Impl::Put(sb, sigHolder);
}
};
CPP_ANONYM_DECLARE_HAS_MEMBER_TYPE(PutterHasIterator, iterator);
CPP_ANONYM_DECLARE_HAS_MEMBER_TYPE(PutterHasValueType, value_type);
template<class SignatureHolder>
struct PutImplForPointerDispensing
{
static void Put(SimpleBlob &sb, SignatureHolder const &sigHolder)
{
typedef CPP_ANONYM_HAS_MEMBER_TYPE(PutterHasIterator, SignatureHolder)::type HasIterator;
typedef CPP_ANONYM_HAS_MEMBER_TYPE(PutterHasValueType, SignatureHolder)::type HasValueType;
typedef and_<HasIterator, HasValueType>::type IsSequence;
typedef PutImplForSequenceDispensing<SignatureHolder, IsSequence> Impl;
Impl::Put(sb, sigHolder);
}
};
template<class SignatureHolder>
struct PutImplForPointerDispensing<SignatureHolder *>
{
static void Put(SimpleBlob &sb, SignatureHolder const *pSigHolder)
{
auto const &sig = pSigHolder->GetSignature();
auto const &blob = sig.GetBlob();
for (auto i = blob.begin(), i_end = blob.end(); i != i_end; ++i)
sb.Put<COR_SIGNATURE>(*i);
}
};
struct Putter
{
Putter(SimpleBlob& sb) :
m_sb(sb)
{ }
template<class SignatureHolder>
Putter& operator ,(SignatureHolder const &v)
{
typedef PutImplForPointerDispensing<SignatureHolder> Impl;
Impl::Put(m_sb, v);
return *this;
}
SimpleBlob& m_sb;
};
template<class T>
Putter operator +=(SimpleBlob& blob, T const &v)
{
return Putter(blob), v;
}
class SignatureImpl::SignatureImplPimpl
{
public:
SignatureImplPimpl(SignatureImpl *pClass) :
m_pClass(pClass)
{ }
void Initialize(IType const *pType)
{
BOOST_THROW_EXCEPTION(Urasandesu::CppAnonym::CppAnonymNotImplementedException());
}
void Initialize(IMethod const *pMethod)
{
_ASSERTE(pMethod != nullptr);
_ASSERTE(m_blob.empty());
auto sb = SimpleBlob();
sb +=
pMethod->GetCallingConvention(),
pMethod->GetParameterTypes().size(),
pMethod->GetReturnType(),
pMethod->GetParameterTypes()
;
m_blob.reserve(sb.Size());
m_blob.assign(sb.Ptr(), sb.Ptr() + sb.Size());
}
void Initialize(IField const *pField)
{
BOOST_THROW_EXCEPTION(Urasandesu::CppAnonym::CppAnonymNotImplementedException());
}
vector<COR_SIGNATURE> const &GetBlob() const
{
return m_blob;
}
private:
SignatureImpl *m_pClass;
vector<COR_SIGNATURE> m_blob;
};
SignatureImpl::SignatureImpl()
{
#ifdef _DEBUG
BOOST_MPL_ASSERT_RELATION(sizeof(SignatureImplPimpl), <=, sizeof(storage_type));
#else
BOOST_MPL_ASSERT_RELATION(sizeof(SignatureImplPimpl), ==, sizeof(storage_type));
#endif
new(Pimpl())SignatureImplPimpl(this);
}
SignatureImpl::~SignatureImpl()
{
Pimpl()->~SignatureImplPimpl();
}
SignatureImpl::SignatureImplPimpl *SignatureImpl::Pimpl()
{
return reinterpret_cast<SignatureImplPimpl *>(&m_storage);
}
SignatureImpl::SignatureImplPimpl const *SignatureImpl::Pimpl() const
{
return const_cast<SignatureImpl *>(this)->Pimpl();
}
void SignatureImpl::Initialize(IType const *pType)
{
Pimpl()->Initialize(pType);
}
void SignatureImpl::Initialize(IMethod const *pMethod)
{
Pimpl()->Initialize(pMethod);
}
void SignatureImpl::Initialize(IField const *pField)
{
Pimpl()->Initialize(pField);
}
vector<COR_SIGNATURE> const &SignatureImpl::GetBlob() const
{
return Pimpl()->GetBlob();
}
} // namespace SignatureDetail {
}}} // namespace Urasandesu { namespace Swathe { namespace Metadata {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment