gecko-dev/ipc/mscom/COMPtrHolder.h
Nathan Froyd 6d0ffbfa26 Bug 1298840 - declare dependent type with typename in ParamTraits<COMPtrHolder<Interface, _IID>>; r=aklotz
MSVC lets this slide, but clang-cl complains about the missing typename.
2016-08-29 21:47:03 -04:00

145 lines
3.5 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_mscom_COMPtrHolder_h
#define mozilla_mscom_COMPtrHolder_h
#include "mozilla/Attributes.h"
#include "mozilla/Move.h"
#include "mozilla/mscom/ProxyStream.h"
#include "mozilla/mscom/Ptr.h"
namespace mozilla {
namespace mscom {
template<typename Interface, const IID& _IID>
class COMPtrHolder
{
public:
typedef ProxyUniquePtr<Interface> COMPtrType;
typedef COMPtrHolder<Interface, _IID> ThisType;
COMPtrHolder() {}
MOZ_IMPLICIT COMPtrHolder(decltype(nullptr))
{
}
explicit COMPtrHolder(COMPtrType&& aPtr)
: mPtr(Forward<COMPtrType>(aPtr))
{
}
Interface* Get() const
{
return mPtr.get();
}
MOZ_MUST_USE Interface* Release()
{
return mPtr.release();
}
void Set(COMPtrType&& aPtr)
{
mPtr = Forward<COMPtrType>(aPtr);
}
COMPtrHolder(const COMPtrHolder& aOther) = delete;
COMPtrHolder(COMPtrHolder&& aOther)
: mPtr(Move(aOther.mPtr))
{
}
// COMPtrHolder is eventually added as a member of a struct that is declared
// in IPDL. The generated C++ code for that IPDL struct includes copy
// constructors and assignment operators that assume that all members are
// copyable. I don't think that those copy constructors and operator= are
// actually used by any generated code, but they are made available. Since no
// move semantics are available, this terrible hack makes COMPtrHolder build
// when used as a member of an IPDL struct.
ThisType& operator=(const ThisType& aOther)
{
Set(Move(aOther.mPtr));
return *this;
}
ThisType& operator=(ThisType&& aOther)
{
Set(Move(aOther.mPtr));
return *this;
}
bool operator==(const ThisType& aOther) const
{
return mPtr == aOther.mPtr;
}
bool IsNull() const
{
return !mPtr;
}
private:
// This is mutable to facilitate the above operator= hack
mutable COMPtrType mPtr;
};
} // namespace mscom
} // namespace mozilla
namespace IPC {
template<typename Interface, const IID& _IID>
struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>>
{
typedef mozilla::mscom::COMPtrHolder<Interface, _IID> paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
mozilla::mscom::ProxyStream proxyStream(_IID, aParam.Get());
int bufLen;
const BYTE* buf = proxyStream.GetBuffer(bufLen);
MOZ_ASSERT(buf || !bufLen);
aMsg->WriteInt(bufLen);
aMsg->WriteBytes(reinterpret_cast<const char*>(buf), bufLen);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
int length;
if (!aMsg->ReadLength(aIter, &length)) {
return false;
}
mozilla::UniquePtr<BYTE[]> buf;
if (length) {
buf = mozilla::MakeUnique<BYTE[]>(length);
if (!aMsg->ReadBytesInto(aIter, buf.get(), length)) {
return false;
}
}
mozilla::mscom::ProxyStream proxyStream(buf.get(), length);
if (!proxyStream.IsValid()) {
return false;
}
Interface* rawInterface = nullptr;
if (!proxyStream.GetInterface(_IID, (void**)&rawInterface)) {
return false;
}
typename paramType::COMPtrType ptr(rawInterface);
aResult->Set(mozilla::Move(ptr));
return true;
}
};
} // namespace IPC
#endif // mozilla_mscom_COMPtrHolder_h