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