// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
#define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
#include <new>
#include "mojo/public/cpp/environment/logging.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
namespace internal {
template <typename Struct>
class StructHelper {
public:
template <typename Ptr>
static void Initialize(Ptr* ptr) { ptr->Initialize(); }
};
} // namespace internal
template <typename Struct>
class StructPtr {
MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(StructPtr, RValue);
public:
typedef typename Struct::Data_ Data_;
StructPtr() : ptr_(NULL) {}
~StructPtr() {
delete ptr_;
}
StructPtr(RValue other) : ptr_(NULL) { Take(other.object); }
StructPtr& operator=(RValue other) {
Take(other.object);
return *this;
}
template <typename U>
U To() const {
return TypeConverter<U, StructPtr>::Convert(*this);
}
void reset() {
if (ptr_) {
delete ptr_;
ptr_ = NULL;
}
}
bool is_null() const { return ptr_ == NULL; }
Struct& operator*() const {
MOJO_DCHECK(ptr_);
return *ptr_;
}
Struct* operator->() const {
MOJO_DCHECK(ptr_);
return ptr_;
}
Struct* get() const { return ptr_; }
void Swap(StructPtr* other) {
std::swap(ptr_, other->ptr_);
}
private:
typedef Struct* StructPtr::*Testable;
public:
operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; }
private:
friend class internal::StructHelper<Struct>;
void Initialize() {
MOJO_DCHECK(!ptr_);
ptr_ = new Struct();
}
void Take(StructPtr* other) {
reset();
Swap(other);
}
Struct* ptr_;
};
// Designed to be used when Struct is small and copyable.
template <typename Struct>
class InlinedStructPtr {
MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InlinedStructPtr, RValue);
public:
typedef typename Struct::Data_ Data_;
InlinedStructPtr() : is_null_(true) {}
~InlinedStructPtr() {}
InlinedStructPtr(RValue other) : is_null_(true) { Take(other.object); }
InlinedStructPtr& operator=(RValue other) {
Take(other.object);
return *this;
}
template <typename U>
U To() const {
return TypeConverter<U, InlinedStructPtr>::Convert(*this);
}
void reset() {
is_null_ = true;
value_.~Struct();
new (&value_) Struct();
}
bool is_null() const { return is_null_; }
Struct& operator*() const {
MOJO_DCHECK(!is_null_);
return value_;
}
Struct* operator->() const {
MOJO_DCHECK(!is_null_);
return &value_;
}
Struct* get() const { return &value_; }
void Swap(InlinedStructPtr* other) {
std::swap(value_, other->value_);
std::swap(is_null_, other->is_null_);
}
private:
typedef Struct InlinedStructPtr::*Testable;
public:
operator Testable() const { return is_null_ ? 0 : &InlinedStructPtr::value_; }
private:
friend class internal::StructHelper<Struct>;
void Initialize() { is_null_ = false; }
void Take(InlinedStructPtr* other) {
reset();
Swap(other);
}
mutable Struct value_;
bool is_null_;
};
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_