michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ michael@0: /* vim: set ts=2 sw=2 et tw=79: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_dom_Nullable_h michael@0: #define mozilla_dom_Nullable_h michael@0: michael@0: #include "mozilla/Assertions.h" michael@0: #include "nsTArrayForwardDeclare.h" michael@0: #include "mozilla/Move.h" michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: // Support for nullable types michael@0: template michael@0: struct Nullable michael@0: { michael@0: private: michael@0: // mIsNull MUST COME FIRST because otherwise the casting in our array michael@0: // conversion operators would shift where it is found in the struct. michael@0: bool mIsNull; michael@0: T mValue; michael@0: michael@0: public: michael@0: Nullable() michael@0: : mIsNull(true) michael@0: {} michael@0: michael@0: explicit Nullable(T aValue) michael@0: : mIsNull(false) michael@0: , mValue(aValue) michael@0: {} michael@0: michael@0: explicit Nullable(Nullable&& aOther) michael@0: : mIsNull(aOther.mIsNull) michael@0: , mValue(mozilla::Move(aOther.mValue)) michael@0: {} michael@0: michael@0: Nullable(const Nullable& aOther) michael@0: : mIsNull(aOther.mIsNull) michael@0: , mValue(aOther.mValue) michael@0: {} michael@0: michael@0: void operator=(const Nullable& aOther) michael@0: { michael@0: mIsNull = aOther.mIsNull; michael@0: mValue = aOther.mValue; michael@0: } michael@0: michael@0: void SetValue(T aValue) { michael@0: mValue = aValue; michael@0: mIsNull = false; michael@0: } michael@0: michael@0: // For cases when |T| is some type with nontrivial copy behavior, we may want michael@0: // to get a reference to our internal copy of T and work with it directly michael@0: // instead of relying on the copying version of SetValue(). michael@0: T& SetValue() { michael@0: mIsNull = false; michael@0: return mValue; michael@0: } michael@0: michael@0: void SetNull() { michael@0: mIsNull = true; michael@0: } michael@0: michael@0: const T& Value() const { michael@0: MOZ_ASSERT(!mIsNull); michael@0: return mValue; michael@0: } michael@0: michael@0: T& Value() { michael@0: MOZ_ASSERT(!mIsNull); michael@0: return mValue; michael@0: } michael@0: michael@0: bool IsNull() const { michael@0: return mIsNull; michael@0: } michael@0: michael@0: bool Equals(const Nullable& aOtherNullable) const michael@0: { michael@0: return (mIsNull && aOtherNullable.mIsNull) || michael@0: (!mIsNull && !aOtherNullable.mIsNull && michael@0: mValue == aOtherNullable.mValue); michael@0: } michael@0: michael@0: bool operator==(const Nullable& aOtherNullable) const michael@0: { michael@0: return Equals(aOtherNullable); michael@0: } michael@0: michael@0: bool operator!=(const Nullable& aOtherNullable) const michael@0: { michael@0: return !Equals(aOtherNullable); michael@0: } michael@0: michael@0: // Make it possible to use a const Nullable of an array type with other michael@0: // array types. michael@0: template michael@0: operator const Nullable< nsTArray >&() const { michael@0: // Make sure that T is ok to reinterpret to nsTArray michael@0: const nsTArray& arr = mValue; michael@0: (void)arr; michael@0: return *reinterpret_cast >*>(this); michael@0: } michael@0: template michael@0: operator const Nullable< FallibleTArray >&() const { michael@0: // Make sure that T is ok to reinterpret to FallibleTArray michael@0: const FallibleTArray& arr = mValue; michael@0: (void)arr; michael@0: return *reinterpret_cast >*>(this); michael@0: } michael@0: }; michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla michael@0: michael@0: #endif /* mozilla_dom_Nullable_h */