1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
14 //----------------------------------------------------------------------
17 SMILValue::SMILValue(const SMILType
* aType
) : mType(SMILNullType::Singleton()) {
20 NS_ERROR("Trying to construct SMILValue with null mType pointer");
24 InitAndCheckPostcondition(aType
);
27 SMILValue::SMILValue(const SMILValue
& aVal
) : mType(SMILNullType::Singleton()) {
28 InitAndCheckPostcondition(aVal
.mType
);
29 mType
->Assign(*this, aVal
);
32 const SMILValue
& SMILValue::operator=(const SMILValue
& aVal
) {
33 if (&aVal
== this) return *this;
35 if (mType
!= aVal
.mType
) {
36 DestroyAndReinit(aVal
.mType
);
39 mType
->Assign(*this, aVal
);
44 // Move constructor / reassignment operator:
45 SMILValue::SMILValue(SMILValue
&& aVal
) noexcept
46 : mU(aVal
.mU
), // Copying union is only OK because we clear aVal.mType
49 // Leave aVal with a null type, so that it's safely destructible (and won't
50 // mess with anything referenced by its union, which we've copied).
51 aVal
.mType
= SMILNullType::Singleton();
54 SMILValue
& SMILValue::operator=(SMILValue
&& aVal
) noexcept
{
56 // Clean up any data we're currently tracking.
57 DestroyAndCheckPostcondition();
60 // Copy the union (which could include a pointer to external memory) & mType:
64 // Leave aVal with a null type, so that it's safely destructible (and won't
65 // mess with anything referenced by its union, which we've now copied).
66 aVal
.mType
= SMILNullType::Singleton();
71 bool SMILValue::operator==(const SMILValue
& aVal
) const {
72 if (&aVal
== this) return true;
74 return mType
== aVal
.mType
&& mType
->IsEqual(*this, aVal
);
77 nsresult
SMILValue::Add(const SMILValue
& aValueToAdd
, uint32_t aCount
) {
78 if (aValueToAdd
.mType
!= mType
) {
79 NS_ERROR("Trying to add incompatible types");
80 return NS_ERROR_FAILURE
;
83 return mType
->Add(*this, aValueToAdd
, aCount
);
86 nsresult
SMILValue::SandwichAdd(const SMILValue
& aValueToAdd
) {
87 if (aValueToAdd
.mType
!= mType
) {
88 NS_ERROR("Trying to add incompatible types");
89 return NS_ERROR_FAILURE
;
92 return mType
->SandwichAdd(*this, aValueToAdd
);
95 nsresult
SMILValue::ComputeDistance(const SMILValue
& aTo
,
96 double& aDistance
) const {
97 if (aTo
.mType
!= mType
) {
98 NS_ERROR("Trying to calculate distance between incompatible types");
99 return NS_ERROR_FAILURE
;
102 return mType
->ComputeDistance(*this, aTo
, aDistance
);
105 nsresult
SMILValue::Interpolate(const SMILValue
& aEndVal
, double aUnitDistance
,
106 SMILValue
& aResult
) const {
107 if (aEndVal
.mType
!= mType
) {
108 NS_ERROR("Trying to interpolate between incompatible types");
109 return NS_ERROR_FAILURE
;
112 if (aResult
.mType
!= mType
) {
113 // Outparam has wrong type
114 aResult
.DestroyAndReinit(mType
);
117 return mType
->Interpolate(*this, aEndVal
, aUnitDistance
, aResult
);
120 //----------------------------------------------------------------------
123 // Wrappers for SMILType::Init & ::Destroy that verify their postconditions
124 void SMILValue::InitAndCheckPostcondition(const SMILType
* aNewType
) {
125 aNewType
->Init(*this);
126 MOZ_ASSERT(mType
== aNewType
,
127 "Post-condition of Init failed. SMILValue is invalid");
130 void SMILValue::DestroyAndCheckPostcondition() {
131 mType
->Destroy(*this);
133 "Post-condition of Destroy failed. "
134 "SMILValue not null after destroying");
137 void SMILValue::DestroyAndReinit(const SMILType
* aNewType
) {
138 DestroyAndCheckPostcondition();
139 InitAndCheckPostcondition(aNewType
);
142 } // namespace mozilla