michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 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 michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsSMILValue.h" michael@0: #include "nsDebug.h" michael@0: #include michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // Public methods michael@0: michael@0: nsSMILValue::nsSMILValue(const nsISMILType* aType) michael@0: : mType(nsSMILNullType::Singleton()) michael@0: { michael@0: if (!aType) { michael@0: NS_ERROR("Trying to construct nsSMILValue with null mType pointer"); michael@0: return; michael@0: } michael@0: michael@0: InitAndCheckPostcondition(aType); michael@0: } michael@0: michael@0: nsSMILValue::nsSMILValue(const nsSMILValue& aVal) michael@0: : mType(nsSMILNullType::Singleton()) michael@0: { michael@0: InitAndCheckPostcondition(aVal.mType); michael@0: mType->Assign(*this, aVal); michael@0: } michael@0: michael@0: const nsSMILValue& michael@0: nsSMILValue::operator=(const nsSMILValue& aVal) michael@0: { michael@0: if (&aVal == this) michael@0: return *this; michael@0: michael@0: if (mType != aVal.mType) { michael@0: DestroyAndReinit(aVal.mType); michael@0: } michael@0: michael@0: mType->Assign(*this, aVal); michael@0: michael@0: return *this; michael@0: } michael@0: michael@0: bool michael@0: nsSMILValue::operator==(const nsSMILValue& aVal) const michael@0: { michael@0: if (&aVal == this) michael@0: return true; michael@0: michael@0: return mType == aVal.mType && mType->IsEqual(*this, aVal); michael@0: } michael@0: michael@0: void michael@0: nsSMILValue::Swap(nsSMILValue& aOther) michael@0: { michael@0: nsSMILValue tmp; michael@0: memcpy(&tmp, &aOther, sizeof(nsSMILValue)); // tmp = aOther michael@0: memcpy(&aOther, this, sizeof(nsSMILValue)); // aOther = this michael@0: memcpy(this, &tmp, sizeof(nsSMILValue)); // this = tmp michael@0: michael@0: // |tmp| is about to die -- we need to clear its mType, so that its michael@0: // destructor doesn't muck with the data we just transferred out of it. michael@0: tmp.mType = nsSMILNullType::Singleton(); michael@0: } michael@0: michael@0: nsresult michael@0: nsSMILValue::Add(const nsSMILValue& aValueToAdd, uint32_t aCount) michael@0: { michael@0: if (aValueToAdd.mType != mType) { michael@0: NS_ERROR("Trying to add incompatible types"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return mType->Add(*this, aValueToAdd, aCount); michael@0: } michael@0: michael@0: nsresult michael@0: nsSMILValue::SandwichAdd(const nsSMILValue& aValueToAdd) michael@0: { michael@0: if (aValueToAdd.mType != mType) { michael@0: NS_ERROR("Trying to add incompatible types"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return mType->SandwichAdd(*this, aValueToAdd); michael@0: } michael@0: michael@0: nsresult michael@0: nsSMILValue::ComputeDistance(const nsSMILValue& aTo, double& aDistance) const michael@0: { michael@0: if (aTo.mType != mType) { michael@0: NS_ERROR("Trying to calculate distance between incompatible types"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return mType->ComputeDistance(*this, aTo, aDistance); michael@0: } michael@0: michael@0: nsresult michael@0: nsSMILValue::Interpolate(const nsSMILValue& aEndVal, michael@0: double aUnitDistance, michael@0: nsSMILValue& aResult) const michael@0: { michael@0: if (aEndVal.mType != mType) { michael@0: NS_ERROR("Trying to interpolate between incompatible types"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: if (aResult.mType != mType) { michael@0: // Outparam has wrong type michael@0: aResult.DestroyAndReinit(mType); michael@0: } michael@0: michael@0: return mType->Interpolate(*this, aEndVal, aUnitDistance, aResult); michael@0: } michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // Helper methods michael@0: michael@0: // Wrappers for nsISMILType::Init & ::Destroy that verify their postconditions michael@0: void michael@0: nsSMILValue::InitAndCheckPostcondition(const nsISMILType* aNewType) michael@0: { michael@0: aNewType->Init(*this); michael@0: NS_ABORT_IF_FALSE(mType == aNewType, michael@0: "Post-condition of Init failed. nsSMILValue is invalid"); michael@0: } michael@0: michael@0: void michael@0: nsSMILValue::DestroyAndCheckPostcondition() michael@0: { michael@0: mType->Destroy(*this); michael@0: NS_ABORT_IF_FALSE(IsNull(), "Post-condition of Destroy failed. " michael@0: "nsSMILValue not null after destroying"); michael@0: } michael@0: michael@0: void michael@0: nsSMILValue::DestroyAndReinit(const nsISMILType* aNewType) michael@0: { michael@0: DestroyAndCheckPostcondition(); michael@0: InitAndCheckPostcondition(aNewType); michael@0: }