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;
  
  
  

Reply via email to