/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ #if !defined(XALANDEQUE_HEADER_GUARD_1357924680) #define XALANDEQUE_HEADER_GUARD_1357924680 // Base include file. Must be first. #include #include #include namespace XALAN_CPP_NAMESPACE { template struct XalanDequeIteratorTraits { typedef Value value_type; typedef Value& reference; typedef Value* pointer; typedef const Value& const_reference; }; template struct XalanDequeConstIteratorTraits { typedef Value value_type; typedef const Value& reference; typedef const Value* pointer; typedef const Value& const_reference; }; template class XalanDequeIterator { public: typedef size_t size_type; typedef typename Traits::value_type value_type; typedef typename Traits::reference reference; typedef typename Traits::pointer pointer; typedef typename Traits::const_reference const_reference; typedef ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; // The non-const iterator type. In the case of the non-const instatiation, this // is the same type. typedef XalanDequeIterator, XalanDeque> Iterator; // The const version needs access to our private data members for copy construction and // assignment. For the const instantiation, this is a superfluous friend declaration, // since it's the same type as the class itself. friend class XalanDequeIterator, XalanDeque>; XalanDequeIterator( XalanDeque* deque, size_type pos) : m_deque(deque), m_pos(pos) { } // This is standard copy-construction for the non-const iterator type. For the // const iterator type, this is copy construction from the non-const type, and the // compiler will generate the standard copy constructor. XalanDequeIterator(const Iterator& iterator) : m_deque(iterator.m_deque), m_pos(iterator.m_pos) { } // This is the standard assignment operator for the non-const iterator type. // For the const iterator type, this is the assignment operator from the // non-const type, and the compiler will generate the standard assignment // operator. XalanDequeIterator& operator=(const Iterator& iterator) { m_deque = iterator.m_deque; m_pos = iterator.m_pos; return *this; } XalanDequeIterator& operator++() { ++m_pos; return *this; } XalanDequeIterator operator++(int) { XalanDequeIterator temp = *this; ++m_pos; return temp; } XalanDequeIterator& operator--() { --m_pos; return *this; } pointer operator->() { return &(*m_deque[m_pos]); } reference operator*() { return (*m_deque)[m_pos]; } const_reference operator*() const { return (*m_deque)[m_pos]; } XalanDequeIterator operator+(difference_type difference) const { return XalanDequeIterator(m_deque, m_pos + difference); } XalanDequeIterator operator-(difference_type difference) const { return XalanDequeIterator(m_deque, m_pos - difference); } difference_type operator-(const XalanDequeIterator& theRHS) const { return m_pos - theRHS.m_pos; } bool operator==(const XalanDequeIterator& theRHS) const { return theRHS.m_deque == m_deque && theRHS.m_pos == m_pos; } bool operator!=(const XalanDequeIterator& theRHS) const { return !(theRHS == *this); } bool operator<(const XalanDequeIterator& theRHS) const { return m_pos < theRHS.m_pos; } private: XalanDeque* m_deque; size_type m_pos; }; /** * Xalan implementation of deque */ template > class XalanDeque { public: typedef size_t size_type; typedef Type value_type; typedef Type& reference; typedef const Type& const_reference; typedef XalanVector BlockType; typedef XalanVector BlockIndexType; typedef XalanDeque ThisType; typedef XalanDequeIterator, ThisType> iterator; typedef XalanDequeIterator, ThisType> const_iterator; typedef std::reverse_iterator reverse_iterator_; typedef std::reverse_iterator const_reverse_iterator_; typedef reverse_iterator_ reverse_iterator; typedef const_reverse_iterator_ const_reverse_iterator; typedef typename ConstructionTraits::Constructor Constructor; typedef typename Constructor::ConstructableType ConstructableType; XalanDeque( MemoryManager& memoryManager, size_type initialSize = 0, size_type blockSize = 10) : m_memoryManager(&memoryManager), m_blockSize(blockSize), m_blockIndex(memoryManager, initialSize / blockSize + (initialSize % blockSize == 0 ? 0 : 1)), m_freeBlockVector(memoryManager) { const ConstructableType defaultValue(*m_memoryManager); using std::fill_n; using std::back_inserter; fill_n( back_inserter(*this), initialSize, defaultValue.value); } XalanDeque( const XalanDeque& theRHS, MemoryManager& theMemoryManager) : m_memoryManager(&theMemoryManager), m_blockSize(theRHS.m_blockSize), m_blockIndex(*theRHS.m_memoryManager, theRHS.size() / theRHS.m_blockSize + (theRHS.size() % theRHS.m_blockSize == 0 ? 0 : 1)), m_freeBlockVector(theMemoryManager) { using std::copy; using std::back_inserter; copy( theRHS.begin(), theRHS.end(), back_inserter(*this)); } static XalanDeque* create( MemoryManager& theManager, size_type initialSize = 0, size_type blockSize = 10) { XalanAllocationGuard theGuard(theManager, theManager.allocate(sizeof(ThisType))); ThisType* const theResult = new (theGuard.get()) ThisType(theManager, initialSize, blockSize); theGuard.release(); return theResult; } ~XalanDeque() { destroyBlockList(m_freeBlockVector); destroyBlockList(m_blockIndex); } iterator begin() { return iterator(this, 0); } const_iterator begin() const { return const_iterator(const_cast(this), 0); } iterator end() { return iterator(this, size()); } const_iterator end() const { return const_iterator(const_cast(this), size()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } bool empty() const { return m_blockIndex.empty(); } size_type size() const { if (m_blockIndex.empty()) { return 0; } else { return (m_blockIndex.size() - 1) * m_blockSize + m_blockIndex.back()->size(); } } value_type& back() { return m_blockIndex.back()->back(); } value_type& operator[](size_type index) { BlockType& block = *m_blockIndex[index / m_blockSize]; return block[index % m_blockSize]; } const value_type& operator[](size_type index) const { BlockType& block = *m_blockIndex[index / m_blockSize]; return block[index % m_blockSize]; } void clear() { typename BlockIndexType::iterator iter = m_blockIndex.begin(); m_freeBlockVector.reserve(m_freeBlockVector.size() + m_blockIndex.size()); while (iter != m_blockIndex.end()) { (*iter)->clear(); m_freeBlockVector.push_back(*iter); ++iter; } m_blockIndex.clear(); } void push_back(const value_type& value) { if (m_blockIndex.empty() || m_blockIndex.back()->size() >= m_blockSize) { pushNewIndexBlock(); } m_blockIndex.back()->push_back(value); } void pop_back() { assert(!empty()); BlockType& lastBlock = *m_blockIndex.back(); lastBlock.pop_back(); if (lastBlock.empty()) { m_freeBlockVector.push_back(&lastBlock); m_blockIndex.pop_back(); } } void resize(size_type newSize) { const ConstructableType defaultValue(*m_memoryManager); if (newSize > size()) { for (size_type i = 0; i < newSize - size(); ++i) { push_back(defaultValue.value); } } else { for (size_type i = 0; i < size() - newSize; ++i) { pop_back(); } } } void swap(XalanDeque& theRHS) { MemoryManager* const temp = m_memoryManager; m_memoryManager = theRHS.m_memoryManager; theRHS.m_memoryManager = temp; theRHS.m_blockIndex.swap(m_blockIndex); theRHS.m_freeBlockVector.swap(m_freeBlockVector); } XalanDeque& operator=(const XalanDeque& theRHS) { if (this != &theRHS) { using std::copy; using std::back_inserter; clear(); copy( theRHS.begin(), theRHS.end(), back_inserter(*this)); } return *this; } MemoryManager& getMemoryManager() { assert (m_memoryManager != 0); return *m_memoryManager; } private: void pushNewIndexBlock() { // Allocate space first, so we don't have to worry // about an out-of-memory error once we've constructed // the new block. m_blockIndex.push_back(0); if (m_freeBlockVector.empty()) { XalanConstruct( *m_memoryManager, m_blockIndex.back(), *m_memoryManager, m_blockSize); } else { m_blockIndex.back() = m_freeBlockVector.back(); // Now that ownership has been transfered, pop // it off the free list. m_freeBlockVector.pop_back(); } assert(m_blockIndex.back() != 0); } void destroyBlockList(BlockIndexType& theBlockIndex) { typename BlockIndexType::iterator iter = theBlockIndex.begin(); while (iter != theBlockIndex.end()) { // Normally, we should be able to just call // the version of XalanDestroy() that accepts // a pointer, but Visual Studio 6 has issues // with partial ordering, so we're stuck with // this for now. if (*iter != 0) { XalanDestroy(*m_memoryManager, **iter); } ++iter; } } MemoryManager* m_memoryManager; const size_type m_blockSize; BlockIndexType m_blockIndex; BlockIndexType m_freeBlockVector; // These are not implemented XalanDeque(); XalanDeque(const XalanDeque&); }; } #endif // XALANDEQUE_HEADER_GUARD_1357924680