/* * 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 "XalanNamespacesStack.hpp" #include "DOMServices.hpp" XALAN_CPP_NAMESPACE_BEGIN XalanNamespacesStack::PrefixResolverProxy::PrefixResolverProxy( const XalanNamespacesStack& theStack, const XalanDOMString& theURI) : m_stack(theStack), m_uri(theURI) { } XalanNamespacesStack::PrefixResolverProxy::~PrefixResolverProxy() { } const XalanDOMString* XalanNamespacesStack::PrefixResolverProxy::getNamespaceForPrefix(const XalanDOMString& prefix) const { return m_stack.getNamespaceForPrefix(prefix); } const XalanDOMString& XalanNamespacesStack::PrefixResolverProxy::getURI() const { return m_uri; } XalanNamespacesStack::XalanNamespacesStackEntry::XalanNamespacesStackEntry(MemoryManagerType& theManager) : m_namespaces(theManager), m_position(m_namespaces.begin()) { } XalanNamespacesStack::XalanNamespacesStackEntry::XalanNamespacesStackEntry(const XalanNamespacesStackEntry& theSource, MemoryManagerType& theManager) : m_namespaces(theSource.m_namespaces, theManager), m_position(m_namespaces.begin() + (const_iterator(theSource.m_position) - theSource.m_namespaces.begin())) { } XalanNamespacesStack::XalanNamespacesStackEntry& XalanNamespacesStack::XalanNamespacesStackEntry::set(const XalanNamespacesStackEntry& theRHS, MemoryManagerType& theManager) { if (this != &theRHS) { XalanNamespacesStackEntry theCopy(theRHS, theManager); swap(theCopy); } return *this; } XalanNamespacesStack::XalanNamespacesStackEntry::~XalanNamespacesStackEntry() { } void XalanNamespacesStack::XalanNamespacesStackEntry::swap(XalanNamespacesStackEntry& theOther) { m_namespaces.swap(theOther.m_namespaces); const iterator theTemp = theOther.m_position; theOther.m_position = m_position; m_position = theTemp; } void XalanNamespacesStack::XalanNamespacesStackEntry::addDeclaration( const XalanDOMString& thePrefix, const XalanDOMChar* theURI, XalanDOMString::size_type theLength) { // If we're at the end, we need to allocate something // new, then update m_position. if (m_position == m_namespaces.end()) { m_namespaces.resize(m_namespaces.size() + 1); m_position = m_namespaces.end() - 1; } value_type& theNamespace = *m_position; // Set the appropriate values... theNamespace.setPrefix(thePrefix); theNamespace.setURI(theURI, theLength); ++m_position; } const XalanDOMString* XalanNamespacesStack::XalanNamespacesStackEntry::findEntry( const XalanDOMString& theKey, MemberFunctionType theKeyFunction, MemberFunctionType theValueFunction) const { if (m_namespaces.empty() == false) { const_iterator i(m_position); do { // m_position is always pointed past the end, so // decrement first. --i; const value_type& ns = (*i); const XalanDOMString& thisKey = (ns.*theKeyFunction)(); if(equals(theKey, thisKey)) { return &(ns.*theValueFunction)(); } } while (i != m_namespaces.begin()); } return 0; } void XalanNamespacesStack::XalanNamespacesStackEntry::clear() { m_namespaces.clear(); m_position = m_namespaces.begin(); } XalanNamespacesStack::XalanNamespacesStack(MemoryManagerType& theManager) : m_resultNamespaces(theManager, 1), m_stackBegin(m_resultNamespaces.begin()), m_stackPosition(m_stackBegin), m_createNewContextStack(theManager) { // m_resultNamespaces is initialized to a size of // 1, so we always have a dummy entry at the // beginning. This makes the implementation // much simpler. } XalanNamespacesStack::~XalanNamespacesStack() { } void XalanNamespacesStack::addDeclaration( const XalanDOMString& thePrefix, const XalanDOMChar* theURI, XalanDOMString::size_type theLength) { assert(theURI != 0); assert(m_createNewContextStack.empty() == false); // Check to see if we need to create a new context and do so if necessary... if (m_createNewContextStack.back() == true) { ++m_stackPosition; if (m_stackPosition == m_resultNamespaces.end()) { m_resultNamespaces.resize(m_resultNamespaces.size() + 1); m_stackPosition = m_resultNamespaces.end() - 1; m_stackBegin = m_resultNamespaces.begin(); } m_createNewContextStack.back() = false; } value_type& theCurrentEntry = *m_stackPosition; // Add a new namespace declaration... theCurrentEntry.addDeclaration(thePrefix, theURI, theLength); } void XalanNamespacesStack::pushContext() { if (m_createNewContextStack.empty() == true) { m_createNewContextStack.reserve(eDefaultCreateNewContextStackSize); } m_createNewContextStack.push_back(true); } void XalanNamespacesStack::popContext() { assert(m_createNewContextStack.empty() == false); if (m_createNewContextStack.back() == false) { assert(m_resultNamespaces.empty() == false && m_stackPosition != m_resultNamespaces.begin()); (*m_stackPosition).reset(); --m_stackPosition; } m_createNewContextStack.pop_back(); } const XalanDOMString* XalanNamespacesStack::findEntry( const XalanDOMString& theKey, MemberFunctionType theFunction) const { if (m_stackPosition == m_stackBegin) { return 0; } else { NamespacesStackType::const_iterator theBegin(m_stackBegin); NamespacesStackType::const_iterator theEnd(m_stackPosition + 1); const XalanDOMString* theValue = 0; do { theValue = ((*(--theEnd)).*theFunction)(theKey); if (theValue != 0) { break; } } while(theBegin != theEnd); return theValue; } } const XalanDOMString* XalanNamespacesStack::getNamespaceForPrefix(const XalanDOMString& thePrefix) const { if(thePrefix == DOMServices::s_XMLString) { return &DOMServices::s_XMLNamespaceURI; } else if (thePrefix == DOMServices::s_XMLNamespace) { return &DOMServices::s_XMLNamespacePrefixURI; } else { return findEntry(thePrefix, &value_type::getNamespaceForPrefix); } } bool XalanNamespacesStack::prefixIsPresentLocal(const XalanDOMString& thePrefix) { // Check to see if we need to create a new context. If so, there are // no prefixes mapped at this level, so return false... if (m_createNewContextStack.back() == true) { return false; } else { return (*m_stackPosition).isPrefixPresent(thePrefix); } } void XalanNamespacesStack::clear() { // Since we always keep one dummy entry at the beginning, // swap with an OutputContextStackType instance of size 1. NamespacesStackType(m_resultNamespaces.getMemoryManager(), 1 ).swap(m_resultNamespaces); m_stackBegin = m_resultNamespaces.begin(); m_stackPosition = m_stackBegin; m_createNewContextStack.clear(); } XALAN_CPP_NAMESPACE_END