Bug 542731, Patch A: Clean up nsSMILValue class. r=roc
authorDaniel Holbert <dholbert@cs.stanford.edu>
Fri, 29 Jan 2010 12:18:50 -0800
changeset 37637 a8810d63a74a7b0ce26ba464a2312cf7202003fa
parent 37636 7bee3d3a7cf2705e668483915c9fdf0750a99c66
child 37638 5ad17deecfe07a47a64c004a1df8bb3e3cc187bc
push id11414
push userdholbert@mozilla.com
push dateFri, 29 Jan 2010 20:19:24 +0000
treeherdermozilla-central@a8810d63a74a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs542731
milestone1.9.3a1pre
Bug 542731, Patch A: Clean up nsSMILValue class. r=roc
content/smil/nsSMILValue.cpp
content/smil/nsSMILValue.h
--- a/content/smil/nsSMILValue.cpp
+++ b/content/smil/nsSMILValue.cpp
@@ -34,78 +34,71 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSMILValue.h"
 #include "nsDebug.h"
 
+//----------------------------------------------------------------------
+// Public methods
+
 nsSMILValue::nsSMILValue(const nsISMILType* aType)
-: mU(),
-  mType(&nsSMILNullType::sSingleton)
+  : mType(&nsSMILNullType::sSingleton)
 {
-  if (!aType) return;
+  if (!aType) {
+    NS_ERROR("Trying to construct nsSMILValue with null mType pointer");
+    return;
+  }
 
-  nsresult rv = aType->Init(*this);
-  NS_POSTCONDITION(mType == aType || (NS_FAILED(rv) && IsNull()),
-    "Post-condition of Init failed. nsSMILValue is invalid");
+  InitAndCheckPostcondition(aType);
 }
 
 nsSMILValue::nsSMILValue(const nsSMILValue& aVal)
-:
-  mU(),
-  mType(&nsSMILNullType::sSingleton)
+  : mType(&nsSMILNullType::sSingleton)
 {
-  nsresult rv = aVal.mType->Init(*this);
-  NS_POSTCONDITION(mType == aVal.mType || (NS_FAILED(rv) && IsNull()),
-    "Post-condition of Init failed. nsSMILValue is invalid");
-  if (NS_FAILED(rv)) return;
+  nsresult rv = InitAndCheckPostcondition(aVal.mType);
+  if (NS_FAILED(rv))
+    return;
+
   mType->Assign(*this, aVal);
 }
 
 const nsSMILValue&
 nsSMILValue::operator=(const nsSMILValue& aVal)
 {
   if (&aVal == this)
     return *this;
 
   if (mType != aVal.mType) {
-    mType->Destroy(*this);
-    NS_POSTCONDITION(IsNull(), "nsSMILValue not null after destroying");
-    nsresult rv = aVal.mType->Init(*this);
-    NS_POSTCONDITION(mType == aVal.mType || (NS_FAILED(rv) && IsNull()),
-      "Post-condition of Init failed. nsSMILValue is invalid");
-    if (NS_FAILED(rv)) return *this;
+    nsresult rv = DestroyAndReinit(aVal.mType);
+    if (NS_FAILED(rv))
+      return *this; // Initialization failed; return early
   }
 
   mType->Assign(*this, aVal);
 
   return *this;
 }
 
 nsresult
 nsSMILValue::Add(const nsSMILValue& aValueToAdd, PRUint32 aCount)
 {
-  if (aValueToAdd.IsNull()) return NS_OK;
-
   if (aValueToAdd.mType != mType) {
     NS_ERROR("Trying to add incompatible types");
     return NS_ERROR_FAILURE;
   }
 
   return mType->Add(*this, aValueToAdd, aCount);
 }
 
 nsresult
 nsSMILValue::SandwichAdd(const nsSMILValue& aValueToAdd)
 {
-  if (aValueToAdd.IsNull())
-    return NS_OK;
-
   if (aValueToAdd.mType != mType) {
     NS_ERROR("Trying to add incompatible types");
     return NS_ERROR_FAILURE;
   }
 
   return mType->SandwichAdd(*this, aValueToAdd);
 }
 
@@ -126,19 +119,44 @@ nsSMILValue::Interpolate(const nsSMILVal
                          nsSMILValue& aResult) const
 {
   if (aEndVal.mType != mType) {
     NS_ERROR("Trying to interpolate between incompatible types");
     return NS_ERROR_FAILURE;
   }
 
   if (aResult.mType != mType) {
-    aResult.mType->Destroy(aResult);
-    NS_POSTCONDITION(aResult.IsNull(), "nsSMILValue not null after destroying");
-    nsresult rv = mType->Init(aResult);
-    NS_POSTCONDITION(aResult.mType == mType
-      || (NS_FAILED(rv) && aResult.IsNull()),
-      "Post-condition of Init failed. nsSMILValue is invalid");
-    if (NS_FAILED(rv)) return rv;
+    // Outparam has wrong type
+    nsresult rv = aResult.DestroyAndReinit(mType);
+    if (NS_FAILED(rv))
+      return rv;
   }
 
   return mType->Interpolate(*this, aEndVal, aUnitDistance, aResult);
 }
+
+//----------------------------------------------------------------------
+// Helper methods
+
+// Wrappers for nsISMILType::Init & ::Destroy that verify their postconditions
+nsresult
+nsSMILValue::InitAndCheckPostcondition(const nsISMILType* aNewType)
+{
+  nsresult rv = aNewType->Init(*this);
+  NS_ABORT_IF_FALSE(mType == aNewType || (NS_FAILED(rv) && IsNull()),
+                    "Post-condition of Init failed. nsSMILValue is invalid");
+  return rv;
+}
+                
+void
+nsSMILValue::DestroyAndCheckPostcondition()
+{
+  mType->Destroy(*this);
+  NS_ABORT_IF_FALSE(IsNull(), "Post-condition of Destroy failed. "
+                    "nsSMILValue not null after destroying");
+}
+
+nsresult
+nsSMILValue::DestroyAndReinit(const nsISMILType* aNewType)
+{
+  DestroyAndCheckPostcondition();
+  return InitAndCheckPostcondition(aNewType);
+}
--- a/content/smil/nsSMILValue.h
+++ b/content/smil/nsSMILValue.h
@@ -71,11 +71,16 @@ public:
   union {
     PRBool mBool;
     PRUint64 mUint;
     PRInt64 mInt;
     double mDouble;
     void* mPtr;
   } mU;
   const nsISMILType* mType;
+
+protected:
+  nsresult InitAndCheckPostcondition(const nsISMILType* aNewType);
+  void     DestroyAndCheckPostcondition();
+  nsresult DestroyAndReinit(const nsISMILType* aNewType);
 };
 
 #endif  // NS_SMILVALUE_H_