/* * 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 #include #include #include #include "AttributeVectorEntryExtended.hpp" XALAN_CPP_NAMESPACE_BEGIN AttributesImpl::AttributesImpl(MemoryManagerType& theManager) : AttributesType(), m_attributesVector(theManager), m_cacheVector(theManager) { } AttributesImpl::~AttributesImpl() { // Clean up everything... clear(); assert(m_attributesVector.empty() == true); deleteEntries(m_cacheVector); } AttributesImpl::AttributesImpl(const AttributesImpl& theSource, MemoryManagerType& theManager) : AttributesType(), m_attributesVector(theManager), m_cacheVector(theManager) { // Use the assignment operator to do the dirty work... *this = theSource; assert(getLength() == theSource.getLength()); } AttributesImpl::AttributesImpl(const AttributesType& theSource, MemoryManagerType& theManager) : AttributesType(), m_attributesVector(theManager), m_cacheVector(theManager) { // 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(theVector.getMemoryManager())); } 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(getMemoryManager()); 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 > 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(getMemoryManager()); 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); } typedef XalanMemMgrAutoPtr AutoPtr; AutoPtr theEntry(getMemoryManager(), getNewEntry(name, type, value, uri, localName)); // Add the new one. m_attributesVector.push_back(theEntry.get()); 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 AttributeVectorEntryExtended::create(name, value, type, uri, localName,getMemoryManager()); } 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