| /* |
| * Copyright 1999-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| // Class header file. |
| #include "AttributesImpl.hpp" |
| |
| |
| |
| #include <algorithm> |
| #include <cassert> |
| |
| |
| |
| #include <xalanc/Include/XalanAutoPtr.hpp> |
| #include <xalanc/Include/STLHelper.hpp> |
| |
| |
| |
| #include "AttributeVectorEntryExtended.hpp" |
| |
| |
| |
| XALAN_CPP_NAMESPACE_BEGIN |
| |
| |
| |
| AttributesImpl::AttributesImpl() : |
| AttributesType(), |
| m_attributesVector(), |
| m_cacheVector() |
| { |
| } |
| |
| |
| |
| AttributesImpl::~AttributesImpl() |
| { |
| // Clean up everything... |
| clear(); |
| |
| assert(m_attributesVector.empty() == true); |
| |
| deleteEntries(m_cacheVector); |
| } |
| |
| |
| |
| AttributesImpl::AttributesImpl(const AttributesImpl& theSource) : |
| AttributesType(), |
| m_attributesVector() |
| { |
| // Use the assignment operator to do the dirty work... |
| *this = theSource; |
| |
| assert(getLength() == theSource.getLength()); |
| } |
| |
| |
| |
| AttributesImpl::AttributesImpl(const AttributesType& theSource) : |
| AttributesType(), |
| m_attributesVector() |
| { |
| // Use the assignment operator to do the dirty work... |
| *this = theSource; |
| |
| assert(getLength() == theSource.getLength()); |
| } |
| |
| |
| |
| void |
| AttributesImpl::deleteEntries(AttributesVectorType& theVector) |
| { |
| // Delete all of the objects in the vector. |
| XALAN_STD_QUALIFIER for_each( |
| theVector.begin(), |
| theVector.end(), |
| DeleteFunctor<AttributeVectorEntryExtended>()); |
| } |
| |
| |
| |
| AttributesImpl& |
| AttributesImpl::operator=(const AttributesImpl& theRHS) |
| { |
| if (this != &theRHS) |
| { |
| // Note that we can't chain up to our base class operator=() |
| // because it's private. |
| |
| // Some temporary structures to hold everything |
| // until we're done. |
| AttributesVectorType tempVector; |
| |
| const unsigned int theLength = theRHS.getLength(); |
| |
| if (theLength > 0) |
| { |
| // Reserve the appropriate capacity right now... |
| tempVector.reserve(theLength); |
| |
| // This will delete everything in tempVector when we're done... |
| CollectionDeleteGuard<AttributesVectorType, |
| DeleteFunctor<AttributeVectorEntryExtended> > theGuard(tempVector); |
| |
| typedef AttributesVectorType::const_iterator const_iterator; |
| |
| const const_iterator theEnd = theRHS.m_attributesVector.end(); |
| |
| // Copy the vector entries, and build the index map... |
| for(const_iterator i = theRHS.m_attributesVector.begin(); i != theEnd; ++i) |
| { |
| AttributeVectorEntryExtended* const theEntry = *i; |
| |
| assert(theEntry != 0); |
| |
| // Add the item... |
| tempVector.push_back( |
| getNewEntry( |
| &*theEntry->m_Name.begin(), |
| &*theEntry->m_Type.begin(), |
| &*theEntry->m_Value.begin(), |
| &*theEntry->m_uri.begin(), |
| &*theEntry->m_localName.begin())); |
| } |
| |
| // OK, we're safe, so swap the contents of the |
| // containers. This is guaranteed not to throw. |
| m_attributesVector.swap(tempVector); |
| } |
| |
| assert(getLength() == theLength); |
| } |
| |
| return *this; |
| } |
| |
| |
| |
| AttributesImpl& |
| AttributesImpl::operator=(const AttributesType& theRHS) |
| { |
| if (this != &theRHS) |
| { |
| // Note that we can't chain up to our base class operator=() |
| // because it's private. |
| |
| // Add all of the attributes to this temp list, |
| // then swap at the end. This means we're exception |
| // safe and don't need any try blocks. |
| AttributesImpl theTempList; |
| |
| const unsigned int theLength = theRHS.getLength(); |
| |
| theTempList.reserve(theLength); |
| |
| // Add each attribute. |
| for(unsigned int i = 0; i < theLength; i++) |
| { |
| theTempList.addAttribute( |
| theRHS.getURI(i), |
| theRHS.getLocalName(i), |
| theRHS.getQName(i), |
| theRHS.getType(i), |
| theRHS.getValue(i)); |
| } |
| |
| // Now that the temp list is built, swap everything. This is |
| // guaranteed not to throw. |
| swap(theTempList); |
| } |
| |
| return *this; |
| } |
| |
| |
| |
| unsigned int |
| AttributesImpl::getLength() const |
| { |
| return unsigned(m_attributesVector.size()); |
| } |
| |
| |
| |
| const XMLCh* |
| AttributesImpl::getURI(const unsigned int index) const |
| { |
| assert(index < getLength()); |
| |
| return &*m_attributesVector[index]->m_uri.begin(); |
| } |
| |
| |
| |
| const XMLCh* |
| AttributesImpl::getLocalName(const unsigned int index) const |
| { |
| assert(index < getLength()); |
| |
| return &*m_attributesVector[index]->m_localName.begin(); |
| } |
| |
| |
| |
| const XMLCh* |
| AttributesImpl::getQName(const unsigned int index) const |
| { |
| assert(index < getLength()); |
| |
| return &*m_attributesVector[index]->m_Name.begin(); |
| } |
| |
| |
| |
| const XMLCh* |
| AttributesImpl::getType(const unsigned int index) const |
| { |
| assert(index < getLength()); |
| |
| return &*m_attributesVector[index]->m_Type.begin(); |
| } |
| |
| |
| |
| const XMLCh* |
| AttributesImpl::getValue(const unsigned int index) const |
| { |
| assert(index < getLength()); |
| |
| return &*m_attributesVector[index]->m_Value.begin(); |
| } |
| |
| |
| |
| #if defined(XALAN_NEEDS_EXPLICIT_TEMPLATE_INSTANTIATION) |
| bool |
| AttributesImpl::NameCompareFunctor::operator()(const AttributeVectorEntryExtended* theEntry) const |
| { |
| return equals(&*theEntry->m_Name.begin(), m_qname); |
| } |
| |
| bool |
| AttributesImpl::URIAndLocalNameCompareFunctor::operator()(const AttributeVectorEntryExtended* theEntry) const |
| { |
| return equals(&*theEntry->m_uri.begin(), m_uri) && equals(&*theEntry->m_localName.begin(), m_localName) ; |
| } |
| #else |
| struct NameCompareFunctor |
| { |
| NameCompareFunctor(const XMLCh* theQName) : |
| m_qname(theQName) |
| { |
| } |
| |
| bool |
| operator()(const AttributeVectorEntryExtended* theEntry) const |
| { |
| return equals(&*theEntry->m_Name.begin(), m_qname); |
| } |
| |
| private: |
| |
| const XMLCh* const m_qname; |
| }; |
| |
| |
| |
| struct URIAndLocalNameCompareFunctor |
| { |
| URIAndLocalNameCompareFunctor( |
| const XMLCh* theURI, |
| const XMLCh* theLocalName) : |
| m_uri(theURI), |
| m_localName(theLocalName) |
| { |
| } |
| |
| bool |
| operator()(const AttributeVectorEntryExtended* theEntry) const |
| { |
| return equals(&*theEntry->m_uri.begin(), m_uri) && equals(&*theEntry->m_localName.begin(), m_localName) ; |
| } |
| |
| private: |
| |
| const XMLCh* const m_uri; |
| const XMLCh* const m_localName; |
| }; |
| #endif |
| |
| |
| |
| const XMLCh* |
| AttributesImpl::getType(const XMLCh* const qname) const |
| { |
| const int theIndex = getIndex(qname); |
| |
| if (theIndex == -1) |
| { |
| return 0; |
| } |
| else |
| { |
| return getType(theIndex); |
| } |
| } |
| |
| |
| |
| const XMLCh* |
| AttributesImpl::getValue(const XMLCh* const qname) const |
| { |
| const int theIndex = getIndex(qname); |
| |
| if (theIndex == -1) |
| { |
| return 0; |
| } |
| else |
| { |
| return getValue(theIndex); |
| } |
| } |
| |
| |
| |
| const XMLCh* |
| AttributesImpl::getType( |
| const XMLCh* const uri, |
| const XMLCh* const localName) const |
| { |
| const int theIndex = getIndex(uri, localName); |
| |
| if (theIndex == -1) |
| { |
| return 0; |
| } |
| else |
| { |
| return getType(theIndex); |
| } |
| } |
| |
| |
| |
| const XMLCh* |
| AttributesImpl::getValue( |
| const XMLCh* const uri, |
| const XMLCh* const localName) const |
| { |
| const int theIndex = getIndex(uri, localName); |
| |
| if (theIndex == -1) |
| { |
| return 0; |
| } |
| else |
| { |
| return getValue(theIndex); |
| } |
| } |
| |
| |
| |
| int |
| AttributesImpl::getIndex( |
| const XMLCh* const uri, |
| const XMLCh* const localName) const |
| { |
| assert(uri != 0 && localName != 0); |
| |
| const AttributesVectorType::const_iterator i = |
| XALAN_STD_QUALIFIER find_if( |
| m_attributesVector.begin(), |
| m_attributesVector.end(), |
| URIAndLocalNameCompareFunctor(uri, localName)); |
| |
| if (i != m_attributesVector.end()) |
| { |
| // Found it, so return the index, which is the difference between |
| // begin() and i. |
| return int(i - m_attributesVector.begin()); |
| } |
| else |
| { |
| return -1; |
| } |
| } |
| |
| |
| |
| int |
| AttributesImpl::getIndex(const XMLCh* const qname) const |
| { |
| assert(qname != 0); |
| |
| const AttributesVectorType::const_iterator i = |
| XALAN_STD_QUALIFIER find_if( |
| m_attributesVector.begin(), |
| m_attributesVector.end(), |
| NameCompareFunctor(qname)); |
| |
| if (i != m_attributesVector.end()) |
| { |
| // Found it, so return the index, which is the difference between |
| // begin() and i. |
| return int(i - m_attributesVector.begin()); |
| } |
| else |
| { |
| return -1; |
| } |
| } |
| |
| |
| |
| void |
| AttributesImpl::clear() |
| { |
| m_cacheVector.insert(m_cacheVector.end(), m_attributesVector.begin(), m_attributesVector.end()); |
| |
| // Clear everything out. |
| m_attributesVector.clear(); |
| } |
| |
| |
| |
| void |
| AttributesImpl::addAttribute( |
| const XMLCh* uri, |
| const XMLCh* localName, |
| const XMLCh* name, |
| const XMLCh* type, |
| const XMLCh* value) |
| { |
| assert(name != 0); |
| assert(type != 0); |
| assert(value != 0); |
| |
| typedef AttributeVectorEntry::XMLChVectorType XMLChVectorType; |
| |
| if (m_attributesVector.capacity() == 0) |
| { |
| m_attributesVector.reserve(eDefaultVectorSize); |
| } |
| |
| XalanAutoPtr<AttributeVectorEntryExtended> theEntry(getNewEntry(name, type, value, uri, localName)); |
| |
| // Add the new one. |
| m_attributesVector.push_back(theEntry.get()); |
| |
| // The entry is now safely in the vector, so release the |
| // XalanAutoPtr... |
| theEntry.release(); |
| } |
| |
| |
| |
| AttributeVectorEntryExtended* |
| AttributesImpl::getNewEntry( |
| const XMLCh* name, |
| const XMLCh* type, |
| const XMLCh* value, |
| const XMLCh* uri, |
| const XMLCh* localName) |
| { |
| assert(name != 0); |
| assert(type != 0); |
| assert(value != 0); |
| assert(uri != 0); |
| assert(localName != 0); |
| |
| if (m_cacheVector.empty() == true) |
| { |
| return new AttributeVectorEntryExtended(name, value, type, uri, localName); |
| } |
| else |
| { |
| AttributeVectorEntryExtended* const theEntry = |
| m_cacheVector.back(); |
| |
| theEntry->clear(); |
| |
| assert(theEntry->m_Name.empty() == true && theEntry->m_Value.empty() == true && |
| theEntry->m_Type.empty() == true && theEntry->m_uri.empty() == true && |
| theEntry->m_localName.empty() == true); |
| |
| theEntry->m_Name.insert(theEntry->m_Name.begin(), name, AttributeVectorEntry::endArray(name) + 1); |
| theEntry->m_Value.insert(theEntry->m_Value.begin(), value, AttributeVectorEntry::endArray(value) + 1); |
| theEntry->m_Type.insert(theEntry->m_Type.begin(), type, AttributeVectorEntry::endArray(type) + 1); |
| theEntry->m_uri.insert(theEntry->m_uri.begin(), uri, AttributeVectorEntry::endArray(uri) + 1); |
| theEntry->m_localName.insert(theEntry->m_localName.begin(), localName, AttributeVectorEntry::endArray(localName) + 1); |
| |
| m_cacheVector.pop_back(); |
| |
| return theEntry; |
| } |
| } |
| |
| |
| |
| bool |
| AttributesImpl::removeAttribute(const XMLCh* name) |
| { |
| assert(name != 0); |
| |
| bool fResult = false; |
| |
| // Update the attribute, if it's already there... |
| const AttributesVectorType::iterator i = |
| XALAN_STD_QUALIFIER find_if( |
| m_attributesVector.begin(), |
| m_attributesVector.end(), |
| NameCompareFunctor(name)); |
| |
| if (i != m_attributesVector.end()) |
| { |
| m_cacheVector.push_back(*i); |
| |
| m_attributesVector.erase(i); |
| |
| fResult = true; |
| } |
| |
| return fResult; |
| } |
| |
| |
| |
| XALAN_CPP_NAMESPACE_END |