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