SMILValue.cpp (4203B)
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/. */ 6 7 #include "SMILValue.h" 8 9 #include <string.h> 10 11 #include "nsDebug.h" 12 13 namespace mozilla { 14 15 //---------------------------------------------------------------------- 16 // Public methods 17 18 SMILValue::SMILValue(const SMILType* aType) : mType(SMILNullType::Singleton()) { 19 mU.mBool = false; 20 if (!aType) { 21 NS_ERROR("Trying to construct SMILValue with null mType pointer"); 22 return; 23 } 24 25 InitAndCheckPostcondition(aType); 26 } 27 28 SMILValue::SMILValue(const SMILValue& aVal) : mType(SMILNullType::Singleton()) { 29 InitAndCheckPostcondition(aVal.mType); 30 mType->Assign(*this, aVal); 31 } 32 33 const SMILValue& SMILValue::operator=(const SMILValue& aVal) { 34 if (&aVal == this) return *this; 35 36 if (mType != aVal.mType) { 37 DestroyAndReinit(aVal.mType); 38 } 39 40 mType->Assign(*this, aVal); 41 42 return *this; 43 } 44 45 // Move constructor / reassignment operator: 46 SMILValue::SMILValue(SMILValue&& aVal) noexcept 47 : mU(aVal.mU), // Copying union is only OK because we clear aVal.mType 48 // below. 49 mType(aVal.mType) { 50 // Leave aVal with a null type, so that it's safely destructible (and won't 51 // mess with anything referenced by its union, which we've copied). 52 aVal.mType = SMILNullType::Singleton(); 53 } 54 55 SMILValue& SMILValue::operator=(SMILValue&& aVal) noexcept { 56 if (!IsNull()) { 57 // Clean up any data we're currently tracking. 58 DestroyAndCheckPostcondition(); 59 } 60 61 // Copy the union (which could include a pointer to external memory) & mType: 62 mU = aVal.mU; 63 mType = aVal.mType; 64 65 // Leave aVal with a null type, so that it's safely destructible (and won't 66 // mess with anything referenced by its union, which we've now copied). 67 aVal.mType = SMILNullType::Singleton(); 68 69 return *this; 70 } 71 72 bool SMILValue::operator==(const SMILValue& aVal) const { 73 if (&aVal == this) return true; 74 75 return mType == aVal.mType && mType->IsEqual(*this, aVal); 76 } 77 78 nsresult SMILValue::Add(const SMILValue& aValueToAdd, uint32_t aCount) { 79 if (aValueToAdd.mType != mType) { 80 NS_ERROR("Trying to add incompatible types"); 81 return NS_ERROR_FAILURE; 82 } 83 84 return mType->Add(*this, aValueToAdd, aCount); 85 } 86 87 nsresult SMILValue::SandwichAdd(const SMILValue& aValueToAdd) { 88 if (aValueToAdd.mType != mType) { 89 NS_ERROR("Trying to add incompatible types"); 90 return NS_ERROR_FAILURE; 91 } 92 93 return mType->SandwichAdd(*this, aValueToAdd); 94 } 95 96 nsresult SMILValue::ComputeDistance(const SMILValue& aTo, 97 double& aDistance) const { 98 if (aTo.mType != mType) { 99 NS_ERROR("Trying to calculate distance between incompatible types"); 100 return NS_ERROR_FAILURE; 101 } 102 103 return mType->ComputeDistance(*this, aTo, aDistance); 104 } 105 106 nsresult SMILValue::Interpolate(const SMILValue& aEndVal, double aUnitDistance, 107 SMILValue& aResult) const { 108 if (aEndVal.mType != mType) { 109 NS_ERROR("Trying to interpolate between incompatible types"); 110 return NS_ERROR_FAILURE; 111 } 112 113 if (aResult.mType != mType) { 114 // Outparam has wrong type 115 aResult.DestroyAndReinit(mType); 116 } 117 118 return mType->Interpolate(*this, aEndVal, aUnitDistance, aResult); 119 } 120 121 //---------------------------------------------------------------------- 122 // Helper methods 123 124 // Wrappers for SMILType::InitValue & ::DestroyValue that verify their 125 // postconditions. 126 void SMILValue::InitAndCheckPostcondition(const SMILType* aNewType) { 127 aNewType->InitValue(*this); 128 MOZ_ASSERT(mType == aNewType, 129 "Post-condition of Init failed. SMILValue is invalid"); 130 } 131 132 void SMILValue::DestroyAndCheckPostcondition() { 133 mType->DestroyValue(*this); 134 MOZ_ASSERT(IsNull(), 135 "Post-condition of Destroy failed. " 136 "SMILValue not null after destroying"); 137 } 138 139 void SMILValue::DestroyAndReinit(const SMILType* aNewType) { 140 DestroyAndCheckPostcondition(); 141 InitAndCheckPostcondition(aNewType); 142 } 143 144 } // namespace mozilla