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