You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by db...@locus.apache.org on 2000/05/30 00:30:10 UTC
cvs commit: xml-xalan/c/src/PlatformSupport AttributeListImpl.cpp AttributeListImpl.hpp
dbertoni 00/05/29 15:30:10
Modified: c/src/PlatformSupport AttributeListImpl.cpp
AttributeListImpl.hpp
Log:
Made assignment operators exception-safe.
Revision Changes Path
1.6 +106 -43 xml-xalan/c/src/PlatformSupport/AttributeListImpl.cpp
Index: AttributeListImpl.cpp
===================================================================
RCS file: /home/cvs/xml-xalan/c/src/PlatformSupport/AttributeListImpl.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- AttributeListImpl.cpp 2000/04/19 16:31:39 1.5
+++ AttributeListImpl.cpp 2000/05/29 22:30:09 1.6
@@ -113,11 +113,26 @@
+void
+AttributeListImpl::deleteEntries(AttributeVectorType& theVector)
+{
+#if !defined(XALAN_NO_NAMESPACES)
+ using std::for_each;
+#endif
+
+ // Delete all of the objects in the temp vector.
+ for_each(theVector.begin(),
+ theVector.end(),
+ DeleteFunctor<AttributeVectorEntry>());
+}
+
+
+
AttributeListImpl&
AttributeListImpl::operator=(const AttributeListImpl& theRHS)
{
#if !defined(XALAN_NO_NAMESPACES)
- using std::make_pair;
+ using std::auto_ptr;
#endif
if (this != &theRHS)
@@ -125,29 +140,52 @@
// Note that we can't chain up to our base class operator=()
// because it's private.
- // Clear everything out...
- clear();
+ // Some temporary structures to hold everything
+ // until we're done.
+ AttributeKeyMapType tempMap;
+ AttributeVectorType tempVector;
const unsigned int theLength = theRHS.getLength();
// Reserve the appropriate capacity right now...
- m_AttributeVector.reserve(theLength);
+ tempVector.reserve(theLength);
- // Copy the vector entries, and build the index map...
- for(unsigned int i = 0; i < theLength; i++)
+ try
{
- assert(theRHS.m_AttributeVector[i] != 0);
+ // Copy the vector entries, and build the index map...
+ for(unsigned int i = 0; i < theLength; i++)
+ {
+ assert(theRHS.m_AttributeVector[i] != 0);
+
+ auto_ptr<AttributeVectorEntry> theEntry(
+ new AttributeVectorEntry(*theRHS.m_AttributeVector[i]));
+
+ // Add the item...
+ tempVector.push_back(theEntry.get());
+
+ // The entry is now safely in the vector, so release the
+ // auto_ptr...
+ AttributeVectorEntry* const entry = theEntry.release();
+
+ // Create an entry in the index map...
+ tempMap.insert(AttributeKeyMapType::value_type(theEntry->m_Name.begin(),
+ entry));
+ }
+ }
+ catch(...)
+ {
+ deleteEntries(tempVector);
- AttributeVectorEntry* const theEntry =
- new AttributeVectorEntry(*theRHS.m_AttributeVector[i]);
+ throw;
+ }
- // Add the item...
- m_AttributeVector.push_back(theEntry);
+ // OK, we're safe, so swap the contents of the
+ // containers. This is guaranteed not to throw.
+ m_AttributeKeyMap.swap(tempMap);
+ m_AttributeVector.swap(tempVector);
- // Create an entry in the index map...
- m_AttributeKeyMap.insert(make_pair(theEntry->m_Name.begin(),
- theEntry));
- }
+ // This will delete all of the old entries.
+ deleteEntries(tempVector);
assert(getLength() == theLength);
assert(m_AttributeKeyMap.size() == m_AttributeVector.size());
@@ -166,20 +204,42 @@
// Note that we can't chain up to our base class operator=()
// because it's private.
- // Clear everything out.
- clear();
-
const unsigned int theLength = theRHS.getLength();
- // Reserve the appropriate capacity right now...
- m_AttributeVector.reserve(theLength);
+ // Some temporary structures to hold everything
+ // until we're done.
+ AttributeKeyMapType tempMap;
+ AttributeVectorType tempVector;
+
+ // Keep our old entries, in case something
+ // bad happens.
+ tempMap.swap(m_AttributeKeyMap);
+ tempVector.swap(m_AttributeVector);
- // Add each attribute.
- for(unsigned int i = 0; i < theLength; i++)
+ try
{
- addAttribute(theRHS.getName(i),
- theRHS.getType(i),
- theRHS.getValue(i));
+ // Reserve the appropriate capacity right now...
+ m_AttributeVector.reserve(theLength);
+
+ // Add each attribute.
+ for(unsigned int i = 0; i < theLength; i++)
+ {
+ addAttribute(theRHS.getName(i),
+ theRHS.getType(i),
+ theRHS.getValue(i));
+ }
+ }
+ catch(...)
+ {
+ // Swap everything back...
+ tempMap.swap(m_AttributeKeyMap);
+ tempVector.swap(m_AttributeVector);
+
+ // This will delete anything new we've
+ // created.
+ deleteEntries(tempVector);
+
+ throw;
}
assert(getLength() == theLength);
@@ -296,10 +356,7 @@
using std::for_each;
#endif
- // Delete all of the objects in the vector.
- for_each(m_AttributeVector.begin(),
- m_AttributeVector.end(),
- DeleteFunctor<AttributeVectorEntry>());
+ deleteEntries(m_AttributeVector);
// Clear everything out.
m_AttributeVector.clear();
@@ -332,7 +389,7 @@
const XMLCh* value)
{
#if !defined(XALAN_NO_NAMESPACES)
- using std::make_pair;
+ using std::auto_ptr;
#endif
assert(name != 0);
@@ -342,7 +399,7 @@
bool fResult = false;
- // Update the attribute, if it's already there
+ // Update the attribute, if it's already there...
const AttributeKeyMapType::iterator i =
m_AttributeKeyMap.find(name);
@@ -357,16 +414,20 @@
}
else
{
- AttributeVectorEntry* const theEntry =
- new AttributeVectorEntry(XMLChVectorType(name, endArray(name) + 1),
- XMLChVectorType(value, endArray(value) + 1),
- XMLChVectorType(type, endArray(type) + 1));
+ auto_ptr<AttributeVectorEntry> theEntry(
+ new AttributeVectorEntry(XMLChVectorType(name, endArray(name) + 1),
+ XMLChVectorType(value, endArray(value) + 1),
+ XMLChVectorType(type, endArray(type) + 1)));
// Add the new one.
- m_AttributeVector.push_back(theEntry);
+ m_AttributeVector.push_back(theEntry.get());
+
+ // The entry is now safely in the vector, so release the
+ // auto_ptr...
+ AttributeVectorEntry* const entry = theEntry.release();
// Create an entry in the index map.
- m_AttributeKeyMap.insert(make_pair(theEntry->m_Name.begin(), theEntry));
+ m_AttributeKeyMap.insert(AttributeKeyMapType::value_type(theEntry->m_Name.begin(), entry));
fResult = true;
}
@@ -386,29 +447,31 @@
assert(m_AttributeKeyMap.size() == m_AttributeVector.size());
#if !defined(XALAN_NO_NAMESPACES)
- using std::find_if;
- using std::equal_to;
+ using std::auto_ptr;
using std::bind1st;
+ using std::equal_to;
+ using std::find_if;
#endif
bool fResult = false;
// Find it in the key map.
- AttributeKeyMapType::iterator i =
+ const AttributeKeyMapType::iterator i =
m_AttributeKeyMap.find(name);
if (i != m_AttributeKeyMap.end())
{
// Found it, so now find the entry in the
// vector.
- AttributeVectorType::iterator j =
+ const AttributeVectorType::iterator j =
find_if(m_AttributeVector.begin(),
m_AttributeVector.end(),
bind1st(equal_to<const AttributeVectorEntry*>(), (*i).second));
assert(j != m_AttributeVector.end());
- // Delete it...
- delete *j;
+ // This will delete the entry, even if something
+ // bad happens updating the containers.
+ auto_ptr<const AttributeVectorEntry> theGuard(*j);
// Erase it from the vector.
m_AttributeVector.erase(j);
1.6 +4 -1 xml-xalan/c/src/PlatformSupport/AttributeListImpl.hpp
Index: AttributeListImpl.hpp
===================================================================
RCS file: /home/cvs/xml-xalan/c/src/PlatformSupport/AttributeListImpl.hpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- AttributeListImpl.hpp 2000/04/19 16:31:39 1.5
+++ AttributeListImpl.hpp 2000/05/29 22:30:09 1.6
@@ -154,7 +154,6 @@
bool
operator==(const AttributeListImpl&) const;
-
#if defined(XALAN_NO_NAMESPACES)
typedef vector<XMLCh> XMLChVectorType;
#else
@@ -197,6 +196,10 @@
AttributeVectorEntry*,
less_null_terminated_arrays<XMLCh> > AttributeKeyMapType;
#endif
+
+ // Helper function to delete entries...
+ static void
+ deleteEntries(AttributeVectorType& theVector);
AttributeKeyMapType m_AttributeKeyMap;
AttributeVectorType m_AttributeVector;